hdu 4419 Colourful Rectangle

 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4419


题目大意:

     给定n个矩形,矩形的长平行于x轴,宽平行于y轴,每个矩形的颜色可能是R,G或B,矩形可能重叠,如果R和G(或G,R)重叠变为RG,如果三色重叠就是RGB,求所有颜色块(R,G,B,RG,RB,GB,RGB)的面积.


题目思路:

     很容易想到扫描线或者矩形切割(矩形切割本人不会....),普通的扫描线求的是单一颜色的面积并,但是这题有7种颜色,所以我们需要把7种颜色都扫出来,一般想到这步就很容易写了,但是写起来会比较麻烦(需要自己打好草稿,用几个数组映射),当然如果熟悉位运算的话就会更容易了.

令R:1 , G:2 , B:4

则RG: R|G=3  RB: R|B=5  GB: G|B=6  RGB: R|G|B=7

这样写起来代码就可以简洁很多了.


代码(非位运算版):

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;

#define ull unsigned __int64
#define ll __int64
//#define ll long long
#define ls rt<<1
#define rs ls|1
#define lson l,mid,ls
#define rson mid+1,r,rs
#define middle l+r>>1
#define INF 0x3F3F3F3F
#define esp (1e-10)
#define MOD 1000000007
#define type ll
typedef pair<int,int> pii;
typedef multiset<int> mset;
typedef multiset<int>::iterator mst_it;
//const double pi=acos(-1.0);
const int M=20000 +5;
#define clr(x,c) memset(x,c,sizeof(x))
type min(type x,type y){return x<y? x:y;}
type max(type x,type y){return x>y? x:y;}
void swap(type& x,type& y){type t=x;x=y;y=t;}
int T,cas=0;

int n,m;
int X[M],cnt[M<<2][3],len[M<<2][7];
ll ans[7];
int sz[6]={6,6,6,4,4,4};

int imp[6][6]={{1,2,3,4,5,6},{0,2,3,4,5,6},{0,1,3,4,5,6},
{2,4,5,6},{1,3,5,6},{0,3,4,6}};

int toc[6][6]={{3,4,3,4,6,6},{3,5,3,6,5,6},{4,5,6,4,5,6},
{6,6,6,6},{6,6,6,6},{6,6,6,6}};

map<char,int>mp;

struct edge{
	int l,r,h,fg;
	void insert(int _l,int _r,int _h,int _fg){
		l=_l,r=_r,h=_h,fg=_fg;
	}
	bool operator < (const edge &t)const{
		return h<t.h;
	}
}p[M];

int bs(int key){
	int l=1,r=m;
	while(l<=m){
		int mid=middle;
		if(key>X[mid]) l=mid+1;
		else if(key<X[mid]) r=mid-1;
		else return mid;
	}return -1;
}

void pushUp(int l,int r,int rt){
	int col=-1;
	if(cnt[rt][0]>0){
		if(cnt[rt][1]>0 && cnt[rt][2]>0) col=6;
		else if(cnt[rt][1]>0) col=3;
		else if(cnt[rt][2]>0) col=4;
		else col=0;
	}else if(cnt[rt][1]>0) col= (cnt[rt][2]>0)? 5:1;
	else if(cnt[rt][2]>0) col=2;
	if(col>-1){
		clr(len[rt],0);
		len[rt][col]=X[r+1]-X[l];
		if(col<6){
			for(int i=0,j;i<sz[col];i++){
				j=len[ls][imp[col][i]]+len[rs][imp[col][i]];
				len[rt][toc[col][i]]+=j;
				len[rt][col]-=j;
			}
		}
	}else if(l==r) clr(len[rt],0);
	else for(int i=0;i<7;i++) len[rt][i]=len[ls][i]+len[rs][i];
}

void update(int l,int r,int rt,int L,int R,int fg){
	if(L<=l && r<=R){
		(fg>0)? cnt[rt][fg-1]++:cnt[rt][-fg-1]--;
		pushUp(l,r,rt);
		return;
	}
	int mid=middle;
	if(L<=mid) update(lson,L,R,fg);
	if(mid<R) update(rson,L,R,fg);
	pushUp(l,r,rt);
}

void preSof(){
	mp['R']=1,mp['G']=2,mp['B']=3;
}

void run(){
    int i,j;
	scanf("%d",&n);
	char op[2];
	int x1,y1,x2,y2;
	for(i=0,m=0;i<n;i++){
		scanf("%s%d%d%d%d",op,&x1,&y1,&x2,&y2);
		p[i<<1].insert(x1,x2,y1,mp[op[0]]);
		p[i<<1|1].insert(x1,x2,y2,-mp[op[0]]);
		X[++m]=x1,X[++m]=x2;
	}
	sort(X+1,X+m+1);
	m=unique(X+1,X+m+1)-(X+1);
	clr(ans,0),clr(cnt,0),clr(len,0);
	sort(p,p+2*n);
	for(i=0;i<2*n-1;i++){
		int l=bs(p[i].l),r=bs(p[i].r);
		update(1,m,1,l,r-1,p[i].fg);
		for(j=0;j<7;j++)
			ans[j]+=ll(p[i+1].h-p[i].h)*ll(len[1][j]);
	}
	printf("Case %d:\n",cas);
	for(i=0;i<7;i++)
		printf("%I64d\n",ans[i]);
}

