从前写货币兑换的时候,写的splay维护凸包,没调出来。
后来写防线修建,我用了set维护凸包,A啦。
从前写永无乡的时候,写的splay启发式合并,没调出来。
后来写dispatching,我用了trep启发式合并,A啦。
我再也不相信splay了T T。
以上纯属一个蒟蒻的扯淡。
#include<iostream>
#include<cstdio>
#include<set>
#include<cmath>
#define N 200005
using namespace std;
int top1,top2,n,m,Q;
int ask[N];
bool vis[N];
double now,ans[N];
struct P {int x,y;} del[N],p[N];
set<P> s;
inline int read()
{
int a=0,f=1; char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
return a*f;
}
inline P operator-(P a,P b)
{
return (P){a.x-b.x,a.y-b.y};
}
inline int operator*(P a,P b)
{
return a.x*b.y-a.y*b.x;
}
inline double dis(P a,P b)
{
return (double)sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
inline bool operator<(P a,P b)
{
return a.x==b.x?a.y<b.y:a.x<b.x;
}
inline void insert(P x)
{
set<P>::iterator r=s.lower_bound(x),l=r,t;
l--;
if ((*r-*l)*(x-*l)<0) return;
now-=dis(*l,*r);
s.insert(x);
while (1)
{
t=r; r++;
if (r==s.end()) break;
if ((*r-x)*(*t-x)>0) break;
now-=dis(*t,*r);
s.erase(t);
}
while (l!=s.begin())
{
t=l; l--;
if ((*t-x)*(*l-x)>0) break;
now-=dis(*t,*l);
s.erase(t);
}
l=r=s.find(x);
l--; r++;
now+=dis(*l,x)+dis(*r,x);
}
int main()
{
m=read(); P base;
base.x=read(); base.y=read();
s.insert((P){0,0}); s.insert((P){m,0}); s.insert(base);
now+=dis((P){0,0},base); now+=dis((P){m,0},base);
n=read();
for (int i=1;i<=n;i++) p[i].x=read(),p[i].y=read();
Q=read();
for (int i=1;i<=Q;i++)
{
int opt=read(),x;
if (opt==1) x=read(),del[++top1]=p[x],vis[x]=1;
else ask[++top2]=top1;
}
for (int i=1;i<=n;i++)
if (!vis[i]) insert(p[i]);
for (int i=top2;i;i--)
{
while (top1>ask[i]) insert(del[top1--]);
ans[i]=now;
}
for (int i=1;i<=top2;i++) printf("%.2lf\n",ans[i]);
return 0;
}