Construct
【问题描述】
随着改革开放的深入推进…… 小T家要拆迁了…… 当对未来生活充满美好憧憬的小T看到拆迁协议书的时候,小T从一位大好的社会主义青年变成了绝望的钉子户。 由于小T的家位于市中心,拆迁工作又难以进行,有关部门决定先把小T家用围栏围起来,以免影响市容。考虑到要建设资源节约型社会,他们希望所用的围栏长度越短越好,由于市中心寸土寸金,在围栏长度最短的情况下,围出的多边形面积越小越好。 为了简化问题,我们约定,小T的家是一个多边形,并且每条边与坐标轴平行,围栏构成的也是多边形,每条边与坐标轴平行。
【输入格式】
在第一行列出整数n——多边形的顶点的数量。在以下n行中的每一行都有两个整数——沿逆时针方向走过这个多边形顺次所经过的顶点的坐标。边界的任意三个连续顶点不在一条直线上。多边形的边界不含自交和自切。
【输出格式】
输出两行,第一行为围栏最短的长度,第二行为长度最短的前提下,最小的面积。
【样例输入】
8
0 0
9 0
9 9
6 9
6 3
3 3
3 6
0 6
【样例输出】
36
63
【数据范围】
对于100%的数据4≤n≤100000,坐标的绝对值不超过109 。
题解:
题意就是求直的凸包
那么我们把这个凸包分成左上、左下、右上、右下
把点按横坐标排下序
每一部分的纵坐标单调递增或者单调递减
用单调栈维护就好了
1 #include<cmath> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<iostream> 6 #include<algorithm> 7 using namespace std; 8 typedef long long lar; 9 const int maxn = 2e5 + 233; 10 const lar inf = 2e9; 11 int n; 12 int top; 13 int num; 14 lar ans; 15 struct point 16 { 17 lar x, y; 18 inline void print() 19 { 20 printf("%lld %lld\n", x, y); 21 } 22 friend inline lar operator * (point a, point b) 23 { 24 return a.x * b.y - a.y * b.x; 25 } 26 }; 27 point mi, ma; 28 point p[maxn]; 29 point s[maxn]; 30 inline bool hor(point a, point b) 31 { 32 return (a.x != b.x) ? a.x < b.x : a.y < b.y; 33 } 34 inline void Scan(int &x) 35 { 36 char c; 37 bool o = false; 38 while(!isdigit(c = getchar())) o = (c != '-') ? o : true; 39 x = c - '0'; 40 while(isdigit(c = getchar())) x = x * 10 + c - '0'; 41 if(o) x = -x; 42 } 43 inline void Max(point &a, point b) 44 { 45 a.x = max(a.x, b.x); 46 a.y = max(a.y, b.y); 47 } 48 inline void Min(point &a, point b) 49 { 50 a.x = min(a.x, b.x); 51 a.y = min 52 (a.y, b.y); 53 } 54 int main() 55 { 56 Scan(n); 57 int x, y; 58 for(int i = 1; i <= n; ++i) 59 { 60 Scan(x), Scan(y); 61 p[i] = (point) {x, y}; 62 } 63 sort(p + 1, p + 1 + n, hor); 64 int up, be; 65 point mi, ma; 66 mi.x = mi.y = inf; 67 ma.x = ma.y = -inf; 68 for(int i = 1; i <= n; ++i) 69 { 70 Max(ma, p[i]); 71 Min(mi, p[i]); 72 } 73 int now = 1; 74 while(now <= n) 75 { 76 if(!top || p[now].y >= s[top].y) s[++top] = p[now]; 77 if(p[now++].y == ma.y) break; 78 } 79 while(now <= n) 80 { 81 while(p[now].y > s[top].y) --top; 82 s[++top] = p[now++]; 83 } 84 for(int i = 1; i < top; ++i) ans += min(s[i + 1].y, s[i].y) * (s[i + 1].x - s[i].x); 85 top = 0; 86 now = 1; 87 while(now <= n) 88 { 89 if(!top || p[now].y <= s[top].y) s[++top] = p[now]; 90 if(p[now++].y == mi.y) break; 91 } 92 while(now <= n) 93 { 94 while(p[now].y < s[top].y) --top; 95 s[++top] = p[now++]; 96 } 97 for(int i = 1; i < top; ++i) ans -= max(s[i + 1].y, s[i].y) * (s[i + 1].x - s[i].x); 98 lar one = (ma.x + ma.y - mi.x - mi.y) << 1; 99 printf("%lld\n%lld", one, ans); 100 }