ARC089D 题解

First Post:

Last Update:

感觉这题顺推下来并不难,关键是对过程中的一些 case 如何统一起来,从而减少讨论工作量。 结论比较有意思,但整道题过程较繁琐。也是一道好题。

先考虑对于结果序列 ,我们能不能将其染成。

首先对于 中为白色的部分,其两边是独立的子问题。可以分开。

先考虑 没有白色的情况,因为操作都是区间覆盖,所以 中的相等连续段可以缩在一起。此时 一定是 RB 交错的形式。注意到如果首尾为 B,在首尾添加一个 R 没有影响(只需要让第一次 R 操作"扩大"一下即可)。所以,每一种只有红蓝色的结果序列,都能被化归到 的形式。

那最后的 也可以看作若干段 与中间一些 拼成的串。设共有 段,每段长度为 。(下文的“长度” 都定义为其中 的个数)

我们考虑一个长度为 的段需要什么样的操作将其染成。

时,只需一个操作 时,需要两个操作 时,操作序列 都是可行的。

用数学归纳法可以得到,当 时,只要操作序列前两个是 ,后面接 个任意字符就行。显然这也是充要条件。

此时我们发现 要分开考虑,枚举 表示 的个数。那我们需要将 串分为 个满足那些段的操作序列。

那么在原串中找到最前面的 。在最前面的 后面分别找到最前的一个 与其配对。将这些字符标记为已经使用。显然我们找到的这些作为那 个操作序列的开头一定是不劣的。

表示第 后面的空余字符数。我们将 从小到大排序,对 的限制就是

考虑 DP 排序后的 数组,设 表示当前到第 位,当前 。转移枚举下一个 相等段的长度 与值 。(乘组合数是因为我们 DP 的是排序后的 数组,要乘组合数还原成排序前的)。

容易用前缀和优化做到

但我们还要解决一个问题,现在我们考虑的 都对应的是原序列的一段 ,怎么将我们考虑的东西还原到原序列上。

先考虑单个 的部分,它恰好有 段,但是首尾两段可能为空,那么我们在这个部分的两端加入两个虚拟,此时这两段不可能为空,但序列长度变成 。这一个段与两边的两个 一共会形成 个分界点,但又是首尾有例外,所以我们在原序列首尾各加一个 ,此时序列长度为 ,一共有 个分界点,那么将缩段后的序列对应到原序列的方案数就是

综上所述,我们枚举 ,表示总的 RB 段数以及单个 R 的段数,然后找到最前的 与对应最前的 ,接着跑那个 DP,最后枚举 的值统计答案。总时间复杂度上界为 ,但显然跑不满,很轻松地过了