[luogu P2521] [HAOI2011]防線修建
[luogu P2521] [HAOI2011]防線修建
題目描述
近來A國和B國的矛盾激化,為了預防不測,A國準備修建一條長長的防線,當然修建防線的話,肯定要把需要保護的城市修在防線內部了。可是A國上層現在還猶豫不決,到底該把哪些城市作為保護對象呢?又由於A國的經費有限,所以希望你能幫忙完成如下的一個任務:
給出你所有的A國城市坐標
A國上層經過討論,考慮到經濟問題,決定取消對i城市的保護,也就是說i城市不需要在防線內了
- A國上層詢問對於剩下要保護的城市,修建防線的總經費最少是多少
你需要對每次詢問作出回答。註意單位1長度的防線花費為1。
A國的地形是這樣的,形如下圖,x軸是一條河流,相當於一條天然防線,不需要你再修建
A國總是有兩個城市在河邊,一個點是(0,0),一個點是(n,0),其余所有點的橫坐標均大於0小於n,縱坐標均大於0。A國有一個不在(0,0)和(n,0)的首都。(0,0),(n,0)和首都這三個城市是一定需要保護的。
(別瞅了,luogu沒有圖)
輸入輸出格式
輸入格式:
第一行,三個整數n,x,y分別表示河邊城市和首都是(0,0),(n,0),(x,y)。
第二行,一個整數m。
接下來m行,每行兩個整數a,b表示A國的一個非首都非河邊城市的坐標為(a,b)。
再接下來一個整數q,表示修改和詢問總數。
接下來q行每行要麽形如1 i,要麽形如2,分別表示撤銷第i個城市的保護和詢問。
輸出格式:
對於每個詢問輸出1行,一個實數v,表示修建防線的花費,保留兩位小數
輸入輸出樣例
輸入樣例#1: 復制4 2 1 2 1 2 3 2 5 2 1 1 2 1 2 2
輸出樣例#1: 復制6.47 5.84 4.47
說明
數據範圍:
30%的數據m<=1000,q<=1000
100%的數據m<=100000,q<=200000,n>1
所有點的坐標範圍均在10000以內, 數據保證沒有重點
想了好久,也碼了好久。剛開始沒有想到時光倒流,往cdq去想了。平衡樹也很難操作。
最後看了發題解——艹,怎麽又沒想到時光倒流!
時光倒流以後,就相當於維護一個支持單點更新的上凸包,並求周長-n。
還好題目限制好了,不然要煩死、、
那我們采取這樣的方法:
插入一個點時,先判斷在不在凸包內。如果不在,則向兩邊維護一個凸包,直到不能刪點或者符合一個凸包時停止。
其中判斷是否在凸包內,通過找兩個點,一個前驅,一個後綴,都在凸包邊上。
其中,設當前插入點為c,前綴為u,後綴為v,滿足u.x<c.x||u.x==c.x&&u.y<c.y,v.x>c.x||v.x==c.x&&v.y>c.y。
如果cross(c-u,v-u)>0(cross表示兩個向量叉積),則說明c在凸包內。
否則向兩邊維護更新凸殼。
根據對稱性,我們只取向左邊的進行研究。
設u為凸包上c的前綴,v為凸包上u的前綴。
當然如果u(0,0),那麽就退出了,(0,0)是不能刪的。
否則如果cross(c-v,u-v)>0,則維護好了,退出,否則就刪了u,繼續。
至此,維護單點更新成功了,且復雜度正確,因為,每個點最多插入一次,刪除一次。
其中求pre,suc可以看做是連帶的,換句話說,次數和刪除操作次數差不多(倍數在常數級)。
這裏的復雜度大致就是nlogn基本的。
但是同樣,我們會有一個棘手的問題->計算周長。
如果每次找凸包上每個點的前驅後綴計算感覺會很慢,也很難寫。
如果我們在刪點,加點時就計算,是不是就比較快呢?
不過要註意,不要漏刪一條邊或多加一條邊,細節還是有點的。
還有,其中前驅後綴插入刪除都是平衡樹的操作。
(splay比stl快?無意搶了luogu‘rank1,233)
code:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <cmath> 5 #define ms(a,x) memset(a,x,sizeof a) 6 using namespace std; 7 8 void OJ() { 9 #ifndef ONLINE_JUDGE 10 freopen("in.txt","r",stdin); 11 freopen("out.txt","w",stdout); 12 #endif 13 } 14 namespace fastIO { 15 #define gec(c) getchar(c) 16 #define puc(c) putchar(c) 17 char ch; 18 inline int read() { 19 int x=0,f=1; ch=getchar(); 20 while (ch<‘0‘||ch>‘9‘) { 21 if (ch==‘-‘) f=-f; 22 ch=gec(); 23 } 24 while (ch>=‘0‘&&ch<=‘9‘) { 25 x=(x<<3)+(x<<1)+ch-‘0‘; 26 ch=getchar(); 27 } 28 return x*f; 29 } 30 } using namespace fastIO; 31 32 const int N=200005; 33 int n,m,q,las; 34 bool vis[N]; double ans[N]; 35 struct query { 36 int t,x; 37 } o[N]; 38 39 #define SplayTree node 40 struct SplayTree { 41 int X,Y; 42 node* c[3]; 43 node () { 44 X=Y=0; 45 c[0]=c[1]=c[2]=0; 46 } 47 } * ro,* g,* U,* V,* re; 48 49 #define vec city 50 struct city { 51 int x,y; 52 city () {} 53 city (int _x,int _y) : 54 x(_x),y(_y) {}; 55 city (node* u) : 56 x(u->X),y(u->Y) {}; 57 } a[N]; 58 int cross (vec u,vec v) { 59 return u.x*v.y-u.y*v.x; 60 } 61 vec operator - (city u,city v) { 62 return vec(u.x-v.x,u.y-v.y); 63 } 64 node* noded (city u) { 65 node* rt=new node(); 66 rt->X=u.x,rt->Y=u.y; 67 return rt; 68 } 69 void setup (node* &x,int X,int Y) { 70 x=new node(),x->X=X,x->Y=Y; 71 } 72 bool dir (node* x) { 73 if (!x->c[2]) return 0; 74 return x->c[2]->c[1]==x; 75 } 76 void linknode (node* y,node* x,bool p) { 77 if (x) x->c[2]=y; 78 if (y) y->c[p]=x; 79 } 80 void rotate (node* x) { 81 bool p=dir(x); node* y=x->c[2]; 82 linknode(y->c[2],x,dir(y)); 83 linknode(y,x->c[p^1],p); 84 linknode(x,y,p^1); 85 } 86 void splay (node* x,node* an) { 87 if (x->c[2]==an) return; 88 while (x->c[2]!=an) { 89 if (x->c[2]->c[2]==an) { 90 rotate(x); 91 if (!an) ro=x; 92 return; 93 } 94 rotate(dir(x)^dir(x->c[2])?x:x->c[2]); 95 rotate(x); 96 } 97 if (!an) ro=x; 98 } 99 bool cmp (node* u,node* v) { 100 return u->X==v->X?u->Y<v->Y:u->X<v->X; 101 } 102 void insert (node* &x,node* u) { 103 if (!x) { 104 g=x=u; 105 return; 106 } 107 bool p=cmp(x,u); 108 insert(x->c[p],u),x->c[p]->c[2]=x; 109 } 110 void erase (node* u) { 111 splay(u,0); 112 if (!ro->c[0]||!ro->c[1]) { 113 if (ro->c[0]) ro=ro->c[0],ro->c[2]=0; else 114 if (ro->c[1]) ro=ro->c[1],ro->c[2]=0; else 115 ro=0; 116 return; 117 } 118 for (re=ro->c[0]; re->c[1]; re=re->c[1]) ; 119 splay(re,ro); 120 re->c[2]=0,re->c[1]=ro->c[1]; 121 if (re->c[1]) re->c[1]->c[2]=re; 122 ro=re; 123 } 124 bool cmp_1 (node* u,node* v) { 125 return u->X==v->X?u->Y<v->Y:u->X<v->X; 126 } 127 bool cmp_2 (node* u,node* v) { 128 return u->X==v->X?u->Y>v->Y:u->X>v->X; 129 } 130 void pre (node* x,node* u) { 131 if (!x) return; 132 if (cmp_1(x,u)) re=x,pre(x->c[1],u); 133 else pre(x->c[0],u); 134 } 135 void suc (node* x,node* u) { 136 if (!x) return; 137 if (cmp_2(x,u)) re=x,suc(x->c[0],u); 138 else suc(x->c[1],u); 139 } 140 #define sqr(x) ((x)*(x)) 141 double dis (node* u,node* v) { 142 return sqrt(sqr(u->X-v->X)+sqr(u->Y-v->Y)); 143 } 144 void maintain () { 145 pre(ro,g),U=re,suc(ro,g),V=re; 146 if (cross(city(g)-city(U),city(V)-city(U))>0) return; 147 if (U->X!=0||U->Y!=0||V->X!=n||V->Y!=0) ans[0]-=dis(U,V); 148 for ( ; ; ) { 149 pre(ro,g),U=re; 150 if (U->X==0&&U->Y==0) { 151 ans[0]+=dis(g,U); 152 break; 153 } 154 pre(ro,U),V=re; 155 if (cross(city(g)-city(V),city(U)-city(V))>0) { 156 ans[0]+=dis(g,U); 157 break; 158 } 159 ans[0]-=dis(U,V); 160 erase(U); 161 } 162 for ( ; ; ) { 163 suc(ro,g),U=re; 164 if (U->X==n&&U->Y==0) { 165 ans[0]+=dis(g,U); 166 break; 167 } 168 suc(ro,U),V=re; 169 if (cross(city(g)-city(V),city(U)-city(V))<0) { 170 ans[0]+=dis(g,U); 171 break; 172 } 173 ans[0]-=dis(U,V); 174 erase(U); 175 } 176 insert(ro,g); 177 splay(g,0); 178 } 179 180 int main() { 181 OJ(); 182 n=read(),a[0].x=read(),a[0].y=read(); 183 m=read(),a[m+1]=city(0,0),a[m+2]=city(n,0); 184 for (int i=1; i<=m; ++i) { 185 a[i].x=read(),a[i].y=read(); 186 } 187 ms(vis,1); 188 q=read(); 189 for (int i=1; i<=q; ++i) { 190 o[i].t=read(); 191 if (o[i].t&1) o[i].x=read(); 192 vis[o[i].x]=0; 193 } 194 ro=0; 195 insert(ro,noded(a[0])); 196 insert(ro,noded(a[m+1])); 197 insert(ro,noded(a[m+2])); 198 ans[0]=dis(noded(a[0]),noded(a[m+1]))+dis(noded(a[0]),noded(a[m+2])); 199 for (int i=1; i<=m; ++i) { 200 if (vis[i]) g=noded(a[i]),maintain(); 201 } 202 for (int i=q; i; --i) { 203 if (o[i].t&1) g=noded(a[o[i].x]),maintain(); 204 else ans[i]=ans[0]; 205 } 206 for (int i=1; i<=q; ++i) { 207 if (~o[i].t&1) printf("%.2lf\n",ans[i]); 208 } 209 return 0; 210 }View Code
[luogu P2521] [HAOI2011]防線修建