【总结】动态dp
Part 1. 序列动态DP
题目描述
一段区间的价值的定义如下:
可在区间内取任意个数, 这些数位置不能重复 且不能相邻.
其和的最大值为这段区间的价值.
如有序列(1,-1,-2,3,4,2,-1),则区间[4,6]的价值为5。
给定一数列, 要求支持下列两种操作:
- 单点修改
- 查询给定区间价值
对于 100 % 100\% 100% 的数据, n , m ≤ 1 0 5 n,m\le 10^5 n,m≤105.
solution:
序列dp+单点修改。
设 f i , 0 f_{i,0} fi,0 表示不选第 i i i 位时最大和, f i , 1 f_{i,1} fi,1 表示选第 i i i 位时最大和
则有状态转移方程:
f i , 0 = m a x ( f i − 1 , 0 , f i − 1 , 1 ) f_{i,0}=max(f_{i-1,0},f_{i-1,1}) fi,0=max(fi−1,0,fi−1,1)
f i , 1 = f i − 1 , 0 + a i f_{i,1}=f_{i-1,0}+a_i fi,1=fi−1,0+ai
单次查询复杂度 O ( n ) O(n) O(n) ,
修改操作直接 O ( 1 ) O(1) O(1) 修改 a i a_i ai 的值。
有 m m m 次操作,算法总复杂度 O ( n m ) O(nm) O(nm)
这个转移写成矩阵就是:
[ f i − 1 , 0 f i − 1 , 1 ] × [ 0 0 a i − ∞ ] = [ f i , 0 f i , 1 ] \left[ \begin{matrix} f_{i-1,0} \\ f_{i-1,1} \end{matrix} \right] × \left[ \begin{matrix} 0 & 0 \\ a_i & -\infty \end{matrix} \right] =\left[ \begin{matrix} f_{i,0} \\ f_{i,1} \end{matrix} \right] [fi−1,0fi−1,1]×[0ai0−∞]=[fi,0fi,1]
我们把 × 变成了 + ,+ 变成了 max。
令 A i = [ 0 0 a i − ∞ ] A_i=\left[ \begin{matrix} 0 & 0 \\ a_i & -\infty \end{matrix} \right] Ai=[0ai0−∞]
初始值 f L − 1 , 0 = f L − 1 , 1 = 0 f_{L-1,0}=f_{L-1,1}=0 fL−1,0=fL−1,1=0
[ L , R ] [L,R] [L,R] 的价值 = [ 0 0 ] \left[ \begin{matrix} 0 \\ 0 \end{matrix} \right] [00] × ∏ i = L R A i \prod_{i=L}^RA_i ∏i=LRAi
若求得区间矩阵乘积,即可直接求得区间价值。
区间矩阵乘积,可用线段树维护。
Part 2. 树上动态DP
给定一个长度为 n n n 的序列,你需要维护两种操作。
①查询一个区间的最大子段和;
②单点修改(即将一个位置上的数改成另一个数)
n , q ≤ 1 0 5 n , q ≤ 10^5 n,q≤105
solution:
定义 A i = [ 0 0 V i − ∞ ] A_i=\left[ \begin{matrix} 0 & 0 \\ V_i & -\infty \end{matrix} \right] Ai=[0Vi0−∞]
不难把状态转移方程写成这个样子:
[
f
v
,
0
f
v
,
1
]
×
[
f
i
,
0
′
f
i
,
0
′
f
i
,
1
′
−
∞
]
=
[
f
i
,
0
f
i
,
1
]
\left[\begin{matrix}f_{v,0} \\ f_{v,1} \end{matrix}\right]×\left[\begin{matrix}f^{'}_{i,0} & f^{'}_{i,0} \\ f^{'}_{i,1} & -\infty\end{matrix}\right]=\left[\begin{matrix}f_{i,0} \\ f_{i,1}\end{matrix}\right]
[fv,0fv,1]×[fi,0′fi,1′fi,0′−∞]=[fi,0fi,1]
对于链的情况,可以写成这个形式:
[ f x , 0 f x , 1 ] \left[ \begin{matrix} f_{x,0} \\ f_{x,1} \end{matrix} \right] [fx,0fx,1] = ∏ i ∈ s u b s t r e e x [ f i , 0 f i , 0 f i , 1 − ∞ ] \prod_{i\in substree_x}\left[\begin{matrix}f_{i,0} & f_{i,0} \\ f_{i,1} & -\infty\end{matrix}\right] ∏i∈substreex[fi,0fi,1fi,0−∞]
线段树可以维护上面那样序列上的 d p dp dp 转移,注意序列上的 d p dp dp 值是可以通过一个原始值乘上若干转移矩阵得到的。
拿到 x x x 的 f v , 0 , f v , 1 {f_{v,0},f_{v,1}} fv,0,fv,1 后,要把它转化成标准形式。
线段树已经完成了区间合并操作,可以很快得到一个单点的值。
注意这里是单点修改,只对一个儿子产生影响,所以可以在原dp值上进行转移修改。
注意 f v , 0 , f v , 1 {f_{v,0},f_{v,1}} fv,0,fv,1 不包括重儿子,重儿子在线段树上查询即可。
v a l v , 0 , v a l v , 1 val_{v,0},val_{v,1} valv,0,valv,1 和 f v , 0 , f v , 1 f_{v,0},f_{v,1} fv,0,fv,1 必须单独处理,后者是不含 s o n x son_x sonx 的前者转移而来!
__EOF__

本文链接:https://www.cnblogs.com/cqbzly/p/17530348.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」