题目描述
题解
将删除转化成倒序插入
首先对于初始点建立凸包,每一次插入,在凸包上找到离这个点最近的两个点然后不断向两边删点维护凹凸性
可以用splay维护
这道题还是比较简单的,没有重点并且点的坐标
∈(0,n)
,所以这只是一个上凸壳,随便维护一下就行了
如果是一个完整的凸包的话,用斜率乱判会更麻烦一些
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define N 200005
const double eps=1e-9;
int dcmp(double x)
{
if (x<=eps&&x>=-eps) return 0;
return (x>0)?1:-1;
}
struct Vector
{
double x,y;
int id;
bool flag;
Vector(double X=0,double Y=0)
{
x=X,y=Y;
}
bool operator < (const Vector &a) const
{
return x<a.x||(x==a.x&&y<a.y);
}
};
typedef Vector Point;
Vector operator + (Vector a,Vector b) {return Vector(a.x+b.x,a.y+b.y);}
Vector operator - (Vector a,Vector b) {return Vector(a.x-b.x,a.y-b.y);}
Vector operator * (Vector a,double b) {return Vector(a.x*b,a.y*b);}
Vector operator / (Vector a,double b) {return Vector(a.x/b,a.y/b);}
struct hp{int p;double ans;}ans[N];
double n,x,y,C;
int m,q,cnt,top,sz,root,opt;
Point c[N],p[N],stack[N];
int f[N],ch[N][2],key[N];
double Dot(Vector a,Vector b)
{
return a.x*b.x+a.y*b.y;
}
double Cross(Vector a,Vector b)
{
return a.x*b.y-a.y*b.x;
}
double Len(Vector a)
{
return sqrt(Dot(a,a));
}
void graham()
{
sort(p+1,p+cnt+1);
top=0;
for (int i=1;i<=cnt;++i)
{
while (top>1&&dcmp(Cross(stack[top]-stack[top-1],p[i]-stack[top-1]))>=0)
--top;
stack[++top]=p[i];
}
int k=top;
for (int i=cnt-1;i>=1;--i)
{
while (top>k&&dcmp(Cross(stack[top]-stack[top-1],p[i]-stack[top-1]))>=0)
--top;
stack[++top]=p[i];
}
if (cnt>1) --top;
}
void clear(int x)
{
f[x]=ch[x][0]=ch[x][1]=key[x]=0;
}
int build(int l,int r,int fa)
{
if (l>r) return 0;
int mid=(l+r)>>1;
int now=++sz;
f[now]=fa;key[now]=stack[mid].id;
int lch=build(l,mid-1,now);
int rch=build(mid+1,r,now);
ch[now][0]=lch;ch[now][1]=rch;
return now;
}
int get(int x)
{
return ch[f[x]][1]==x;
}
void rotate(int x)
{
int old=f[x],oldf=f[old],wh=get(x);
ch[old][wh]=ch[x][wh^1];
if (ch[old][wh]) f[ch[old][wh]]=old;
ch[x][wh^1]=old;
f[old]=x;
if (oldf) ch[oldf][ch[oldf][1]==old]=x;
f[x]=oldf;
}
void splay(int x,int tar)
{
for (int fa;(fa=f[x])!=tar;rotate(x))
if (f[fa]!=tar)
rotate((get(x)==get(fa))?fa:x);
if (!tar) root=x;
}
int find(int id)
{
int now=root,ans=0;
while (1)
{
if (dcmp(c[key[now]].x-c[id].x)<=0)
{
ans=now;
if (ch[now][1]) now=ch[now][1];
else break;
}
else
{
if (ch[now][0]) now=ch[now][0];
else break;
}
}
splay(ans,0);
return ans;
}
int pre()
{
if (!ch[root][0]) return 0;
int now=ch[root][0];
while (ch[now][1]) now=ch[now][1];
return now;
}
int nxt()
{
if (!ch[root][1]) return 0;
int now=ch[root][1];
while (ch[now][0]) now=ch[now][0];
return now;
}
void del(int x)
{
splay(x,0);
if (!ch[root][0]&&!ch[root][1]) {root=0;return;}
if (!ch[root][0])
{
int oldroot=root;
root=ch[root][1];
f[root]=0;
clear(oldroot);
return;
}
if (!ch[root][1])
{
int oldroot=root;
root=ch[root][0];
f[root]=0;
clear(oldroot);
return;
}
int oldroot=root;
int leftbig=pre();splay(leftbig,0);
ch[root][1]=ch[oldroot][1];
f[ch[root][1]]=root;
clear(oldroot);
return;
}
int main()
{
scanf("%lf%lf%lf",&n,&x,&y);
scanf("%d",&m);
for (int i=1;i<=m;++i) scanf("%lf%lf",&c[i].x,&c[i].y),c[i].id=i;
c[++m].x=0,c[m].y=0,c[m].id=m;c[++m].x=n,c[m].y=0,c[m].id=m;c[++m].x=x,c[m].y=y,c[m].id=m;
scanf("%d",&q);
for (int i=1;i<=q;++i)
{
scanf("%d",&opt);
if (opt==1)
{
scanf("%d",&ans[i].p);
c[ans[i].p].flag=true;
}
}
for (int i=1;i<=m;++i)
if (!c[i].flag) p[++cnt]=c[i];
graham();
for (int i=2;i<=top;++i) C+=Len(stack[i]-stack[i-1]);
root=build(1,top,0);
for (int i=q;i>=1;--i)
{
if (ans[i].p)
{
Point P=c[ans[i].p];
int aa,bb,cc,dd;
aa=find(P.id);
cc=pre();
bb=nxt();
splay(bb,0);
dd=nxt();
if (aa&&bb&&dcmp(Cross(P-c[key[aa]],c[key[bb]]-P))>=0) continue;
else
{
C-=Len(c[key[aa]]-c[key[bb]]);
C+=Len(P-c[key[aa]]);
C+=Len(P-c[key[bb]]);
}
while (aa&&cc&&dcmp(Cross(c[key[aa]]-c[key[cc]],P-c[key[aa]]))>=0)
{
C-=Len(P-c[key[aa]]);
C-=Len(c[key[aa]]-c[key[cc]]);
C+=Len(P-c[key[cc]]);
del(aa);
aa=cc;splay(aa,0);
cc=pre();
}
while (bb&&dd&&dcmp(Cross(c[key[bb]]-P,c[key[dd]]-c[key[bb]]))>=0)
{
C-=Len(P-c[key[bb]]);
C-=Len(c[key[bb]]-c[key[dd]]);
C+=Len(P-c[key[dd]]);
del(bb);
bb=dd;splay(bb,0);
dd=nxt();
}
splay(aa,0);
splay(bb,aa);
ch[ch[root][1]][0]=++sz;
f[sz]=ch[root][1];
key[sz]=ans[i].p;
}
else ans[i].ans=C;
}
for (int i=1;i<=q;++i)
if (!ans[i].p) printf("%.2lf\n",ans[i].ans);
}