【HDU4419 Colourful Rectangle】 线段树面积并
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4419
题目大意:给你n个矩形,每个矩形都有一种颜色,矩形覆盖会出现另外一种颜色,问你所有矩形中不同的颜色各出现的面积。
解题思路:开始一直只用一个标记,1,2,4,处理来处理去发现一直搞不来。最后用两个标记,一个存+1,-1,和普通面积并类似,另外开一个三位的标记数组,0位表示'R',1位表示‘G’,2位表示‘B’,sum数组要开8个状态(和8颗线段树思想类似),每次处理到当前节点时,该节点所有sum值清0(叶子节点的sum[u][0]表示的就是区间长度,要进行预先建树),根据自己当前的状态再由孩子传递数值上来进行更新操作。这题很巧妙的用到了或运算,表示我开始没想到,发散性思维 O.O。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 7 #define lz 2*u,l,mid 8 #define rz 2*u+1,mid+1,r 9 typedef long long lld; 10 const int maxn=22222; 11 lld sum[4*maxn][10]; 12 int flag[4*maxn][3]; 13 int X[maxn]; 14 lld ans[8]; 15 16 struct Node 17 { 18 int lx, rx, y; 19 int c, s; 20 Node() {}; 21 Node(int lx_, int rx_, int y_, int c_, int s_) 22 { 23 lx=lx_, rx=rx_, y=y_, c=c_, s=s_; 24 } 25 bool operator <(const Node &S) const 26 { 27 if(y==S.y) return s>S.s; 28 else return y<S.y; 29 } 30 } line[maxn]; 31 32 int find(int tmp, int n) 33 { 34 int l=1, r=n, mid; 35 while(l<=r) 36 { 37 mid=(l+r)>>1; 38 if(X[mid]==tmp) return mid; 39 else if(X[mid]<tmp) l=mid+1; 40 else r=mid-1; 41 } 42 } 43 44 void push_up(int u, int l, int r) 45 { 46 int state=0; 47 for(int i=0; i<=2; i++) if(flag[u][i]) state|=(1<<i); 48 memset(sum[u],0,sizeof(sum[u])); 49 if(l==r) sum[u][state]=X[r+1]-X[l]; 50 else 51 { 52 for(int i=0; i<8; i++) 53 sum[u][state|i]+=sum[2*u][i]+sum[2*u+1][i]; 54 } 55 } 56 57 void build(int u, int l, int r) 58 { 59 memset(sum[u],0,sizeof(sum[u])); 60 memset(flag[u],0,sizeof(flag[u])); 61 if(l==r) 62 { 63 sum[u][0]=X[r+1]-X[l]; 64 return ; 65 } 66 int mid=(l+r)>>1; 67 build(lz); 68 build(rz); 69 sum[u][0]=sum[2*u][0]+sum[2*u+1][0]; 70 } 71 72 void Update(int u, int l, int r, int tl, int tr, int s, int c) 73 { 74 if(tl>tr) return ; 75 if(tl<=l&&r<=tr) 76 { 77 flag[u][s]+=c; 78 push_up(u,l,r); 79 return ; 80 } 81 int mid=(l+r)>>1; 82 if(tr<=mid) Update(lz,tl,tr,s,c); 83 else if(tl>mid) Update(rz,tl,tr,s,c); 84 else 85 { 86 Update(lz,tl,mid,s,c); 87 Update(rz,mid+1,tr,s,c); 88 } 89 push_up(u,l,r); 90 } 91 92 int main() 93 { 94 int n, T, tcase=0; 95 cin >> T; 96 while(T--) 97 { 98 cin >> n; 99 int num=0; 100 memset(flag,0,sizeof(flag)); 101 memset(sum,0,sizeof(sum)); 102 memset(ans,0,sizeof(ans)); 103 for(int i=0; i<n; i++) 104 { 105 int x1,x2,y1,y2, s; 106 char ch[2]; 107 scanf("%s%d%d%d%d",ch,&x1,&y1,&x2,&y2); 108 if(ch[0]=='R') s=0; 109 else if(ch[0]=='G') s=1; 110 else s=2; 111 line[++num]=Node(x1,x2,y1,s,1); 112 X[num]=x1; 113 line[++num]=Node(x1,x2,y2,s,-1); 114 X[num]=x2; 115 } 116 sort(X+1,X+num+1); 117 sort(line+1,line+num+1); 118 int k=1; 119 for(int i=2; i<=num; i++) 120 if(X[i]!=X[i+1]) X[++k]=X[i]; 121 build(1,1,k); 122 for(int i=1; i<num; i++) 123 { 124 int l=find(line[i].lx,k); 125 int r=find(line[i].rx,k)-1; 126 Update(1,1,k,l,r,line[i].c,line[i].s); 127 for(int j=1; j<=7; j++) 128 ans[j]+=sum[1][j]*(line[i+1].y-line[i].y); 129 } 130 printf("Case %d:\n",++tcase); 131 swap(ans[3],ans[4]); 132 for(int i=1; i<=7; i++) cout << ans[i] <<endl; 133 } 134 return 0; 135 }