bzoj-2300 防线修建

题意:

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

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

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--]);
	}
}
时间: 2024-10-06 14:10:36

bzoj-2300 防线修建的相关文章

BZOJ [HAOI2011]防线修建(动态凸包)

听说有一种很高端的东西叫动态凸包维护dp就像学一下,不过介于本人还不会动态凸包就去学了下,还是挺神奇的说,维护上下凸包的写法虽然打得有点多不过也只是维护复制黏贴的事情而已罢了. 先说下动态凸包怎么写吧,搞棵平衡树存上下凸壳然后每次插入一个点就往他左右维护看是否满足凸性否则就弹出,就是这么简单 这道题就是删点然后询问凸壳,那么离线反着做就行了 出题人还是挺良心的直接让你维护上凸壳就行了,还不用管边界条件 用set打了一下,比较慢但还是挺好打的= = 换新blog挺多功能得试试的,现在想搞个像HZW

BZOJ 2300: [HAOI2011]防线修建( 动态凸包 )

离线然后倒着做就变成了支持加点的动态凸包...用平衡树维护上凸壳...时间复杂度O(NlogN) ----------------------------------------------------------------------- #include<cmath> #include<cstdio> #include<cctype> #include<cstring> #include<cstdlib> #include<algori

【BZOJ 2300】 2300: [HAOI2011]防线修建 (动态凸包+set)

2300: [HAOI2011]防线修建 Description 近来A国和B国的矛盾激化,为了预防不测,A国准备修建一条长长的防线,当然修建防线的话,肯定要把需要保护的城市修在防线内部了.可是A国上层现在还犹豫不决,到底该把哪些城市作为保护对象呢?又由于A国的经费有限,所以希望你能帮忙完成如下的一个任务: 1.给出你所有的A国城市坐标 2.A国上层经过讨论,考虑到经济问题,决定取消对i城市的保护,也就是说i城市不需要在防线内了 3.A国上层询问对于剩下要保护的城市,修建防线的总经费最少是多少

防线修建 bzoj 2300

防线修建(1s 512MB)defense [问题描述] 近来A国和B国的矛盾激化,为了预防不测,A国准备修建一条长长的防线,当然修建防线的话,肯定要把需要保护的城市修在防线内部了.可是A国上层现在还犹豫不决,到底该把哪些城市作为保护对象呢?又由于A国的经费有限,所以希望你能帮忙完成如下的一个任务: 1.给出你所有的A国城市坐标 2.A国上层经过讨论,考虑到经济问题,决定取消对i城市的保护,也就是说i城市不需要在防线内了 3.A国上层询问对于剩下要保护的城市,修建防线的总经费最少是多少 你需要对

bzoj千题计划236:bzoj2300: [HAOI2011]防线修建

http://www.lydsy.com/JudgeOnline/problem.php?id=2300 维护动态凸包,人懒用的set 用叉积判断,不要用斜率 #include<set> #include<cmath> #include<cstdio> #include<iostream> using namespace std; #define N 100001 struct node { int x,y; node(int x_=0,int y_=0):

【BZOJ2300】[HAOI2011]防线修建 set维护凸包

[BZOJ2300][HAOI2011]防线修建 Description 近来A国和B国的矛盾激化,为了预防不测,A国准备修建一条长长的防线,当然修建防线的话,肯定要把需要保护的城市修在防线内部了.可是A国上层现在还犹豫不决,到底该把哪些城市作为保护对象呢?又由于A国的经费有限,所以希望你能帮忙完成如下的一个任务: 1.给出你所有的A国城市坐标 2.A国上层经过讨论,考虑到经济问题,决定取消对i城市的保护,也就是说i城市不需要在防线内了 3.A国上层询问对于剩下要保护的城市,修建防线的总经费最少

【题解】P2521 [HAOI2011]防线修建(动态凸包)

[题解]P2521 [HAOI2011]防线修建(动态凸包) 凸包是易插入不好删除的东西,按照剧情所以我们时光倒流 然后问题就是维护凸包的周长,支持加入 本来很简单,但是计算几何就是一些小地方经验不足容易WA和RE 然后代码注释里有一些经验 //@winlere #include<iostream> #include<set> #include<cstdio> #include<cstring> #include<algorithm> #incl

BZOJ 2300 HAOI 2011 防线修建 动态维护凸包

题目大意:一些成熟分布在第一象限中,现在要建造一个防线来保护他们,但是随着时间的推移,必须要舍弃一些城市,但是不会舍弃首都.问最短的防线需要多长. 思路:在每一个时刻求一个上凸包就是答案了.当然这样做时间复杂度就呵呵了.考虑一下动态维护凸包.因为只有上凸包,所以处理起来会相对方便.我们只需把在凸包中的点按照x坐标排序,然后二分一下把点插入凸包,然后左右用斜率维护一下,这样每次插点的时间复杂度大概是O(logn).但是这样只能插点不能删点,所以离线处理一下,把删点转化为插点,最后倒着输出. (我比

cogs 547:[HAOI2011] 防线修建

★★★☆   输入文件:defense.in   输出文件:defense.out   简单对比 时间限制:1 s   内存限制:128 MB 题目描述: 近来A国和B国的矛盾激化,为了预防不测,A国准备修建一条长长的防线,当然修建防线的话,肯定要把需要保护的城市修在防线内部了.可是A国上层现在还犹豫不决,到底该把哪些城市作为保护对象呢?又由于A国的经费有限,所以希望你能帮忙完成如下的一个任务: 给出你所有的A国城市坐标 A国上层经过讨论,考虑到经济问题,决定取消对i城市的保护,也就是说i城市不

bzoj2300【HAOI2011】防线修建

题目描述 近来A国和B国的矛盾激化,为了预防不测,A国准备修建一条长长的防线,当然修建防线的话,肯定要把需要保护的城市修在防线内部了.可是A国上层现在还犹豫不决,到底该把哪些城市作为保护对象呢?又由于A国的经费有限,所以希望你能帮忙完成如下的一个任务: 1.给出你所有的A国城市坐标 2.A国上层经过讨论,考虑到经济问题,决定取消对i城市的保护,也就是说i城市不需要在防线内了 3.A国上层询问对于剩下要保护的城市,修建防线的总经费最少是多少 你需要对每次询问作出回答.注意单位1长度的防线花费为1.