最大子段和动态规划_浅谈动态dp

1468ed313e65b24783c228b0f7e7d783.png

编者:樱初音斗橡皮 以及只有几篇题解和一些咕咕咕的东西的blog(真的非常懒。。。咕咕咕)

2020/08/10 update:指出部分事实性错误并修复LaTeX错误。

最近花了许多时间来理解、调试动态 dp 的模板题,终于 AC 了。网上的 blog 看了很多,不过讲得都是一笔带过,让我等蒟蒻很迷茫。。因此决定写一篇看得懂的 blog。。

序列上的动态 dp 问题

1. 单次询问

我们都知道最大子段和问题。

题目链接

问题1. 已知长度为

的序列 ​,求
​。(
​)

解答:设

​ 表示 ​
,则 ​
​ 。

递推求出 ​
后取 ​
即可。

容易写出暴力代码:

ans

这是经典的动态规划入门例题。那么,如果是多次区间询问呢?

2. 区间询问

题目链接

问题2. 已知长度为

​ 的序列 ​
​ 组询问,每次给定 ​
,求 ​
。(
​)

解答:(此处不考虑离线分治、维护区间和与前后缀最大和以及最大子段和等等神奇的解法)

我们把状态转移方程写在这里。

编者于 2020/08/10 注:以下所有状态转移方程和矩阵中,dp数组的含义与上文代码中相同,即 dp[i] 表示“以 i 为结尾的最大子段和”,而非所求的 [L,R] 区间内的最大子段和。求后者需要额外添加一维矩阵状态。

把它写成矩阵形式。

问:慢着,这个矩阵我看着好像不太对?

答:这里我们重新定义了矩阵的运算。

众所周知,

​ 。这里我们把原来的矩阵乘法中,乘法运算替换为加法运算,加法运算替换为
​ 运算,即:

经过手算验证后,我们发现一个惊人的事实:这个新定义的矩阵运算同样满足结合律!即:

(事实上,如果对矩阵中的元素重新定义“乘”和“加”运算(在这里分别是加法和取

​ ),只需满足“乘”对“加”有分配律,即可证明这样的矩阵乘法同样满足结合律。)

因此,我们可以把它写作 ​

而无需打括号。

这样的矩阵有什么用呢?定义 ​

,则容易发现
​ 仅和
有关。

对于一个询问 ​

,答案相当于求
​,而

因此,可以使用线段树/平衡树(

)/猫树(
)/拓展 Tarjan(
,离线)/分块(
)等方法求出
的值,乘以
即可求出答案。

(事实上,我们设 ​

,则 ​
,因此 ​
,其中​
是零向量。)

(值得注意的是,这样的矩阵存在单位元 ​

,但并不一定存在逆,所以不能使用前缀积的方式进行计算,也不能用树状数组维护。)

这种将状态转移方程转化为矩阵乘积再用数据结构维护的方法,就是传说中的动态 dp。

3. 单点修改,区间询问

题目链接

问题3. 已知长度为

​的序列
​ 次操作,包括修改:给定
,把
修改为​
;询问:给定
​,求
​。(​

解答:前面我们提到过,矩阵​

有关,且仅和​
有关。因此,修改
​时,对
​进行修改即可。

这样,问题就变成了单点修改矩阵,区间询问矩阵乘积。可用线段树/平衡树(

)/分块(
​)等维护。

这样的做法,能不能推广到树上去呢?

4. 树上区间赋值,区间询问

题目链接

问题4. 已知节点数为

,带点权的树,​
次操作,包括修改:给定
,把
的链上

的节点点权赋值为

;询问:给定
,求
的链上的最大子段和。

解答:把序列上的东西推广到树上,且树的形态不发生变化,第一个想到的就是树剖。

维护重链信息,我们仍然使用线段树/平衡树/分块。对原树进行树链剖分,修改时,把

的链划分为
条重链,每条重链都用线段树/平衡树/分块维护。区间赋值可以在线段树/平衡树/分块上打延迟标记(lazy-tag)。这样就有一个问题:对于矩阵
是多少?首先可以想到快速幂。然而这样会多一个
。能不能
求出呢?

其实是可以的。设

​,分两种情况讨论:

第一,​

。有:

依此类推,由数学归纳法可证得

​。

第二,​

。有:

依此类推,由数学归纳法可证得

​。

这样,我们就可以通过线段树/平衡树/分块的区间赋值操作, 线段树/平衡树

/分块
完成一次修改。

询问的时候,将询问链拆成

段,求出每一段的矩阵积,再乘起来便可以得到整条链的矩阵乘积。

总时间复杂度:线段树/平衡树

,分块

等等!树上的询问链的问题,除了树链剖分还能想到什么?

对了!还有 LCT(Link-Cut-Tree)。LCT 同样可以维护动态 dp。节点维护单点矩阵和 splay 的子树中矩阵乘积,每次链修改/链查询的时候,把操作链 split 出来,在平衡树上打标记/询问即可。这里要注意的是 splay push_up 操作的时候,必须维护正序及倒序的子树矩阵乘积,且严格按照中序遍历的方法乘。这是因为 LCT 操作的时候需要换根,换根就需要子树翻转。然而和上文

的推导一样,翻转后的子树矩阵可以
推导。关于子树翻转的矩阵变化,读者可以自行推导。

5. 总结

所谓动态 dp,就是把状态转移方程改写为矩阵后用数据结构维护的算法。通常配合线段树/平衡树/分块等维护序列的数据结构使用对于树上的链修改和链查询,可以使用树链剖分。

对于树上的子树查询,需要其它手段,敬请期待我的下一篇文章。

我是yyc樱初音(洛谷:樱初音斗橡皮),是一个初三OIer&MOer,想看更多内容请点赞、收藏,关注我吧!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值