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