求http://acm.hdu.edu.cn/showproblem.php?pid=4419
求不同颜色的覆盖面积。
#include<cstring> #include<cstdio> #include<algorithm> using namespace std; typedef __int64 lld; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int maxn = 65537; lld sum[maxn][1<<3]; int x[20010]; int cover[maxn][4]; struct seg { int l,r,h,flag; seg(){} seg(int _l,int _r,int _h,int _flag):l(_l),r(_r),h(_h),flag(_flag){} bool operator < (const seg &cmp) const { if(h!=cmp.h) return h<cmp.h; return flag<cmp.flag; } }ss[20010]; inline void pushup(int rt,int l,int r) { int s=0,i;// 有cover表示这个区间被完全覆盖了, 不能由子区间来改变 for(i=1;i<=3;i++) if(cover[rt][i]) s|=1<<(i-1);//和子区间没关系的状态 for(i=0;i<8;i++) sum[rt][i]=0; if(l==r) { sum[rt][s]=x[r+1]-x[l]; } else { for(i=0;i<8;i++) /* keys */ sum[rt][i|s] += sum[rt<<1][i] + sum[rt<<1|1][i]; } } void update(int L,int R,int c,int l,int r,int rt) { if(L <= l && r <= R){ if(c>0) cover[rt][c]++; else cover[rt][-c]--; pushup(rt,l,r); return ; } int m=l+r>>1; if(L <= m) update(L,R,c,lson); if(R > m) update(L,R,c,rson); pushup(rt,l,r); } void build(int l,int r,int rt) { int i; for(i=1;i<=3;i++) cover[rt][i]=0; for(i=1;i<8;i++) sum[rt][i]=0; sum[rt][0]=x[r+1]-x[l]; if(l==r) { return ;} int m=l+r>>1; build(lson); build(rson); } lld ans[1<<3]; int main() { char col[5]; int n,i,j,tot,ca=1,t,flag; int x1,y1,x2,y2; scanf("%d",&t); while(t--) { scanf("%d",&n); for(i=1,tot=0;i<=n;i++) { scanf("%s%d%d%d%d",col,&x1,&y1,&x2,&y2); x[tot]=x1; if(col[0]=='R') flag=1; else if(col[0]=='G') flag=2; else flag=3; ss[tot++]=seg(x1,x2,y1,flag); x[tot]=x2; ss[tot++]=seg(x1,x2,y2,-flag); } sort(x,x+tot); sort(ss,ss+tot); n=unique(x,x+tot)-x; build(0,n-2,1); memset(ans,0,sizeof(ans)); for(i=0;i<tot-1;i++) { int left=lower_bound(x,x+n,ss[i].l)-x; int right=lower_bound(x,x+n,ss[i].r)-x-1; update(left,right,ss[i].flag,0,n-2,1); for(j=1;j<8;j++) ans[j]+=sum[1][j]*(ss[i+1].h-ss[i].h); } printf("Case %d:\n",ca++); printf("%I64d\n%I64d\n%I64d\n%I64d\n%I64d\n%I64d\n%I64d\n",ans[1],ans[2],ans[4],ans[3],ans[5],ans[6],ans[7]); } return 0; }