1. 程式人生 > >[BZOJ2300]防線修建

[BZOJ2300]防線修建

沒有 == name fin main break sqrt ace for

第一次寫水平序凸包,感覺跟極角序凸包差不多

凸包的刪除看上去不太可做,但我們發現這題沒有強制在線,所以我們離線統計答案

離線之後把操作反序,刪除就變為插入了

用平衡樹維護凸包,每插入一個點,就不停刪除它左右兩邊不滿足凸包性質的點

每個點只會被插入刪除各一次,不會超時

 1 #include<stdio.h>
 2 #include<math.h>
 3 #include<set>
 4 using namespace std;
 5 const double eps=1e-8;
 6 struct point{
 7     double x,y;
 8
point(double a=.0,double b=.0){ 9 x=a; 10 y=b; 11 } 12 }c[100010],cc; 13 bool operator<(point a,point b){ 14 if(a.x==b.x)return a.y<b.y; 15 return a.x<b.x; 16 } 17 set<point>s,tmp; 18 set<point>::iterator ita,itb,it; 19 int ask[200010]; 20 double ans,tans[200010
]; 21 double dist(point a,point b){ 22 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); 23 } 24 double cross(double x1,double y1,double x2,double y2){ 25 return x1*y2-y1*x2; 26 } 27 void insert(point x){ 28 ita=s.lower_bound(x); 29 itb=ita; 30 ita--; 31 if(cross(x.x-ita->x,x.y-ita->y,itb->x-x.x,itb->y-x.y)>=-eps)return
; 32 ans-=dist(*ita,*itb); 33 while(ita!=s.begin()){ 34 it=ita; 35 it--; 36 if(cross(ita->x-it->x,ita->y-it->y,x.x-ita->x,x.y-ita->y)>=-eps){ 37 ans-=dist(*ita,*it); 38 cc=*it; 39 s.erase(ita); 40 ita=s.find(cc); 41 }else 42 break; 43 } 44 it=itb; 45 it++; 46 while(it!=s.end()){ 47 if(cross(itb->x-x.x,itb->y-x.y,it->x-itb->x,it->y-itb->y)>=-eps){ 48 ans-=dist(*it,*itb); 49 cc=*it; 50 s.erase(itb); 51 itb=s.find(cc); 52 }else 53 break; 54 it=itb; 55 it++; 56 } 57 ans+=dist(x,*ita)+dist(x,*itb); 58 s.insert(x); 59 } 60 int main(){ 61 int i,a,b,m,q; 62 scanf("%d%d%d",&i,&a,&b); 63 ans=dist(point(),point(a,b))+dist(point(i,0),point(a,b)); 64 s.insert(point()); 65 s.insert(point(i,0)); 66 s.insert(point(a,b)); 67 scanf("%d",&m); 68 for(i=1;i<=m;i++){ 69 scanf("%lf%lf",&c[i].x,&c[i].y); 70 tmp.insert(c[i]); 71 } 72 scanf("%d",&q); 73 for(i=1;i<=q;i++){ 74 scanf("%d",&a); 75 if(a==1){ 76 scanf("%d",ask+i); 77 tmp.erase(c[ask[i]]); 78 } 79 } 80 for(it=tmp.begin();it!=tmp.end();it++)insert(*it); 81 for(i=q;i>0;i--){ 82 if(ask[i]) 83 insert(c[ask[i]]); 84 else 85 tans[i]=ans; 86 } 87 for(i=1;i<=q;i++){ 88 if(ask[i]==0)printf("%.2lf\n",tans[i]); 89 } 90 }

[BZOJ2300]防線修建