CSU 2022/2015 Artwork(并查集+逆向思维)

2022: Artwork

Submit Page    Summary    Time Limit: 4 Sec     Memory Limit: 512 Mb     Submitted: 77     Solved: 16    

Description

A template for an artwork is a white grid of n × m squares. The artwork will be created by painting q horizontal and vertical black strokes. A stroke starts from square (x1, y1), ends at square (x2,y2)(x1=x2(x2,y2)(x1=x2 or y1=y2)y1=y2) and changes the color of all squares (x, y) to black where x1 ≤ x ≤ x2 and y1 ≤ y ≤ y2. The beauty of an artwork is the number of regions in the grid. Each region consists of one or more white squares that are connected to each other using a path of white squares in the grid, walking horizontally or vertically but not diagonally. The initial beauty of the artwork is 1. Your task is to calculate the beauty after each new stroke. Figure A.1 illustrates how the beauty of the artwork varies in Sample Input 1.

Input

The first line of input contains three integers n, m and q (1 ≤ n, m ≤ 1000, 1 ≤ q ≤ 104). Then follow q lines that describe the strokes. Each line consists of four integersx1,y1,x2x1,y1,x2 and y2(1 ≤ x1 ≤ x2 ≤ n, 1 ≤ y1 ≤ y2 ≤ m). Either x1 = x2 or y1=y2y1=y2(or both).

Output

For each of the q strokes, output a line containing the beauty of the artwork after the stroke.

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

Hint

Source

NCPC 2016


        大致题意,每次可以把两个同行或者同列的点之间涂黑,然后每进行一次操作统计一次图的连通分量。
      一道套路题,之前貌似做过两次。直接考虑逆向思维,从最后的分隔状态开始,每次往前减少一个操作,判断连通分量的减少情况。用权值表示每个地点被覆盖的次数,一旦出现覆盖次数变为0,即要进行更新,更新时首先增加一个连通分量,表示其本身,其次在合并四个方向,每进行一次合并减少一个连通分量。具体见代码(现场代码略丑):
#include<cstdio>
#include<cstring>
#include<vector>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
typedef long long ll;
const int N=1e6+10;
using namespace std;

int X[4]={0,0,-1,1};
int Y[4]={1,-1,0,0};

struct query{int x1,y1,x2,y2;} Q[10010];

int n,m,q,f[N],num[1010][1010],p[1010][1010];
int ans[10010],tot=0; bool v[N];

int find(int x)
{
	return f[x]==x?x:f[x]=find(f[x]);
}

bool check(int x,int y)
{
	if (x<=0||y<=0||x>n||y>m) return 0;
	return 1;
}

void work(int x,int y)
{
	tot++;
	f[num[x][y]]=num[x][y];
	for(int k=0;k<4;k++)
	{
		int xx=x+X[k],yy=y+Y[k];
		if (!check(xx,yy)||p[xx][yy]) continue;
		if (find(num[xx][yy])==find(num[x][y])) continue;
		f[find(num[xx][yy])]=find(num[x][y]); tot--;
	}
}

int main(){
	int no=0;
	scanf("%d%d%d",&m,&n,&q);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			num[i][j]=++no,f[no]=no;
	for(int i=1;i<=q;i++)
	{
		int x1,y1,x2,y2;
		scanf("%d%d%d%d",&y1,&x1,&y2,&x2);
		if (x1==x2)
		{
			if (y1>y2) swap(y1,y2);
			for(int j=y1;j<=y2;j++) p[x1][j]++;
		} else
		{
			if (x1>x2) swap(x1,x2);
			for(int j=x1;j<=x2;j++) p[j][y1]++;
		}
		Q[i]=query{x1,y1,x2,y2};
	}

	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			if (p[i][j]) continue;
			for(int k=0;k<4;k++)
			{
				int xx=i+X[k],yy=j+Y[k];
				if (!check(xx,yy)) continue;
				if (p[xx][yy]) continue;
				if (find(num[xx][yy])==find(num[i][j])) continue;
				f[find(num[xx][yy])]=find(num[i][j]);
			}
		}

	memset(v,0,sizeof(v));
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			if (p[i][j]) continue;
			int fa=find(num[i][j]);
			if (v[fa]) continue;
			v[fa]=1; tot++;
		}
	ans[q]=tot;

	for(int k=q;k>=2;k--)
	{
		if (Q[k].x1==Q[k].x2)
		{
			for(int i=Q[k].y1;i<=Q[k].y2;i++)
				if (!--p[Q[k].x1][i]) work(Q[k].x1,i);
		} else
		{
			for(int i=Q[k].x1;i<=Q[k].x2;i++)
				if (!--p[i][Q[k].y2]) work(i,Q[k].y2);
		}
		ans[k-1]=tot;
	}
	for(int i=1;i<=q;i++)
		printf("%d\n",ans[i]);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值