• 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;
    }
    
  • 相关阅读:
    QGIS 编译
    Ubuntu: 无法使用su命令
    win7 与 Ubuntu 16.04 文件传送
    OSGEarth编译
    GADL配置编译
    C++ 类对象和 指针的区别
    C++ Primer Plus 第六版笔记
    Windows下使用doxygen阅读和分析C/C++代码
    _MSC_VER详细介绍
    LUA学习之一 初次接触
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/16792075.html
Copyright © 2020-2023  润新知