动态dp

动态DP

基础概念#

从一道简单的问题说起#

  • 有一个长度为 n 的序列 ai,每个数可以选或者不选,但相邻两个数不能同时选,最大化选出的数的和。

有一个简单的 dp,设 fi,0/1 表示前 i 个数,第 i 个数是否选了的最大价值,转移时

  • fi,1=fi1,0+ai
  • fi,0=max(fi1,0,fi1,1)

现在把这个问题加强一下:

  • 有一个长度为 n 的序列 ai,每个数可以选或者不选,但相邻两个数不能同时选,最大化选出的数的和,需要支持单点修改和对区间查询。

我们可以把转移写成矩阵的形式:

[fi,0fi,1]=[fi1,0fi1,1]×[0ai0]

其中矩阵乘法定义为 (max,+) 乘法。

不妨令

Mi=[0ai0]

那么答案可以写成

[00]×i=1nMi

现在是单点修改,区间查询,我们可以用线段树维护区间内的 Mi 的乘积,因为矩阵乘法有结合律所以这样做是正确的。

这样子就可以在 Θ(nlogn) 复杂度内解决这个问题。

类似上面的过程,在解决动态,范围查询的动态规划问题时,用数据结构维护矩阵乘法的方式也被称为动态 dp,也可以简称为 ddp。

练习 [ABC246Ex] 01? Queries#

练习 CF750E New Year and Old Subsequence#

树上的情况(静态)#

P5024 [NOIP2018 提高组] 保卫王国#

fx,0/1 表示 x 子树内 , x 是否选了的最小代价,转移是显然的。

同时换根 dp 求出 gx,0/1 代表 x 子树外,x 是否选了的最小代价。

询问时,把所有点拆成 a 子树内,b 子树内,lca(a,b) 的子树外,ab 的路径上。

前三者分别是 fa,fb,glca(a,b),对于后者,我们考虑倍增,设 Fx,k,0/1,0/1 表示 xx2k 级祖先这段范围内(不算 x 子树,但是算路径上其他点的子树),x 是否选了,x2k 级祖先是否选了的最小代价。

那么询问时倍增出一段链上的 F 即可,复杂度 Θ((n+m)logn)

练习 P8820 [CSP-S 2022] 数据传输#

树上的情况(动态)#

P4719 【模板】"动态 DP"&动态树分治#

没有修改时,设 fx,0/1 表示 x 子树内,节点 x 是否选了的最大权值和,转移是显然的:

  • fx,0=ysonxmax(fy,0,fy,1)
  • fx,1=ysonxfy,0+ax

但是树的结构不太好维护信息,因此考虑做一下轻重链剖分,设 hxx 的重儿子。

现在考虑把每个点的 dp 写成关于其重儿子信息的矩阵,轻儿子的信息暴力维护。

对于轻儿子,维护

wx,0=ysonx&yhxmax(fy,0,fy,1)

wx,1=ysonx&yhxfy,0

那么每条重链上的转移可以写成:

[fx,0fx,1]=[fhx,0fhx,1]×[wx,0wx,1+axwx,0]

此时就可以维护每条重链的乘积了。

单点修改时,注意到只有 x 到根这条路径上的点的信息需要修改,并且 w 会发生变化的点一定只有每条重链的链顶的父亲,一共不超过 Θ(logn) 个点,每次修改过 w 之后重新更新一下所在重链的线段树的区间矩阵,再修改该重链链顶父亲的 w,以此类推,需要修改 Θ(logn) 次线段树,因此复杂度为 Θ(mlog2n)

练习 P6021 洪水#

全局平衡二叉树#

全局平衡二叉树是一个可以将普通树剖套线段树变成 1log 的东西。

还是轻重链剖分,对于每条重链,建立一棵特殊的线段树。

sii 的轻子树大小,每次选取 s 的带权中点作为分界线递归。

考虑复杂度,定义一个线段树节点的重量为区间内所有点的轻子树大小和,定义一个线段树叶子的重量为轻子树的大小和,容易发现每次跳父亲重量倍增,因此只会跳 Θ(logn) 次。

P4751 【模板】"动态DP"&动态树分治(加强版)#

进阶题目#

CF1286D LCC#

考虑最先碰撞的一定是相邻两个粒子,具体的,可以相遇,向左追击,向右追击三种。

把所有碰撞所需时间排序,枚举最先碰撞的是哪种情况,那么就是要求时间更小的碰撞都不发生的概率。

相当于有若干限制,形如 i,i+1 不能同时选 xy,记为 oki,x,y=0

那么考虑依旧维护矩阵乘积,转移可以写成

[fi,0fi,1]=[fi1,0fi1,1]×[pi,0×oki1,0,0pi,1×oki1,0,1pi,0×oki1,1,0pi,1×oki1,1,1]

单点更新,全局查询,写一个线段树即可。

复杂度 Θ(nlogn)

P4426 [HNOI/AHOI2018] 毒瘤#

题目保证了 mn10,也就是说,如果我们找出一颗生成树,那么只会有不超过 11 条非树边。

考虑容斥,2m(n1) 枚举每条非树边是否被钦定,对于每条非树边,钦定它连着的两个点同时被选,那么现在问题就是,对于一棵树,每次钦定两个点必须选,或者取消钦定,求这棵树的独立集个数。

用树剖/全局平衡二叉树维护动态 dp 即可。

CF573D Bear and Cavalry#

P6666 [清华集训2016] 数据交互#

ZJOI2022 深搜#

posted @   Larunatrecy  阅读(159)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示
主题色彩