hdu4533 威威猫系列故事——晒被子
生活還要繼續,太陽也照常升起,今天,威威貓在第一象限曬了N條矩形的被子,被子的每條邊都和坐標軸平行,不同被子的某些部分可能會疊在一起。這時候,在原點處突然發了場洪水,時間t的時候,洪水會蔓延到( t, t ),即左下角為( 0, 0 ) ,右上角為( t, t )的矩形內都有水。
悲劇的威威貓想知道,在時間t1, t2, t3 ... tx 的時候,他有多少面積的被子是濕的?
Input 輸入數據首先包含一個正整數T,表示有T組測試數據;
每組數據的第一行首先是一個整數N,表示有N條被子;
接下來N行,每行包含四個整數x1, y1, x2, y2,代表一條被子的左下角和右上角的坐標;
然后接下來一行輸入一個整數x,表示有x次詢問;
再接下來x行,輸入x個嚴格單調遞增的整數,每行一個,表示威威貓想知道的時間ti。
[Technical Specification]
T <= 5
0 < N <= 20000
1 <= x1 < x2 <= 200000
1 <= y1 < y2 <= 200000
1 <= x <= 20000
1 <= ti <= 200000 (1 <= i <= x )
Output 對于每次詢問,請計算并輸出ti時有多少面積的被子是濕的,每個輸出占一行。
Sample Input 1 2 1 1 3 3 2 2 4 4 5 1 2 3 4 5
Sample Output 0 1 5 8 8
這題里求的面積是各個矩形的面積和,并不是矩形面積的并,即相互不影響,因為對于各個時段,矩形的面積都可以用A*t^2+B*t+C表示,所以我們可以用樹狀數組或者線段樹分別維護A,B,C,每次讀入一個矩形,就記錄它對不同時間段t的影響,然后把相應的系數加到線段樹中。
當一個矩形讀入時(左下角坐標(x1,y1),右上角坐標(x2,y2)),有四種影響情況:
1.0~max(x1,y1) 這個時期因為t時間形成的矩形在該矩形下面,對面積沒有影響,所以不用考慮。
2.如果存在t時間形成的矩形部分覆蓋該矩形,但沒有碰到或者超過該矩形的上邊或者右邊,那么要同時更新A,B,C,表達式為(t-x1)*(t-y1)。這里的判斷表達式為如果(max(x1,y1)<min(x2,y2)),則更新max(x1,y1)~min(x2,y2)。
3.t時間內形成的矩形恰好碰到或者越過右邊或上邊的一條,即這段時間內的矩形面積變化中(x2-x1)或(y2-y1)為常數,那么要更新,注意,這里更新的時候要分類討論,具體看代碼。
4.max(x2,y2)~maxn,這個時期因為t時間形成的矩形已經完全覆蓋矩形,所以要更新C,加上面積常數。
寫線段樹的時候注意,三個變量要一起存,不能開三個線段樹,會超內存的。
線段樹代碼:
#include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<string> #include<algorithm> using namespace std; #define ll __int64 #define maxn 200050 ll A,B,C; ll a[10]; struct node{ll l,r,cnt1,cnt2,cnt3,flag; }b[4*maxn];void build(ll l,ll r,ll i) {ll mid;b[i].l=l;b[i].r=r;b[i].cnt1=b[i].cnt2=b[i].cnt3=0;b[i].flag=1;if(l==r)return;mid=(l+r)/2;build(l,mid,i*2);build(mid+1,r,i*2+1); } void update(ll l,ll r,ll a[],ll i) {ll mid;if(b[i].l==l && b[i].r==r){b[i].cnt1+=a[1];b[i].cnt2+=a[2];b[i].cnt3+=a[3];return;}mid=(b[i].l+b[i].r)/2;if(r<=mid)update(l,r,a,i*2);else if(l>mid)update(l,r,a,i*2+1);else{update(l,mid,a,i*2);update(mid+1,r,a,i*2+1);} }void question(ll id,ll i) {ll mid;if(b[i].l==id && b[i].r==id){A=b[i].cnt1;B=b[i].cnt2;C=b[i].cnt3;return;}if(b[i].cnt1){b[i*2].cnt1+=b[i].cnt1;b[i*2+1].cnt1+=b[i].cnt1;b[i].cnt1=0;}if(b[i].cnt2){b[i*2].cnt2+=b[i].cnt2;b[i*2+1].cnt2+=b[i].cnt2;b[i].cnt2=0;}if(b[i].cnt3){b[i*2].cnt3+=b[i].cnt3;b[i*2+1].cnt3+=b[i].cnt3;b[i].cnt3=0;}mid=(b[i].l+b[i].r)/2;if(id<=mid)question(id,i*2);else question(id,i*2+1); }int main() {ll i,j,x1,x2,y1,y2,t,t1,t2;int T,n,m;scanf("%d",&T);while(T--){scanf("%d",&n);build(1,maxn,1);for(i=1;i<=n;i++){scanf("%I64d%I64d%I64d%I64d",&x1,&y1,&x2,&y2);if(max(x1,y1)<min(x2,y2)){a[1]=1;a[2]=-(x1+y1);a[3]=x1*y1;update(max(x1,y1),min(x2,y2)-1,a,1);}if(x2<y2){a[1]=0;a[2]=-x1+x2;a[3]=y1*(x1-x2);update(max(x2,y1),y2-1,a,1); }if(y2<x2){a[1]=0;a[2]=-y1+y2;a[3]=x1*(y1-y2);update(max(y2,x1),x2-1,a,1); }a[1]=0;a[2]=0;a[3]=(x2-x1)*(y2-y1);update(max(x2,y2),maxn,a,1);}scanf("%d",&m);for(i=1;i<=m;i++){scanf("%I64d",&t);A=B=C=0;question(t,1);printf("%I64d\n",A*t*t+B*t+C);}}return 0; }
#include <iostream> #include <cstdio> #include <cstring> #define maxn 200010 #define ll __int64 using namespace std; ll max(ll a,ll b){return a>b?a:b; } ll min(ll a,ll b){return a<b?a:b; }struct segment{ll b[maxn],ans;void clear(){memset(b,0,sizeof(b));}int lowbit(ll x){return x&(-x);}void update(ll pos,ll num){while(pos<=maxn){b[pos]+=num;pos+=lowbit(pos);}}ll getsum(ll pos){ans=0;while(pos>0){ans+=b[pos];pos-=lowbit(pos);}return ans;} }A,B,C;void fun(ll l,ll r,ll num1,ll num2,ll num3){A.update(l,num1);A.update(r+1,-num1);B.update(l,num2);B.update(r+1,-num2);C.update(l,num3);C.update(r+1,-num3); }int main() { int t; scanf("%d",&t); while(t--) { A.clear(); B.clear(); C.clear(); int n,m; scanf("%d",&n); for(int i=0;i<n;i++) { ll x1,y1,x2,y2; scanf("%I64d%I64d%I64d%I64d",&x1,&y1,&x2,&y2); if(max(x1,y1)<min(x2,y2)) fun(max(x1,y1),min(x2,y2),1,-(x1+y1),x1*y1); if(x2<y2) fun(max(x2,y1)+1,y2,0,-x1+x2,y1*(x1-x2)); if(y2<x2) fun(max(y2,x1)+1,x2,0,-y1+y2,x1*(y1-y2)); fun(max(x2,y2)+1,maxn,0,0,(x2-x1)*(y2-y1)); } scanf("%d",&m); while(m--) { ll t; scanf("%I64d",&t); ll ans=0; ans+=A.getsum(t)*t*t; ans+=B.getsum(t)*t; ans+=C.getsum(t); printf("%I64d\n",ans); } } return 0; }
轉載于:https://www.cnblogs.com/herumw/p/9464703.html
總結
以上是生活随笔為你收集整理的hdu4533 威威猫系列故事——晒被子的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C#中var类型
- 下一篇: 4.SharePoint的权限