【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:\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 }
View Code

 

你可能感兴趣的:(HDU)