题目链接:Zebras
题意
给定一个 字符串,要求找出其中满足下列条件的子序列:
- 子序列中 相间;
- 子序列以 开头,以 结尾;
- 任意两个子序列之间没有交集;
- 所有子序列的并为整个序列。
输出找出的子序列方案,子序列的个数不必最少,只要合法即可。
输入
输入只有一行,为一个只包含 和 的字符串 。
输出
第一行输出一个整数 ,表示子序列的个数,接下去 行,每行表示一个子序列,每行第一个整数为 ,表示第 个子序列中的字符个数,接下去 个整数每个整数表示序列中的第 个元素在原字符串中的下标,下标从 开始。如果无法构造出满足条件的序列,输出 。
样例
输入 |
---|
0010100 |
输出 |
3 3 1 3 4 3 2 5 6 1 7 |
输入 |
---|
111 |
输出 |
-1 |
题解
将所有 字符所在的下标放到一个 中,所有 字符所在的下标放到一个 中,每次交替从这两个 中选出大于当前 或者 的下标的最小值,将这个下标记录到答案中,并从查找的集合中删去,如果某一次查找中,查找到的最后一个数字不是 ,则说明 的数量不够,需要输出 ,如果所有的 间隔序列都查找完毕,而存 的下标的集合仍为非空,则输出 ,其他情况均可以构造出满足条件的 间隔序列,最后注意把所有多出来的 都单独放到一个序列作为答案。
过题代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <algorithm>
#include <sstream>
using namespace std;
#define LL long long
const int maxn = 200000 + 100;
int len, cnt, Index, num;
bool flag;
vector<int> G[maxn];
set<int> st[2];
set<int>::iterator it;
char str[maxn];
int main() {
#ifdef LOCAL
freopen("test.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif // LOCAL
ios::sync_with_stdio(false);
while(scanf("%s", str + 1) != EOF) {
cnt = 0;
flag = true;
len = strlen(str + 1);
st[0].clear();
st[1].clear();
for(int i = 1; i <= len; ++i) {
st[str[i] - '0'].insert(i);
}
while(!st[0].empty() && !st[1].empty()) {
Index = 0;
G[++cnt].clear();
it = st[0].begin();
while(it != st[0].end() && it != st[1].end()) {
num = *it;
G[cnt].push_back(num);
st[Index].erase(it);
Index = 1 - Index;
it = st[Index].upper_bound(num);
}
if(str[G[cnt].back()] == '1') {
flag = false;
break;
}
}
if(!st[1].empty() || !flag) {
printf("-1\n");
continue;
}
while(!st[0].empty()) {
G[++cnt].clear();
G[cnt].push_back(*st[0].begin());
st[0].erase(st[0].begin());
}
printf("%d\n", cnt);
for(int i = 1; i <= cnt; ++i) {
len = G[i].size();
printf("%d", len);
for(int j = 0; j < len; ++j) {
printf(" %d", G[i][j]);
}
printf("\n");
}
}
return 0;
}