「BZOJ2300」[HAOI2011] 防线修建
操作离线之后倒着做,只有加点操作。
用set动态维护凸包即可。
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
#include<set>
#define For(i,a,b) for(int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(int i=(a);i>=(b);i--)
const int N=100007;
typedef long long LL;
typedef double db;
using namespace std;
int n,m,q,cnt,no[N],qs[N][2],top;
db ans,res[N];
template<typename T>void read(T &x) {
char ch=getchar(); x=0; T f=1;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}
struct pt {
int x,y;
pt(){}
pt(int x,int y):x(x),y(y){}
friend bool operator <(const pt&A,const pt&B) {
return A.x<B.x||(A.x==B.x&&A.y<B.y);
}
}p[N],a[N],h[N];
set<pt>s;
pt operator - (const pt&A,const pt&B) { return pt(A.x-B.x,A.y-B.y); }
int cross(pt A,pt B) { return A.x*B.y-A.y*B.x; }
LL dot(pt A,pt B) { return (LL)A.x*B.x+A.y*B.y; }
db length(pt A) { return sqrt(dot(A,A)); }
void make_ham(int n) {
sort(a+2,a+n+1);
h[++top]=a[1]; h[++top]=a[2];
For(i,3,n) {
while(top>1&&cross(h[top]-h[top-1],a[i]-h[top-1])>=0) top--;
h[++top]=a[i];
}
For(i,1,top) {
s.insert(h[i]);
if(i>1) ans+=length(h[i]-h[i-1]);
}
}
#define IT set<pt>::iterator
void insert(int id) {
pt x=p[id];
IT l=s.lower_bound(x);
IT r=l,t; --l;
if(cross(x-*l,*r-*l)>=0) return;
ans-=length(*l-*r);
while(1) {
t=r; r++; if(r==s.end()) break;
if(cross(*t-x,*r-x)>=0) {
ans-=length(*t-*r); s.erase(t);
}
else break;
}
while(1) {
if(l==s.begin()) break;
t=l; l--;
if(cross(*t-*l,x-*l)>=0) {
ans-=length(*t-*l); s.erase(t);
}
else break;
}
s.insert(x);
l=r=s.find(x);
--l; ++r;
ans+=length(*l-x)+length(*r-x);
}
#define DEBUG
int main() {
#ifdef DEBUG
freopen("2300.in","r",stdin);
freopen("2300.out","w",stdout);
#endif
read(n); read(p[0].x); read(p[0].y);
read(m);
For(i,1,m) { read(p[i].x); read(p[i].y); }
read(q);
For(i,1,q) {
read(qs[i][0]);
if(qs[i][0]==1) {
read(qs[i][1]);
no[qs[i][1]]=1;
}
}
a[++cnt]=pt(0,0); a[++cnt]=pt(n,0);
For(i,0,m) if(!no[i]) a[++cnt]=p[i];
make_ham(cnt);
Rep(i,q,1) {
int o=qs[i][0],x=qs[i][1];
if(o==2) res[i]=ans;
else insert(x);
}
For(i,1,q) if(qs[i][0]==2) printf("%.2lf\n",res[i]);
return 0;
}