# Comet OJ - Contest #13-C2

C2-佛御石之钵 -不碎的意志-」(困难版)

## 代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=1005;
int map[maxn][maxn],fa1[maxn][maxn],fa2[maxn*maxn],id[maxn][maxn],n,m,q,tot,ans;
char s[maxn];
int get1(int x,int y) {return (fa1[x][y]==y)?y:fa1[x][y]=get1(x,fa1[x][y]);}
void uni1(int x,int u,int v){fa1[x][get1(x,u)]=get1(x,v);}
int get2(int x){return (fa2[x]==x)?x:fa2[x]=get2(fa2[x]);}
void uni2(int u,int v){fa2[get2(u)]=get2(v);}
int dx[5]={0,1,-1,0,0};
int dy[5]={0,0,0,1,-1};
void mark(int x,int y) {//color (x,y)
id[x][y]=++tot;ans++;fa2[tot]=tot;
if(get1(x,y)!=get1(x,y+1))uni1(x,y,y+1);
for(int i=1;i<=4;i++) {
int nx=x+dx[i],ny=y+dy[i];
if(1<=nx<=n&&1<=ny<=m&&id[nx][ny]) {
if(get2(id[nx][ny])!=get2(id[x][y])){uni2(id[nx][ny],id[x][y]);ans--;}
}
}
}
int main() {
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) {
scanf("%s",s+1);
for(int j=1;j<=m;j++)map[i][j]=(s[j]=='1')?1:0;
}
for(int i=1;i<=n;i++)for(int j=1;j<=m+1;j++)fa1[i][j]=j;
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(map[i][j])mark(i,j);
scanf("%d",&q);
for(int t=1;t<=q;t++) {
int d[5];scanf("%d%d%d%d",&d[1],&d[3],&d[2],&d[4]);//x1 x2 y1 y2
for(int i=d[1];i<=d[2];i++) {
for(int j=get1(i,d[3]);j<=d[4];j=get1(i,j)) {
mark(i,j);
}
}
printf("%d\n",ans);
}
return 0;
}


posted @ 2019-10-27 10:39  GavinZheng  阅读(217)  评论(0编辑  收藏  举报