AtCoder Beginner Contest 250

F - One Fourth

https://atcoder.jp/contests/abc250/tasks/abc250_f

Time Limit: 2 sec / Memory Limit: 1024 MB

Score : 500 points

Problem Statement

ABC 250 is a commemorable quarter milestone for Takahashi, who aims to hold ABC 1000, so he is going to celebrate this contest by eating as close to 1/4 of a pizza he bought as possible.

The pizza that Takahashi bought has a planar shape of convex N-gon. When the pizza is placed on an xy-plane, the i-th vertex has coordinates (Xi,Yi).

Takahashi has decided to cut and eat the pizza as follows.

  • First, Takahashi chooses two non-adjacent vertices from the vertices of the pizza and makes a cut with a knife along the line passing through those two points, dividing the pizza into two pieces.
  • Then, he chooses one of the pieces at his choice and eats it.

Let aa be the quarter (=1/4) of the area of the pizza that Takahashi bought, and bb be the area of the piece of pizza that Takahashi eats. Find the minimum possible value of 8×|ab|. We can prove that this value is always an integer.

Constraints

  • All values in input are integers.
  • 4N105
  • |Xi|,|Yi|4×108
  • The given points are the vertices of a convex N-gon in the counterclockwise order.

Input

Input is given from Standard Input in the following format:

N
X1 Y1
X2 Y2

XN YN

Output

Print the answer as an integer.


Sample Input 1

5
3 0
2 3
-1 3
-3 1
-1 -1

Sample Output 1

1

Suppose that he makes a cut along the line passing through the 3-rd and the 5-th vertex and eats the piece containing the 4-th vertex.
Then, a=332×14=338​, b=4, and 8×|ab|=1, which is minimum possible.


Sample Input 2

4
400000000 400000000
-400000000 400000000
-400000000 -400000000
400000000 -400000000

Sample Output 2

1280000000000000000

Sample Input 3

6
-816 222
-801 -757
-165 -411
733 131
835 711
-374 979

Sample Output 3

157889

我的笔记

O(N3) 法:TLE x20

思路:

P0,P1,,PN (P代表点) 中任取 Pi,Pj,且 Pi,Pj 不可相邻,规定吃掉包含 Pi+1 的部分。所有情况 8×|ab| 的最小值即为所求。

求法:

Pi,Pj 不相邻判断:i,j 相差的绝对值不可 1。并且也不能等于 N1, 即 i=0,j=N1j=0,i=N1 的情况。

包含 Pi+1 的部分的面积求法:如图,SBCDE=SBCD+SBDE,即将多边形以 Pi 为顶点划分为三角形。

三角形面积:已知 ABC 的三个顶点 A(x1,y1),B(x2,y2),C(x3,y3),可以用向量叉乘表示面积: 2SABC=AB×AC,即:

SABC=12|ijkx2x1y2y10x3x1y3y10|=12|(x3x1)(y2y1)(x2x1)(y3y1)|

代码:

#include <bits/stdc++.h>

using namespace std;

const int SIZE = 1e5 + 10;
int N;
pair<int, int> points[SIZE];

inline long long areax2(pair<int, int> a, pair<int, int> b, pair<int, int> c)
{
    return abs(1ll * (c.first - a.first) * (b.second - a.second) - 1ll * (b.first - a.first) * (c.second - a.second));
}

int main()
{
    cin >> N;
    for (int i = 0; i < N; i++)
        cin >> points[i].first >> points[i].second;
    long long ax8 = 0;
    for (int i = 1; i < N - 1; i++)
    {
        ax8 += areax2(points[0], points[i], points[i + 1]);
    }
    long long ans = INT64_MAX;
    // START
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++)
        {
            if (abs(i - j) <= 1 || abs(i - j) == N - 1)
                continue;
            long long bx2 = 0;
            for (int k = (i + 1) % N; k != j; k = (k + 1) % N)
            {
                bx2 += areax2(points[i], points[k], points[(k + 1) % N]);
            }
            ans = min(ans, abs(ax8 - 4 * bx2));
        }
    }
    // END
    cout << ans << endl;
    return 0;
}

O(N2) 法:TLE x11

上面的方法是从多边形分割为小三角形计算,同一个小三角形的面积重复计算了很多次。我们可以用小三角形的面积来组成多边形,可以减少很多次计算。

思路:

P0,P1,,PN 任取 Pi,逆时针方向依次加上以 Pi 为顶点的小三角形的面积,每次加上后计算一次结果的最小值。

如下图,若取 B 为顶点,那么计算 SBCD,SBCD+SBDE,依此为吃掉的面积计算 8×|ab| 的结果。

求法:

j=(i+1)modN,将已有面积加上以 Pi,Pj,P(j+1)modN 为顶点的三角形的面积,每次操作后将 j 更新为 (j+1)modN,一共进行 N2 次操作(因为不能沿着边切割)

取模很重要!只要是 +1 ,序号都有可能超过 N 而重新从 0 开始。

代码:

// 将此代码替换到方法一代码的START注释与END注释之间
for (int i = 0; i < N; i++)
{
    long long bx2 = 0;
    for (int j = (i + 1) % N, t = 0; t < N - 2; j = (j + 1) % N, t++)
    {
        bx2 += areax2(points[i], points[j], points[(j + 1) % N]);
        ans = min(ans, abs(ax8 - 4 * bx2));
    }
}

O(N) 法:AC

思路:

既然题目要求 8×|ab| 最小,那么可以用滑动窗口:若 b<a,那就是切少了,得多切点;若 b>a,那就是切多了,得少切点。

求法:

i 初始为 0j 初始为 1,如果 b<a,那么加上以 Pi,Pj,P(j+1)modN 为顶点的三角形面积,j 更新为 (j+1)modN 然后再继续加三角形,直到 ba。然后再去掉以 Pi,P(i+1)modN,Pj 为顶点的三角形面积,i 加一,直到 b<a.

代码:

// 将此代码替换到方法一代码的START注释与END注释之间
long long bx2 = 0;
int j = 1;
for (int i = 0; i < N; i++)
{
    while (bx2 * 4 < ax8)
    {
        bx2 += areax2(points[i], points[j], points[(j + 1) % N]);
        j = (j + 1) % N;
        ans = min(ans, abs(ax8 - 4 * bx2));
    }
    bx2 -= areax2(points[i], points[(i + 1) % N], points[j]);
    ans = min(ans, abs(ax8 - 4 * bx2));
}