CF1605B

我们来看一下这道题:

其实是要把 $1$ 都放在 后面,$0$ 都放在前面。

具体一点,假设 $1$ 的个数为 $k$ 个,字符串长度为 $len$,

那么我们要将 $1$ 放在 $len - k + 1$ 到 $len$,将 $0$ 放在 $1$ 到 $len - k$,分两种情况:

  1. $len - k + 1$ 到 $len$ 全是 $1$,则答案为 $0$。
  2. 不全为 $1$,即有 $0$,假定有 $m$ 个 $0$ 在 $len - k + 1$ 到 $len$,显然在 $1$ 到 $len - k$ 也有 $m$ 个 $1$,那我们把这 $2m$ 个字符反转,则会变成后面 $m$ 个变成 $1$,前面 $m$ 个变成 $0$,即总体的$len - k + 1$ 到 $len$ 就全是 $1$ 了,$1$ 到 $len - k$ 就全是 $0$ 了,满足条件!

代码时间到:

#include <cstdio>
#include <iostream>
using namespace std;

const int maxn = 1010;
int num1[maxn], num2[maxn], ans1[maxn], ans2[maxn];
// num1[i]表示从前往后第i个1所在的位置,num2[i]表示从后往前第i个0所在的位置
char c[maxn];

int main() {
    int T; scanf ("%d", &T);
    while (T --) {
        int n; scanf ("%d%s", &n, c + 1);
        int c1 = 0, c2 = 0;
        for (int i = 1; i <= n; ++i) if (c[i] == '1') num1[++c1] = i;
        for (int i = n; i >= 1; --i) if (c[i] == '0') num2[++c2] = i;
        int cnt = 0;
        for (int i = 1; i <= min (c1, c2); ++i) {
            if (num1[i] < num2[i]) {
                ans1[++cnt] = num1[i]; ans2[cnt] = num2[i];
            } else break;
        }
        if (cnt == 0) {
            printf ("0\n"); 这个 0 记得别忘记特判哦!
        } else {
            printf ("1\n%d ", 2 * cnt);
            for (int i = 1; i <= cnt; ++i) printf ("%d ", ans1[i]);
            for (int i = cnt; i >= 1; --i) printf ("%d ", ans2[i]); // 这里记得要倒叙输出!
            printf ("\n");
        }
    }
    return 0;
}
posted @ 2021-11-18 13:48  wangzhongyuan  阅读(2)  评论(0编辑  收藏  举报  来源