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;
}
posted @ 2015-05-05 19:04  NanoApe  阅读(164)  评论(0编辑  收藏  举报
AmazingCounters.com