bzoj 2300: [HAOI2011]防线修建

(提前声明,,,代码丑陋之极。。。。)

一眼看到这个题,,好神哇,,不会做。。

然后发现可以翻过来,离线处理,把删点改成加点会比较简单,这样就办成了一个动态加点维护上凸壳了呀!!!我的天呢!!!(这不是神犇拿来装逼的东西??)

因为我太虚把,所以先搞出来了最后的凸壳什么样子。

然后想,上凸壳这么神的东西,加进去会导致原来的点无效,就要删除,还要支持插入点,而且要有序,,一想可以用set维护一下啊,然后对于要往里面加的点,要先判断是不是在凸壳里面,不是的话,加上这个点,在往两边暴力修改,(就是判断是不是满足凸壳就好),思路就是这么简单。。

(代码能力真的是个蛋疼的东西。。。。整整调了半天。。)

(把最后凸壳插入set的时候写错数组,一开始把向两边修改的代码写的奇蠢无比,快7,80行,里面的迭代器不知道it--和--it是不是和数一样用,然后就乱写,各种各样sb错误。。。诶,,,实在虚。。)

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<cmath>
  5 #include<map>
  6 #include<iostream>
  7 #include<set>
  8 #define N 100005
  9 #define eps 1e-8
 10 using namespace std;
 11 int n,m,Q,cnt,top,num;
 12 bool vis[N];
 13 double x,y,ans,ans1[N<<1];
 14 struct point{double x,y;}pre[N],p[N],st[N],del[N];
 15 struct query{int opt,pos;}q[N<<1];
 16 set<point > s;
 17 set<point > :: iterator it1,it2,it,old;
 18 bool operator < (point a, point b)
 19 {
 20     return a.x<b.x;
 21 }
 22 inline double dis(point a, point b)
 23 {
 24     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
 25 }
 26 inline double cross(point p1, point p2, point p0)
 27 {
 28     return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);
 29 }
 30 inline bool cmp(point a, point b)
 31 {
 32     if (cross(a,b,pre[0])==0) return dis(a,pre[0])<dis(b,pre[0]);
 33     return cross(a,b,pre[0])>0;
 34 }
 35 void Graham()
 36 {
 37     pre[2].x=n; pre[2].y=0.0;
 38     pre[1].x=x; pre[1].y=y;
 39     pre[0].x=0.0; pre[0].y=0.0;
 40     cnt=2;
 41     for (int i=1; i<=m; i++)
 42         if (!vis[i]) pre[++cnt]=p[i];
 43 //    for (int i=1; i<=cnt; i++)
 44 //        cout<<pre[i].x<<"     "<<pre[i].y<<endl; cout<<endl;
 45     top=2;
 46     sort(pre+1,pre+cnt+1,cmp);
 47     st[0]=pre[0],st[1]=pre[1],st[2]=pre[2];
 48     for (int i=3; i<=cnt; i++)
 49     {
 50         while (top && cross(pre[i],st[top],st[top-1])>=0) top--;
 51         st[++top]=pre[i];
 52     }
 53     for (int i=0; i<=top; i++)
 54         s.insert(st[i]);   //sbsbsbsbbsb...insert(pre[..])heheheheh,,,f**k??!!
 55     st[++top]=pre[0];
 56     for (int i=0; i<top; i++)
 57         ans+=dis(st[i],st[i+1]);
 58     ans-=n;
 59 //    printf("%lf",ans); while (1);
 60 }
 61 void rebuild(int i)
 62 {
 63     //for (it=s.begin(); it!=s.end(); it++)
 64 //        printf("%lf  %lf\n",(*it).x,(*it).y); system("pause");
 65     point new_in=p[i];    num=0;
 66     it=s.lower_bound(new_in); old=it;
 67     point a=*it; it--; point b=*it; 
 68 //    printf("%lf %lf\n",a.x,a.y);
 69 //    printf("%lf",new_in.y-a.y-(b.y-a.y)/(a.x-b.x)*(a.x-new_in.x));system("pause");
 70     if (new_in.y-a.y-(b.y-a.y)/(a.x-b.x)*(a.x-new_in.x)>eps)
 71     {
 72         ans-=dis(a,b);
 73         ans+=dis(new_in,a); ans+=dis(new_in,b);
 74     }
 75     else return;
 76     it1=it; it--; it2=it;
 77     for (;it1!=s.begin(); it2--,it1--)
 78     {
 79         point c=*it1,d=*it2;
 80         if (cross(d,c,new_in)>0)
 81         {
 82             ans-=dis(new_in,c);
 83             ans-=dis(c,d);
 84             ans+=dis(new_in,d);
 85             del[++num]=c;
 86         }
 87     }
 88     it=old; it1=it; it++; it2=it;
 89     for (; it2!=s.end(); it1++,it2++)
 90     {
 91         point c=*it1,d=*it2;
 92         if (cross(c,d,new_in)>0)
 93         {
 94             ans-=dis(new_in,c);
 95             ans-=dis(c,d);
 96             ans+=dis(new_in,d);
 97             del[++num]=c;
 98         }
 99         else break;
100     }
101     for (int j=1; j<=num; j++)
102     {
103     //    if (del[j].x==x && del[j].y==y) continue;
104         s.erase(s.find(del[j]));
105     }
106     s.insert(new_in);
107 }
108 int main()
109 {
110     scanf("%d%lf%lf%d",&n,&x,&y,&m);
111     for (int i=1; i<=m; i++)
112         scanf("%lf%lf",&p[i].x,&p[i].y);
113     scanf("%d",&Q);
114     for (int i=1; i<=Q; i++) 
115     {
116         scanf("%d",&q[i].opt);
117         if (q[i].opt==1) 
118         {
119             scanf("%d",&q[i].pos);
120             vis[q[i].pos]=1;
121         }
122     }
123     Graham(); int tot=0;
124     for (int i=Q; i>=1; i--)
125     {
126         if (q[i].opt==2) ans1[++tot]=ans;
127         else rebuild(q[i].pos);
128     }
129     for (int i=tot; i>=1; i--)
130         printf("%.2lf\n",ans1[i]);
131     return 0;
132 }

 

posted @ 2017-02-28 21:06  ws_ccd  阅读(274)  评论(0编辑  收藏  举报