【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。

  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:
",++tcase);
131         swap(ans[3],ans[4]);
132         for(int i=1; i<=7; i++)  cout << ans[i] <<endl;
133     }
134     return 0;
135 }
View Code
原文地址:https://www.cnblogs.com/kane0526/p/3219163.html