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

防線修建 bzoj 2300,bzoj2300

編輯:C++入門知識

防線修建 bzoj 2300,bzoj2300


防線修建(1s 512MB)defense

【問題描述】

近來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

2

1 2

3 2

5

2

1 1

2

1 2

2

【樣例輸出】

6.47

5.84

4.47

【數據范圍】

30%的數據m<=1000,q<=1000

100%的數據m<=100000,q<=200000,n>1

所有點的坐標范圍均在10000以內, 數據保證沒有重點


 

題解:

主要算法:Set;計算幾何;快速排序;

題意即為支持刪點維護一個上凸殼

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

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

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

如果這個點在凸包外

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

向兩個方向維護上凸殼

這個過程用set實現

  1 #include<algorithm>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<cstdio>
  6 #include<cmath>
  7 #include<set>
  8 using namespace std;
  9 inline int Get()
 10 {
 11     int x = 0;
 12     char c = getchar();
 13     while('0' > c || c > '9') c = getchar();
 14     while('0' <= c && c <= '9')
 15     {
 16         x = (x << 3) + (x << 1) + c - '0';
 17         c = getchar();
 18     }
 19     return x;
 20 }
 21 const int me = 200233;
 22 int n, m, x, y, e;
 23 int nu;
 24 double sum;
 25 struct dot
 26 {
 27     int x, y;
 28     inline bool operator < (const dot &z) const
 29     {
 30         if(x != z.x) return x < z.x;
 31         return y < z.y;
 32     }
 33 };
 34 dot o;
 35 dot a[me];
 36 int flag[me];
 37 bool vis[me];
 38 int num[me];
 39 double ans[me];
 40 multiset<dot> c;
 41 inline double Dis(const int &ax, const int &ay, const int &bx, const int &by)
 42 {
 43     return sqrt((ax - bx) * (ax - bx) + (ay - by) * (ay - by));
 44 }
 45 inline int Cross(const int &ax, const int &ay, const int &bx, const int &by)
 46 {
 47     return ax * by - bx * ay;
 48 }
 49 inline void Add(dot v)
 50 {
 51     multiset<dot>::iterator l = c.upper_bound(v), r = l;
 52     --l;
 53     if(Cross((r -> x) - (l -> x), (r -> y) - (l -> y), v.x - (l -> x), v.y - (l -> y)) <= 0) return;
 54     sum -= Dis((l -> x), (l -> y), (r -> x), (r -> y));
 55     multiset<dot>::iterator now;
 56     while(l != c.begin())
 57     {
 58         now = l;
 59         --l;
 60         if(Cross(v.x - (l -> x), v.y - (l -> y), (now -> x) - (l -> x), (now -> y) - (l -> y)) >= 0)
 61         {
 62             ++l;
 63             break;
 64         }
 65         sum -= Dis((now -> x), (now -> y), (l -> x), (l -> y));
 66         c.erase(now);
 67     }
 68     while(true)
 69     {
 70         now = r;
 71         ++r;
 72         if(r == c.end())
 73         {
 74             --r;
 75             break;
 76         }
 77         if(Cross(v.x - (r -> x), v.y - (r -> y), (now -> x) - (r -> x), (now -> y) - (r -> y)) <= 0)
 78         {
 79             --r;
 80             break;
 81         }
 82         sum -= Dis((now -> x), (now -> y), (r -> x), (r -> y));
 83         c.erase(now);
 84     }
 85     c.insert(v);
 86     sum += Dis((l -> x), (l -> y), v.x, v.y) + Dis(v.x, v.y, (r -> x), (r -> y));
 87 }
 88 int main()
 89 {
 90     o.x = o.y = 0; 
 91     c.insert(o);
 92     o.x = n = Get();
 93     c.insert(o);
 94     o.x = x = Get();
 95     o.y = y = Get();
 96     c.insert(o);
 97     m = Get();
 98     sum = Dis(0, 0, x, y) + Dis(x, y, n, 0);
 99     for(int i = 1; i <= m; ++i)
100     {
101         a[i].x = Get();
102         a[i].y = Get();
103     }
104     e = Get();
105     for(int i = 1; i <= e; ++i)
106     {
107         flag[i] = Get();
108         if(flag[i] == 1)
109         {
110             num[i] = Get();
111             vis[num[i]] = true;
112         }
113     }
114     for(int i = 1; i <= m; ++i)
115         if(!vis[i])
116             Add(a[i]);
117     for(int i = e; i >= 1; --i)
118     {
119         if(flag[i] == 1) Add(a[num[i]]);
120         else ans[++nu] = sum;
121     }
122     for(int i = nu; i >= 1; --i)
123         printf("%.2lf\n", ans[i]);
124 }

 

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