BISHI88 小苯的魔法染色¶
中等通过率 26.42%python3样例通过牛客 AC贪心二分字符串
讲解章节:二分
一句话
至多 m 次区间覆盖,每次长度 <= k,把所有 'W' 盖住,求最小 k。
解题思路¶
这题考什么¶
二分答案 + 贪心判定。k 越大越容易完成,可行性对 k 单调,于是二分 k。 二分答案见 44-二分,区间覆盖贪心见 47-贪心。
判定 check(k):从左往右扫,遇到第一个还没被盖住的 'W'(设在位置 p), 最优做法一定是把区间放成 [p, p+k-1]——起点再往左只会浪费长度, 往右就盖不住 p。于是贪心地放一段、跳到 p+k 之后继续找下一个未覆盖的 'W', 统计用了几段,段数 <= m 即可行。这个贪心是「最少区间覆盖点集」的标准结论。
数据规模与复杂度¶
n <= 2e5。判定 O(n)(每次只在 W 位置列表上跳,用 bisect 更快, 但线性扫已经够),二分 log n ≈ 18 次,总计约 3.6e6,稳过。 这里把所有 W 的下标先收集成数组,判定时用 bisect 跳到下一个未覆盖的 W, 单次判定降到 O(段数 * log n),比逐格扫更快。
坑在哪¶
- 若字符串本身全是 'R'(无 W),答案是 0 而不是 1。 题面「输出一个正整数」是假的:实测数据里有全 R 的测试点,期望输出 0。 一次都不用施法,最小的 k 自然是 0;
- m <= n 保证了 k = n 一定可行(一次盖全),二分右端取 n 即可;
- 「至多 m 次」——用不满不扣分,判定写 <= m 而不是 == m;
- 输入的字符串单独一行且不含空格,用 split() 按 token 取正好是一整个串。
样例复核¶
n=5, m=2, s="WRWWR",W 在下标 0,2,3。 k=2: 盖 [0,1],下一个未覆盖 W 是 2,盖 [2,3],共 2 段 <= 2 ✓; k=1: 需要 3 段 > 2 ✗。答案 2,与样例一致。
参考实现¶
[:octicons-arrow-left-16: BISHI87](BISHI87.md) [BISHI89 :octicons-arrow-right-16:](BISHI89.md)