【学习笔记】连续段 dp

在进行一些序列计数问题时,会遇到状态转移的时候限制 \(a_i\) 与相邻两个数 \(a_{i-1},a_{i+1}\) 的关系(如大小、差值等)。为了更好地解决此类问题,可以在序列两端插入新的值(一般按照大小关系有序插入),所以计数的策略是钦定一些固定的段中间不能再插入新的值了,每次插入只能在两个固定的段中间的区域插入,所以叫做连续段 dp。


P5999

考虑把跳跃的排列拿出来,这个排列需要满足的要求如下:

  • \(p_1 = s,p_n = t\)

  • $\forall 2 \le i \le n - 1 ,(p_i < p_{i-1} \land p_i < p_{i+1}) \lor (p_i > p_{i-1} \land p_i > p_{i+1}) $

考虑从小到大插入数值,钦定一个连续段内都是合法的,且连续段的开头大于它下一个数,连续段的结尾小于它上一个数(首尾除外)。设 \(dp_{i,j}\) 为插入了 \(1 \sim i\),且连续段个数为 \(j\) 的方案数,设 \(d_i = [i>s] + [i>t]\)

考虑转移,特殊处理 \(i=s,i=t\),有 \(dp_{i,j} = dp_{i - 1, j - 1} + dp_{i - 1, j}\),表示是否在开头/结尾新建一段。当 \(i\neq s \land i \neq t\) 时,有三种转移。

  • 新建一个段,\(dp_{i, j} = dp_{i - 1, j - 1} \times (j - d_i)\)

  • 拓展一个段,在本题中,一个合法的连续段无法进行拓展,因为拓展之后这个连续段并不满足第一个/最后一个大于后一个/前一个数了。

  • 合并两个段,\(dp_{i, j} = dp_{i - 1, j + 1} \times j\)

复杂度为 \(\Theta(n^2)\)

CF1515E

可以按照时间顺序依次加入电脑,即先加入第一次开的,再加入第二次开的,在加入的时候考虑是否有 \(i-1,i+1\) 都开了的情况。

相同地,考虑设 \(dp_{i,j}\) 为加入了 \(i\) 个电脑,有 \(j\) 个加入时间的连续段的方案数。由于没有头和尾的限制,所以不用特殊处理,转移如下。

  • 新建一个段,\(dp_{i,j} = dp_{i-1,j-1} \times j\)

  • 拓展一个段,可以一次拓展一个或两个,\(dp_{i,j} = 2j \times (dp_{i-1,j}+dp_{i-2,j})\)

  • 合并两个段,可以一次加入两个或三个到中间,不能只加一个,\(dp_{i,j} = 2j \times dp_{i-2,j+1} + j \times dp_{i-3,j+1}\)

答案即为 \(dp_{n,1}\),复杂度 \(\Theta(n^2)\)

P7967

显然题目可以转化为:对于每个 \(k\) 求排列 \(p\) 的个数满足 \(\sum\limits_{i=1}^{n-1} \max(a_{p_i},a_{p_{i+1}}) = k\),贡献是 \(\binom{l-k}{n}\)

\(a_i\) 排序, 考虑设 \(dp_{i,j,k}\) 为加入了前 \(i\) 小的数,连续段个数为 \(j\),且每个连续段内部的 \(\max(a_{p_i},a_{p_{i+1}})\) 之和为 \(k\) 的方案数。转移和上面类似。

\(dp_{i,j,k} \leftarrow dp_{i-1,j-1,k} \times j, dp_{i,j,k} \leftarrow 2j \times dp_{i-1,j,k-a_i}, dp_{i,j,k} \leftarrow dp_{i-1,j+1,k-2a_i} \times j\),分别表示新建、拓展、合并段。

最后答案即为 \(\sum\limits_{i=0}^l dp_{n,1,i} \times \binom{l-i}{n}\)

复杂度 \(\Theta(n^2 l)\)

P9197

考虑从小到大加入 \(a_i\),那么可以把绝对值拆开,考虑每个数的贡献。对于一个 \(f_i\),若加入 \(i\)\(i\) 左边、右边都没有数,贡献为 \(-2f_i\),若有且仅有一边有数,贡献是 \(0\),否则是 \(2f_i\)

那么可以设计 \(dp_{i,j,k,d}\) 表示加入 \(a_1 \sim a_i\)\(j\) 个连续段,当前所有数的贡献之和为 \(k\) ,开头结尾钦定的个数 \(d\)\(d \in \{0,1,2\}\))的方案数。转移有:

  • \(dp_{i,j,k,d} = dp_{i-1,j-1,k+2f_i,d} \times (j-d)+ dp_{i-1,j-1,k+f_i} \times (3-d) \times [d=1 \lor d=2]\)

  • \(dp_{i,j,k,d} = dp_{i-1,j,k,d} \times (2j - d) + dp_{i-1,j,k-f_i} \times (3-d) \times [d=1 \lor d=2]\)

  • \(dp_{i,j,k,d} = dp_{i-1,j+1,k-2f_i,d} \times j\)

可以发现,由于有正负性的存在,可能 \(k\) 会先减到很小,后面再加回来。所以第三维实际上是 \(\Theta(nl)\) 的,总复杂度是 \(\Theta(n^3l)\) 的,无法通过。

考虑有没有什么办法能让 \(k\) 单调不降。考虑差分,设 \(b_i = a_{i+1} - a_i\),钦定 \(b_n = 0\),那么一个 \(b_i\) 的贡献为满足 \(\min(p_j,p_{j+1}) \le i, \max(p_j,p_{j+1}) > i\)\(j\) 的个数。

那么当加入 \(i\) 时,已经加入的所有数(包括 \(i\))旁边没加入的数的个数之和就是贡献的个数。\(dp\) 状态相同,转移如下。

  • \(dp_{i,j,k,d} = dp_{i-1,j-1,k-b_i(2j-d),d} \times (j-d) + dp_{i-1,j-1,k-b_i(2j-d),d-1} \times (3-d) \times [d=1 \lor d=2]\)

  • \(dp_{i,j,k,d} = dp_{i-1,j,k-b_i(2j-d),d} \times (2j-d) + dp_{i-1,j,k-b_i(2j-d),d-1} \times (3-d) \times [d=1 \lor d=2]\)

  • \(dp_{i,j,k,d} = dp_{i-1,j+1,k-b_i(2j-d),d} \times j\)

答案为 \(\sum\limits_{i=0}^l dp_{n,1,i,2}\),复杂度 \(\Theta(n^2l)\)

posted @ 2024-07-29 20:46  FantasyNumber  阅读(412)  评论(0)    收藏  举报