码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj-2300 防线修建

时间:2015-09-30 08:32:34      阅读:184      评论:0      收藏:0      [点我收藏+]

标签:bzoj   凸包   set   

题意:

给出一个点集,每次可能删去一个点或查询上凸包的面积;

保证无重点,保证最左面 最右面的点一定在凸包上;

n<=100000,m<=200000;


题解:

动态凸包问题,然而这道题的保证简直极为良心;

所以呢,我们就可以用set来水这道题啦;

我还是涨了不少姿势的,比如迭代器居然可以自减;

离线所有的操作之后处理,就是凸包加点了;

每次来一个点,判断一下加不加入,之后左面干点右面干点,插进去就好了;

不过这题细节还是用很多,主要是边界问题吧;

时间复杂度O(set(n))O(nlogn);


代码:


#include<set>
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 110000
#define iter set<Point>::iterator
using namespace std;
const double INF=1e100;
struct Point
{
	int x,y;
	Point(){}
	Point(int _,int __):x(_),y(__){}
	friend bool operator <(Point a,Point b)
	{
		if(a.x==b.x)
			return a.y<b.y;
		return a.x<b.x;
	}
	friend bool operator ==(Point a,Point b)
	{
		return a.x==b.x&&a.y==b.y;
	}
	friend bool slope (Point a,Point b,Point c)
	{
		double s1=a.x==b.x?(a.y<b.y?INF:-INF):(a.y-b.y)*1.0/(a.x-b.x);
		double s2=b.x==c.x?(b.y<c.y?INF:-INF):(b.y-c.y)*1.0/(b.x-c.x);
		return s1<s2;
	}
	friend double dis(Point a,Point b)
	{
		return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+0.0);
	}
}a[N],p;
int Qx[N<<1],top;
bool Q[N<<1],ban[N];
double st[N<<1];
set<Point>s;
int main()
{
	int n,m,q,i,j,k;
	double ans;
	scanf("%d%d%d",&n,&p.x,&p.y);
	s.insert(p),s.insert(Point(0,0)),s.insert(Point(n,0));
	scanf("%d",&m);
	for(i=1;i<=m;i++)
	{
		scanf("%d%d",&a[i].x,&a[i].y);
	}
	scanf("%d",&q);
	for(i=1;i<=q;i++)
	{
		scanf("%d",&k);
		if(k==1)
		{
			Q[i]=1;
			scanf("%d",Qx+i);
			ban[Qx[i]]=1;
		}
	}
	ans=dis(p,Point(0,0))+dis(p,Point(n,0));
	for(i=1;i<=m;i++)
	{
		if(!ban[i])
		{
			iter it1=s.insert(a[i]).first;
			iter it2=it1,temp=it1;
			it1++,it2--;
			if(slope(*it2,a[i],*it1))
				{s.erase(temp);continue;}
			if(*it1==Point(n,0)&&*it2==Point(0,0))
				ans=0;
			else
				ans-=dis(*it1,*it2);
			temp=it1;
			while(++temp!=s.end()&&slope(a[i],*it1,*temp))
				ans-=dis(*it1,*temp),s.erase(it1++);
			temp=it2;
			while(temp--!=s.begin()&&slope(*temp,*it2,a[i]))
				ans-=dis(*it2,*temp),s.erase(it2--);
			ans+=dis(a[i],*it1)+dis(a[i],*it2);
		}
	}
	for(i=q;i>=1;i--)
	{
		if(Q[i])
		{
			iter it1=s.insert(a[Qx[i]]).first;
			iter it2=it1,temp=it1;
			it1++,it2--;
			if(slope(*it2,a[Qx[i]],*it1))
				{s.erase(temp);continue;}
			if(*it1==Point(n,0)&&*it2==Point(0,0))
				ans=0;
			else
				ans-=dis(*it1,*it2);
			temp=it1;
			while(++temp!=s.end()&&slope(a[Qx[i]],*it1,*temp))
				ans-=dis(*it1,*temp),s.erase(it1++);
			temp=it2;
			while(temp--!=s.begin()&&slope(*temp,*it2,a[Qx[i]]))
				ans-=dis(*it2,*temp),s.erase(it2--);
			ans+=dis(a[Qx[i]],*it1)+dis(a[Qx[i]],*it2);
		}
		else
			st[++top]=ans;
	}
	while(top)
	{
		printf("%.2lf\n",st[top--]);
	}
}



bzoj-2300 防线修建

标签:bzoj   凸包   set   

原文地址:http://blog.csdn.net/ww140142/article/details/48824451

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!