题目大意:在二维平面内给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