hdu 4419 Colourful Rectangle (2012杭州区域赛 1010 )

扫描  + 线段树;

首先离散化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] );
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值