Loading

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;
}
posted @ 2022-10-14 16:36  脂环  阅读(20)  评论(0编辑  收藏  举报