Codeforces 950C Zebras ( 贪心 && 模拟 )
题意 : 给出一个 01 串,要求你将其分隔出若干个子序列 ( 每个数字只能属于某一个子序列 ) ,子序列必须满足由 0 开头和结尾,且中间需 01 交替构成。若无法做到,则输出 -1。
分析 :
很容易想到需要去贪心配对 0 和 1
即 能 01 交替去构造就尽量选择这种方案,这样才能用更少的 0 去配对尽量多的 1
用 vector<int> idx[] 这个二维数组来装各个子序列的信息
使用两个 set 来装现在以 0 结尾以及以 1 结尾的子序列的下标
然后 O(n) 从左到右扫一遍,对于 0 元素去检查是否当前有子序列以 1 结尾
有的话则填在其后,否则创造出新的子序列,以这个 0 为开头。如果没有,
说明无法做到了,输出 -1
#include<bits/stdc++.h> #define LL long long using namespace std; const int maxn = 2e5 + 10; int num0, num1, len, ans, arr[maxn]; vector<int> idx[maxn]; set<int> zero, one; int main(void) { while(true){ char ch; scanf("%c", &ch); if(ch == '\n') break; if(ch == '0') num0++, arr[++len] = 0; else num1++, arr[++len] = 1; } if(num0 <= num1){ puts("-1"); return 0; } for(int i=1; i<=len; i++){ if(arr[i] == 0){ num0--; if(one.size() == 0){ idx[ans].push_back(i); zero.insert(ans++); }else{ int ii = *one.begin(); one.erase(one.begin()); idx[ii].push_back(i); zero.insert(ii); } }else{ num1--; if(num0 <= 0){ puts("-1"); return 0; } if(zero.size() == 0){ puts("-1"); return 0; }else{ int ii = *zero.begin(); zero.erase(zero.begin()); idx[ii].push_back(i); one.insert(ii); } } } if(one.size() > 0){ puts("-1"); return 0; } printf("%d\n", ans); for(int i=0; i<ans; i++){ printf("%d ", idx[i].size()); for(int j=0; j<idx[i].size(); j++){ printf("%d ", idx[i][j]); }puts(""); } return 0; }