Title Link: http://acm.hdu.edu.cn/viewcode.php?rid=32159923
Abstract: there are n rectangular blocks. These rectangular blocks have three different colors: R, G and B. the color of the final area is determined by the type of color in the area. What is the area of the seven colors of R, G, B, RG, Rb, GB and RGB.
Idea: in the previous example of area coverage, we use a one-dimensional array to maintain the length of the covered area. Because there are colors, we can open another one-dimensional representation of color. In addition, the color of the region is determined by the different types of colors, so the color judgment can be well used or calculated.
- (why don't you push down in the scan line) the example of scan line uses the data structure of line segment tree, but we query the whole every time and don't ask about a certain sub interval, so we don't need to push down.
AC1:
//cover[root][i] indicates the number of times the interval is covered by the ith color
#include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define lowbit(x) ( x&(-x) ) #define pi 3.141592653589793 #define e 2.718281828459045 #define INF 0x3f3f3f3f #define mid ((l + r)>>1) #define chl root<<1 #define chr root<<1|1 using namespace std; typedef unsigned long long ull; typedef long long LL; const int manx=2e4+10; int sum[manx<<3][8],cover[manx<<3][3],X[manx<<1],n; struct node { int y,lx,rx,color; int val; friend bool operator<(node a,node b) { return a.y<b.y; } }line[manx<<1]; void init() { memset(sum,0,sizeof(sum)); memset(cover,0,sizeof(cover)); } void eval(int root,int l,int r) { int white=X[r+1]-X[l],Color=0; for(int i=0; i<=2; i++) if(cover[root][i]) Color|=(1<<i); for(int i=1; i<=7; i++) sum[root][i]=0; for(int i=1; i<=7; i++) { sum[root][i|Color]+=sum[chl][i]+sum[chr][i]; white-=sum[chl][i]+sum[chr][i]; } if(Color) sum[root][Color]+=white; } void change(int root,int l,int r,int ll,int rr,int color,int val) { if(l==ll&&r==rr) { cover[root][color]+=val; eval(root,l,r); return; } if(rr<=mid) change(chl,l,mid,ll,rr,color,val); else if(ll>mid) change(chr,mid+1,r,ll,rr,color,val); else { change(chl,l,mid,ll,mid,color,val); change(chr,mid+1,r,mid+1,rr,color,val); } eval(root,l,r); } int main() { int t,x1,y1,x2,y2,Cas=0;; char str[2]; scanf("%d",&t); while(t--) { scanf("%d",&n); init(); for(int i=1; i<=n; i++) { int color; scanf("%s%d%d%d%d",str,&x1,&y1,&x2,&y2); if(str[0]=='R') color=2; else if(str[0]=='G') color=1; else color=0; line[2*i]=node{y1,x1,x2,color,1}; X[2*i]=x1; line[2*i-1]=node{y2,x1,x2,color,-1}; X[2*i-1]=x2; } sort(line+1,line+2*n+1); sort(X+1,X+2*n+1); int cnt=unique(X+1,X+2*n+1)-X-1; LL ans[8]= {0}; for(int i=1; i<2*n; i++) { int l=lower_bound(X+1,X+cnt+1,line[i].lx)-X; int r=lower_bound(X+1,X+cnt+1,line[i].rx)-X-1; int dy=line[i+1].y-line[i].y; change(1,1,cnt,l,r,line[i].color,line[i].val); for(int i=1; i<=7; i++) ans[i]+=(LL)sum[1][i]*(LL)dy; } printf("Case %d:\n",++Cas); printf("%lld\n%lld\n%lld\n%lld\n%lld\n%lld\n%lld\n",ans[4],ans[2],ans[1],ans[6],ans[5],ans[3],ans[7]); } return 0; }
AC2:
Record how you felt when you were looking for bug s.. Really MLE to cry.
Originally, I felt happy to find the scan line. Later, I reduced the second dimension of sum to 7 (sum []), and then tried to store the data in the vector. The result was super memory. What's important is that I found another sand carving error later: I wrote the cnt in the lower bound as 2*n
Later, I found that my previous thinking was a little complicated: cover can only record the times of three colors, and judge the final color when retrospectively updating the length of coverage area, so the operation of cover will be very simple
//cover[root][i]=1 means the interval is covered by I colors
#include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define lowbit(x) ( x&(-x) ) #define pi 3.141592653589793 #define e 2.718281828459045 #define INF 0x3f3f3f3f #define mid ((l + r)>>1) #define chl root<<1 #define chr root<<1|1 using namespace std; typedef unsigned long long ull; typedef long long LL; const int manx=2e4+10; int sum[manx<<3][8],cover[manx<<3][8],X[manx<<1],n; struct node { int y,lx,rx,color; int val; friend bool operator<(node a,node b) { return a.y<b.y; } }line[manx<<1]; void init() { memset(sum,0,sizeof(sum)); memset(cover,0,sizeof(cover)); //for(int i=1; i<=(n<<4); i++) // cover[i][0]=1; } void eval(int root,int l,int r) { int white=X[r+1]-X[l],Color=0; for(int i=1; i<=7; i++) if(cover[root][i]) { Color=max(Color,i); } for(int i=1; i<=7; i++) sum[root][i]=0; for(int i=1; i<=7; i++) { sum[root][i|Color]+=sum[chl][i]+sum[chr][i]; white-=sum[chl][i]+sum[chr][i]; } if(Color) sum[root][Color]+=white; } void change(int root,int l,int r,int ll,int rr,int color,int val) { if(l==ll&&r==rr) { if(val==1) { int flag=0; for(int i=1; i<=7; i++) if(cover[root][i]) { flag=max(flag,i); } cover[root][(1<<color)]++; if(flag&&flag!=(1<<color)) cover[root][flag|(1<<color)]=1; } else { cover[root][(1<<color)]--; if(!cover[root][(1<<color)]) for(int i=1; i<=7; i++) if((i&(1<<color))&&cover[root][i])//color is required { cover[root][i]=0; int temp=i-(1<<color); if(temp!=1&&temp!=2&&temp!=4) cover[root][temp]=1; } } eval(root,l,r); return; } if(rr<=mid) change(chl,l,mid,ll,rr,color,val); else if(ll>mid) change(chr,mid+1,r,ll,rr,color,val); else { change(chl,l,mid,ll,mid,color,val); change(chr,mid+1,r,mid+1,rr,color,val); } eval(root,l,r); } int main() { int t,x1,y1,x2,y2,Cas=0;; char str[2]; scanf("%d",&t); while(t--) { scanf("%d",&n); init(); for(int i=1; i<=n; i++) { int color; scanf("%s%d%d%d%d",str,&x1,&y1,&x2,&y2); if(str[0]=='R') color=2; else if(str[0]=='G') color=1; else color=0; line[2*i]=node{y1,x1,x2,color,1}; X[2*i]=x1; line[2*i-1]=node{y2,x1,x2,color,-1}; X[2*i-1]=x2; } sort(line+1,line+2*n+1); sort(X+1,X+2*n+1); int cnt=unique(X+1,X+2*n+1)-X-1; LL ans[8]= {0}; for(int i=1; i<2*n; i++) { int l=lower_bound(X+1,X+cnt+1,line[i].lx)-X; int r=lower_bound(X+1,X+cnt+1,line[i].rx)-X-1; int dy=line[i+1].y-line[i].y; change(1,1,cnt,l,r,line[i].color,line[i].val); for(int i=1; i<=7; i++) ans[i]+=(LL)sum[1][i]*(LL)dy; } printf("Case %d:\n",++Cas); printf("%lld\n%lld\n%lld\n%lld\n%lld\n%lld\n%lld\n",ans[4],ans[2],ans[1],ans[6],ans[5],ans[3],ans[7]); } return 0; }