int main(){
    //freopen("1.in","r",stdin);
    //freopen("1.out","w",stdout);
	preSof();
    //run();
    //while(~scanf("%d",&n) && n) run();
    for(scanf("%d",&T),cas=1;cas<=T;cas++) run();
    //system("pause");
    return 0;
}



代码(位运算版):

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;

#define ull unsigned __int64
#define ll __int64
//#define ll long long
#define ls rt<<1
#define rs ls|1
#define lson l,mid,ls
#define rson mid+1,r,rs
#define middle l+r>>1
#define INF 0x3F3F3F3F
#define esp (1e-10)
#define MOD 1000000007
#define type ll
typedef pair<int,int> pii;
typedef multiset<int> mset;
typedef multiset<int>::iterator mst_it;
//const double pi=acos(-1.0);
const int M=20000 +5;
#define clr(x,c) memset(x,c,sizeof(x))
type min(type x,type y){return x<y? x:y;}
type max(type x,type y){return x>y? x:y;}
void swap(type& x,type& y){type t=x;x=y;y=t;}
int T,cas=0;

int n,m,num[8]={0,1,2,4,3,5,6,7};
int X[M],cnt[M<<2][3],len[M<<2][8];
ll ans[8];
map<char,int>mp;

struct edge{
	int l,r,h,fg;
	void insert(int _l,int _r,int _h,int _fg){
		l=_l,r=_r,h=_h,fg=_fg;
	}
	bool operator < (const edge &t)const{
		return h<t.h;
	}
}p[M];

int bs(int key){
	int l=1,r=m;
	while(l<=m){
		int mid=middle;
		if(key>X[mid]) l=mid+1;
		else if(key<X[mid]) r=mid-1;
		else return mid;
	}return -1;
}

void pushUp(int l,int r,int rt){
	int i,col=0;
	for(i=0;i<3;i++) if(cnt[rt][i]>0) col|=1<<i;
	if(col>0){
		clr(len[rt],0);
		len[rt][col]=X[r+1]-X[l];
		for(i=1;i<=7;i++) if((i|col)!=col){
			int tmp=len[ls][i]+len[rs][i];
			len[rt][i|col]+=tmp;
			len[rt][col]-=tmp;
		}
	}else if(l==r) clr(len[rt],0);
	else for(i=1;i<=7;i++) len[rt][i]=len[ls][i]+len[rs][i];
}

void update(int l,int r,int rt,int L,int R,int fg){
	if(L<=l && r<=R){
		(fg>0)? cnt[rt][fg-1]++:cnt[rt][-fg-1]--;
		pushUp(l,r,rt);
		return;
	}
	int mid=middle;
	if(L<=mid) update(lson,L,R,fg);
	if(mid<R) update(rson,L,R,fg);
	pushUp(l,r,rt);
}

void preSof(){
	mp['R']=1,mp['G']=2,mp['B']=3;
}

void run(){
    int i,j;
	scanf("%d",&n);
	char op[2];
	int x1,y1,x2,y2;
	for(i=0,m=0;i<n;i++){
		scanf("%s%d%d%d%d",op,&x1,&y1,&x2,&y2);
		p[i<<1].insert(x1,x2,y1,mp[op[0]]);
		p[i<<1|1].insert(x1,x2,y2,-mp[op[0]]);
		X[++m]=x1,X[++m]=x2;
	}
	sort(X+1,X+m+1);
	m=unique(X+1,X+m+1)-(X+1);
	clr(ans,0),clr(cnt,0),clr(len,0);
	sort(p,p+2*n);
	for(i=0;i<2*n-1;i++){
		int l=bs(p[i].l),r=bs(p[i].r);
		update(1,m,1,l,r-1,p[i].fg);
		for(j=1;j<=7;j++)
			ans[j]+=ll(p[i+1].h-p[i].h)*ll(len[1][j]);
	}
	printf("Case %d:\n",cas);
	for(i=1;i<=7;i++)
		printf("%I64d\n",ans[num[i]]);
}

int main(){
    //freopen("1.in","r",stdin);
    //freopen("1.out","w",stdout);
	preSof();
    //run();
    //while(~scanf("%d",&n) && n) run();
    for(scanf("%d",&T),cas=1;cas<=T;cas++) run();
    //system("pause");
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值