这个题可以在线做,splay维护凸包的同时维护区间最值线段树,当删除一个点就找跨过这个点的不在凸包上的点的y最值,然后分下去
由于一次确定一个点,所以复杂度还是nlogn的,只是比较难写
如果一个操作非常麻烦,可以考虑对立面,所以就可以考虑倒着加点,就可以直接用splay维护了
注:
引用函数注意对应关系
注意=号
码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int op[100005][2],lll,rrr,sz[100005],ch[100005][2],fu[100005],i,j,n,m,Q,rt,tot,sta[100005],top,dui[100005];
double daan[100005],ans,x[100005],y[100005];
bool wu[100005];
struct dian
{
double x,y;
int id;
}D[100005];
void up(int o)
{
sz[o]=sz[ch[o][0]]+sz[ch[o][1]]+1;
}
void set(int o,int wh,int child)
{
ch[o][wh]=child;
if(child)fu[child]=o;
up(o);
}
int getwh(int o)
{
return ch[fu[o]][0]==o?0:1;
}
void rotate(int o)
{
int fa=fu[o];
int ye=fu[fa];
int wh=getwh(o);
set(fa,wh,ch[o][wh^1]);
set(o,wh^1,fa);
fu[o]=ye;
if(ye)ch[ye][ch[ye][0]==fa?0:1]=o;
}
void splay(int o,int tar)
{
for(;fu[o]!=tar;rotate(o))
if(fu[fu[o]]!=tar)
getwh(o)==getwh(fu[o])?rotate(fu[o]):rotate(o);
if(tar==0)rt=o;
}
void dfs(int o)
{
if(o==0)return;
cout<<"'"<<x[o]<<" "<<y[o]<<"'"<<"(";
dfs(ch[o][0]);cout<<",";
dfs(ch[o][1]);
cout<<")";
}
void del(int o)
{
splay(o,0);
if(ch[o][0]==0)
{
rt=ch[o][1];
fu[ch[o][1]]=0;
}
else
if(ch[o][1]==0)
{
rt=ch[o][0];
fu[ch[o][0]]=0;
}
else
{
int p=ch[o][0];
while(ch[p][1])p=ch[p][1];
set(p,1,ch[o][1]);
fu[ch[o][0]]=0;
splay(p,0);
}
}
int xin(int X,int Y)
{
int o=++tot;
x[o]=X;
y[o]=Y;
sz[o]=1;
return o;
}
double xl(double ax,double ay,double bx,double by)
{if(ax==bx)return -9999999999999;
return (ay-by)/(ax-bx);
}
double jl(double ax,double ay,double bx,double by)
{
return sqrt((ax-bx)*(ax-bx)+(ay-by)*(ay-by));
}
int jian(int l,int r)
{
if(l>r)return 0;
int mid=(l+r)>>1,o=++tot;
x[o]=D[sta[mid]].x;
y[o]=D[sta[mid]].y;
set(o,0,jian(l,mid-1));
set(o,1,jian(mid+1,r));
return o;
}
bool cmp(dian a,dian b)
{
if(a.x==b.x)return a.y<b.y;
return a.x<b.x;
}
void tubao()
{
sort(D+1,D+1+n,cmp);
for(i=1;i<=n;i++)
dui[D[i].id]=i;
int i;
for(i=1;i<=n;i++)
{
if(wu[D[i].id])continue;
while(top>=2&&xl(D[i].x,D[i].y,D[sta[top-1]].x,D[sta[top-1]].y)>=xl(D[sta[top-1]].x,D[sta[top-1]].y,D[sta[top]].x,D[sta[top]].y))top--;
sta[++top]=i;
}
for(i=1;i<=top;i++)
{
ans+=jl(D[sta[i]].x,D[sta[i]].y,D[sta[i-1]].x,D[sta[i-1]].y);
}
rt=jian(1,top);
}
int xiao(double X)
{
int o=rt,last=0,ll=0;
while(o)
{last=o;
if(x[o]<X&&(x[o]>x[ll]||ll==0))ll=o;
if(x[o]<X)o=ch[o][1];
else o=ch[o][0];
}
splay(last,0);
return ll;
}
int da(double X)
{
int o=rt,last=0,rr=0;
while(o)
{last=o;
if(x[o]>X&&(x[o]<x[rr]||rr==0))rr=o;
if(x[o]<=X)o=ch[o][1];
else o=ch[o][0];
}
splay(last,0);
return rr;
}
int main()
{
scanf("%d",&m);
scanf("%lf%lf",&D[0].x,&D[0].y);
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%lf%lf",&D[i].x,&D[i].y);
D[i].id=i;
}
D[++n].x=D[0].x;D[n].y=D[0].y;D[n].id=n;
D[++n].x=0;D[n].y=0;D[n].id=n;
D[++n].x=m;D[n].y=0;D[n].id=n;
D[0].x=D[0].y=D[0].id=0;
scanf("%d",&Q);
for(i=1;i<=Q;i++)
{scanf("%d",&op[i][0]);
if(op[i][0]==1)scanf("%d",&op[i][1]),wu[op[i][1]]=1;
}
tubao();
for(i=Q;i>=1;i--)
{//dfs(rt);cout<<endl;
if(op[i][0]==2)
daan[i]=ans;
else
{
int st=dui[op[i][1]];
int ll=xiao(D[st].x),rr=da(x[ll]);
if(xl(x[ll],y[ll],D[st].x,D[st].y)>xl(x[ll],y[ll],x[rr],y[rr]))
{
ans-=jl(x[ll],y[ll],x[rr],y[rr]);
lll=xiao(x[ll]);
while(x[lll]<x[ll]&&xl(x[lll],y[lll],D[st].x,D[st].y)>xl(x[lll],y[lll],x[ll],y[ll]))
{ ans-=jl(x[ll],y[ll],x[lll],y[lll]); del(ll);ll=lll;lll=xiao(x[ll]); }
rrr=da(x[rr]);
while(x[rrr]>x[rr]&&xl(x[rr],y[rr],D[st].x,D[st].y)<xl(x[rrr],y[rrr],D[st].x,D[st].y))
{ ans-=jl(x[rr],y[rr],x[rrr],y[rrr]); del(rr);
rr=rrr;
rrr=da(x[rr]); }
ans+=jl(x[ll],y[ll],D[st].x,D[st].y)+jl(x[rr],y[rr],D[st].x,D[st].y);
splay(ll,0);
int p=ch[ll][1];
if(p==0)
{
set(ll,1,xin(D[st].x,D[st].y));
}else
{
while(ch[p][0])p=ch[p][0];
set(p,0,xin(D[st].x,D[st].y));
}splay(tot,0);
}
}
}
for(i=1;i<=Q;i++)
if(op[i][0]==2)printf("%.2lf\n",daan[i]);
}