->题目请戳这里<-
题目大意:在二维平面内给n个矩形,矩形有3种颜色,不同颜色相交的部分就产生了不同的颜色,一共就有7种颜色。对于每个区域内的颜色与某中颜色覆盖的次数无关,只与覆盖的颜色种类有关,求最后这n个矩形相交产生7种颜色的面积。
题目分析:这题和这道hdu1255思路基本是一样的,不过1255求的是重复覆盖2+次面积并,情况简单些,这里3种颜色一交就会产生7种情况,分析就稍微复杂一点点。
下面简单分析下:
对于线段树节点的定义:我选择用2个数组保存信息,数组col表示当前节点被覆盖的颜色种类,col[1]表示覆盖颜色R,col[2]表示覆盖了颜色G,col[3]表示覆盖了颜色B;len表示当前区间7种颜色下的有效长度,len[1] - len[7]分别表示当前区间下R,G,B,RG,RB,GB,RGB这7种颜色的有效长度。
对于每个区域,如果当前区域是叶子节点,即不能再分成子区间了,那么这个区域只能有7种情况中的一种。直接根据覆盖的情况确定当前区间的有效长度。
如果当前区间不是叶子节点,那么就考虑当前区间的颜色覆盖情况:
1:如果当前区间3种颜色全部覆盖,那么这整个区间都是RGB,计算len[7];
2:如果当前区间覆盖了2种颜色,假设覆盖了RG,那么这个区间只可能有2种颜色,RGB和RG,至少是RG,那么先算RGB,当前区间的RGB就是左右子区间的RGB+左右子区间的B(想一想,为什么),当前区间的RG就是当前整个区间长度-RGB长度,其他2种当前区间恰好被2种颜色同时覆盖的情况类似;
3:如果当前区间恰好只覆盖了一种颜色,假设覆盖了R,那么当前区间颜色覆盖情况就有4种:R,RG,RB,RGB,先算RGB,长度就是左右子区间的RGB和左右子区间的GB长度之和,RG的长度就是左右子区间能提供G的长度之和,即左右子区间的G,RG,RB同理,R的长度就是剩下的长度了,这里一定要想清楚,其他还有2种情况也是类似的。
4:如果当前区间没有颜色恰好覆盖,那么直接将左右子区间的各种颜色相加即可。
废话就这么多了,详情请见代码:
#include <iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 10005; char color[3]; int hash[N<<1]; __int64 ans[10]; struct node { int x,y1,y2; int flag,c; }line[N<<1]; struct nd { int col[4]; __int64 len[8]; }tree[N<<4]; int cmp(struct node a,struct node b) { return a.x < b.x; } void build(int num,int s,int e) { memset(tree[num].col,0,sizeof(tree[num].col)); memset(tree[num].len,0,sizeof(tree[num].len)); if(s == e) return; int mid = (s + e)>>1; build(num<<1,s,mid); build(num<<1|1,mid + 1,e); } void cal_len(int num,int s,int e) { memset(tree[num].len,0,sizeof(tree[num].len)); if(tree[num].col[1] && tree[num].col[2] && tree[num].col[3]) { tree[num].len[7] = hash[e + 1] - hash[s]; return; } if(tree[num].col[1] && tree[num].col[2]) { tree[num].len[7] = tree[num<<1].len[7] + tree[num<<1|1].len[7] + tree[num<<1].len[3] + tree[num<<1|1].len[3]; tree[num].len[7] += (tree[num<<1].len[5] + tree[num<<1|1].len[5] + tree[num<<1].len[6] + tree[num<<1|1].len[6]); tree[num].len[4] = hash[e + 1] - hash[s] - tree[num].len[7]; return; } if(tree[num].col[1] && tree[num].col[3]) { tree[num].len[7] = tree[num<<1].len[7] + tree[num<<1|1].len[7] + tree[num<<1].len[2] + tree[num<<1|1].len[2]; tree[num].len[7] += (tree[num<<1].len[4] + tree[num<<1|1].len[4] + tree[num<<1].len[6] + tree[num<<1|1].len[6]); tree[num].len[5] = hash[e + 1] - hash[s] - tree[num].len[7]; return; } if(tree[num].col[2] && tree[num].col[3]) { tree[num].len[7] = tree[num<<1].len[7] + tree[num<<1|1].len[7] + tree[num<<1].len[1] + tree[num<<1|1].len[1]; tree[num].len[7] += (tree[num<<1].len[5] + tree[num<<1|1].len[5] + tree[num<<1].len[4] + tree[num<<1|1].len[4]); tree[num].len[6] = hash[e + 1] - hash[s] - tree[num].len[7]; return; } if(tree[num].col[1]) { tree[num].len[7] = tree[num<<1].len[7] + tree[num<<1|1].len[7] + tree[num<<1].len[6] + tree[num<<1|1].len[6]; tree[num].len[5] = tree[num<<1].len[5] + tree[num<<1|1].len[5] + tree[num<<1].len[3] + tree[num<<1|1].len[3]; tree[num].len[4] = tree[num<<1].len[4] + tree[num<<1|1].len[4] + tree[num<<1].len[2] + tree[num<<1|1].len[2]; tree[num].len[1] = hash[e + 1] - hash[s] - tree[num].len[4] - tree[num].len[5] - tree[num].len[7]; return; } if(tree[num].col[2]) { tree[num].len[7] = tree[num<<1].len[7] + tree[num<<1|1].len[7] + tree[num<<1].len[5] + tree[num<<1|1].len[5]; tree[num].len[6] = tree[num<<1].len[6] + tree[num<<1|1].len[6] + tree[num<<1].len[3] + tree[num<<1|1].len[3]; tree[num].len[4] = tree[num<<1].len[4] + tree[num<<1|1].len[4] + tree[num<<1].len[1] + tree[num<<1|1].len[1]; tree[num].len[2] = hash[e + 1] - hash[s] - tree[num].len[4] - tree[num].len[6] - tree[num].len[7]; return; } if(tree[num].col[3]) { tree[num].len[7] = tree[num<<1].len[7] + tree[num<<1|1].len[7] + tree[num<<1].len[4] + tree[num<<1|1].len[4]; tree[num].len[6] = tree[num<<1].len[6] + tree[num<<1|1].len[6] + tree[num<<1].len[2] + tree[num<<1|1].len[2]; tree[num].len[5] = tree[num<<1].len[5] + tree[num<<1|1].len[5] + tree[num<<1].len[1] + tree[num<<1|1].len[1]; tree[num].len[3] = hash[e + 1] - hash[s] - tree[num].len[6] - tree[num].len[5] - tree[num].len[7]; return; } int i;//如果都不是,直接将左右子区间的合并 for(i = 1;i <= 7;i ++) tree[num].len[i] = tree[num<<1].len[i] + tree[num<<1|1].len[i]; } void insert(int num,int s,int e,int l,int r,int add,int kind) { if(s == e) { tree[num].col[kind] += add; memset(tree[num].len,0,sizeof(tree[num].len)); if(tree[num].col[1] && tree[num].col[2] && tree[num].col[3]) { tree[num].len[7] = hash[e + 1] - hash[s]; return; } if(tree[num].col[1] && tree[num].col[2]) { tree[num].len[4] = hash[e + 1] - hash[s]; return; } if(tree[num].col[1] && tree[num].col[3]) { tree[num].len[5] = hash[e + 1] - hash[s]; return; } if(tree[num].col[2] && tree[num].col[3]) { tree[num].len[6] = hash[e + 1] - hash[s]; return; } if(tree[num].col[1]) { tree[num].len[1] = hash[e + 1] - hash[s]; return; } if(tree[num].col[2]) { tree[num].len[2] = hash[e + 1] - hash[s]; return; } if(tree[num].col[3]) { tree[num].len[3] = hash[e + 1] - hash[s]; return; } return; } if(s == l && e == r) { tree[num].col[kind] += add; cal_len(num,s,e); return; } int mid = (s + e)>>1; if(r <= mid) insert(num<<1,s,mid,l,r,add,kind); else { if(l > mid) insert(num<<1|1,mid + 1,e,l,r,add,kind); else { insert(num<<1,s,mid,l,mid,add,kind); insert(num<<1|1,mid + 1,e,mid + 1,r,add,kind); } } cal_len(num,s,e); } int gety(int x,int len) { int l = 1; int r = len; int mid; while(l <= r) { mid = (l + r)>>1; if(hash[mid] == x) return mid; else { if(hash[mid] > x) r = mid - 1; else l = mid + 1; } } return -1; } int main() { int n,i,m; int cas = 0; int t; int x1,x2,y1,y2; scanf("%d",&t); while(t --) { scanf("%d",&n); for(i = 1;i < n + n;i += 2) { scanf("%s",color); int tt; if(color[0] == 'R') tt = 1; if(color[0] == 'G') tt = 2; if(color[0] == 'B') tt = 3; scanf("%d%d%d%d",&x1,&y1,&x2,&y2); line[i].x = x1; line[i].y1 = y1; line[i].y2 = y2; line[i].flag = 1; line[i].c = tt; line[i + 1].c = tt; line[i + 1].x = x2; line[i + 1].y1 = y1; line[i + 1].y2 = y2; line[i + 1].flag = -1; hash[i] = y1; hash[i + 1] = y2; } m = 2; sort(hash + 1,hash + n + n + 1); for(i = 2;i <= n + n;i ++)// if(hash[i] != hash[i - 1]) hash[m ++] = hash[i]; m --; build(1,1,m); sort(line + 1,line + n + n + 1,cmp); int l,r; memset(ans,0,sizeof(ans)); l = gety(line[1].y1,m); r = gety(line[1].y2,m) - 1; insert(1,1,m,l,r,line[1].flag,line[1].c); for(i = 2;i <= n + n;i ++) { __int64 w = line[i].x - line[i - 1].x; for(int j = 1;j <= 7;j ++) ans[j] += w * tree[1].len[j]; l = gety(line[i].y1,m); r = gety(line[i].y2,m) - 1; insert(1,1,m,l,r,line[i].flag,line[i].c); } printf("Case %d:\n",++cas); for(i = 1;i <= 7;i ++) printf("%I64d\n",ans[i]); } return 0; } //218MS 3348K