【题目链接】http://www.lydsy.com/JudgeOnline/problem.php?id=2300
【解题思路】离线倒序处理。问题就变成了每次加一个点维护凸包。用splay查找当前所加点对凸壳有影响的区间的两个端点。splay以横坐标为序,记录每个点与前后两个点的斜率。
【呆马】
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<iostream>
const int N=1e5+10;
const double inf=1e18,eps=1e-6;
using namespace std;
struct st{int l,r;double x,y,lk,rk;} New,a[N];
struct st1{int tag,x;} q[N<<1];
struct st2{double x,y;} p[N];
int n,m,l,r,t,i,last,root,ansn,fa[N];
double x,y,z,ans,Ans[N<<1];
bool del[N];
double dis(st a,st b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
double slo(st a,st b)
{
if (fabs(a.x-b.x)<eps) return b.y>a.y?inf:-inf;
return (b.y-a.y)/(b.x-a.x);
}
void zag(int x)
{
int y=fa[x];
if (a[fa[y]].l==y) a[fa[y]].l=x;
else a[fa[y]].r=x;
fa[x]=fa[y];
if (!fa[x]) root=x;
fa[y]=x;
fa[a[x].l]=y;
a[y].r=a[x].l;
a[x].l=y;
}
void zig(int x)
{
int y=fa[x];
if (a[fa[y]].l==y) a[fa[y]].l=x;
else a[fa[y]].r=x;
fa[x]=fa[y];
if (!fa[x]) root=x;
fa[y]=x;
fa[a[x].r]=y;
a[y].l=a[x].r;
a[x].r=y;
}
void splay(int x,int tag)
{
for (;(!tag && fa[x]) || (tag && fa[x]!=root && fa[fa[x]]!=root);)
{
int y=fa[x],z=fa[y];
if (!z)
{
if (a[y].l==x) zig(x);
else zag(x);
}
else
{
if (a[y].l==x)
{
if (a[z].l==y) zig(y),zig(x);
else zig(x),zag(x);
}
else
{
if (a[z].r==y) zag(y),zag(x);
else zag(x),zig(x);
}
}
}
if (tag && fa[x]!=root)
{
if (a[fa[x]].l==x) zig(x);
else zag(x);
}
}
void findl(int p)
{
if (!p || l==-1) return;
if (abs(a[p].x-New.x)<eps && a[p].y>New.y){l=-1; return;}
if (a[p].x>=New.x) findl(a[p].l);
else if (slo(a[p],New)<a[p].lk) l=p,findl(a[p].r);
else findl(a[p].l);
}
void findr(int p)
{
if (!p || r==-1) return;
if (abs(a[p].x-New.x)<eps && a[p].y>New.y){r=-1; return;}
if (a[p].x<=New.x) findr(a[p].r);
else if (slo(New,a[p])>a[p].rk) r=p,findr(a[p].l);
else findr(a[p].r);
}
void dfs(int x)
{
if (a[x].l) dfs(a[x].l);
ans-=dis(a[x],a[last]);
last=x;
if (a[x].r) dfs(a[x].r);
}
void dele(int x)
{
if (!x) return;
fa[x]=a[fa[x]].l=0;
dfs(x);
}
void insert(double x,double y)
{
New.x=x;
New.y=y;
l=r=0;
findl(root);
findr(root);
if (l<0 || r<0) return;
splay(l,0);
splay(r,1);
a[++t].x=x;
a[t].y=y;
a[t].lk=slo(a[root],a[t]);
a[t].rk=slo(a[t],a[a[root].r]);
if (a[t].lk<a[t].rk){t--; return;}
a[root].rk=a[t].lk;
a[a[root].r].lk=a[t].rk;
ans+=dis(a[l],New)+dis(a[r],New);
last=l;
dele(a[a[root].r].l);
ans-=dis(a[last],a[r]);
a[fa[t]=a[root].r].l=t;
}
int main()
{
scanf("%lf%lf%lf\n%d\n",&z,&x,&y,&n);
for (i=1;i<=n;i++) scanf("%lf%lf\n",&p[i].x,&p[i].y);
scanf("%d\n",&m);
for (i=1;i<=m;i++)
{
scanf("%d",&q[i].tag);
if (q[i].tag==1)
{
scanf("%d",&q[i].x);
del[q[i].x]=1;
}
}
fa[a[1].l=2]=fa[t=a[1].r=3]=root=1;
a[1].x=x;
a[1].y=y;
a[3].x=z;
a[2].lk=inf;
a[3].rk=-inf;
a[1].lk=a[2].rk=slo(a[2],a[1]);
a[1].rk=a[3].lk=slo(a[1],a[3]);
ans=dis(a[1],a[2])+dis(a[1],a[3]);
for (i=1;i<=n;i++)
if (!del[i]) insert(p[i].x,p[i].y);
for (;m;m--)
if (q[m].tag==1) insert(p[q[m].x].x,p[q[m].x].y);
else Ans[++ansn]=ans;
for (;ansn;ansn--) printf("%.2f\n",Ans[ansn]);
}