link
不难看出,我们可以通过枚举 \(1,2\) 位置来确定每个位置的奇偶性,然后考虑如何对着我们构造的奇偶性来构造解。
不难发现,对于暗着的灯且奇偶性为奇数,我们肯定直接操作最优。然后对于当前没有暗灯且为奇数,如果存在暗灯且为偶数,那么两边一定存在一个亮的灯且奇偶性为奇数,那亮的灯后面一个一定也是亮的灯且奇偶性为奇数,那么我们就可以 \(1,2,1,3\) 这样操作。
可以证明,操作数 \(\le 2\times n\)。
#include <bits/stdc++.h> using namespace std; #define Int register int #define MAXN 100005 template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;} template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);} template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');} template <typename T> inline void chkmax (T &a,T b){a = max (a,b);} template <typename T> inline void chkmin (T &a,T b){a = min (a,b);} vector <int> ans; int n,a[MAXN],d[MAXN]; int lst (int x){return x == 1 ? n : x - 1;} int nxt (int x){return x == n ? 1 : x + 1;} void fuckit (int x){ a[lst (x)] ^= 1,a[x] ^= 1,a[nxt (x)] ^= 1,d[x] ^= 1,ans.push_back (x); } void makeit1 (int i){ if (!a[i] && d[i]) fuckit (i),makeit1 (lst (i)),makeit1 (nxt (i)); } void makeit2 (int i){ if (!a[i] && !d[i]){ if (d[nxt (i)]) fuckit (i),fuckit (nxt (i)),fuckit (i),fuckit (nxt (nxt (i))),makeit2 (nxt (nxt (nxt (i)))); else fuckit (i),fuckit (lst (i)),fuckit (i),fuckit (lst (lst (i))),makeit2 (lst (lst (lst (i)))); } } bool check (int s1,int s2){ d[1] = s1,d[2] = s2,ans.clear (); for (Int i = 3;i <= n;++ i) d[i] = d[i - 2] ^ d[i - 1] ^ a[i - 1] ^ 1; for (Int i = 1;i <= n;++ i) if ((d[i] ^ d[lst (i)] ^ d[nxt (i)] ^ a[i]) == 0) return 0; for (Int i = 1;i <= n;++ i) makeit1 (i); for (Int i = 1;i <= n;++ i) makeit2 (i); write (ans.size()),putchar ('\n'); for (Int i = 0;i < ans.size();++ i) write (ans[i]),putchar (' '); putchar ('\n'); return 1; } signed main(){ int T;read (T); while (T --> 0){ read (n); for (Int i = 1;i <= n;++ i) scanf ("%1d",&a[i]); for (Int s1 = 0;s1 < 2;++ s1) for (Int s2 = 0;s2 < 2;++ s2) if (check (s1,s2)) goto there; puts ("0");there:; } return 0; }