防線修建 BZOJ 2300

2022-08-21 16:45:11 字數 3142 閱讀 7324

防線修建

【問題描述】

近來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點的保護,那麼防線變成下圖 

【輸入格式】

第一行,三個整數n,x,y分別表示河邊城市和首都是(0,0),(n,0),(x,y)。

第二行,乙個整數m。

接下來m行,每行兩個整數a,b表示a國的乙個非首都非河邊城市的座標為(a,b)。

再接下來乙個整數q,表示修改和詢問總數。

接下來q行每行要麼形如1 i,要麼形如2,分別表示撤銷第i個城市的保護和詢問。

【輸出格式】

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

【樣例輸入】

4 2 1

21 2

3 25

21 1

21 2

2【樣例輸出】

6.47

5.84

4.47

【資料範圍】

30%的資料m<=1000,q<=1000

100%的資料m<=100000,q<=200000,n>1

所有點的座標範圍均在10000以內, 資料保證沒有重點

題解:題意即為支援刪點維護乙個上凸殼

由於只需要支援刪點的操作

那麼離線倒序處理,就變為加點操作

若要加入的點在凸包內,那就把它丟掉······

如果這個點在凸包外

分別考慮這個點左右兩邊的點

向兩個方向維護上凸殼

這個過程用set實現

1 #include2 #include3 #include4 #include5 #include6 #include7 #include

8using

namespace

std;

9 inline int

get()

1019

return

x;20}21

const

int me = 200233;22

intn, m, x, y, e;

23int

nu;24

double

sum;

25struct

dot26

33};

34dot o;

35dot a[me];

36int

flag[me];

37bool

vis[me];

38int

num[me];

39double

ans[me];

40 multisetc;

41 inline double dis(const

int &ax, const

int &ay, const

int &bx, const

int &by)

4245 inline int cross(const

int &ax, const

int &ay, const

int &bx, const

int &by)

4649 inline void

add(dot v)

5065 sum -= dis((now -> x), (now -> y), (l -> x), (l ->y));

66c.erase(now);67}

68while(true)69

77if(cross(v.x - (r -> x), v.y - (r -> y), (now -> x) - (r -> x), (now -> y) - (r -> y)) <= 0)78

82 sum -= dis((now -> x), (now -> y), (r -> x), (r ->y));

83c.erase(now);84}

85c.insert(v);

86 sum += dis((l -> x), (l -> y), v.x, v.y) + dis(v.x, v.y, (r -> x), (r ->y));87}

88int

main()

89104 e =get();

105for(int i = 1; i <= e; ++i)

106113

}114

for(int i = 1; i <= m; ++i)

115if(!vis[i])

116add(a[i]);

117for(int i = e; i >= 1; --i)

118122

for(int i = nu; i >= 1; --i)

123 printf("

%.2lf\n

", ans[i]);

124 }

bzoj 2300 防線修建

題意 給出乙個點集,每次可能刪去乙個點或查詢上凸包的面積 保證無重點,保證最左面 最右面的點一定在凸包上 n 100000,m 200000 題解 動態凸包問題,然而這道題的保證簡直極為良心 所以呢,我們就可以用set來水這道題啦 我還是漲了不少姿勢的,比如迭代器居然可以自減 離線所有的操作之後處理...

HAOI2011 BZOJ2300 防線修建

description 近來a國和b國的矛盾激化,為了預防不測,a國準備修建一條長長的防線,當然修建防線的話,肯定要把需要保護的城市修在防線內部了。可是a國上層現在還猶豫不決,到底該把哪些城市作為保護物件呢?又由於a國的經費有限,所以希望你能幫忙完成如下的乙個任務 給出你所有的a國城市座標 a國上層...

BZOJ2300 HAOI2011 防線修建

每次刪乙個點或詢問剩餘點的凸包周長 刪乙個點好麻煩呀,考慮離線,倒著操作將刪點改為加點 然後就簡單了,用一顆平衡樹維護凸包中的點,倒著把點加回去 splay可以用set 論熟練運用stl code include include include include include include inc...