题意:给定n个矩形,每个矩形有一种颜色,RGB中的一种。相交的部分可能为RG,RB,GB,RGB,问这n个矩形覆盖的面积中,7种颜色的面积分别为多少
思路:把x轴离散化做扫描线,线段树维护一个扫描区间竖直方向上的各种颜色的长度
刚开始想着直接维护每段区间上7种颜色的长,但是写到删除的时候发现没办法删除,
然后想了半天,发现:需要的只是整个区间的颜色长度信息,所以,对于颜色更新来说,不需要往下传标记,只需要维护上push_up就好了
所以添加删除就简单多了。
用 1 2 4 分别代表R G B 然后RG RB GB RGB 分别为3 5 6 7
没有颜色用0来表示
线段树每个节点记录下R,G,B 分别被覆盖了几次。
往上更新的时候只需要考虑左右儿子的线段覆盖了父亲的颜色后总的区间各个颜色长度为多少即可,注意单个长度的情况。
一直卡在64位类型的转化上,全都换成64位的不对,最后强制转化才对的。。
// 略长,但是比较可看, /// R:1 G:2 B:4 int hash[256]; struct scanline { int x,y1,y2; int col; int flag ; void set(int _x,int _y1,int _y2,int _col ,int _flag) { x = _x ; y1 = _y1 ; y2 = _y2 ; col = _col ; flag = _flag ; } }; bool cmp(scanline t1, scanline t2) { if(t1.x != t2.x)return t1.x < t2.x; return t1.flag > t2.flag; } scanline sc[maxn * 3]; int y[maxn * 3 ]; int num; struct node { int l,r; int ml,mr; int c1,c2,c4; int l1[8]; int mid() { return (l + r) /2; } int len() { return mr - ml; } }; long long area[10]; node tt[maxn * 3 * 3 ]; int nn ; void init(int root ) { memset(tt[root].l1,0,sizeof(tt[root].l1)); tt[root].c1 = tt[root].c2 = tt[root].c4 = 0 ; } void update1(int root ) { // printf("root = %d ",root); int col = 0 ; if(tt[root].c1 > 0 ) col = col|1; if(tt[root].c2 > 0 ) col = col|2; if(tt[root].c4 > 0 ) col = col|4; //printf("update1: col = %d ",col); memset(tt[root].l1,0,sizeof(tt[root].l1)); if(tt[root].r - tt[root].l == 1 ) { tt[root].l1[col] = tt[root].len(); } else if(col == 0 ) { for(int i = 0 ;i < 8 ;i ++ ) tt[root].l1[i] = tt[root*2].l1[i] + tt[root*2+1].l1[i]; } else if(col != 0 ) { for(int i = 0; i < 8; i ++ ) tt[root].l1[i|col] += (tt[root*2].l1[i] + tt[root*2+1].l1[i]); } return ; } void build(int root ,int l,int r ) { tt[root].l = l ; tt[root].r = r; tt[root].ml = y[l-1]; tt[root].mr = y[r-1]; init(root); tt[root].l1[0] = tt[root].len(); if( l + 1 >= r ) return ; int mid = tt[root].mid(); build(root * 2 , l , mid ); build(root * 2 + 1 , mid , r); return ; } void upd(int root ,int l,int r ,int col,int val ) { if(l <= tt[root].ml && tt[root].mr <= r) { if(col == 1 ) tt[root].c1 += val ; else if(col == 2 ) tt[root].c2 += val ; else if(col == 4 ) tt[root].c4 += val ; update1(root); return ; } if(r <= tt[root * 2 ].mr ) upd(root * 2 , l,r,col,val); else if(l >= tt[root * 2 + 1].ml ) upd(root * 2 + 1, l,r ,col,val); else { upd(root * 2 ,l,r,col,val); upd(root * 2 + 1 ,l,r,col,val); } update1(root); } int main() { int x1,x2,y1,y2; memset(hash,0,sizeof(hash)); hash['R'] = 1 ; hash['G'] = 2 ; hash['B'] = 4 ; int cas,ccc; ccc = 0; char str[5]; scanf("%d",&cas); int n ; while(cas -- ) { num = 0 ; scanf("%d",&n); for(int i = 1 ; i <= n ; i++ ) { scanf("%s %d %d %d %d",str,&x1,&y1,&x2,&y2); y[num] = y1 ; num ++ ; sc[num].set(x1,y1,y2,hash[str[0]],1); y[num] = y2 ; num ++ ; sc[num].set(x2,y1,y2,hash[str[0]],-1); } int n1; n1 = num ; sort(y ,y + num); nn = unique(y , y + num) - y; build(1,1,nn); sort(sc + 1 , sc + n1 + 1,cmp); memset(area,0,sizeof(area)); int i ; i = 1 ; while(i <= n1 ) { int j = i ; while(sc[j].x == sc[i].x && j <= n1 ) { upd(1,sc[j].y1,sc[j].y2,sc[j].col,sc[j].flag); j ++ ; } int len ; if(j == n1 + 1 ) len = 0 ; else len = sc[j].x - sc[i].x; update1(1); for(int k = 1 ; k < 8 ; k ++ ) area[k] = area[k] + (long long)(tt[1].l1[k]) * (long long)(len) ; i = j ; } printf("Case %d: ",++ccc); printf("%I64d %I64d %I64d %I64d %I64d %I64d %I64d ",area[1],area[2],area[4],area[3],area[5],area[6],area[7]); ///cout<<area[1]<<endl<<area[2]<<endl<<area[4]<<endl<<area[3]<<endl<<area[5]<<endl<<area[6]<<endl<<area[7]<<endl; } return 0 ; }