CF1572B Xor of 3

发布时间 2023-03-23 21:45:58作者: DCH233

CF1572B Xor of 3

做多了这种题,感觉好套路。。

首先观察操作性质,有一个有解的必要条件:所有值异或和为 \(0\),因为每次操作不会改变 \(1\) 的个数的奇偶性。然后再观察一下,发现如果从前缀异或和的角度看待这个操作会变得非常简单,大概就是

\[s_{k-1}, s_k, s_{k+1}, s_{k + 2} \rightarrow s_{k - 1}, s_{k + 2}, s_{k - 1}, s_{k + 2} \]

注意到偶数位置和奇数位置的值互不影响的,所以考虑奇偶性。

首先来看 \(n\) 为奇数的情况。这时候不难看出偶数位置可以通过操作 \(1,3,5......,(n-2)\) 来全部变成零,所以现在只需考虑奇数位,由上面的必要条件有 \(s_n = 0\),所以可以操作 \((n-2),(n-4)......,1\) 全部变成 \(0\)

然后是 \(n\) 为偶数的情况。我们希望沿用上面的做法,结果发现充要条件在样例就假掉了。思考这是为什么。考察这种情况和 \(n\) 为奇数的情况有何区别:就是我们没有办法通过 \(1,3,5......\) 把偶数位全部消成 \(0\),但是可以通过 \((n-2),(n-4)......\) 把偶数位全部消成 \(0\),相应的,奇数位就寄掉了。所以需要考虑奇数位,这时候就很明显了:有解还需满足奇数位存在 \(0\),我们可以通过两边的操作把剩下的奇数位消成 \(0\),这样这道题就做完了。

#include <bits/stdc++.h>
 
using namespace std;
 
typedef long long LL;
 
namespace IO {
  #define isdigit(x) (x >= '0' && x <= '9')
  template<typename T>
  inline void read(T &x) {
    x = 0; char ch = getchar(); int f = 0;
    for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
    for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
    if(f) x = -x;
  }
  template<typename T>
  inline void write(T x) {
    if(x < 0) putchar('-'), x = -x;
    if(x > 9) write(x / 10);
    putchar(x % 10 + '0');
  }
  #undef isdigit
}
using namespace IO;
 
const int N = 2e5 + 10;
int n, a[N], s[N];
int ans[N];
 
void solve() {
  read(n);
  for(int i = 1; i <= n; ++i)
    read(a[i]), s[i] = s[i - 1] ^ a[i];
  int tot = 0;
  if(n & 1) {
    if(s[n] == 1) {
      puts("NO");
      return;
    }
    for(int i = n - 2; i >= 1; i -= 2)
      ans[++tot] = i;
    for(int i = 3; i + 2 <= n; i += 2)
      ans[++tot] = i;
  }
  else {
    int pos = 0;
    for(int i = 1; i <= n; i += 2)
      if(s[i] == 0) {
        pos = i;
        break;
      }
    if(!pos || s[n] == 1) {
      puts("NO");
      return ;
    }
    for(int i = pos + 1; i + 2 <= n; i += 2)
      ans[++tot] = i;
    for(int i = pos - 2; i >= 1; i -= 2)
      ans[++tot] = i;
    for(int i = n - 2; i >= 1; i -= 2)
      ans[++tot] = i;
  }
  puts("YES");
  printf("%d\n",tot);
  for(int i = 1; i <= tot; ++i)
    printf("%d ",ans[i]);
  puts("");
}
 
int main() {
  int T; read(T);
  while(T--) solve();
}