扫描 + 线段树;
首先离散化y, 节点用二进制保存7种颜色的个数,
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<algorithm>
using namespace std;
#define M 20010
struct Line
{
int up, down, x, left, col;
Line(){}
Line( int a, int b, int c, int d, int e):
x(a), down(b), up(c), left(d), col(e){}
bool operator < ( const Line &a ) const
{
return x < a.x;
}
}line[M];
int Y[M], cnt;
long long ans[8];
struct Node
{
int l, r, col[8], v[4];
int mid() { return (l+r)>>1; }
}node[M*4];
void build(int l, int r, int p )
{
node[p].l = l; node[p].r = r;
memset(node[p].col, 0, sizeof(node[p].col));
memset(node[p].v, 0, sizeof(node[p].v));
node[p].col[0] = Y[r] - Y[l]; //初始化白色;
if( l + 1 == r ) return;
int mid = node[p].mid();
build(l, mid, p*2);
build(mid, r, p*2+1);
}
void UP( int p )
{
int res = 0;
for( int i = 0; i < 3; i++ ) if( node[p].v[i] )
res += (1<<i); //当前节点的颜色
memset( node[p].col, 0, sizeof(node[p].col) ); //初始化为0,因为当前颜色由子节点的颜色和当前颜色一起决定
if( node[p].l + 1 == node[p].r ){ //没有子节点
node[p].col[res] = Y[node[p].r] - Y[node[p].l];
return;
}
for( int i = 0; i < 8; i++ ){ //(res|i),表示当前节点的颜色与子节点的颜色重合
node[p].col[res|i] += node[p*2].col[i];
node[p].col[res|i] += node[p*2+1].col[i];
}
}
void update( int x, int y, int col, int left, int p )
{
if( x <= node[p].l && y >= node[p].r ){
node[p].v[col] += left;
UP(p);
return;
}
int mid = node[p].mid();
if( mid >= y )
update( x, y, col, left, p*2 );
else if( mid <= x )
update( x, y, col, left, p*2+1 );
else{
update( x, y, col, left, p*2 );
update( x, y, col, left, p*2+1 );
}
UP( p );
}
int main()
{
int T;
scanf( "%d", &T );
int n, e, tt = 0;
int x1, y1, x2, y2, k, i;
char c;
long long cur, pre, len;
while( T-- ){
scanf( "%d", &n );
memset( ans, 0, sizeof(ans) );
cnt = e = 0;
for(i = 0; i < n; i++ ){
scanf( " %c%d%d%d%d", &c, &x1, &y1, &x2, &y2 );
if( c == 'R' ) k = 0;
if( c == 'G' ) k = 1;
if( c == 'B' ) k = 2;
line[e++] = Line( x1, y1, y2, 1, k );
line[e++] = Line( x2, y1, y2, -1, k );
Y[cnt++] = y1; Y[cnt++] = y2;
}
sort( Y, Y+cnt );
cnt = unique( Y, Y+cnt ) - Y; //离散化, uinique()是去掉重复的数,返回不相同的数的个数
build( 0, cnt-1, 1 );
sort(line, line+e);
pre = line[0].x;
i = 0;
while( i < e ){
cur = line[i].x;
for( int j = 1; j < 8; j++ ){
len = node[1].col[j];
ans[j] += (cur-pre)*len;
}
while( line[i].x == cur ){
y1 = lower_bound( Y, Y+cnt, line[i].down ) - Y; //离散化, 返回Y中第一个大于等于line[i].down的下标
y2 = lower_bound( Y, Y+cnt, line[i].up ) - Y;
update( y1, y2, line[i].col, line[i].left, 1 );
i++;
}
pre = cur;
}
printf( "Case %d:\n", ++tt );
printf( "%I64d\n%I64d\n%I64d\n%I64d\n%I64d\n%I64d\n%I64d\n",
ans[1], ans[2], ans[4], ans[3], ans[5], ans[6], ans[7] );
}
}