思维题
题目意思:
给出一个 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 */