Loading

7.1 CW 模拟赛 T3. 列序号括

前言

打的太烂了, 一定要注意策略

心态, 策略, 停滞
注意规划一下停滞时间

思路

删除一个合法括号序列, 问你删除后字典序最小的的合法括号序列是多少

我草, 场上啥都不会, 我要把失去的拿回来

考虑一下 \(n \leq 500\)
因为是取不取一个点的问题, 所以尝试类分段法

\(f_{i, j}\) 表示以 \(i\) 开头的子序列, 现在被删除的左括号个数减去右括号个数为 \(j\) 时的最小字典序
那么不难发现

\[ \begin{align*} f_{i, j} \stackrel{\min}{\longleftarrow} \begin{cases} f_{k, j + 1} & s_i =\; ) \\ f_{k, j - 1} & s_i = ( \end{cases} \end{align*} \]

比较可爱的是这个东西达到了 \(\mathcal{O} (n^3)\), 这是优化之后的复杂度, 因为字符串操作的复杂度是 \(\mathcal{O} (n)\)

考虑优化
\(\rm{dp}\) 已经没有优化空间了

考虑一个性质, 我们每次删除一段之后, 一定要和之后的左括号/空位接壤不然一定是不优的
也就是说, 只要确定要删一个左括号, 那么这个左括号所在的一段的下一段右括号都必须被删除
根据这个结论我们可以发现每次删除的都是一个合法括号子串
我草, 这个性质真是能看出来的吗?

但是反正别管这那的了, 有了这个性质可以干掉 \(j\) 变成 \(\mathcal{O} (n^2)\)

考虑这种字典序比较我们是有先例的: [USACO23DEC] Minimum Longest Trip G
看一下能不能类似的做

显然是可以的, 我们只需要动态维护 \(lst_{i, j}\) 表示 \(f_i\) 之前 \(2^j\) 的点和对应的 \(\rm{hash}\) 值即可


破防专用分界线


因为删除的要是一个合法括号子串, 所以我们可以考虑在转移过程中维护删除左端点数量\(-\)删除右端点数量
又因为字典序的特殊性质, 我们倒着维护
显然是一个取不取问题, 用经典做法做到 \(\mathcal{O} (n^3)\)

考虑优化这个算法\((\)不优化最终做法, 因为我觉得我看不出来这个性质\()\)
显然只能优化字典序比较部分, 动态维护状态链和 \(\rm{hash}\) 值, 以及状态对应的位置即可

总结

选不选, 选多少问题的经典做法

神奇的性质, 摆了

字典序问题特有的比较方法

注意到状态转移构成的是一个有向无环图, 所以可以动态维护状态链和 \(\rm{hash}\) 值, 以及状态对应的位置

posted @ 2025-07-07 19:07  Yorg  阅读(7)  评论(0)    收藏  举报