「动态规划」第2章 数据结构优化 DP
总结
这些题目都是先要列出形式比较好的 DP 转移式。最好是一维、二维数点形式的。然后使用树状数组和线段树优化。有时可以直接上前缀和优化。
此外,为了减少转移式的复杂性,如果某一维度的转移非常简单(例如只 \(dp_{\dots,j}\) 只从 \(dp_{\dots,j-1}\) 转移而来),那么这一维度就可以放在最外层循环。
例题
A. 【例题1】递增子序列
给定一个长度为 \(n\) 的序列,求有多少个子序列满足长度为 \(m\),并且递增。
答案对 \(123456789\) 取模。
设 \(dp_{i,j}\) 表示 \(i\) 结尾的长为 \(j\) 的上升子序列的个数。\(dp_{i,j}=\sum\limits_{a_k<a_i}dp_{k,j-1}\)。显然这可以用树状数组优化,把 \(j\) 的循环放在外面就可以用一个树状数组搞定。做完了。
B. 基站选址
注意到可以预处理 \(st_i,ed_i\),表示如果要满足 \(i\) 位置,必须在 \([st_i,ed_i]\) 的村庄中建设至少一个基站。
状态:\(dp_{i,j}\) 表示考虑前 \(i\) 个村庄,强制选择 \(i\),已经选择了 \(j\) 个的最小代价。
转移:\(dp_{i,j}=dp_{k,j-1}+c_i+cost(i,j)\) 其中 \(cost(i,j)=\sum\limits_{st_o>k,ed_o<i}w_o\)。后者是一个二位数点,将所有村庄按照 \(ed\) 排序,再用线段树维护就行了。
C. 折线统计
注意:连续多个点呈现上升趋势,视为一段上升段。反之亦然。
先把这些点对 \(x_i\) 排序。设 \(dp_{i,j,0/1}\) 表示考虑前 \(i\) 个点,选取了 \(j\) 个,最后一段上升/下降的方案数。
\(dp_{i,j,0}=\sum\limits_{a_k<a_i}(dp_{k,j,0}+dp_{k,j-1,1})\)
\(dp_{i,j,1}=\sum\limits_{a_k>a_i}(dp_{k,j,1}+dp_{k,j-1,0})\)
之后用树状数组优化即可。
D. 免费馅饼
做法略。讲一点关键点:列出了转移的限制之后,检查这个限制能否转化为二维数点。
E. 优美玉米
需要一定的注意力才能注意到“所有操作都一定是后缀操作”。做法略。
F. 地精部落
感觉和 C 题没什么区别,乐。做法略。

浙公网安备 33010602011771号