BZOJ-2300 [HAOI2011]防线修建
将问题离线倒序处理,问题变成动态加点维护凸包。
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <iostream> #include <cctype> #include <set> #define rep(i, l, r) for(int i=l; i<=r; i++) #define down(i, l, r) for(int i=l; i>=r; i--) #define maxn 200009 using namespace std; inline int read() { int x=0, f=1; char ch=getchar(); while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while (isdigit(ch)) x=x*10+ch-'0', ch=getchar(); return x*f; } struct P{int x, y;} a[200005], del[100005]; double dis(P a, P b){return sqrt((double)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));} P operator - (P a, P b){return (P){a.x-b.x, a.y-b.y};} double operator * (P a, P b){return a.x*b.y-a.y*b.x;} bool operator < (P a, P b){if (a.x==b.x) return a.y<b.y; else return a.x<b.x;} set<P> q; int n, m, Q, b[maxn], t1, t2; double now=0, res[maxn]; bool mark[maxn]; void insert(P p) { set<P>::iterator r=q.lower_bound(p), l=r, t; l--; if ((*r-*l)*(p-*l)<0) return; now-=dis(*l, *r); while (1) { t=r++; if (r==q.end()) break; if ((*r-p)*(*t-p)>0) break; now-=dis(*t, *r); q.erase(t); } while (l!=q.begin()) { t=l--; if ((*t-p)*(*l-p)>0) break; now-=dis(*t, *l); q.erase(t); } q.insert(p); l=r=q.find(p); l--; r++; now+=dis(*l, p)+dis(*r, p); } int main() { n=read(); q.insert((P){0, 0}); q.insert((P){n, 0}); P bas; bas.x=read(); bas.y=read(), q.insert(bas); now+=dis((P){0, 0}, bas)+dis((P){n, 0}, bas); m=read(); rep(i, 1, m) a[i].x=read(), a[i].y=read(); Q=read(); rep(i, 1, Q) { int type=read(), x; if (type==1) x=read(), del[++t1]=a[x], mark[x]=1; else b[++t2]=t1; } rep(i, 1, m) if (!mark[i]) insert(a[i]); int T=t1; down(i, t2, 1) { while (T>b[i]) insert(del[T--]); res[i]=now; } rep(i, 1, t2) printf("%.2lf\n", res[i]); return 0; }