P2521 [HAOI2011]防线修建
良心的动态凸包模板题
各种保证是真的舒服 $2333$
因为只有删除操作,所以直接倒过来变成插入就行了
上动态凸包,用 $set$ 把凸包的点按 $x,y$ 为一二关键字排序,然后加点的时候找找前驱后继看看要不要删,顺便维护当前凸包长度,没了
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<set> using namespace std; typedef long long ll; typedef double db; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } const int N=4e5+7; struct poi { db x,y; poi (db a=0,db b=0) { x=a,y=b; } inline poi operator - (const poi &tmp) const { return poi(x-tmp.x,y-tmp.y); } inline bool operator < (const poi &tmp) const { return x!=tmp.x ? x<tmp.x : y<tmp.y; } }A[N],P[N],st[N]; inline db Cross(poi A,poi B) { return A.x*B.y-A.y*B.x; } inline db Dot(poi A,poi B) { return A.x*B.x+A.y*B.y; } inline db Len(poi A) { return sqrt(Dot(A,A)); } inline bool cmp(const poi &A,const poi &B) { return (Cross(A,B)>0)||(Cross(A,B)==0&&Len(A)<Len(B)); } int n,m,Q,tot,d[N][2]; bool vis[N]; db ans[N],now; set <poi> S; void Tubao() { sort(P+1,P+tot+1,cmp); int Top=0; for(int i=1;i<=tot;st[++Top]=P[i],i++) while( Top>1 && Cross(P[i]-st[Top-1],st[Top]-st[Top-1])>=0 ) Top--; for(int i=3;i<=Top;i++) now+=Len(st[i]-st[i-1]); now+=Len(st[Top]-st[1]); for(int i=1;i<=Top;i++) S.insert(st[i]); } inline void Insert(poi A) { set <poi>::iterator l=S.lower_bound(A),r=l,t; l--; if(Cross(A-(*l),(*r)-(*l))>0) return; now-=Len((*r)-(*l)); while(r!=S.end()) { t=r; r++; if(r==S.end()) break; if(Cross((*r)-A,(*t)-A)>0) break; now-=Len((*r)-(*t)); S.erase(t); } while(l!=S.begin()) { t=l; l--; if(Cross((*l)-A,(*t)-A)<0) break; now-=Len((*l)-(*t)); S.erase(t); } S.insert(A); l=r=S.find(A); l--; r++; now+=Len(A-(*l))+Len(A-(*r)); } int main() { n=read(); int x=read(),y=read(); m=read(); A[m+1]=poi(x,y); A[m+2]=poi(0,0); A[m+3]=poi(n,0); for(int i=1;i<=m;i++) A[i].x=read(),A[i].y=read(); m+=3; Q=read(); for(int i=1;i<=Q;i++) { d[i][0]=read(); if(d[i][0]==1) d[i][1]=read(),vis[d[i][1]]=1; } for(int i=1;i<=m;i++) if(!vis[i]) P[++tot]=A[i]; Tubao(); for(int i=Q;i>=1;i--) { if(d[i][0]==2) ans[i]=now; else Insert(A[d[i][1]]); } for(int i=1;i<=Q;i++) if(d[i][0]==2) printf("%.2f\n",ans[i]); return 0; }