1 条题解
-
0
自动搬运
来自洛谷,原作者为

Alex_Wei
**搬运于
2025-08-24 22:55:49,当前版本为作者最后更新于2024-02-29 01:03:35,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
P10215 [CTS2024] 字符串游戏
翻转字符串,每次删去 并获得其在 中的出现次数作为分数,记为 ,则有简单 DP:设 表示 的答案,则 。
容易做到 :建出 SAM,转移 前加入 的所有后缀,即从 对应的结点开始在 link 树上跳父亲,并将经过结点的 值加 , 求 。通过 dfs 序拍平换成 BIT,则修改和查询均为 。
次转移是无法接受的。
首先有个很显然的性质,对 ,。于是如果 ,那么 一定更优。因此只需保留 递增的单调栈上的转移点。
此外还有 ,也很容易理解,因为 出现的位置一定也有 出现。这个性质在算法三、四时需要用到。
充分发挥人类智慧,每次只取单调栈上的前 个和后 个转移,无法通过。思考一下什么时候这样做会寄掉。打表观察发现,当字符串形如若干个 拼接时,对较大的 ,若 ,则策略为选择一整个 循环节,但该决策点在单调栈中间,导致不能正确转移。
做法一
继续打出寄掉时单调栈的信息,发现决策点与其下一个位置的 相差不大,但 值相差非常大,根本不是同一个数量级:决策点的位置是前一个 ,且对 ,,但对 ,,其中 是循环节长度。
基于打表观察得出的信息,我们再次充分发挥人类智慧,认为对于单调栈上的相邻两个位置 ,只有当 时, 才会作为转移点,其中 是一个大于且接近 的常数, 即普通单调栈。经测试,取 均可通过, 较小时常数过大, 较大时不能保证正确性。
时间复杂度 ,正确性未知,但是比 std 快。
做法二
从出题人角度思考,一定会造出大循环串套小循环串卡掉这种做法。循环串会导致单调栈上一段区间的 形成等差数列,大胆猜测根据某种神秘的单调性,只保留等差数列的两端是正确的,或者说,很难卡掉正确性。但是转移点数量依然为 。
既然只保留一条直线的两端是可行的(指可以通过本题测试数据的正确性验证,并非结论),考虑到斜率会下降,我们不妨更大胆一些,只保留凸包上的点(每个点的横坐标是它在单调栈上的位置,不是在原序列的位置,很幽默)。虽然转移点数量为 ,不仅时间复杂度不对,正确性也没有保证,但它就是通过了,而且比 std 快。
做法三
一个不那么明显的观察是,对 ,当 时, 减小的量不大于 减小的量。因为 出现的地方 一定出现,而 相较于 少出现的地方, 也一定相对应地相较于 少出现了。
于是一个位置会被它之前的位置反超,这是另类决策单调性,使用二分栈解决,时间复杂度 。需在线计算 ,需要可持久化线段树,常数过大导致无法通过。
做法四
考虑所有没有被 弹出的单调栈上的位置,设最后一个这样的位置为 ,则 。对 ,若 是 的决策点,则
$$f_p \geq occ(q + 1, p) - f_q \geq occ(q + 1, i) - f_q = f_i > f_p $$矛盾。这说明每次只需用栈顶位置 更新 ,若 则弹出,否则退出。
时间复杂度 。需要倍增定位子串,这也是做法一、二比做法四更快的原因。
- 1
信息
- ID
- 9853
- 时间
- 2000ms
- 内存
- 512MiB
- 难度
- 7
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者