我们发现只要倒着操作就可以把删除变成插入了,然后就可以用平衡树维护动态凸包了。(←set水掉的sb)
AC代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
#include<cmath>
#define N 300005
#define sqr(x) (x)*(x)
using namespace std;
struct node{ int x,y; }a[N],c[N];
set<node> s; int n,m; double len,ans[N]; bool bo[N];
int read(){
int x=0,fu=1; char ch=getchar();
while (ch<'0' || ch>'9'){ if (ch=='-') fu=-1; ch=getchar(); }
while (ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); }
return x*fu;
}
node operator -(node u,node v){ u.x-=v.x; u.y-=v.y; return u; }
int crs(node u,node v){ return u.x*v.y-u.y*v.x; }
double dist(node u,node v){
return sqrt((double)(sqr(u.x-v.x)+sqr(u.y-v.y)));
}
bool operator <(node u,node v){
return u.x<v.x || u.x==v.x && u.y<v.y;
}
int main(){
node p; p.x=0; p.y=0; s.insert(p);
n=p.x=read(); s.insert(p);
p.x=read(); p.y=read(); s.insert(p);
len=sqrt((double)(sqr(p.x)+sqr(p.y)))+sqrt((double)(sqr(n-p.x)+sqr(p.y)));
n=read(); int i,cnt=0;
for (i=1; i<=n; i++){ a[i].x=read(); a[i].y=read();}
m=read();
memset(bo,1,sizeof(bo));
for (i=1; i<=m; i++){
c[i].x=read(); if (c[i].x==1){ c[i].y=read(); bo[c[i].y]=0; }
}
for (i=1; i<=n; i++) if (bo[i]){ c[++m].x=1; c[m].y=i; }
set<node>:: iterator l,r,t;
for (i=m; i; i--){
if (c[i].x==1){
p=a[c[i].y];
l=r=s.lower_bound(p); l--;
if (crs(p-*l,*r-*l)<=0){
len-=dist(*l,*r);
for (t=r,r++; r!=s.end(); t=r,r++){
if (crs(*r-p,*t-p)>0) break;
len-=dist(*r,*t); s.erase(t);
}
for (t=l,l--; t!=s.begin(); t=l,l--){
if (crs(*t-p,*l-p)>0) break;
len-=dist(*l,*t); s.erase(t);
}
s.insert(p); l=r=s.find(p);
l--; r++; len+=dist(*l,p)+dist(*r,p);
}
} else ans[++cnt]=len;
}
for (i=cnt; i; i--) printf("%.2f\n",ans[i]);
return 0;
}
by lych
2016.3.14