Codeforces Round #825 (Div. 2) D. Equal Binary Subsequences
题意是给一个01序列,允许进行一次操作,任选其中一个子序列,将其循环向右位移一次。之后问能否将这个序列划分为两个不相交的相等的子序列。
首先特判不可能的情况,即0和1的个数为奇数。之后两位两位考虑,假设相邻两位是00或者11,那么两个相等的数分别分给两个子序列即可。如果是01或者10,那么假设a子序列分到1,b子序列分到0,则下一次相邻两位不相等时就让a子序列分到0,b子序列分到1,这样可以保证两个子序列中0和1的个数是对应的,但不能使两个子序列完全相等。这时就要用到题目说的循环右移。例如对于1001,前两位选0,后两位选1进行右移,得到1100,这样交替选择就能保证最终的串\(2k-1\)和\(2k\)位的数都相等了。
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n;
string s;
void solve() {
cin >> n;
cin >> s;
int one = 0, zero = 0;
for(auto x : s) {
if(x == '0') zero++;
else one++;
}
if((zero & 1) || (one & 1)) {
puts("-1");
return;
}
vector<int> v;
bool flag = 0;
for(int i = 0; i < 2 * n; i += 2) {
if(s[i] != s[i + 1]) {
if(s[i] - '0' == flag) {
v.push_back(i);
} else {
v.push_back(i + 1);
}
flag ^= 1;
}
}
if(!v.size()) {
puts("0");
} else {
char tmp = s[v[v.size() - 1]];
for(int i = v.size() - 1; i > 0; i--) {
s[v[i]] = s[v[i - 1]];
}
s[v[0]] = tmp;
cout << v.size() << endl;
for(auto x : v) {
cout << x + 1 << " ";
}
cout << endl;
}
for(int i = 0; i < 2 * n; i += 2) {
cout << i + 1 << " ";
}
cout << endl;
}
signed main() {
int T = 1;
cin >> T;
while(T--) {
solve();
}
return 0;
}