Description
给出一个 n×m n × m 的网格,初始状态所有格子均为白色, q q 次操作,每次操作会把该网格的几个格子涂黑,问每次操作后白色格子的连通分支数,两个白块相邻当且仅当它们共边
Input
第一行三个整数表示网格行列数和操作数,之后 q q 行每行输入四个整数,表示将所有满足 x1≤x≤x2,y1≤y≤y2 x 1 ≤ x ≤ x 2 , y 1 ≤ y ≤ y 2 的格子 (x,y) ( x , y ) 涂黑,且输入保证 x1=x2 x 1 = x 2 或 y1=y2 y 1 = y 2
(1≤n,m≤1000,1≤q≤104,1≤x1≤x2≤n,1≤y1≤y2≤m) ( 1 ≤ n , m ≤ 1000 , 1 ≤ q ≤ 10 4 , 1 ≤ x 1 ≤ x 2 ≤ n , 1 ≤ y 1 ≤ y 2 ≤ m )
Output
每次操作后,输出白块连通分支数
Sample Input
4 6 5
2 2 2 6
1 3 4 3
2 5 3 5
4 6 4 6
1 6 4 6
Sample Output
1
3
3
4
3
Solution
离线,从后往前看即为把一些黑块变成白块,该白块会把其上下左右的白块所属连通分支合并,用并查集维护即可
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
#define y1 yy1
#define y2 yy2
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=1005,maxq=10005;
int n,m,num,f[maxn*maxn],a[maxn][maxn],q,x1[maxq],y1[maxq],x2[maxq],y2[maxq],ans[maxq];
int dx[]={-1,0,1,0};
int dy[]={0,-1,0,1};
void init(int n)
{
for(int i=1;i<=n;i++)f[i]=i;
}
int find(int x)
{
if(f[x]==x)return x;
return f[x]=find(f[x]);
}
void unite(int x,int y)
{
x=find(x),y=find(y);
if(x==y)return ;
num--;
f[x]=y;
}
int ID(int x,int y)
{
return (x-1)*m+y;
}
int main()
{
while(~scanf("%d%d%d",&n,&m,&q))
{
init(n*m);
memset(a,0,sizeof(a));
for(int i=1;i<=q;i++)
{
scanf("%d%d%d%d",&x1[i],&y1[i],&x2[i],&y2[i]);
if(x1[i]==x2[i])
for(int j=y1[i];j<=y2[i];j++)a[x1[i]][j]++;
else
for(int j=x1[i];j<=x2[i];j++)a[j][y1[i]]++;
}
num=n*m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(!a[i][j])
for(int k=0;k<4;k++)
{
int ii=i+dx[k],jj=j+dy[k];
if(ii>=1&&ii<=n&&jj>=1&&jj<=m&&!a[ii][jj])
{
unite(ID(i,j),ID(ii,jj));
}
}
else num--;
for(int i=q;i>=1;i--)
{
ans[i]=num;
if(x1[i]==x2[i])
for(int j=y1[i];j<=y2[i];j++)
{
a[x1[i]][j]--;
if(a[x1[i]][j])continue;
num++;
for(int k=0;k<4;k++)
{
int ii=x1[i]+dx[k],jj=j+dy[k];
if(ii>=1&&ii<=n&&jj>=1&&jj<=m&&!a[ii][jj])
unite(ID(x1[i],j),ID(ii,jj));
}
}
else
for(int j=x1[i];j<=x2[i];j++)
{
a[j][y1[i]]--;
if(a[j][y1[i]])continue;
num++;
for(int k=0;k<4;k++)
{
int ii=j+dx[k],jj=y1[i]+dy[k];
if(ii>=1&&ii<=n&&jj>=1&&jj<=m&&!a[ii][jj])
unite(ID(j,y1[i]),ID(ii,jj));
}
}
}
for(int i=1;i<=q;i++)printf("%d\n",ans[i]);
}
return 0;
}