记一类连续段dp

连续段 dp 通常用在,需要同时考虑值在序列上位置,和相邻值关系的计数问题上。

此时如果我们直接常规 dp,需要记录每个数是否用过,复杂度容易退化到指数级。

此时可以考虑把 dp 搬到值域上,由于转移仅关心大小关系或者仅关心较大值,此时所有的连续段都等价的,即可快速转移。

此类 dp 的状态设计通常为 dp[i][k][...] 表示考虑完前 \(i\) 小的元素,连成 \(k\) 个连续段,满足 ... 条件的方案数,状态设计在满足大小关系(已填入的数 \(\le\) 当前数)的基础上能够简单更新。

转移一般含三种:新增一段;连在某一段 左/右 侧;合并两个段。

复杂度 \(\mathcal O(n^2F)\)\(F\) 是剩下部分的复杂度。


P5999 [CEOI 2016] kangaroo

显然这里只关心每个数与相邻两个数的位置关系

而我们的转移方式天然钦定了大小关系。显然连在某一段一侧的转移是不合法的,剩下两种都是合法的。

注意这里要额外考虑数是否在边界上,额外增加一维表示边界是否被占即可。


P9197 [JOI Open 2016] 摩天大楼

即求 \(\sum |a_i-a_{i-1}|=k\) 的方案数。

按值域从小往大枚举,转移顺序天然钦定大小关系,在小的数上 \(-v\),在大的数上 \(+v\),即可查分出 \(|a_i-a_{i-1}|\)

但是这样会导致值域过大,也可以记录段的边界和数的差,例如,假如当前数下降了 \(v\),且有 \(k\) 个边界,那么总和即增加 \(kv\)

这道题也要考虑边界问题。


P7967 [COCI 2021/2022 #2] Magneti

即求 \(\sum \max(a_i,a_{i-1})=k\) 的方案数。

这里转移仅关心较大值。我们直接从小到大枚举转移即可。

posted @ 2026-07-19 10:42  CuteNess  阅读(4)  评论(0)    收藏  举报