[经典题]括号序列

题目

题目描述
一个序列的子序列如果是合法括号序列,就称其为 “合括子序列” 。如果一个序列的所有 “合括子序列” 中的最长者,长度恰为 2 k 2k 2k ,则该序列是 “好的” 。求长度为 n n n 的 “好的” 序列个数。

数据范围与提示
数据组数 T ≤ 2 × 1 0 5 T\le 2\times 10^5 T≤2×105 ,数据范围 2 k ≤ n ≤ 2 × 1 0 5 2k\le n\le 2\times 10^5 2k≤n≤2×105 。

思路

首先要进行一个转换。设 ( 为 + 1 +1 +1 ,) 为 − 1 -1 −1 ,设前缀和为 s i s_i si​ ,则 “合括子序列” 最长者的长度为
n − s n + 2 min ⁡ i = 1 n s i n-s_n+2\min_{i=1}^{n}s_i n−sn​+2i=1minn​si​

理由很简单。在 s i ≥ 0 s_i\ge 0 si​≥0 的情况下,左括号多,必然可以全部匹配。出现问题肯定是第一个 s i = − 1 s_i=-1 si​=−1 。此时你可以 重新设置零点,因为这个 ) 是无用的,如果 s s s 只统计使用了的括号,后面的 s s s 实际上都要 + 1 +1 +1 才对。于是乎,后面即使再出现 s j = − 1 s_j=-1 sj​=−1 也是完全匹配的情况。下一个转折点是 s j = − 2 s_j=-2 sj​=−2 ,又可以重新设置零点。一共有 ∣ min ⁡ s i ∣ |\min s_i| ∣minsi​∣ 个转折点,也就有这么多个右括号没有被用到。

最后一截还可能剩余了左括号。最后的剩余左括号数量是 s n s_n sn​ 吗?错,是 s n + ∣ min ⁡ s i ∣ s_n+|\min s_i| sn​+∣minsi​∣ 才对。别忘了我们重新设置了零点的。显然 s n + ∣ min ⁡ s i ∣ s_n+|\min s_i| sn​+∣minsi​∣ 为非负整数。所以 n n n 减去二者即是 n − s n − 2 ∣ min ⁡ s i ∣ n-s_n-2|\min s_i| n−sn​−2∣minsi​∣ 为 “合括子序列” 最长的长度。考虑到 min ⁡ s i ≤ 0 \min s_i\le 0 minsi​≤0 就把绝对值符号去掉了而已。

有了这个式子,考虑枚举 t = min ⁡ s i t=\min s_i t=minsi​ ,此时必然需要
s n = n − 2 k + 2 t s_n=n-2k+2t sn​=n−2k+2t

如何计算方案数?把 s i s_i si​ 随 i i i 变化的图像画出来,再把坐标系旋转 4 5 ∘ 45^{\circ} 45∘ ,这不就是格点图内的移动吗?终止点是 ( n − s n 2 , n + s n 2 ) (\frac{n-s_n}{2},\frac{n+s_n}{2}) (2n−sn​​,2n+sn​​) 。而 t t t 的限制成为了不能越过 y = x + t y=x+t y=x+t 这条直线,且必须碰触一次。卡特兰的变形嘛。方案数
( n ( n + s n ) / 2 ) − ( n ( n + s n ) / 2 − t + 1 ) {n\choose (n+s_n)/2}-{n\choose (n+s_n)/2-t+1} ((n+sn​)/2n​)−((n+sn​)/2−t+1n​)

别忘了 s n s_n sn​ 和 t t t 并不是独立的。将 s n s_n sn​ 用 t t t 替换,你会惊讶的发现第二个组合数内的 t t t 消失了!
( n n − k + t ) − ( n n − k + 1 ) {n\choose n-k+t}-{n\choose n-k+1} (n−k+tn​)−(n−k+1n​)

为了确保碰触一次,减去没能越过 y = x + t + 1 y=x+t+1 y=x+t+1 这条直线的方案数,即 ( n k − t ) − ( n n − k ) {n\choose k-t}-{n\choose n-k} (k−tn​)−(n−kn​) 后,我们知道了 t = min ⁡ s i t=\min s_i t=minsi​ 的方案数是
( n k ) − ( n k − 1 ) {n\choose k}-{n\choose k-1} (kn​)−(k−1n​)

你没看错,跟 t t t 无关!而 t t t 的取值是多少呢?只要 y = x + t y=x+t y=x+t 能在 ( 0 , 0 ) (0,0) (0,0) 去 ( n − s n 2 , n + s n 2 ) (\frac{n-s_n}{2},\frac{n+s_n}{2}) (2n−sn​​,2n+sn​​) 的路径中出现就可以。也就是 f ( n − s n 2 ) ∈ [ 0 , n + s n 2 ] f(\frac{n-s_n}{2})\in[0,\frac{n+s_n}{2}] f(2n−sn​​)∈[0,2n+sn​​] 且 f ( 0 ) ≤ 0 f(0)\le 0 f(0)≤0 。解出
2 k − n ≤ t ≤ 0 2k-n\le t\le 0 2k−n≤t≤0

进而 t t t 的取值数量是 n − 2 k + 1 n-2k+1 n−2k+1 ,乘以每个 t t t 的方案数就是答案了。竟然是 O ( 1 ) \mathcal O(1) O(1) 计算,这难道不令人啧啧惊奇吗?

代码

输出 ( n − 2 k + 1 ) ( C n k − C n k − 1 ) (n-2k+1)(C_{n}^{k}-C_{n}^{k-1}) (n−2k+1)(Cnk​−Cnk−1​) 你都不会么?

上一篇:自闭症青年的突显网络、默认模式网络和*执行网络功能连接的差异


下一篇:7.mongoose 默认校验参数和自定义校验器