题目链接: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;
}