題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=4419
題目大意:給你n個矩形,每個矩形都有一種顏色,矩形覆蓋會出現另外一種顏色,問你所有矩形中不同的顏色各出現的面積。
解題思路:開始一直只用一個標記,1,2,4,處理來處理去發現一直搞不來。最後用兩個標記,一個存+1,-1,和普通面積並類似,另外開一個三位的標記陣列,0位表示'R',1位表示‘G’,2位表示‘B’,sum陣列要開8個狀態(和8顆線段樹思想類似),每次處理到當前節點時,該節點所有sum值清0(葉子節點的sum[u][0]表示的就是區間長度,要進行預先建樹),根據自己當前的狀態再由孩子傳遞數值上來進行更新操作。這題很巧妙的用到了或運算,表示我開始沒想到,發散性思維 O.O。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; #define lz 2*u,l,mid
#define rz 2*u+1,mid+1,r
typedef long long lld;
const int maxn=;
lld sum[*maxn][];
int flag[*maxn][];
int X[maxn];
lld ans[]; struct Node
{
int lx, rx, y;
int c, s;
Node() {};
Node(int lx_, int rx_, int y_, int c_, int s_)
{
lx=lx_, rx=rx_, y=y_, c=c_, s=s_;
}
bool operator <(const Node &S) const
{
if(y==S.y) return s>S.s;
else return y<S.y;
}
} line[maxn]; int find(int tmp, int n)
{
int l=, r=n, mid;
while(l<=r)
{
mid=(l+r)>>;
if(X[mid]==tmp) return mid;
else if(X[mid]<tmp) l=mid+;
else r=mid-;
}
} void push_up(int u, int l, int r)
{
int state=;
for(int i=; i<=; i++) if(flag[u][i]) state|=(<<i);
memset(sum[u],,sizeof(sum[u]));
if(l==r) sum[u][state]=X[r+]-X[l];
else
{
for(int i=; i<; i++)
sum[u][state|i]+=sum[*u][i]+sum[*u+][i];
}
} void build(int u, int l, int r)
{
memset(sum[u],,sizeof(sum[u]));
memset(flag[u],,sizeof(flag[u]));
if(l==r)
{
sum[u][]=X[r+]-X[l];
return ;
}
int mid=(l+r)>>;
build(lz);
build(rz);
sum[u][]=sum[*u][]+sum[*u+][];
} void Update(int u, int l, int r, int tl, int tr, int s, int c)
{
if(tl>tr) return ;
if(tl<=l&&r<=tr)
{
flag[u][s]+=c;
push_up(u,l,r);
return ;
}
int mid=(l+r)>>;
if(tr<=mid) Update(lz,tl,tr,s,c);
else if(tl>mid) Update(rz,tl,tr,s,c);
else
{
Update(lz,tl,mid,s,c);
Update(rz,mid+,tr,s,c);
}
push_up(u,l,r);
} int main()
{
int n, T, tcase=;
cin >> T;
while(T--)
{
cin >> n;
int num=;
memset(flag,,sizeof(flag));
memset(sum,,sizeof(sum));
memset(ans,,sizeof(ans));
for(int i=; i<n; i++)
{
int x1,x2,y1,y2, s;
char ch[];
scanf("%s%d%d%d%d",ch,&x1,&y1,&x2,&y2);
if(ch[]=='R') s=;
else if(ch[]=='G') s=;
else s=;
line[++num]=Node(x1,x2,y1,s,);
X[num]=x1;
line[++num]=Node(x1,x2,y2,s,-);
X[num]=x2;
}
sort(X+,X+num+);
sort(line+,line+num+);
int k=;
for(int i=; i<=num; i++)
if(X[i]!=X[i+]) X[++k]=X[i];
build(,,k);
for(int i=; i<num; i++)
{
int l=find(line[i].lx,k);
int r=find(line[i].rx,k)-;
Update(,,k,l,r,line[i].c,line[i].s);
for(int j=; j<=; j++)
ans[j]+=sum[][j]*(line[i+].y-line[i].y);
}
printf("Case %d:\n",++tcase);
swap(ans[],ans[]);
for(int i=; i<=; i++) cout << ans[i] <<endl;
}
return ;
}