SGU 177 Square
题意:给出一个n×n的矩阵,矩阵上每个格子最开始都是白色的,给出m个操作,每个操作会把一个矩形染成黑色或白色,问最后有多少个白的格子。
思路:这题让我不禁想起了poj 2528,这类的染色问题应该都能用并查集搞……从后往前处理操作,这样已经画过的地方就不会第二次被染色,然后把染过的标记一下,接下来就是用并查集把染过的“跳过去”就好了,在这个过程中统计一下染过的黑色格子的数量,用总量一减就OK了~不过按这题的数据量来看,线段树应该也是完全没问题的……
————————————————
版权声明:本文为CSDN博主「qian99」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qian99/article/details/17171575
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<map> #include<queue> #include<set> #include<stack> #include<cmath> #include<vector> #define inf 0x3f3f3f3f #define Inf 0x3FFFFFFFFFFFFFFFLL #define eps 1e-9 #define pi acos(-1.0) using namespace std; typedef long long ll; const int maxn=1000+10; int parents[maxn][maxn]; bool vis[maxn][maxn]; int Find(int r,int x) { return parents[r][x]==x?x:parents[r][x]=Find(r,parents[r][x]); } struct Paint { int x1,y1,x2,y2; int colors; void readit() { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); } void change() { if(x1>x2) swap(x1,x2); if(y1>y2) swap(y1,y2); } }paints[maxn*5]; int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int n,m; scanf("%d%d",&n,&m); char str[5]; for(int i=0;i<m;++i) { paints[i].readit(); paints[i].change(); scanf("%s",str); if(str[0]=='b') paints[i].colors=1; else paints[i].colors=0; } for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) parents[i][j]=j; memset(vis,0,sizeof(vis)); int total=n*n; int now,f; for(int i=m-1;i>=0;--i) { for(int j=paints[i].x1;j<=paints[i].x2;++j) { now=paints[i].y1; while(now<=paints[i].y2) { f=Find(j,now); if(f==now&&!vis[j][now]) { vis[j][now]=true; parents[j][now]=paints[i].y2; if(paints[i].colors) total--; now++; } else now=f+1; } } } printf("%d\n",total); return 0; }
Sol2:
倒着扫描每个矩形,处理每个矩形时,向后遍历判断后面的矩形是否与其重叠,重叠的话就分割冲若干种小的矩形继续处理,直到最后统计没有被覆盖的面积..实现直接看代码吧..
#include <iostream> #include <cstdio> #include <memory.h> using namespace std; typedef long long ll; int n,m; int x1[10020],x2[10020],y1[10020],y2[10020]; int col[10020]; char c[3]; int cnt; void slove(int xs,int ys,int xt,int yt,int d,int c) { while (((xs>=x2[d])||(xt<=x1[d])||(ys>=y2[d])||(yt<=y1[d]))&& d<=m) //如果左上角点所在行>=第D个矩形右下角,即在第D个矩形下方 // 右下角行<=第D个矩形左上角,即在其上方,后面两个同理 d++; if (d==m+1) { if (c) cnt+=(yt-ys)*(xt-xs); //出现了多少个黑色点 return; } if (xs<x1[d]) { slove(xs,ys,x1[d],yt,d+1,c); xs=x1[d]; } if (xt>x2[d]) { slove(x2[d],ys,xt,yt,d+1,c); xt=x2[d]; } if (ys<y1[d]) slove(xs,ys,xt,y1[d],d+1,c); if (yt>y2[d]) slove(xs,y2[d],xt,yt,d+1,c); } int main() { // freopen("in.txt","r",stdin); scanf("%d%d",&n,&m); cnt=0; for (int i=1; i<=m; i++) { scanf("%d%d%d%d",&x1[i],&y1[i],&x2[i],&y2[i]); if (x1[i]>x2[i]) swap(x1[i],x2[i]); if (y1[i]>y2[i]) swap(y1[i],y2[i]); x2[i]++; y2[i]++; scanf("%s",c); if (c[0]=='b') col[i]=1; else col[i]=0; } for (int i=m; i>=1; i--) { if (col[i]) slove(x1[i],y1[i],x2[i],y2[i],i+1,1); } cout<<n*n-cnt<<endl; return 0; }