CF 1912 A NEKO's Maze Game

Posted liuchanglc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF 1912 A NEKO's Maze Game相关的知识,希望对你有一定的参考价值。

题目传送门

  • 题目描述

NEKO#ΦωΦ has just got a new maze game on her PC!

The game‘s main puzzle is a maze, in the forms of a 2×n2×n rectangle grid. NEKO‘s task is to lead a Nekomimi girl from cell (1,1)(1,1) to the gate at (2,n)(2,n) and escape the maze. The girl can only move between cells sharing a common side.

However, at some moments during the game, some cells may change their state: either from normal ground to lava (which forbids movement into that cell), or vice versa (which makes that cell passable again). Initially all cells are of the ground type.

After hours of streaming, NEKO finally figured out there are only qq such moments: the ii-th moment toggles the state of cell (ri,ci)(ri,ci) (either from ground to lava or vice versa).

Knowing this, NEKO wonders, after each of the qq moments, whether it is still possible to move from cell (1,1)(1,1) to cell (2,n)(2,n) without going through any lava cells.

Although NEKO is a great streamer and gamer, she still can‘t get through quizzes and problems requiring large amount of Brain Power. Can you help her?

  • 输入

The first line contains integers nn, qq (2n1052≤n≤105, 1q1051≤q≤105).

The ii-th of qq following lines contains two integers riri, cici (1ri21≤ri≤2, 1cin1≤ci≤n), denoting the coordinates of the cell to be flipped at the ii-th moment.

It is guaranteed that cells (1,1)(1,1) and (2,n)(2,n) never appear in the query list.

  • 输出

 

For each moment, if it is possible to travel from cell (1,1)(1,1) to cell (2,n)(2,n), print "Yes", otherwise print "No". There should be exactly qq answers, one after every update.

You can print the words in any case (either lowercase, uppercase or mixed).

 

  • 样例

  • 样例输入

技术图片
5 5
2 3
1 4
2 4
2 3
1 4
View Code

 

  • 样例输出

技术图片
Yes
No
No
No
Yes
View Code

一句话题意:2*n的迷宫,从(1,1)出发到(2,n),初始时全部的都是地面,每次询问会把一个地面给变成熔浆,熔浆变成地面,熔浆不能通过,问是否可以走到。

  • 分析:

我们先开一个a数组存储每个方格当前的状态,0表示地面,1表示熔岩

在一个长度为n,宽度为2的迷宫中,有三种情况不能从(1,1)走到(2,n)

情况一
0 1 0 0 0
0 1 0 0 0
情况二
 0 1 0 0 0
0 0 1 0 0
情况三
0 0 1 0 0
0 1 0 0 0

情况一:a[1][n]和a[2][n]同时为1

情况二:a[1][n]和a[2][n+1]同时为1 或 a[2][n]和a[1][n+1]同时为1

情况三:a[1][n]和a[2][n-1]同时为1 a[2][n]和a[1][n-1]同时为1

在其他情况下,总能通过别的点到达(2,n)

如果我们一个一个去枚举的话,那么1e5的数据肯定会超时

所以我们可以记录一下以上三种情况出现的次数,当次数不为0时,输出No,否则输出Yes

写代码的时候再考虑一下边界问题就可以了

  • 代码

技术图片
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=1e5+5;
int ans=0;
int a[3][maxn];
int main(){
    int n,q;
    scanf("%d%d",&n,&q);
    for(int i=1;i<=q;i++){
        int aa,bb;
        scanf("%d%d",&aa,&bb);
        if(a[aa][bb]==1){
            a[aa][bb]=0;
            if(aa==1){
                if(a[2][bb]==1) ans--;
                if(a[2][bb+1]==1 && bb+1<=n) ans--;
                if(a[2][bb-1]==1 && bb>1) ans--;
            } else {
                if(a[1][bb]==1) ans--;
                if(a[1][bb+1]==1 && bb+1<=n) ans--;
                if(a[1][bb-1]==1 && bb>1) ans--;
            }//如果这个点是由岩浆变成地面的话,之前算出来的ans就要更新
            //因为之前形成断路的地方现在不一定还有断路
            if(ans==0) printf("Yes
");
            else printf("No
");
        } else {
            a[aa][bb]=1;
            if(aa==1){
                if(a[2][bb]==1) ans++;
                if(a[2][bb+1]==1 && bb+1<=n) ans++;//bb+1<=n防止超出边界
                if(a[2][bb-1]==1 && bb>1) ans++;//bb>1防止超出边界
            } else {
                if(a[1][bb]==1) ans++;
                if(a[1][bb+1]==1 && bb+1<=n) ans++;
                if(a[1][bb-1]==1 && bb>1) ans++;
            }
            //如果这个点是由地面变成岩浆的话,之前算出来的ans就要更新
            //因为之前没有断路的地方现在可能会有断路
            if(ans==0) printf("Yes
");
            else printf("No
");
        }
    }
    return 0;
}
View Code

 

这个代码不是很优秀,但是比较直观

如果你已经理解的话,我们可以把代码进一步简化

  • 优化

首先是空间上的优化,我们可以开一个2*1e5的数组,将原来的两行分别用k和!k表示,跟我们写的滚动数组方法类似

其次我们可以不必要写太多判断,有些判断合并就可以

最后我们可以删去一些不必要的头文件,再用一些位运算,使代码更加简洁高效

代码

技术图片
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int a[2][maxn];
int main(){
    int q,ans=0,n;
    scanf("%d%d",&n,&q);
    int x,y;
    while(q--){
        scanf("%d%d",&x,&y);
        x--;//x--,方便以后的 ^ 运算 
        a[x][y]^=1;//改变这个位置的状态 
        int m=a[x][y]*2-1;//如果是 0 就是可以走,那结果就要减,1的话加 
        ans+=m*(a[x^1][y-1]+a[x^1][y]+a[x^1][y+1]);//进行ans的累加 
        if(ans==0)
            printf("Yes
");
        else printf("No
");
    }
    return 0;
}
View Code
  • 比较

技术图片

时间上虽然差不多,但内存和长度减少了不少,看代码也更清晰

最重要的是,这样写思维可以提升上去,不然那么容易过了也没什么意思

 

以上是关于CF 1912 A NEKO's Maze Game的主要内容,如果未能解决你的问题,请参考以下文章

题解 CF1292A NEKO's Maze Game

CF1293C - NEKO's Maze Game 分块

NEKO's Maze Game-cf

#614 C. NEKO's Maze Game

CodeForces 1292A NEKO's Maze Game(思维)

Codeforces Round #614 (Div. 2) C - NEKO's Maze Game