题解 P7914 【[CSP-S 2021] 括号序列】(区间 dp,前缀和优化)
这是一篇带着牢骚的题解(见末尾),为了纪念我支离破碎的 CSP2021。
括号串题,考场上第一眼看过去以为 *
能在满足 \(k\) 的情况下随便插入,于是设 \(f[i][j][k]\) 表示前 \(i\) 个字符、有 \(j\) 个带匹配的 (
、并且末尾有 \(k\) 个连续 *
的合法串数量,随便转移一下就可以了,光速码完后发现过不了第一个样例,然后发现自己太 navie
了。
发现线性 dp 貌似不好实现,改用区间 dp 试试。
设 \(f[l,r]\) 表示区间 \([l,r]\) 的合法串数量,那么有一下几种情况:
-
\(s[l]\) 和 \(s[r]\) 分别可以是
(
和)
,\([l+1,k]\) 可以是*
,那么就由 \(f[k+1,r-1]\) 转移过来。 -
\(s[l]\) 和 \(s[r]\) 分别可以是
(
和)
,\([k,r-1]\) 可以是*
,那么就由 \(f[l+1,k-1]\) 转移过来。 -
\(s[l]\) 和 \(s[r]\) 分别可以是
(
和)
,\([l+1,r-1]\) 可以是*
,那么就由 \(f[l+1,k-1]\) 转移过来。(可以在处理上面两种时顺带转移掉) -
由 \(f[l,k]\) 和 \(f[k+1,r]\) 转移过来。
-
\([k+1,d-1]\) 可以是
*
,由 \(f[l,k]\) 和 \(f[d,r]\) 转移过来。
枚举 \(l\) 和 \(r\) 需要 \(O(n^2)\),其中第 \(5\) 种的转移需要 \(O(n^2)\),复杂度是 \(O(n^4)\),显然过不了。
但仔细发现第 \(5\) 种中 \(d\) 的枚举可以用后缀和优化掉,于是变成了 \(O(n^3)\)。
码完后你就会发现第 \(2\) 给样例过不了。
因为第 \(4\) 种和第 \(5\) 种转移有问题,一个例子: ()()()
。此时 \(f[1,2]\cdot f[3,6]\) 和 \(f[1,4]\cdot f[5,6]\) 两种转移实际上重复了。
怎么解决?
令 \(P\) 为形如 ()
、(A)
、(S)
、(AS)
、(SA)
的串,那么这种会重复转移的串就形如:\(P_1P_2P_3\ldots P_m\)(相邻的 \(P\) 中间有可能有若干 *
,下同),我们可以枚举 \(P_1\),而剩下的 \(P_2P_3\ldots P_m\) 就是一个普通的合法串,这样的转移就没有重复了。
那么我们就可以额外设 \(g[l,r]\) 表示区间 \([l,r]\) 形如 \(P\) 的数量(相当于只有第 \(1,2,3\) 种转移的 \(f[l,r]\))。
过不了第一个样例的线性 dp 代码:link
100pts 的区间 dp 代码:link
最后谈一下感想吧,我本身属于那种思维能力不强的选手,考场上看到 T1T3 这种一股 cf 味的题肯定是放到后面做的。T1T3 暴力写完后去推了会 T1,发现不是单峰函数之后就直接放弃了,接下来就是漫长的刚 T2 的过程,中间无数次发现题目读错,代码删删写写,但是始终过不了第 \(2\) 个样例,最后人已经是麻木的了,最后 15min 的时候回头去看看 T1,发现机廊增加时新来的飞机停在哪个机廊是没有影响的,一个 set 的做法就立马会了,但是最终还是没打完。
考完后发现自己 T2 没过样例 \(2\) 是因为把一个地方的 s[k]
打成了 k
,这么一个 zz 的错误耗掉了几乎整场考试的时间。
或许我可以说,是考场降智没让我一眼看出 T1 的性质。
或许我可以说,是一个手残让我把 T2 的 100pts 亲手变成了 0pts。
或许我可以说,我运气不好,开题的顺序不对,但凡先去刚 T1T3 都能有 200+
但这已经不重要了,重要的就是我很弱,我 cf 打的少,我不敢面对自己思维能力弱这个事实。
现在已经初三了,说早也不早,说晚也不晚。
以前你我见识自为高过世人,我今日才知自误了。以后还该立志功名,以荣耀显达为是。