/*
和胡浩大牛写的hdu 1255题的大体思路差不多,先把矩形线段化,在一个数轴上覆盖,再枚举另一个数轴求面积(再枚举之前先排好序),只不过这题的状态比较多,要把Pushup函数改一下,这里不仅仅是处理覆盖一次和多次的问题了,还要考虑颜色的重叠问题,处理的时候有点像容斥,用二进制的1,2,4表示r,g,b这样便于处理,最后覆盖过程就大体差不多了;
代码如下:
*/
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int N=20000; const int t[8]={0,1,2,4,3,5,6,7}; struct tree{__int64 n[8];} sum[N<<2]; struct seg{ __int64 x1,x2,h,v; bool operator <(const seg &tem) const {return h<tem.h;} } line[N]; __int64 X[N]; __int64 cnt[N<<2][4]; void Set(int k,__int64 x1,__int64 y1,__int64 x2,__int64 y2,int v) { X[k]=x1; X[k+1]=x2; line[k].x1=x1;line[k].x2=x2;line[k].h=y1;line[k].v=v; line[k+1].x1=x1;line[k+1].x2=x2;line[k+1].h=y2;line[k+1].v=-v; } void Pushup(int i,int l,int r) { int j,R=1,G=2,B=4,k=0; __int64 tem; if(cnt[i][1]>0)k|=R; if(cnt[i][2]>0)k|=G; if(cnt[i][3]>0)k|=B; memset(sum[i].n,0,sizeof(sum[i].n)); if(k) { sum[i].n[k]=X[r+1]-X[l]; if(l==r)return; for(j=1;j<=7;j++)//主要思路在这个循环,这里参考了各个大牛的思路,很简洁,很漂亮; { if((k|j)!=k){ tem=sum[i<<1].n[j]+sum[i<<1|1].n[j]; sum[i].n[k]-=tem; sum[i].n[k|j]+=tem; } } } else if(l<r) for(j=1;j<=7;j++)sum[i].n[j]=sum[i<<1].n[j]+sum[i<<1|1].n[j]; } void update(int i,int l,int r,int a,int b,int v) { if(l==a&&r==b) { if(v<0) --cnt[i][-v]; else ++cnt[i][v]; Pushup(i,l,r); return ; } int mid=(l+r)>>1; if(b<=mid) update(i<<1,l,mid,a,b,v); else if(b>mid&&a<=mid) { update(i<<1,l,mid,a,mid,v); update(i<<1|1,mid+1,r,mid+1,b,v); } else update(i<<1|1,mid+1,r,a,b,v); Pushup(i,l,r); } int Bin(int l,int r,__int64 v) { int mid; while(l<=r) { mid=(l+r)>>1; if(X[mid]==v) return mid; else if(X[mid]>v) r=mid-1; else l=mid+1; } return -1; } int main() { char op[5]; int cas,cass,n,k,m,i,j; __int64 x1,x2,y1,y2,ans[8]; scanf("%d",&cass); for(cas=1;cas<=cass;cas++) { m=0; scanf("%d",&n); while(n--) { scanf("%s%I64d%I64d%I64d%I64d",op,&x1,&y1,&x2,&y2); if(op[0]=='R')k=1; if(op[0]=='G')k=2; if(op[0]=='B')k=3; Set(m,x1,y1,x2,y2,k); m+=2; } sort(X,X+m); sort(line,line+m); for(i=k=1;i<m;i++) if(X[i-1]<X[i]) X[k++]=X[i]; int l,r; memset(ans,0,sizeof(ans)); memset(cnt,0,sizeof(cnt)); memset(sum,0,sizeof(sum)); for(i=0;i<m-1;i++) { l=Bin(0,k-1,line[i].x1); r=Bin(0,k-1,line[i].x2)-1; if(l<=r)update(1,0,k-1,l,r,line[i].v); for(j=1;j<=7;j++) ans[j]+=sum[1].n[j]*(line[i+1].h-line[i].h); } printf("Case %d:\n",cas); for(i=1;i<=7;i++) printf("%I64d\n",ans[t[i]]); } return 0; } /* 10 2 G 0 0 2 2 B 1 1 3 3 */