Gym - 101550A(Artwork 倒序+并查集)
Posted sykline
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gym - 101550A(Artwork 倒序+并查集)相关的知识,希望对你有一定的参考价值。
题目:
思路:
1、对输入数据离线,先把所有的黑线都画出来,统计一下剩余的白色连通块的个数,dfs过程将一个连通块放到一个集合中。
2、倒着往前消去黑线,如果当前的块A是白块就看他的四周有没有白块:有白块B,看A和B的祖先是不是一样,一样的话pass,否则合并连通块并且白色连通块的数目减一(当然第一个是跳过的)。四周全是黑块的话,白色连通块的数量加一。
3、用栈存储一下每一步的答案,最后输出就可以了。
PS:看错了q的数据范围,卡了三天,话说前两天答案状态是WA在test5,第三天就成了memor limit exceeded,然后就发现自己的错误了。菜是原罪啊!!
代码:
#include <bits/stdc++.h> #define inf 1e9 #define FRE() freopen("in.txt","r",stdin) using namespace std; typedef long long ll; const ll MOD = 2147493647; const int maxn = 1e3+10; int mp[maxn][maxn],fa[maxn*maxn],vis[maxn][maxn]; int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}}; struct label { int r1,c1; int r2,c2; } l[maxn*10]; int r,c,q,num_white; int getId(int x,int y) { return x*c+y; } void init() { num_white = 0; memset(mp,0,sizeof(mp)); memset(vis,0,sizeof(vis)); for(int i = 0; i<maxn*maxn; i++) { fa[i] = i; } return; } int Find(int x) { return fa[x]==x ? x : fa[x] = Find(fa[x]); } void input() { int x1,x2,y1,y2; for(int i = 0; i<q; i++) { scanf("%d%d%d%d",&l[i].c1,&l[i].r1,&l[i].c2,&l[i].r2); l[i].c1--,l[i].c2--,l[i].r1--,l[i].r2--; if(l[i].r1==l[i].r2) { int x = l[i].r1; for(int j = l[i].c1; j<=l[i].c2; j++) mp[x][j]++; } else if(l[i].c1==l[i].c2) { int y = l[i].c2; for(int j = l[i].r1; j<=l[i].r2; j++) mp[j][y]++; } } } bool inside(int x,int y) { if(x>=0 && x<r && y>=0 && y<c) return true; return false; } void dfs(int x,int y,int iid) { int id = getId(x,y); vis[x][y] = 1; fa[id] = iid; for(int i = 0; i<4; i++) { int tx = x+dir[i][0],ty = y+dir[i][1]; if(inside(tx,ty) && !mp[tx][ty] && !vis[tx][ty]) { dfs(tx,ty,iid); } } return; } bool _union(int x,int y) { int tx = Find(x),ty = Find(y); if(tx!=ty) { fa[tx] = ty; return true; } return false; } void solve(int x,int y) { int f = 0,isfirst = 0; for(int i = 0; i<4; i++) { int tx = x+dir[i][0],ty = y+dir[i][1]; if(inside(tx,ty)) { if(!mp[tx][ty]) { f = 1; if(_union(getId(x,y),getId(tx,ty))) { isfirst++; if(isfirst == 1) continue; else num_white--; } } } } if(!f) num_white++; } void check() { for(int i = 0; i<r; i++) { for(int j = 0; j<c; j++) { printf("%d ",mp[i][j]); } printf(" "); } cout<<"GG"<<endl; } void countWhite() { for(int i = 0; i<r; i++) { for(int j = 0; j<c; j++) { int id = getId(i,j); if(!mp[i][j] && !vis[i][j]) { dfs(i,j,id); num_white++; } } } } int main() { //FRE(); scanf("%d%d%d",&c,&r,&q); init(); input(); countWhite(); stack<int> ans; for(int i = q-1; i>=0; i--) { ans.push(num_white); int x1 = l[i].r1,x2=l[i].r2,y1=l[i].c1,y2=l[i].c2; if(x1==x2) { for(int j=y1; j<=y2; j++) { mp[x1][j]--; if(mp[x1][j]==0) { solve(x1,j); } } } else if(y1==y2) { for(int j=x1; j<=x2; j++) { mp[j][y1]--; if(mp[j][y1]==0) { solve(j,y1); } } } //check(); } while(!ans.empty()) { printf("%d ",ans.top()); ans.pop(); } return 0; } /* 4 6 5 2 2 2 6 1 3 4 3 2 5 3 5 4 6 4 6 1 6 4 6 */ /* 1 3 3 4 3 */
以上是关于Gym - 101550A(Artwork 倒序+并查集)的主要内容,如果未能解决你的问题,请参考以下文章
Gym - 101002D:Programming Team (01分数规划+树上依赖背包)
IOS::如何获取 MPMediaquery Songsquery Artwork
UVA1445 LA4636 POJ3802 Cubist Artwork贪心
2019-2020 ACM-ICPC Brazil Subregional Programming Contest Problem A Artwork (并查集)