Live2D

Secret of Tianqiu Valley 题解

link

Solution

不难看出,我们可以通过枚举 \(1,2\) 位置来确定每个位置的奇偶性,然后考虑如何对着我们构造的奇偶性来构造解。

不难发现,对于暗着的灯且奇偶性为奇数,我们肯定直接操作最优。然后对于当前没有暗灯且为奇数,如果存在暗灯且为偶数,那么两边一定存在一个亮的灯且奇偶性为奇数,那亮的灯后面一个一定也是亮的灯且奇偶性为奇数,那么我们就可以 \(1,2,1,3\) 这样操作。

可以证明,操作数 \(\le 2\times n\)

Code

#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;
}
posted @ 2022-01-25 22:18  Dark_Romance  阅读(111)  评论(0编辑  收藏  举报