连续段DP

参考资料

插入类型 DP
连续段 DP
插入 DP 总结 题目多。
插入 dp 学习笔记 这个题目也不少,并且除了套路之外,还有不少比较乱搞的。


简介

连续段 DP,也叫插入 DP,这是一个经典的 DP trick,与传统序列上的DP不同,他不需要考虑元素具体是什么,他只需要考虑相对顺序。

引入

一般来说,用连续段 DP 解决的题目有如下特征:

  • 元素不能重复使用,一般与排列计数有关(这种比较板)。

  • 需要满足一定的条件,一般与大小关系、位置关系有关(用插入 DP 后就是与插入顺序有关了)。

  • 可能需要满足一些函数性质,比如说像波浪形函数一样,比如说 kangoroo。

解法

核心就是对插入过程进行 DP,只考虑考虑插入相对顺序,结合具体题目具体分析。

  • 乱搞型:状态定义不那么确定,但是始终围绕这新元素插入这一核心。
  • 套路型:\(f_{i,j}\) 表示插入前 \(i\) 个数分成了 \(j\) 个连续段,转移就是考虑三种操作加入、新开、合并,不用考虑连续段之间的下标间隔问题,因为不合法的一定不在最终答案里。

注意事项

  1. 结合具体题目分析,不要看到满足特征就套。

题目

[ABC468G] Restricted Permutation \(\checkmark\)

题目大意

给定长度为 \(n\) 的字符串 \(s\)(仅含 o 和 x)。求满足以下条件的 \(1\sim n\) 排列 \(P\) 的数量 \(\bmod 998244353\):对每个 \(k=1,\dots,n\),\(s_k=\) o 当且仅当 \(P\) 中存在一个连续子序列恰好是 \(1,2,\dots,k\) 的某个排列,否则,若不存在则 \(s_k=\) x。
\(1\le N\le 2000\),\(S\) 仅含 o 和 x。

解题思路

套路化的,我们设 \(f_{i,j}\) 表示插入前 \(i\) 个数分成 \(j\) 个连续段的答案,转移如下:

  • 新开一个段:\(f_{i,j}\gets j\times f_{i-1,j-1}\)。
  • 加入旧段:\(f_{i,j}\gets 2j\times f_{i-1,j}\)
  • 合并两个段:\(f_{i,j} \gets j\times f_{i-1,j+1}\)。

需要注意的是,如果 \(s_i=\) o,\(j=1\);如果 \(s_i\ne\) x,\(j>1\),最后答案是 \(f_{n,1}\),需要特判一下开头和结尾是不是 o。

复杂度 \(O(n^2)\)。

CF1515E Phoenix and Computers \(\checkmark\)

题目大意

有 \(n\) 台电脑排成一排,初始全关。每次手动打开一台未打开的电脑;若某台电脑左右相邻都已打开且它未打开,则自动打开。求手动打开所有电脑的不同顺序数量(手动打开的电脑集合或顺序不同即不同)对质数 \(M\) 取模。
\(3\le n\le 400,\ 10^8\le M\le 10^9\),\(M\) 为质数。

解题思路

这道题明显与连续段有关,并且考虑的是打开电脑也就是插入的顺序,这无比完美的适配于连续段 DP。
类似的,设 \(dp_{i,j}\) 表示打开了 \(i\) 台电脑,并形成了 \(j\) 段。

转移如下,这题还需要考虑自动打开的情况:

  1. 新建段:\(dp_{i+1,j+1} \leftarrow dp_{i,j} \times (j+1)\)
  2. 加入某一段:\(dp_{i+1,j} \leftarrow dp_{i,j} \times 2 \times j\),\(dp_{i+2,j} \leftarrow dp_{i,j} \times 2 \times j\)
  3. 合并块:\(dp_{i+2,j-1} \leftarrow dp_{i,j} \times 2 \times (j-1)\),\(dp_{i+3,j-1} \leftarrow dp_{i,j} \times (j-1)\) 注意合并块不能有 \(dp_{i+1,j-1} \leftarrow dp_{i,j} \times (j-1)\),因为会自动打开。

刷表完成转移即可,答案是 \(dp_{n,1}\)。

复杂度 \(O(n^2)\)。

P5999 [CEOI 2016] kangaroo \(\checkmark\)

题目大意

从 \(s\) 出发到 \(t\),经过 \(1\sim n\) 每个草丛恰好一次,要求每次跳跃方向与前一次相反(即路径呈锯齿形),求不同访问顺序的方案数 \(\bmod 10^9+7\)。
\(2\le n\le 2\times10^3,\ 1\le s,t\le n\),保证至少有一种方案。

解题思路

这题并没有那么显然,它满足的特征就是排列+函数型,这种我们就可以考虑插入去考虑,至于怎么想到的嘛?这就有点智慧了。

我们一样的状态定义,从小到大枚举插入,但需要注意的是,这道题需要保证波浪形,所以我们不考虑加入操作(因为他可能会破坏形状),只考虑合并和新开,这样就有一个性质,连续段左右端点一定比再往里一个的要小,可以保证波浪形了。转移是比较简单的需要注意的是,类似于第一个题,但是需要注意的是考虑到 \(s\) 和 \(t\) 之后不能新开在开头或者结尾了,并且插入 \(s\) 和 \(t\) 的操作比较特别,它们可以考虑加入,需要特别记录一下是否到 \(s,t\)。

复杂度 \(O(n^2)\)。

P7967 [COCI 2021/2022 #2] Magneti \(\checkmark\)

题目大意

在 \(l\) 个连续空位上放置 \(n\) 个磁铁(每个空位最多一个),所有磁铁必须放置。第 \(i\) 个磁铁有吸引半径 \(a_i\),若两个磁铁之间的距离小于 \(a_i\),则它们会相互吸引。求使得任意两个磁铁都不相互吸引的方案数,对 \(10^9+7\) 取模。
\(1\le n\le 50,\ n\le l\le 10000,\ 1\le r_i\le l\)。

解题思路

这道题明显没有这么直接了当了,他多加了一个覆盖限制,不过还是好做的,我们还是记录连续段个数,同时也要记录这些连续段总的覆盖长度,最后拿插板法算一算。

首先按照 \(a_i\) 从小到大排序(这样就使得在转移中的方便考虑很多),定义 \(f_{i,j,k}\) 表示添加了 \(1\sim i\) 个磁铁,连续段个数为 \(j\),总覆盖长度(不延伸出去)为 \(k\) 的方案数。

转移方程:

  • 新开:\(f_{i,j,k}\gets j\times f_{i-1,j-1,k-1}\)。
  • 加入:\(f_{i,j,k}\gets 2j\times f_{i-1,j,k-a_i}\)。
  • 合并:\(f_{i,j,k}\gets j\times f_{i-1,j+1,k-2a_i+1}\)

答案:\(\sum_{k=1}^l f_{n,1,k}\times {l-k+n\choose n}\)。

复杂度:\(O(n^2 l)\)。

posted @ 2026-09-20 09:24  lcx_OIer  阅读(27)  评论(0)    收藏  举报