思维题
题目意思:
给出一个 2 * n (n <= 1e5) 矩阵,矩阵的每一个格子都可以放石头,或者取石头。
现在要求从点 (1, 1) 走到点 (2, n), 问是否有路可走。 题目给出了 q 次操作,每次是一个坐标(x, y),
如果 (x, y) 上没有石头,就放石头; 如果 (x, y) 上有石头,就拿掉石头。
本题要点:
1、用 0 和 1 两个整数来表示 点(x, y) 是否有石头, vis[x][y] == 0, 没有; vis[x][y] == 1,有石头。
0 和 1 之间的切换用 异或 vis[x][y] ^= 1;
2、 如果第一行点 (1, y) 上面有石头,第二行 三个点 (2, y - 1), (2, y), (2, y + 1) 如果有石头,就相当于
有一把锁,锁死了道路。用 block 来记录锁的数量。 每加入一个点,就判断是否能增加锁, 增加多少把。
当拿掉某点的石头的时候,就判断,锁的数量减少的多少。
3、有了以上维护 锁的数量block 的操作,判断每次是否 有路可走,就看 block的值了。
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int MaxN = 1e5 + 10;
int n, q, x, y;
int vis[3][MaxN];
int block = 0; // 有多少把锁
int dy[3] = {-1, 0, 1};
void handle(int flag)
{
int tmp_x, tmp_y = 0;
if(x == 1) tmp_x = 2;
else tmp_x = 1;
for(int i = 0; i < 3; ++i)
{
tmp_y = y + dy[i];
if(tmp_y >= 1 && tmp_y <= n)
{
if(vis[tmp_x][tmp_y])
{
block = block + flag;
}
}
}
}
int main()
{
scanf("%d%d", &n, &q);
for(int i = 0; i < q; ++i)
{
scanf("%d%d", &x, &y);
vis[x][y] ^= 1;
if(vis[x][y])
{
handle(1);
}else{
handle(-1);
}
if(block)
{
printf("No\n");
}else{
printf("Yes\n");
}
}
return 0;
}
/*
5 5
2 3
1 4
2 4
2 3
1 4
*/
/*
Yes
No
No
No
Yes
*/