bzoj2146 Construct

题目描述

随着改革开放的深入推进…… 小T家要拆迁了…… 当对未来生活充满美好憧憬的小T看到拆迁协议书的时候,小T从一位大好的社会主义青年变成了绝望的钉子户。 由于小T的家位于市中心,拆迁工作又难以进行,有关部门决定先把小T家用围栏围起来,以免影响市容。考虑到要建设资源节约型社会,他们希望所用的围栏长度越短越好,由于市中心寸土寸金,在围栏长度最短的情况下,围出的多边形面积越小越好。 为了简化问题,我们约定,小T的家是一个多边形,并且每条边与坐标轴平行,围栏构成的也是多边形,每条边与坐标轴平行。 


输入格式

在第一行列出整数n——多边形的顶点的数量。在以下n行中的每一行都有两个整数——沿逆时针方向走过这个多边形顺次所经过的顶点的坐标。边界的任意三个连续顶点不在一条直线上。多边形的边界不含自交和自切。


输出格式

输出两行,第一行为围栏最短的长度,第二行为长度最短的前提下,最小的面积。


【数据范围】
对于100%的数据4≤n≤100000,坐标的绝对值不超过109 。

  • 题解

    • 可能和凸包没有什么关系吧。。。。。
    • 周长显然,直接将所有框起来即可,$2 * (max \{ x_{i} \}  -  min\{ x_{i} \} \ \  + \ \  max \{ y_{i} \}  -  min\{ y_{i} \}) $
    • 将所有都框起来并不是面积最小,因为有些部分收进去周长不会边长,但是面积会减小;
    • 但是也不能全部收进去因为会有类似于“凹”字的形状收进去后周长会变大;
    • 考虑每次从上到下扫描,维护当前横坐标的最大值和最小值,如果更新了最大值或最小值就新建一个拐点和新点;
    • 再从下面来一次,直接得到了点数O(2*n)的框,求面积即可;
 1 #include<bits/stdc++.h>
 2 #define inf 0x7fffffff
 3 #define ll long long 
 4 using namespace std;
 5 const int N = 200010;
 6 int n,c1,c2,c3,c4;
 7 struct P{
 8     int x,y;
 9     P(int X=0,int Y=0):x(X),y(Y){};
10     bool operator <(const P&a)const{return x<a.x;} 
11 }p[N],p1[N],p2[N],p3[N],p4[N];
12 char gc(){
13     static char*P1,*P2,s[1000000];
14     if(P1==P2)P2=(P1=s)+fread(s,1,1000000,stdin);
15     return(P1==P2)?EOF:*P1++;
16 }
17 int rd(){
18     int x=0,f=1;char c=gc();
19     while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
20     while(c>='0'&&c<='9')x=x*10+c-'0',c=gc();
21     return x*f; 
22 }
23 ll crs(const P&a,const P&b){return (ll)a.x*b.y-(ll)a.y*b.x;}
24 int main(){
25     #ifndef ONLINE_JUDGE
26     freopen("bzoj2146.in","r",stdin);
27     freopen("bzoj2146.out","w",stdout);
28     #endif
29     n=rd();
30     for(int i=1;i<=n;++i)p[i].x=rd(),p[i].y=rd();
31     sort(p+1,p+n+1);
32     for(int i=1,j=1,mn=inf,mx=-inf;i<=n;i=j){
33         int mn1=inf,mx1=-inf;
34         for(;j<=n&&p[j].x==p[i].x;j++){
35              mn1=min(mn1,p[j].y);
36             mx1=max(mx1,p[j].y);
37         }
38         if(mn1<mn){
39             if(mn!=inf)p1[++c1]=P(p[i].x,mn);
40             p1[++c1]=P(p[i].x,mn=mn1);
41         }
42         if(mx1>mx){
43             if(mx!=-inf)p2[++c2]=P(p[i].x,mx);
44             p2[++c2]=P(p[i].x,mx=mx1);
45         }
46     }
47     
48     for(int i=n,j=n,mn=inf,mx=-inf;i;i=j){
49         int mn1=inf,mx1=-inf;
50         for(;j&&p[j].x==p[i].x;j--){
51             mn1=min(mn1,p[j].y);
52             mx1=max(mx1,p[j].y);
53         }
54         if(mn1<mn){
55             if(mn!=inf)p3[++c3]=P(p[i].x,mn);
56             p3[++c3]=P(p[i].x,mn=mn1);
57         }
58         if(mx1>mx){
59             if(mx!=-inf)p4[++c4]=P(p[i].x,mx);
60             p4[++c4]=P(p[i].x,mx=mx1);
61         }
62     }
63     P lst = p2[1];
64     ll ans1=0,ans2=0;
65     for(int i=1;i<=c1;++i){
66         ans1+=abs(p1[i].x-lst.x)+abs(p1[i].y-lst.y);
67         ans2+=crs(lst,p1[i]);
68         lst=p1[i];
69     }
70     for(int i=c3;i;--i){
71         ans1+=abs(p3[i].x-lst.x)+abs(p3[i].y-lst.y);
72         ans2+=crs(lst,p3[i]);
73         lst=p3[i];
74     }
75     for(int i=1;i<=c4;++i){
76         ans1+=abs(p4[i].x-lst.x)+abs(p4[i].y-lst.y);
77         ans2+=crs(lst,p4[i]);
78         lst=p4[i];
79     }
80     for(int i=c2;i;--i){
81         ans1+=abs(p2[i].x-lst.x)+abs(p2[i].y-lst.y);
82         ans2+=crs(lst,p2[i]);
83         lst=p2[i];
84     }
85     printf("%lld\n%lld\n",ans1,ans2>>1);
86     return 0;
87 } 
bzoj2146

猜你喜欢

转载自www.cnblogs.com/Paul-Guderian/p/10280320.html