【bzoj 2300】: [HAOI2011]防线修建


http://www.lydsy.com/JudgeOnline/problem.php?id=2300


离线+set维护凸包

第一次码这个,还跑得飞快。。。


#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <set>
using namespace std;
#define rep(i,l,r) for(int i=(l),_=(r);i<=_;i++)
#define per(i,r,l) for(int i=(r),_=(l);i>=_;i--)
#define MS(arr,x) memset(arr,x,sizeof(arr))
#define INE(i,u) for(int i=head[u];~i;i=e[i].next)
#define LL long long
inline const int read()
{int r=0,k=1;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1;
for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0';return k*r;}

int n,m,q;
struct Point{
	int x,y;
	Point(){}
	Point(int x,int y):x(x),y(y){}
	Point operator-(const Point &b)const{return Point(x-b.x,y-b.y);}
	int operator^(const Point &b)const{return x*b.y-y*b.x;}
	bool operator<(const Point &b)const{return x!=b.x?x<b.x:y<b.y;}
}M,a[100010];
struct ques{
	int type,x;
}b[200010];
bool del[100010];
set<Point>S;
double ans[200010],nowans;
int tot;

double sqr(double x){return x*x;}
double dis(Point A,Point B)
{
	return sqrt(sqr(A.x-B.x)+sqr(A.y-B.y));
}
void insert(Point P)
{
	set<Point>::iterator L,R=S.lower_bound(P),tmp;
	L=R; L--;
	if((*R-P^*L-P)>=0) return;
	nowans-=dis(*L,*R);
	while(L->x!=0)
	{
		tmp=L; tmp--;
		if((P-*L^*tmp-*L)<0) break;
		nowans-=dis(*L,*tmp);
		S.erase(*L);
		L=tmp;
	}
	while(R->x!=n)
	{
		tmp=R; tmp++;
		if((*tmp-*R^P-*R)<0) break;
		nowans-=dis(*R,*tmp);
		S.erase(*R);
		R=tmp;
	}
	S.insert(P);
	nowans+=dis(*L,P);
	nowans+=dis(P,*R);
}

void input()
{
    n=read();
    M.x=read(); M.y=read();
    rep(i,1,m=read()) a[i].x=read(),a[i].y=read();
    rep(i,1,q=read())
    {
    	b[i].type=read();
    	if(b[i].type==1)
    	{
    		b[i].x=read();
    		del[b[i].x]=1;
    	}
    }
    S.insert(Point(0,0));
    S.insert(Point(n,0));
    S.insert(M);
    nowans=dis(Point(0,0),M)+dis(M,Point(n,0));
    rep(i,1,m) if(!del[i]) insert(a[i]);
}
void solve()
{
	per(i,q,1)
	{
		if(b[i].type==1)
		{
			insert(a[b[i].x]);
		}
		else ans[++tot]=nowans;
	}
	per(i,tot,1) printf("%.2f\n",ans[i]);
}

int main()
{
    freopen("_.in","r",stdin); freopen("_.out","w",stdout);
    input(),solve();
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值