【Rain in ACStar HDU-3340】
·你正從AC星球返回,天又下起凸包雨,只好到線段樹下躲雨。
·英文題,述大意:
????? 一個豎直平面的美麗天空,會下凸包雨。凸包雨指的是邊數為3~6的多邊形,并且每一個它都遵守一個神奇定律,那就是自己不會有兩個橫坐標相同的點(即每個凸包自己的頂點不會出現在一條垂直于x軸的直線上)。現在有Q個操作:第一種是放置一個凸包雨(即輸入其邊數,并從其橫坐標最小點開始順時針讀入頂點坐標[x,y<=1000000000]);第二種是詢問,即讀入l,r來詢問我們橫坐標在[l,r]之間的雨滴的面積總和(被切開的雨也算),也就是求[l,r]的凸包總面積。(Q<=25000)
·分析:
????? 凸包雨很多,詢問很多。我們需要使用數據結構加以維護。請選擇一款你是喜愛的數據結構滿足以下條件:①你喜歡②可以維護區間的凸包面積!
但問題是這是一個二維的問題,我們需要加以轉化,目的是使每個凸包的面積便于使用某種美妙的數據結構維護。
????? 嘗試將計算形形色色的凸包的方法單一化,我們從一個簡單可愛的四邊形入手:現在知道其頂點坐標,怎么求面積?
??????????????????????????????????????????????
?
?????? 我們探索面積求法的目的需要再次說明:使得對各種多邊形面積計算的方法單一化。從坐標的角度思考,我們可以想到作差法(這很常用),但是選擇它的一個主要原因是,可以將任意多邊形分解為幾個梯形的面積加加減減的美好結果(當然,矩形,三角形這里可看做特殊的梯形,因為它們的面積計算同樣滿足:S=(l1+l2)*h/2)。即:將面積計算方法單一化。如圖:
?
?
??????????? 如美麗的圖:我們發現,四邊形面積就可以使用兩個綠色梯形的面積減去兩個黃色梯形的面積。很開心發現這個結論。但是我們需要進一步推廣,獲得一個普遍的計算方式。我們需要快速確定什么該減什么時候該加。順著輸入的順序(從最左邊點的逆時針)如圖:
?????????????????????????????
??????? 按照讀入順序,我們根據上文結論,可以知道,這個多邊形的面積是上頂點為(5 1)(4 5)的梯形面積和減去上頂點為(1 2)(2 3)(3 4)的梯形面積。接著你就驚奇地發現,有規律:按照逆時針順序,對于一個點a,如果它的上一個點的橫坐標比它小,那么以它倆為上頂點的梯形面積就要減去;反之,如果是橫坐標大,則這個梯形的面積就要加上(想一想,很容易)。所以在讀入后就可以按照這個方法了。
?????? 怎么操作?現在我們獲得了求梯形面積的方法,基于相鄰每個點的坐標。這個時候就是數據結構了。對于一個梯形,就用小學的面積公式,意思說我們只需要維護上下底的長度(即兩個點的縱坐標)。如個圖:
???????????????????????????
?????? 你決定了,要使用線段樹啦啦。實際上寫代碼時候,我們可以引入一個思想和一個變量來使得CODING更加美妙。思想是我們可以看做是線段樹維護等差數列(注意維護等差數列的基本思路:維護左右端點和公差)。方法是引入公差,即凸包那一條邊的斜率,這樣便于計算在線段樹PushDown的時候的中間數。
??????? 線段樹的特別的參數有:A(左端點加的值,即等差數列第一項),B(左端點加的值),ratio(斜率),它們對應的Lazy數組是:a[],b[],G[],另外,需要維護一個Sum[]表示當前區間的面積和(面積加加減減)。例子在這里:(例如向區間[1,4]插入等差數列{1,2,3,4})
?????? 最后是一些美妙的提醒和細節處理:
①注意在Lazy下放和線段樹區間分裂時都可能會有取中項的操作
②離散化詢問,以及點的橫坐標(所以在計算的時候一定要調用原長)
③本題的一個線段樹葉子結點是l+1==r表示一段小區間。
④在PushDown時和update到達指定區間時都需要計算Sum(即Sum[u]+=)
????? 剩下的都在代碼里面,無比美妙。
?
1 #define D double 2 #define lch u<<1 3 #include<stdio.h> 4 #define rch u<<1|1 5 #define M (l+r>>1) 6 #include<algorithm> 7 #define Up Sum[u]=Sum[lch]+Sum[rch] 8 #define go(i,a,b) for(int i=a;i<=b;i++) 9 #define Rar(a) a=lower_bound(T+1,T+n+1,a)-T 10 using namespace std; 11 const int N=250003;char c[N]; 12 int C,m,t,tt,kk,k,n,len[N],T[N],I,J; 13 D A[N*4],B[N*4],Sum[N*4],G[N*4],ratio,ans; 14 struct Q{int l,r;}q[N];struct P{int x,y;}p[N][7]; 15 D Cal(D a,int s,D rate){return 1.0*a+1.0*s*rate;} 16 void build(int u,int l,int r) 17 { 18 A[u]=B[u]=Sum[u]=G[u]=0;if(l+1==r)return; 19 build(lch,l,M);build(rch,M,r); 20 } 21 void Down(int u,int l,int r) 22 { 23 G[lch]+=G[u],G[rch]+=G[u];A[lch]+=A[u];B[rch]+=B[u]; 24 D Z=Cal(A[u],T[M]-T[l],G[u]); 25 Sum[lch]+=1.0*(A[u]+Z)*(T[M]-T[l])/2; 26 Sum[rch]+=1.0*(Z+B[u])*(T[r]-T[M])/2; 27 B[lch]+=Z,A[rch]+=Z,A[u]=B[u]=G[u]=0; 28 } 29 void update(int u,int l,int r,int L,int R,D a,D b) 30 { 31 if(L<=l&&r<=R){A[u]+=a;B[u]+=b;G[u]+=ratio; 32 Sum[u]+=1.0*(a+b)*(T[r]-T[l])/2;return;}Down(u,l,r); 33 if(R<=M)update(lch,l,M,L,R,a,b); 34 else if(L>=M)update(rch,M,r,L,R,a,b); 35 else{D Z=Cal(a,T[M]-T[L],ratio); 36 update(lch,l,M,L,M,a,Z);update(rch,M,r,M,R,Z,b);}Up; 37 } 38 void query(int u,int l,int r,int L,int R) 39 { 40 if(L<=l&&r<=R){ans+=Sum[u];return;};Down(u,l,r); 41 if(L<M)query(lch,l,M,L,R); 42 if(R>M)query(rch,M,r,L,R); 43 } 44 int main(){scanf("%d",&C);while(C--&&scanf("%d",&m)) 45 { 46 n=k=t=tt=kk=0; 47 go(i,1,m){scanf(" %c",&c[i]); 48 if(c[i]=='R'&&scanf("%d",&len[++t])) 49 go(j,1,len[t])scanf("%d%d",&p[t][j].x,&p[t][j].y),T[++n]=p[t][j].x; 50 if(c[i]=='Q'&&scanf("%d%d",&q[k].l,&q[++k].r))T[++n]=q[k].l,T[++n]=q[k].r;} 51 52 sort(T+1,T+n+1);n=unique(T+1,T+n+1)-T-1; 53 go(i,1,k)Rar(q[i].l),Rar(q[i].r);build(1,1,n); 54 go(i,1,t)go(j,1,len[i])Rar(p[i][j].x); 55 56 go(i,1,m)if(c[i]=='R'&&++tt)go(j,1,len[tt]) 57 { 58 I=j,J=j!=len[tt]?j+1:1; 59 int x1=p[tt][I].x,y1=p[tt][I].y,x2=p[tt][J].x,y2=p[tt][J].y; 60 if(x1<x2)y1*=-1,y2*=-1;else swap(x1,x2),swap(y1,y2); 61 ratio=1.0*(y2-y1)/(T[x2]-T[x1]);update(1,1,n,x1,x2,y1,y2); 62 } 63 else ++kk,ans=0,query(1,1,n,q[kk].l,q[kk].r),printf("%.3f\n",ans); 64 }return 0;}//Paul_Guderian?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
人們在卑微地倒立,可樓群卻都高高在上,
這是不能接受的事實,真實得就像夢境一樣。————汪峰《不能接受的事實》
轉載于:https://www.cnblogs.com/Paul-Guderian/p/7226112.html
總結
以上是生活随笔為你收集整理的【Rain in ACStar HDU-3340】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第四篇: python函数续
- 下一篇: [ACM] hdu 1285 确定比赛名