方法一: D P DP DP

由于确定的答案对我们没有影响,只计算相邻数字的胜负情况

定义 f [ i ] [ 0 / 1 ] f[i][0/1] f[i][0/1]为 a i , a i + 1 a_i,a_{i+1} ai,ai+1的胜负情况,每次直接暴力转移即可。


方法二:构造

考虑怎么来构造

由于一个数 p x p_x px只取决于 a k , a k + 1 a_k,a_{k+1} ak,ak+1的胜负关系和 a k − 1 , a k a_{k-1},a_k ak−1,ak的胜负关系就好了

然后由于 a 1 a_1 a1没有前缀,所以暂时只考虑 a 1 , a 2 a_1,a_2 a1,a2的胜负关系

如果 p 1 = 2 p_1=2 p1=2显然无解

如果 p 1 = 0 p_1=0 p1=0,要么 r k 1 ( 1 ) = r k 2 ( 1 ) = 0 rk_1(1)=rk_2(1)=0 rk1(1)=rk2(1)=0,要么 r k 1 ( 1 ) = r k 2 ( 1 ) = 1 rk_1(1)=rk_2(1)=1 rk1(1)=rk2(1)=1

不过这两种情况都不会影响 r k 1 ( 2 ) , r k 2 ( 2 ) rk_1(2),rk_2(2) rk1(2),rk2(2),所以继续往后看

如果 p 1 = 1 p_1=1 p1=1

有两种情况

第一种是 r k 1 ( 1 ) = 1 , r k 2 ( 1 ) = 0 rk_1(1)=1,rk_2(1)=0 rk1(1)=1,rk2(1)=0

此时对 p 2 p_2 p2的贡献是 − 1 -1 −1或者 + 1 +1 +1

另一种是 r k 1 ( 1 ) = 0 , r k 2 ( 1 ) = 1 rk_1(1)=0,rk_2(1)=1 rk1(1)=0,rk2(1)=1,其实和上面相同

由于当 p i + 1 = 2 p_{i+1}=2 pi+1=2时无解,所以我们只需要远离 2 2 2这个数就好了

于是发现,在考虑完第 i i i次比赛后,我们对第 i + 1 i+1 i+1次做相应的操作

那么每次我们只需要关注 a i , a i + 1 a_i,a_{i+1} ai,ai+1的胜负情况即可

复杂度优化到 O ( n ) O(n) O(n)

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
int n,p[maxn];
int main()
{
int flag = 1;
cin >> n;
for(int i=1;i<=n;i++) scanf("%d",&p[i] );
for(int i=1;i<n;i++)
{
if( p[i]>=2 ) flag = 0;
if( p[i]==0 ) continue;
else
{
if( p[i+1]==0 ) p[i+1]++;
else p[i+1]--;
}
}
if( flag&&p[n]==0 ) cout << "YES";
else cout << "NO";
}