题意:
给出一个点集,每次可能删去一个点或查询上凸包的面积;
保证无重点,保证最左面 最右面的点一定在凸包上;
n<=100000,m<=200000;
题解:
动态凸包问题,然而这道题的保证简直极为良心;
所以呢,我们就可以用set来水这道题啦;
我还是涨了不少姿势的,比如迭代器居然可以自减;
离线所有的操作之后处理,就是凸包加点了;
每次来一个点,判断一下加不加入,之后左面干点右面干点,插进去就好了;
不过这题细节还是用很多,主要是边界问题吧;
时间复杂度O(set(n))O(nlogn);
代码:
#include<set> #include<math.h> #include<stdio.h> #include<string.h> #include<algorithm> #define N 110000 #define iter set<Point>::iterator using namespace std; const double INF=1e100; struct Point { int x,y; Point(){} Point(int _,int __):x(_),y(__){} friend bool operator <(Point a,Point b) { if(a.x==b.x) return a.y<b.y; return a.x<b.x; } friend bool operator ==(Point a,Point b) { return a.x==b.x&&a.y==b.y; } friend bool slope (Point a,Point b,Point c) { double s1=a.x==b.x?(a.y<b.y?INF:-INF):(a.y-b.y)*1.0/(a.x-b.x); double s2=b.x==c.x?(b.y<c.y?INF:-INF):(b.y-c.y)*1.0/(b.x-c.x); return s1<s2; } friend double dis(Point a,Point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+0.0); } }a[N],p; int Qx[N<<1],top; bool Q[N<<1],ban[N]; double st[N<<1]; set<Point>s; int main() { int n,m,q,i,j,k; double ans; scanf("%d%d%d",&n,&p.x,&p.y); s.insert(p),s.insert(Point(0,0)),s.insert(Point(n,0)); scanf("%d",&m); for(i=1;i<=m;i++) { scanf("%d%d",&a[i].x,&a[i].y); } scanf("%d",&q); for(i=1;i<=q;i++) { scanf("%d",&k); if(k==1) { Q[i]=1; scanf("%d",Qx+i); ban[Qx[i]]=1; } } ans=dis(p,Point(0,0))+dis(p,Point(n,0)); for(i=1;i<=m;i++) { if(!ban[i]) { iter it1=s.insert(a[i]).first; iter it2=it1,temp=it1; it1++,it2--; if(slope(*it2,a[i],*it1)) {s.erase(temp);continue;} if(*it1==Point(n,0)&&*it2==Point(0,0)) ans=0; else ans-=dis(*it1,*it2); temp=it1; while(++temp!=s.end()&&slope(a[i],*it1,*temp)) ans-=dis(*it1,*temp),s.erase(it1++); temp=it2; while(temp--!=s.begin()&&slope(*temp,*it2,a[i])) ans-=dis(*it2,*temp),s.erase(it2--); ans+=dis(a[i],*it1)+dis(a[i],*it2); } } for(i=q;i>=1;i--) { if(Q[i]) { iter it1=s.insert(a[Qx[i]]).first; iter it2=it1,temp=it1; it1++,it2--; if(slope(*it2,a[Qx[i]],*it1)) {s.erase(temp);continue;} if(*it1==Point(n,0)&&*it2==Point(0,0)) ans=0; else ans-=dis(*it1,*it2); temp=it1; while(++temp!=s.end()&&slope(a[Qx[i]],*it1,*temp)) ans-=dis(*it1,*temp),s.erase(it1++); temp=it2; while(temp--!=s.begin()&&slope(*temp,*it2,a[Qx[i]])) ans-=dis(*it2,*temp),s.erase(it2--); ans+=dis(a[Qx[i]],*it1)+dis(a[Qx[i]],*it2); } else st[++top]=ans; } while(top) { printf("%.2lf\n",st[top--]); } }
时间: 2024-10-06 14:10:36