【BZOJ2300】[HAOI2011]防线修建 set维护凸包
生活随笔
收集整理的這篇文章主要介紹了
【BZOJ2300】[HAOI2011]防线修建 set维护凸包
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
【BZOJ2300】[HAOI2011]防線修建
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 12
1 2
3 2
5
2
1 1
2
1 2
2
Sample Output
6.475.84
4.47
HINT
m<=100000,q<=200000,n>1 所有點的坐標范圍均在10000以內, 數據保證沒有重點題解:容易想到離線,然后本題就變成了加點和維護凸包,可以用平衡樹來維護凸包來搞(以前一直以為必須用Splay,結果發現好像set就行)。
具體地,我們在set中的點是按x值從小到大排序的。在加入一個點時,先找到凸包中它的前驅和后繼節點,用叉積判一下當前點是否已經在凸包里面。如果在則不用加點,否則加入當前點,并不斷執行以下操作:
如果當前點和左側兩個點形成的不是上凸包,則將當前點的前驅刪掉,否則退出。
右面同理。
然后就做完了,細節也不是特別多。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <set> #include <cmath> using namespace std; const int maxn=200010; struct point {int x,y;point() {}point(int a,int b) {x=a,y=b;}bool operator != (const point &a) const {return (x!=a.x)||(y!=a.y);}bool operator < (const point &a) const {return (x==a.x)?(y<a.y):(x<a.x);}point operator - (const point &a) const {return point (x-a.x,y-a.y);}int operator * (const point &a) const {return x*a.y-y*a.x;} }p[maxn]; double dis(const point &a,const point &b) {return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));} set<point> s; set<point>::iterator it; double ans; int n,m,q; int del[maxn],op[maxn],qi[maxn]; double qa[maxn]; inline int rd() {int ret=0,f=1; char gc=getchar();while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar();return ret*f; } inline void add(point x) {point a,b,c;it=s.upper_bound(x),b=*it,it--,a=*it;if(x.x==b.x) return ;if((x-a)*(b-x)>=0) return ;ans-=dis(a,b);while(a!=point(0,0)){it--,c=*it;if((a-c)*(x-a)>=0) ans-=dis(a,c),s.erase(s.find(a)),a=c;else break;}it=s.find(b);while(b!=point(n,0)){it++,c=*it;if((b-x)*(c-b)>=0) ans-=dis(b,c),s.erase(s.find(b)),b=c;else break;}ans+=dis(a,x)+dis(x,b);s.insert(x); } int main() {int i,a,b;n=rd(),a=rd(),b=rd(),m=rd();s.insert(point(0,0)),s.insert(point(n,0)),s.insert(point(a,b));ans=dis(point(0,0),point(a,b))+dis(point(n,0),point(a,b));for(i=1;i<=m;i++) p[i].x=rd(),p[i].y=rd();q=rd();for(i=1;i<=q;i++){op[i]=rd();if(op[i]==1) qi[i]=rd(),del[qi[i]]=1;}for(i=1;i<=m;i++) if(!del[i]) add(p[i]);for(i=q;i>=1;i--){if(op[i]==2) qa[i]=ans;else add(p[qi[i]]);}for(i=1;i<=q;i++) if(op[i]==2) printf("%.2lf\n",qa[i]);return 0; }轉載于:https://www.cnblogs.com/CQzhangyu/p/7965400.html
總結
以上是生活随笔為你收集整理的【BZOJ2300】[HAOI2011]防线修建 set维护凸包的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据结构和算法之排序五:选择排序
- 下一篇: AirPods Pro空间音频开启方法