题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4419
题目大意:给出红绿蓝三种颜色的矩形,这些颜色的矩形重叠在一起组合成其他的颜色(共7种),求各种颜色的面积。
方法:前面处理扫描线的操作都是很基本的操作,关键的操作是在往上更新的时候,首先在红绿蓝用1,2,4表示,然后再通过位运算可以算出组合成的其他颜色,更新关键操作是参考网上的神代码,具体看程序。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 20005
typedef __int64 LL;
struct Line
{
LL xl, xr, y, tp;
Line(){}
Line(LL xl, LL xr, LL y, LL tp):
xl(xl), xr(xr), y(y), tp(tp){}
bool operator < (const Line& b)const
{
return y<b.y;
}
}line[maxn];
LL X[maxn];
struct node
{
LL l, r, vnl, vnr;
LL tp[4], sum[8];
}v[maxn<<2];
void build(LL l, LL r, LL n)
{
v[n].l = l, v[n].r = r;
v[n].vnl = X[l], v[n].vnr = X[r];
memset(v[n].tp, 0, sizeof(v[n].tp));
memset(v[n].sum, 0, sizeof(v[n].sum));
if (l+1==r)
return;
LL mid = (l+r) >> 1;
build(l, mid, n<<1);
build(mid, r, n<<1|1);
}
void pushup(int n)
{
LL k = 0, R = 1, G = 2, B = 4;
if (v[n].tp[1]>0)
k|=R;
if (v[n].tp[2]>0)
k|=G;
if (v[n].tp[3]>0)
k|=B;
memset(v[n].sum, 0, sizeof(v[n].sum));
if (k)
{
v[n].sum[k] = v[n].vnr - v[n].vnl;
if (v[n].l+1==v[n].r)
return;
for (LL i=1; i<8; i++)//关键地方在这里
{
if ((k|i)!=k)
{
LL temp = v[n<<1].sum[i] + v[n<<1|1].sum[i];
v[n].sum[k] -= temp;
v[n].sum[k|i] += temp;
}
}
}
else
{
for (int i=1; i<8; i++)
v[n].sum[i] = v[n<<1].sum[i] + v[n<<1|1].sum[i];
}
}
void update(LL l, LL r, LL n, LL tp)
{
if (l<=v[n].vnl && v[n].vnr<=r)
{
if (tp<0)
--v[n].tp[-tp];
else
++v[n].tp[tp];
pushup(n);
return ;
}
LL mid = (v[n].l + v[n].r) >> 1;
if (r<=X[mid])
update(l, r, n<<1, tp);
else if (l>=X[mid])
update(l, r, n<<1|1, tp);
else
{
update(l, X[mid], n<<1, tp);
update(X[mid], r, n<<1|1, tp);
}
pushup(n);
}
int main()
{
char str[5];
LL ncase, n, ans[8];
cin >> ncase;
for (LL k=1; k<=ncase; k++)
{
cin >> n;
LL num = 0;
for (LL i=0; i<n; i++)
{
LL x1, y1, x2, y2, tp;
cin >> str >> x1 >> y1 >> x2 >> y2;
if (str[0]=='R')
tp = 1;
else if (str[0]=='G')
tp = 2;
else
tp = 3;
line[++num] = Line(x1, x2, y1, tp);
X[num] = x1;
line[++num] = Line(x1, x2, y2, -tp);
X[num] = x2;
}
sort(X+1, X+num+1);
sort(line+1, line+num+1);
n = 1;
for (LL i=2; i<=num; i++)
if (X[i]!=X[i-1])
X[++n] = X[i];
memset(ans, 0, sizeof(ans));
build(1, n, 1);
for (LL i=1; i<num; ++i)
{
update(line[i].xl, line[i].xr, 1, line[i].tp);
LL yy = (line[i+1].y - line[i].y);
for (LL j=1; j<8; j++)
ans[j] += v[1].sum[j] * yy;
}
LL h[8] = {0, 1, 2, 4, 3, 5, 6, 7};
printf("Case %I64d:\n", k);
for (LL i=1; i<8; i++)
printf("%I64d\n", ans[h[i]]);
}
return 0;
}