“为你写诗,为你静止,为你做不可能的事”,爱情是一种怪事,它让奎奎开始学习画画。奎奎认为一张画的艺术价值等于画上的白色联通块个数(当一个格子和它上下左右四个方向上的某个相邻格子颜色相同,则认为它们属于同一个联通块),奎奎还认为他作画的艺术价值和妹子对他的好感度紧密相关,因此奎奎非常在意每一时刻他的画的艺术价值。 为了简化题目,奎奎在一张n行m列的白色矩形格子画布上作画,他一共画了q笔,每一笔都是从(x1,y1)格子开始到(x2,y2)格子结束(x1=x2或y1=y2),将所有满足x1<=x<=x2并且y1<=y<=y2的格子涂黑。奎奎想知道当他画完每一笔之后,这幅画的艺术价值是多少。
输入
第一行三个整数n,m,q (1≤n, m≤1000, 1≤q≤10000 )
下面q行每行4个整数x1,y1,x2,y2 (1≤x1≤x2≤n, 1≤y1≤y2≤m)描述奎奎画的q条线段的起点和终点
输出
q行,对于奎奎画的每一条线段,输出一行一个整数表示该线段画完之后画布上白色联通块的个数。
样例输入 Copy
4 6 5
2 2 2 6
1 3 4 3
2 5 3 5
4 6 4 6
1 6 4 6
样例输出 Copy
1
3
3
4
3
求每一次操作之后剩下的白色连通块的个数。
初始时,每一块看作一个连通块,利用并查集,每合并一次连通块 -1 。
为了方便,我们可以倒着求。
注意这个题:每次画的那一笔是线段,保证了x1 = x2 或者 y1 = y2。
这样1e7的复杂度就有保证了。
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<map>
#include<queue>
#define ll long long
#define llu unsigned ll
#define pr make_pair
#define pb push_back
using namespace std;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const int maxn=1100;
int c[maxn][maxn];
struct node
{
int x,y;
}a1[maxn*10],a2[maxn*10];
int f[maxn*maxn],ans[maxn*10];
int n,m,q;
int nmax,cnt;
int get(int x,int y)
{
return x*nmax+y;
}
void init(void)
{
for(int i=1;i<maxn*maxn;i++)
f[i]=i;
}
int fi(int x)
{
if(x!=f[x])
f[x]=fi(f[x]);
return f[x];
}
int xx[]={0,0,-1,1};
int yy[]={-1,1,0,0};
bool check(int x,int y)
{
if(x<1||x>n||y<1||y>m) return false;
return true;
}
void doit(int i,int j)
{
for(int k=0;k<4;k++)
{
int nx=i+xx[k];
int ny=j+yy[k];
if(!check(nx,ny)) continue;
if(c[nx][ny]) continue;
int cc=fi(get(nx,ny));
int dd=fi(get(i,j));
if(cc!=dd)
cnt--,f[cc]=dd;
}
}
int main(void)
{
scanf("%d%d%d",&n,&m,&q);
nmax=max(n,m);
init();
for(int i=1;i<=q;i++)
{
scanf("%d%d%d%d",&a1[i].x,&a1[i].y,&a2[i].x,&a2[i].y);
for(int x=a1[i].x;x<=a2[i].x;x++)
for(int y=a1[i].y;y<=a2[i].y;y++)
c[x][y]++;
}
cnt=n*m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(c[i][j]) cnt--;
else doit(i,j);
}
}
for(int i=q;i>=1;i--)
{
ans[i]=cnt;
for(int x=a1[i].x;x<=a2[i].x;x++)
{
for(int y=a1[i].y;y<=a2[i].y;y++)
{
c[x][y]--;
if(c[x][y]==0)
{
++cnt;
doit(x,y);
}
}
}
}
for(int i=1;i<=q;i++)
printf("%d\n",ans[i]);
return 0;
}