有一個結論:
當 \((1,1)\) 不能抵達 \((2,n)\) 時,必定存在一個點對,這兩個點的值均為真,且坐標中的 \(x\) 互異,\(y\) 的差 \(\leq 1\)
這個結論的正確性感覺非常顯然,就不多說了。
下圖可以形象地解釋點對的位置關系。
那對於每個點的值,只要開一個數組 f[i][j]
記錄一下即可。
有了上述結論,我們記一個變量 \(cnt\) 表示 " 有多少對滿足上述結論的點對 " ,則 \(cnt=0\) 時,\((1,1)\) 可以抵達 \((2,n)\) ,反之不可抵達。重點在於如何維護 \(cnt\) 。
對於每次反轉的點 \((x,y)\) ,我們都需要往 \(cnt\) 里 扣除 \(/\) 補上 \((x,y)\) 的貢獻,具體的:(為了方便異或 \(x\) 從 \(0\) 到 \(1\)
若 \(f[x][y]=1\) ,令 \(cnt-=f[x \ xor \ 1][y-1]+f[x \ xor \ 1][y]+f[x \ xor \ 1][y+1]\),\(f[x][y]=0\)
若 \(f[x][y]=0\) ,令 \(cnt+=f[x \ xor \ 1][y-1]+f[x \ xor \ 1][y]+f[x \ xor \ 1][y+1]\),\(f[x][y]=1\)
這樣就可以起到維護 \(cnt\) 的效果了,時間復雜度 \(O(n)\) 。
Code 部分
#include<cstdio>
#define RI rgeister int
using namespace std;
inline int read()
{
int x=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-f;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
return x*f;
}
const int N=100100;
int n,q;
int f[2][N];
int cnt;
int main()
{
n=read(),q=read();
while(q--)
{
int x=read()-1,y=read();
switch(f[x][y])
{
case 1:{
cnt-=f[x^1][y-1]+f[x^1][y]+f[x^1][y+1];
f[x][y]=0;
break;
}
case 0:{
cnt+=f[x^1][y-1]+f[x^1][y]+f[x^1][y+1];
f[x][y]=1;
break;
}
}
puts(!cnt?"Yes":"No");
}
return 0;
}
\[thanks \ for \ watching \]