JZOJ 1980. 【2011集训队出题】Construct
Description
隨著改革開放的深入推進……
小T家要拆遷了……
當對未來生活充滿美好憧憬的小T看到拆遷協議書的時候,小T從一位大好的社會主義青年變成了絕望的釘子戶。
由于小T的家位于市中心,拆遷工作又難以進行,有關部門決定先把小T家用圍欄圍起來,以免影響市容。考慮到要建設資源節約型社會,他們希望所用的圍欄長度越短越好,由于市中心寸土寸金,在圍欄長度最短的情況下,圍出的多邊形面積越小越好。
為了簡化問題,我們約定,小T的家是一個多邊形,并且每條邊與坐標軸平行,圍欄構成的也是多邊形,每條邊與坐標軸平行。
Input
在第一行列出整數n——多邊形的頂點的數量。在以下n行中的每一行都有兩個整數——沿逆時針方向走過這個多邊形順次所經過的頂點的坐標。邊界的任意三個連續頂點不在一條直線上。多邊形的邊界不含自交和自切。
Output
輸出兩行,第一行為圍欄最短的長度,第二行為長度最短的前提下,最小的面積。
Sample Input
8
0 0
9 0
9 9
6 9
6 3
3 3
3 6
0 6
Sample Output
36
63
Data Constraint
Hint
【數據范圍】
對于10%的數據n≤20
對于70%的數據n≤5000
對于100%的數據4≤n≤100000,坐標的絕對值不超過10^9 。
Solution
首先,可以發現周長是一定的,就是用一個矩形套住那個多邊形。
之后又可以發現,為了使面積最小,肯定是在矩形的四周挖去一些類似鋸齒形的多邊形。
于是我們把點排序,用一個單調棧處理點,四個角各處理一遍即可。
時間復雜度 O(N?log?N) 。
Code
#include<cstdio> #include<algorithm> #include<cctype> using namespace std; typedef long long LL; const int N=1e5+1; const LL inf=1e10; struct data {LL x,y; }a[N],p1,p2; int top; LL sum; LL st[N]; inline int read() {int X=0,w=0; char ch=0;while(!isdigit(ch)) w|=ch=='-',ch=getchar();while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();return w?-X:X; } inline LL min(LL x,LL y){return x<y?x:y;} inline LL max(LL x,LL y){return x>y?x:y;} inline bool cmp(data x,data y) {return x.x<y.x || x.x==y.x && x.y<y.y; } int main() {int n=read();p1.x=p1.y=inf,p2.x=p2.y=-inf;for(int i=1;i<=n;i++){a[i].x=read(),a[i].y=read();p1.x=min(p1.x,a[i].x),p1.y=min(p1.y,a[i].y);p2.x=max(p2.x,a[i].x),p2.y=max(p2.y,a[i].y);}sort(a+1,a+1+n,cmp);sum=(p2.x-p1.x)*(p2.y-p1.y);for(int i=1;i<=n;i++)if(!top) st[++top]=i; else{if(a[st[top]].y<a[i].y){if(a[st[top]].x^a[i].x) top++;st[top]=i;}if(a[i].y==p2.y) break;}for(int i=2;i<=top;i++) sum-=(a[st[i]].y-a[st[i-1]].y)*(a[st[i]].x-a[st[1]].x);top=0;for(int i=n;i;i--)if(!top) st[++top]=i; else{if(a[st[top]].y<a[i].y){if(a[st[top]].x^a[i].x) top++;st[top]=i;}if(a[i].y==p2.y) break;}for(int i=2;i<=top;i++) sum-=(a[st[i]].y-a[st[i-1]].y)*(a[st[1]].x-a[st[i]].x);top=0;for(int i=1;i<=n;i++)if(!top) st[++top]=i; else{if(a[st[top]].y>a[i].y){if(a[st[top]].x^a[i].x) top++;st[top]=i;}if(a[i].y==p1.y) break;}for(int i=2;i<=top;i++) sum-=(a[st[i-1]].y-a[st[i]].y)*(a[st[i]].x-a[st[1]].x);top=0;for(int i=n;i;i--)if(!top) st[++top]=i; else{if(a[st[top]].y>a[i].y){if(a[st[top]].x^a[i].x) top++;st[top]=i;}if(a[i].y==p1.y) break;}for(int i=2;i<=top;i++) sum-=(a[st[i-1]].y-a[st[i]].y)*(a[st[1]].x-a[st[i]].x);printf("%lld\n%lld",2*(p2.x-p1.x+p2.y-p1.y),sum);return 0; }總結
以上是生活随笔為你收集整理的JZOJ 1980. 【2011集训队出题】Construct的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hdu 3062. Party
- 下一篇: JZOJ 2308. 【中山市选2011