0%

CF-1075-E. Majority Wins?

题目大意

题目总结:Majority Wins?

1. 目标

给定一个长度为 nn 的二进制字符串 ss,通过最少总代价的操作将其最终转化为一个只包含字符 1 的字符串(即长度为 1 且内容为 1)。

2. 操作定义

在当前字符串中选择一段连续的子串 g[lr]g[l \dots r],计算其中 01 出现的次数:

  • 如果某个字符出现的次数 不少于 另一个字符(即出现次数 \ge 另一方),则可以用该字符替换掉整个子串。

  • 操作代价:等于该子串的长度,即 rl+1r - l + 1

  • 你可以进行多次操作,每次操作后的字符串长度会缩短。

例如,字符串010010可以通过用成本为44的操作将子串1001替换为1来在一次操作中转换为010;字符串1111可以通过在整个字符串上执行成本为44的操作转换为1;字符串0100可以通过取子串100转换为00。

3. 输出要求

  • 输出将字符串转化为 1 的最小总代价。

  • 如果无法转化,则输出 1


样例解释

  • 样例 1 (0):由于只有一个 0,无法通过任何操作产生 1。输出 1

  • 样例 2 (1):已经是 1,无需操作。输出 0

  • 样例 4 (10):选择子串 10(长度 2),其中 1 的数量(1个)不少于 0 的数量(1个),可替换为 1。代价为 2

  • 样例 5 (010)

    1. 选择子串 01 替换为 1,字符串变为 10,代价为 22
    2. 选择子串 10 替换为 1,代价为 22
    3. 总代价 2+2=42 + 2 = 4
  • 样例 6 (00111000)

    1. 选择子串 001111 占多数)替换为 1,字符串变为 1000,代价 55
    2. 选择子串 101 不少于 0)替换为 1,字符串变为 100,代价 22
    3. 再次对 10 进行操作变为 1,字符串变为 1,代价 22
    4. 总代价 5+2+2=95 + 2 + 2 = 9

思路讲解

其实这道题目就是一个分类讨论,感觉放在 C 也没什么问题。

  1. E was proposed as C, and C as B

不难发现,答案再大,不会超过 n+3n+3

image

然后直接输出 nn 的情况就是 1 的数量大于等于 0 的数量的时候。

输出 n+1n+1 是什么情况呢?首先 01 串首部或者尾部为 1 时,输出这个 n+1n+1

还有就是当存在一个位置,使得 suf(1)suf(0)+1\text{suf}(1)≥\text{suf}(0)+1 数量的时候(这个是因为多容纳一个 0 也没事)(suf(x)\text{suf}(x) 代表该位置后缀 xx 数量)。

同理可得 pre(1)pre(0)+1\text{pre}(1)≥\text{pre}(0)+1

那么什么时候输出这个 n+2n+2 呢?当存在一个位置,使得 suf(1)suf(0)\text{suf}(1)≥\text{suf}(0) 数量的时候(表示肯定有 0 嘛,那么我们不妨消掉一个,就可以回到上面一种情况)。

同理可得 pre(1)pre(0)\text{pre}(1)≥\text{pre}(0)

其他情况,就输出 n+3n+3

然后,你忐忑地提交了,发现 WA 了,为什么呢?对拍!

1
2
3
1
10
0000110000

该样例也应该输出这个 n+2n+2,但是我们输出了 n+3n+3,这个是因为什么呢?

image

我们发现 ‘11' 这个东西非常特殊,可以压制两边的 0,你会发现,‘101’ 就不可以压制两边的 0 了。

因此,只要找到 ‘11' 那么答案不会大于 n+2n+2

1
2
3
if (s.find("11")!=string::npos) {
ans=min(ans,N+2);
}

再次忐忑地提交,你发现竟然过了?

AC代码

AC

https://codeforces.com/contest/2189/submission/360277668

心路历程(WA,TLE,MLE……)