HDU 4419 Colourful Rectangle (線段樹掃描線),hdu4419
http://acm.hdu.edu.cn/showproblem.php?pid=4419
Colourful RectangleTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1272 Accepted Submission(s): 504
Problem DescriptionWe use Red, Green and Blue to make new colours. See the picture below:
Now give you n rectangles, the colour of them is red or green or blue. You have calculate the area of 7 different colour. (Note: A region may be covered by same colour several times, but it’s final colour depends on the kinds of different colour)
InputThe first line is an integer T(T <= 10), the number of test cases. The first line of each case contains a integer n (0 < n <= 10000), the number of rectangles. Then n lines follows. Each line start with a letter C(R means Red, G means Green, B means Blue) and four integers x1, y1, x2, y2(0 <= x1 < x2 < 10^9, 0 <= y1 < y2 < 10^9), the left-bottom's coordinate and the right-top's coordinate of a rectangle.
OutputFor each case, output a line "Case a:", a is the case number starting from 1,then 7 lines, each line contain a integer, the area of each colour. (Note: You should print the areas as the order: R, G, B, RG, RB, GB, RGB).
Sample Input
32R 0 0 2 2G 1 1 3 3 3R 0 0 4 4G 2 0 6 4B 0 2 6 63G 2 0 3 8G 1 0 6 1B 4 2 7 7
Sample Output
Case 1:3301000Case 2:44124444Case 3:012150000
Source2012 ACM/ICPC Asia Regional Hangzhou Online
題意:
給出R,G,B三種顏色的矩形的資料,求最後7種顏色(R,G,B,RG,RB,GB,RGB)的面積是多少?
分析:
顯然的線段樹掃描線,可以說這題非常考驗對線段樹掃描線的理解,如果只會用模板,恐怕很難做出來。
R,G,B三種顏色最後會產生7種顏色(無色不算),可以預見本題對編碼品質要求相當之高。
update()操作和一般的線段樹掃描線並無太大的不同,本題的精髓在於query()!
一般的簡單掃描線甚至不用寫query,因為根結點維護的區間覆蓋長度就是我們所需要的。但是本題需要從複雜的資訊中分出7種資訊!顯然根結點不能直接拿來用。
什麼樣的資訊是我們需要的呢?如果我們能確定一個區間(結點)的顏色,那麼該區間(結點)的資訊就是我們所需要的,否則我們應繼續查詢他的左右兒子。那麼如何確定一個區間(結點)的顏色呢?顯然如果R,G,B三色要麼能覆蓋整個區間或不在這個區間(見我代碼中的judge()函數),那麼該區間的顏色就能確定!然後再計算該區間(結點)的有用資訊(_plus()函數)。
如果僅僅如此,依然只是套模板的水平。本題與一般的線段樹掃描線的不同之處在於查詢時需要向下傳遞資訊(pushdown()函數)!為什嗎?比如在[3,7)區間內,R覆蓋了[3,7)這一條,G覆蓋了[5,7)這一條,當我們查詢到[3,7)時,並不能確定該區間(結點)的顏色,所以我們就要查詢它的左右兒子。但如果直接查詢,可能會丟失一部分我們需要的資訊,比如[3,7)的R,如果不下傳,這條線段的資訊就會被丟失!當然,我們查詢過後需要恢複下傳的資訊(recover()函數),否則會出現資訊的重複,導致最終無法把線段刪除乾淨。
/* * * Author : fcbruce * * Date : 2014-09-23 23:34:34 * */#include <cstdio>#include <iostream>#include <sstream>#include <cstdlib>#include <algorithm>#include <ctime>#include <cctype>#include <cmath>#include <string>#include <cstring>#include <stack>#include <queue>#include <list>#include <vector>#include <map>#include <set>#define sqr(x) ((x)*(x))#define LL long long#define itn int#define INF 0x3f3f3f3f#define PI 3.1415926535897932384626#define eps 1e-10#ifdef _WIN32 #define lld "%I64d"#else #define lld "%lld"#endif#define maxm #define maxn 10007using namespace std;long long l_r,l_g,l_b,l_rg,l_rb,l_gb,l_rgb;struct __seg{ int l,r,h,type,col; bool operator < (const __seg &s)const { return h<s.h; }}seg[maxn<<1];int X[maxn<<1];int sum_r[maxn<<2],sum_g[maxn<<2],sum_b[maxn<<2];int col_r[maxn<<2],col_g[maxn<<2],col_b[maxn<<2];inline voidpushup(int k,int l,int r){ int lc=k*2+1,rc=k*2+2; sum_r[k]=sum_g[k]=sum_b[k]=0; if (r-l>1) { sum_r[k]=sum_r[lc]+sum_r[rc]; sum_g[k]=sum_g[lc]+sum_g[rc]; sum_b[k]=sum_b[lc]+sum_b[rc]; } if (col_r[k]>0) sum_r[k]=X[r]-X[l]; if (col_g[k]>0) sum_g[k]=X[r]-X[l]; if (col_b[k]>0) sum_b[k]=X[r]-X[l];}voidupdate(int a,int b,int col,int v,int k,int l,int r){ if (b<=l || r<=a) return ; if (a<=l && r<=b) { switch(col) { case 1:col_r[k]+=v;break; case 2:col_g[k]+=v;break; case 3:col_b[k]+=v;break; } pushup(k,l,r); return ; } update(a,b,col,v,k*2+1,l,l+r>>1); update(a,b,col,v,k*2+2,l+r>>1,r); pushup(k,l,r);}inline booljudge(int k,int l,int r){ return (sum_r[k]==X[r]-X[l] || sum_r[k]==0) && (sum_g[k]==X[r]-X[l] || sum_g[k]==0) && (sum_b[k]==X[r]-X[l] || sum_b[k]==0);}inline void_plus(int k,int l,int r){ int type=0; if (sum_r[k]==X[r]-X[l]) type|=1<<0; if (sum_g[k]==X[r]-X[l]) type|=1<<1; if (sum_b[k]==X[r]-X[l]) type|=1<<2; switch (type) { case 0: break; case 1: l_r+=X[r]-X[l]; break; case 2: l_g+=X[r]-X[l]; break; case 3: l_rg+=X[r]-X[l]; break; case 4: l_b+=X[r]-X[l]; break; case 5: l_rb+=X[r]-X[l]; break; case 6: l_gb+=X[r]-X[l]; break; case 7: l_rgb+=X[r]-X[l]; break; }}inline voidpushdown(int k,int l,int r){ int lc=k*2+1,rc=k*2+2,m=l+r>>1; col_r[lc]+=col_r[k]; col_r[rc]+=col_r[k]; col_g[lc]+=col_g[k]; col_g[rc]+=col_g[k]; col_b[lc]+=col_b[k]; col_b[rc]+=col_b[k]; pushup(lc,l,m); pushup(rc,m,r);}inline voidrecover(int k,int l,int r){ int lc=k*2+1,rc=k*2+2,m=l+r>>1; col_r[lc]-=col_r[k]; col_r[rc]-=col_r[k]; col_g[lc]-=col_g[k]; col_g[rc]-=col_g[k]; col_b[lc]-=col_b[k]; col_b[rc]-=col_b[k]; pushup(lc,l,m); pushup(rc,m,r);}voidquery(int k,int l,int r){ if (judge(k,l,r)) { _plus(k,l,r); return ; } pushdown(k,l,r); query(k*2+1,l,l+r>>1); query(k*2+2,l+r>>1,r); recover(k,l,r);}intmain(){#ifdef FCBRUCE freopen("/home/fcbruce/code/t","r",stdin);#endif // FCBRUCE int T_T,__=0; scanf("%d",&T_T); while (T_T--) { int n; scanf("%d",&n); char _col; int x1,y1,x2,y2; int cnt=0,xn=0,col; for (int i=0;i<n;i++) { scanf(" %c%d%d%d%d",&_col,&x1,&y1,&x2,&y2); switch (_col) { case 'R': col=1; break; case 'G': col=2; break; case 'B': col=3; break; } seg[cnt++]=(__seg){x1,x2,y1,1,col}; seg[cnt++]=(__seg){x1,x2,y2,-1,col}; X[xn++]=x1; X[xn++]=x2; } sort(seg,seg+cnt); sort(X,X+xn); xn=unique(X,X+xn)-X; xn--; int last=0; long long a_r,a_g,a_b,a_rg,a_rb,a_gb,a_rgb; a_r=a_g=a_b=a_rg=a_rb=a_gb=a_rgb=0; memset(sum_r,0,sizeof sum_r); memset(sum_g,0,sizeof sum_g); memset(sum_b,0,sizeof sum_b); memset(col_r,0,sizeof col_r); memset(col_g,0,sizeof col_g); memset(col_b,0,sizeof col_b); for (int i=0;i<cnt;i++) { int a=lower_bound(X,X+xn,seg[i].l)-X; int b=lower_bound(X,X+xn,seg[i].r)-X; int col=seg[i].col,v=seg[i].type; l_r=l_g=l_b=l_rg=l_rb=l_gb=l_rgb=0; query(0,0,xn); a_r+=l_r*(seg[i].h-last); a_g+=l_g*(seg[i].h-last); a_b+=l_b*(seg[i].h-last); a_rg+=l_rg*(seg[i].h-last); a_rb+=l_rb*(seg[i].h-last); a_gb+=l_gb*(seg[i].h-last); a_rgb+=l_rgb*(seg[i].h-last); last=seg[i].h; update(a,b,col,v,0,0,xn); } printf("Case %d:\n",++__); printf(lld "\n",a_r); printf(lld "\n",a_g); printf(lld "\n",a_b); printf(lld "\n",a_rg); printf(lld "\n",a_rb); printf(lld "\n",a_gb); printf(lld "\n",a_rgb); } return 0;}