Codeforces 949A Zebras(构造)

题目链接:Zebras

题意

给定一个 01 01 字符串,要求找出其中满足下列条件的子序列:

  1. 子序列中 01 01 相间;
  2. 子序列以 0 0 开头,以 0 结尾;
  3. 任意两个子序列之间没有交集;
  4. 所有子序列的并为整个序列。

输出找出的子序列方案,子序列的个数不必最少,只要合法即可。

输入

输入只有一行,为一个只包含 0 0 1 的字符串 s (1|s|2×105) s   ( 1 ≤ | s | ≤ 2 × 10 5 )

输出

第一行输出一个整数 k (1k|s|) k   ( 1 ≤ k ≤ | s | ) ,表示子序列的个数,接下去 k k 行,每行表示一个子序列,每行第一个整数为 li (1li|s|),表示第 i i 个子序列中的字符个数,接下去 li 个整数每个整数表示序列中的第 j j 个元素在原字符串中的下标,下标从 1 开始。如果无法构造出满足条件的序列,输出 1 − 1

样例

输入
0010100
输出
3
3 1 3 4
3 2 5 6
1 7
输入
111
输出
-1
题解

将所有 0 0 字符所在的下标放到一个 set 中,所有 1 1 字符所在的下标放到一个 set 中,每次交替从这两个 set s e t 中选出大于当前 0 0 或者 1 的下标的最小值,将这个下标记录到答案中,并从查找的集合中删去,如果某一次查找中,查找到的最后一个数字不是 0 0 ,则说明 0 的数量不够,需要输出 1 − 1 ,如果所有的 01 01 间隔序列都查找完毕,而存 1 1 的下标的集合仍为非空,则输出 1,其他情况均可以构造出满足条件的 01 01 间隔序列,最后注意把所有多出来的 0 0 <script type="math/tex" id="MathJax-Element-58">0</script> 都单独放到一个序列作为答案。

过题代码

#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值