沧海桑田
沧海桑田

注意到行数很少,考虑枚举行。
首先我们可以设定一个 \(fa\) 并查集数组,\(\text{find(p)=find(q)}\) 表示两个点在同一个连通块内(不限于陆地,海洋也可以),所以我们可以设一个 \(col\) 数组,表示当前这个点是在海洋还是在陆地,这样对于opt=1的情况,我们就可以很好的解决,只要满足
\(col[x_1\times N+y_1]=1\) 且 \(col[x_2 \times N + y_2]=1\) 且 \(find(x_1\times N+y_1)=find(x_2 \times N + y_2)\) 就可以了
然后看第二个东西,我们是要把一个区间变成陆地,那我们可以枚举行,对于每一行的操作,考虑跳跃的操作,再次设定 \(nxt_{i,j}\) 表示第 \(i\) 行第 \(j\) 列跳到的下一个海洋在哪一列,具体直接参考(染色问题)!
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10, M = 50 * N;
int fa[M], net[52][N], m;
bool col[M];
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
int find(int x)
{
if (x == fa[x])
return x;
return fa[x] = find(fa[x]);
}
int getnext(int x, int y)
{
if (net[x][y] == y)
return y;
return net[x][y] = getnext(x, net[x][y]);
}
void access(int x, int y)
{
int p = (x - 1) * N + y;
col[p] = 1;
for (int i = 0; i < 4; i++)
{
int q = (x + dx[i] - 1) * N + (y + dy[i]);
if (q < 1 || q > 50 * N || !col[q])
continue;
fa[find(p)] = find(q);
}
}
int main()
{
for (int i = 1; i <= M; i++)
fa[i] = i;
for (int i = 1; i <= 50; i++)
for (int j = 1; j <= N; j++)
net[i][j] = j;
cin >> m;
while (m--)
{
int opt, x1, y1, x2, y2;
scanf("%d%d%d%d%d", &opt, &x1, &y1, &x2, &y2);
if (opt)
{
int p = (x1 - 1) * N + y1, q = (x2 - 1) * N + y2;
if (col[p] && col[q] && find(p) == find(q))
puts("1");
else
puts("0");
}
else
{
if (x1 > x2)
swap(x1, x2);
if (y1 > y2)
swap(y1, y2);
for (int i = x1; i <= x2; i++)
{
int x = getnext(i, y1);
while (x <= y2)
access(i, x), x = net[i][x] = getnext(i, x + 1);
}
}
}
return 0;
}

浙公网安备 33010602011771号