3.31考试T2

题目描述

有一个\(n*m\)的地图,把左边界和右边界粘起来使得形成一个圆柱,现在要不断地挖去其中的格子,要求任何时候都存在一条从最上方到最下方的路径(四联通),如果某次操作不满足要求则不做,问最后有多少次操作是成功的。

题解

从上到下四联通可以转化成从左到右删去的点不能够八联通,考虑怎么判断是否八联通。

首先我们将地图复制一遍,左边一份,右边一份,每次在左边和右边依次加入删去的点,然后我们对于删去的点进行维护。

我们使用并查集维护联通块,每个点的\(fa\)代表它所在的联通块中删去最早的点。

如果加入的两个点所在的联通块相同的话,由于这两个点本质上又是一个点,所以就形成了从左到右的八联通通道。

注意:额外判断\(m=1\)时,加入任何一个点肯定会导致从左到右删去的点能够八联通。

#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
const int N = 6e5 + 5;
int n, m, Q, ans, fa[N], cnt, vis[3005][6005], pos[N];
int nx[10] = {0, 0, 0, 1, 1, 1, -1, -1, -1};
int ny[10] = {0, 1, -1, 0, 1, -1, 0, 1, -1};
inline int read()
{
	int x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
int find(int x) {return fa[x] == x ? fa[x] : fa[x] = find(fa[x]);}
int way(int x, int y)
{
	if(m == 1) return 0; int u, v; cnt ++;
	for(int k = 1; k <= 2; k ++)
	{
		if(k == 1) u = x, v = y; else u = x, v = y + m;
		for(int i = 1; i <= 8; i ++)
		{
			int uu = u + nx[i], vv = v + ny[i];
			if(uu < 1 || uu > n) continue;
			if(vv > 2 * m) vv -= 2 * m; else if(vv <= 0) vv += 2 * m;
			if(vis[uu][vv])
			{
				if(k == 1) pos[find(vis[uu][vv])] = cnt;
				else if(pos[find(vis[uu][vv])] == cnt) return 0;
			}
		}
	}
	return 1;
}
int main()
{
	n = read(); m = read(); Q = read(); int x, y;
	for(int i = 1; i <= 2 * Q; i ++) fa[i] = i;
	for(int num = 1, u, v; num <= Q; num ++)
	{
		x = read(); y = read();
		if(way(x, y))
		{
			vis[x][y] = num; vis[x][y + m] = num + Q;
			for(int k = 1; k <= 2; k ++)
			{
				if(k == 1) u = x, v = y; else u = x, v = y + m;
				for(int i = 1; i <= 8; i ++)
				{
					int uu = u + nx[i], vv = v + ny[i];
					if(uu < 1 || uu > n) continue;
					if(vv > 2 * m) vv -= 2 * m; else if(vv <= 0) vv += 2 * m;
					if(vis[uu][vv]) fa[find(vis[u][v])] = find(vis[uu][vv]);
				}
			}
			ans ++;
		}
	}
	printf("%d\n", ans);
	return 0;
}
posted @ 2020-03-31 17:25  Sunny_r  阅读(132)  评论(2编辑  收藏  举报