程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> bzoj2300【HAOI2011】防線修建

bzoj2300【HAOI2011】防線修建

編輯:關於C

Description

近來A國和B國的矛盾激化,為了預防不測,A國准備修建一條長長的防線,當然修建防線的話,肯定要把需要保護的城市修在防線內部了。可是A國上層現在還猶豫不決,到底該把哪些城市作為保護對象呢?又由於A國的經費有限,所以希望你能幫忙完成如下的一個任務: 1.給出你所有的A國城市坐標 2.A國上層經過討論,考慮到經濟問題,決定取消對i城市的保護,也就是說i城市不需要在防線內了 3.A國上層詢問對於剩下要保護的城市,修建防線的總經費最少是多少 你需要對每次詢問作出回答。注意單位1長度的防線花費為1。 A國的地形是這樣的,形如下圖,x軸是一條河流,相當於一條天然防線,不需要你再修建 A國總是有兩個城市在河邊,一個點是(0,0),一個點是(n,0),其余所有點的橫坐標均大於0小於n,縱坐標均大於0。A國有一個不在(0,0)和(n,0)的首都。(0,0),(n,0)和首都這三個城市是一定需要保護的。

\

上圖中,A,B,C,D,E點為A國城市,且目前都要保護,那麼修建的防線就會是A-B-C-D,花費也就是線段AB的長度+線段BC的長度+線段CD的長度,如果,這個時候撤銷B點的保護,那麼防線變成下圖

\

 

Input

第一行,三個整數n,x,y分別表示河邊城市和首都是(0,0),(n,0),(x,y)。 第二行,一個整數m。 接下來m行,每行兩個整數a,b表示A國的一個非首都非河邊城市的坐標為(a,b)。 再接下來一個整數q,表示修改和詢問總數。 接下來q行每行要麼形如1 i,要麼形如2,分別表示撤銷第i個城市的保護和詢問。

Output

對於每個詢問輸出1行,一個實數v,表示修建防線的花費,保留兩位小數

Sample Input

4 2 1
2
1 2
3 2
5
2
1 1
2
1 2
2

Sample Output

6.47
5.84
4.47

HINT

m<=100000,q<=200000,n>1
所有點的坐標范圍均在10000以內, 數據保證沒有重點

凸包上刪點很難處理,所以我們考慮離線,將刪點操作轉化為加點操作。

於是現在問題變成了:維護一個支持加點操作的動態凸包。

每次加一個點判斷是否在凸包內,然後用set找兩邊相鄰的點,再兩邊分別維護。

 
#include
#include
#include
#include
#include
#include
#include
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 200005
using namespace std;
int n,x,y,m,q;
int opt[maxn];
bool tag[maxn];
double now,ans[maxn];
struct data{int x,y;}a[maxn];
set s;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline double dis(data a,data b)
{
	return sqrt((double)(a.x-b.x)*(a.x-b.x)+(double)(a.y-b.y)*(a.y-b.y));
}
inline data operator -(data a,data b)
{
	return (data){a.x-b.x,a.y-b.y};
}
inline int operator *(data a,data b)
{
	return a.x*b.y-a.y*b.x;
}
inline bool operator <(data a,data b)
{
	return a.x==b.x?a.y::iterator l=s.lower_bound(x),r=l,t;
	l--;
	if ((*r-*l)*(x-*l)<0) return;
	now-=dis(*l,*r);
	for(;;)
	{
		t=r;r++;
		if (r==s.end()) break;
		if ((*r-x)*(*t-x)>0) break;
		now-=dis(*t,*r);
		s.erase(t);
	}
	for(;;)
	{
		if (l==s.begin()) break;
		t=l;l--;
		if ((x-*l)*(*t-*l)>0) break;
		now-=dis(*t,*l);
		s.erase(t);
	}
	s.insert(x);
	l=r=s.find(x);l--;r++;
	now+=dis(*l,x)+dis(*r,x);
}
int main()
{
	n=read();x=read();y=read();
	s.insert((data){0,0});s.insert((data){n,0});s.insert((data){x,y});
	now=dis((data){0,0},(data){x,y})+dis((data){n,0},(data){x,y});
	m=read();
	F(i,1,m) a[i].x=read(),a[i].y=read();
	q=read();
	F(i,1,q)
	{
		int flg=read();
		opt[i]=(flg==2)?0:read();
		if (opt[i]) tag[opt[i]]=true;
	}
	F(i,1,m) if (!tag[i]) add_data(a[i]);
	D(i,q,1)
	{
		if (opt[i]) add_data(a[opt[i]]);
		else ans[i]=now;
	}
	F(i,1,q) if (!opt[i]) printf("%.2lf\n",ans[i]);
	return 0;
}


 

 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved