序列上动态 $dp$
引入-普通的序列上动态 $dp$
已知长度 $n$ 的序列 $A$ ,$q$ 组询问中每次给定 $L,R$ ,求 $\max_{L\leq l\leq r\leq R} \sum_{i=l}^r a_i$
注:这是 $\text{WC2018}$ 猫锟的课件例题
可以用线段树 $(O(N+Q\log N))$ ,猫树 $O(N\log N+Q)$ , 拓展 $\text{Tarjan}$ 离线 $(O(N+Q\log N))$ ,分块 $(O(N+Q\sqrt N))$ ,论文 $O(N+Q)$ 求出 $M_RM_{R-1}…M_{L+1}$ 的值,并乘 $\begin{bmatrix}A_L \\ 0\end{bmatrix}$ 求出答案
这不是重点
对于序列 $a$ 上操作,有如下的贪心算法:
记录 $cur,ans$ ,有转移:
重新定义矩阵运算,乘法改为加法,加法改为取 $\max$ :
谔谔谔,注意 $mat_{1,2}$ 这个讨论了之前的 $cur,ans$ 都 $<a_i$ 的情况,一般来说重新定义的矩阵乘法中能处理该问题,但再输出答案时需要对此进行取 $\max$
至此,最大子区间和中每一位的转移可以以矩阵的形式被表示,单点修改对应单个矩阵的修改
可能有人发现矩阵的式子和猫老师的不太一样,原因是wtcl,按猫老师的式子写不出来>﹏<
1 | const int INF=2147483647>>2; |
更复杂一点的序列上动态 $dp$
CF750E New Year and Old Subsequence
给定一个数字序列,每次询问一个区间,求区间内至少删去几个字符可以是该串包含子序列 $2017$ ,且不包含 $2016$
好吧猫老师还有需要支持单点修改的
没有删除操作的话就不怎么算是动态dp了(
首先由题得,这里的矩阵乘法中加法将被定义为取 $\min$
用 $0/1/2/3/4$ 替代 $\varnothing/2/20/201/2017$
设 $f_{i,0/1/2/3/4}$ 表示最少需要删去多少个字符才能在 $[1,i]$ 中包含 $\varnothing/2/20/201/2017$
有转移:
注意不成立的时候值应设为 $INF$
如此常系数齐次线性递推式可以变成矩阵形式
同上,线段树维护一下矩阵乘即可
1 | struct Matrix{ |
树上动态 $dp$
概述
树上动态 $dp$ 指一类支持树上单点修改全局查询题,一些信息可以通过暴力的线性树形 $dp$ 求出,一些问题需要支持子树或链上询问 $dp$ 值
转化
显然这类问题无法继续套用序列上的算法,而一种思路就是将其转化为序列问题—树链剖分—每一条重链都是一个序列上的问题
对于每一个节点的 $dp$ 值,如果其儿子都计算完毕,则可以计算该点的 $dp$ 值。于是可以选择任意符合该条件的顺序进行 $dp$
与之类似的,如果一条重链 $A$ 的顶端节点的父亲在重链 $B$ 中,就令 $A$ 的父亲重链为 $B$ ,由此能得到一颗重链树
如果按照重链树的顺序,且每条重链从下往上计算,则是合法的,因为每个儿子不是某条子重链的顶端(轻儿子),就是重儿子
- 为什么是重链剖分
- 重链至多 $\log n$条,时间复杂度不劣
- 一条重链在 $dfn$ 上的区间连续
- 重链的链尾都是叶子节点,易于处理起始状态
转移
对于一条重链上的问题
轻儿子的 $dp$ 值已经被计算,和节点本身的值可一起被视作输入
而修改的时候,按照重链树形一条一条往上改,每次会单点修改重链上一个点的本身或者轻边的信息
由此,问题被转化为了 $\log n$ 条重链上做序列动态 $dp$ 问题
例题-单点修改,区间询问
P4719 【模板】”动态 DP”&动态树分治
给出一棵树,每个点有点权,要求支持单点点权修改,查询以 $1$ 为根的一颗子树的最大权独立集
最大权独立集:相连的点不同时选得到的权值最大的点集
首先考虑弱化版,即没有修改操作
暴力 $dp$ :设 $f_{i,c}$ 表示以 $i$ 为根的子树中满足 $c=[i 在所选独立集中]$ 的最大独立集,有转移:
再考虑完整的问题:怎样再重链里快速修改并查询该链的 $dp$ 值
不妨设点 $i$ 的编号就是 $i$ ,$g_{i,0/1}$ 表示点 $i$ 的轻儿子可取可不取/都不取的最大权独立集,那么有:
由此易得,在重链上:
观察式子不难发现,前两项看作输入的一部分,仅有最后一项和 $f_{i+1,}$ 有关,这里着重说明*如何构造矩阵的转移:
首先发现 $c=1$ 时 $g_{i,1},a_i$ 都仅与 $i$ 有关,考虑如何合并:更改 $g_{i,0/1}$ 的定义为: $i$ 号点只考虑轻儿子取自己的最大权独立集
那么式子变为 $f_{i,c}=g_{i,c}+\max\{f_{i+1,0},f_{i+1,1}-\infin\times c\}$
先将 $f$ 的转移方程拆开并变形:
然后把已知状态和要转移的状态写在一起:
$1\times 2$ 的矩阵形成了 $1\times 2$ 的矩阵,那么矩阵 $X$ 为 $2\times 2$
把位置对应上去有:
那么有:
再考虑矩阵乘法的顺序:初始信息位于叶子节点,即链尾处,由于 $dfn$ ,链尾在区间右端,链头在左端,所以矩阵乘法应是转移矩阵在前,要维护的在后,即:
1 | const int N=1e5+5; |
P5024 [NOIP2018 提高组] 保卫王国
一棵树,有点权,要求最小权覆盖集,其中每组询问指定两个点的状态(选/不选)
最小权覆盖集=全集-最大权独立集
强制选择/不选相当于把该点权值改为 $\pm INF$
参考模板题即可
1 |
|
P3781 [SDOI2017]切树游戏
给定一颗有点权无根树,一颗树的价值为其所有点权值的异或和,支持两种操作:单点修改,查询有多少棵树满足价值为 $k$
照例先考虑暴力 $dp$ :
设 $f_{i,j}$ 表示深度最小点(最高点)异或和为 $j$ 的连通块个数,答案即为 $\sum_{i=1}^n f_{i,k}$
易得转移为:$\displaystyle{f_{u,k}=\sum_{i\oplus j=k} f_{u,i}\times f_{v,j}+f_{u,k}}$
枚举 $i,j$ 有复杂度 $O(nm\times 128^2)$
观察到式子的下标是异或卷积的形式,$FWT$ 显然能优化到 $O(nm\times 128\log 128)$ ,但可以一直使用 $FWT$ 的数组计算,仅在开始结尾做 $FWT$ 的转化,时间复杂度可被简化为 $O((n+\log 128)\times 128)$
注意:如此后异或卷积 $a=b*c$ 为 $FWT_a=FWT_b · FWT_c$ ,即逐位相乘
考虑额外记录 $h_{i,k}$ 表示 $i$ 子树中 $f_{i,k}$ 的和,使 $dp$ 有子树的阶段性
再考虑到易于转移(过于简洁)的 $dp$ 式子,发现这是一个支持单点修改,查询的树上动态 $dp$ ,具体过程见上面,这里略
再从生成函数(多项式?) 的角度来更好的表达 $dp$ 过程:
对于每个节点 $u$ 上的所有 $f_{u,*}$ ,考虑用一个生成函数来表示所有的情况,即:
其中 $z$ 就是无实意的未知数( $x$ ),其项数 $i$ 表示子树权值为 $i$ ,前面的系数自然就是权值为 $i$ 的情况数
那么 $dp$ 转移能被简化为:
$val_u$ 是节点 $u$ 的权值,后面的 $z^0$ 作用显然: 设 $u$ 有两个子节点 $v1,v2$ ,将式子展开后能看出 $z^0$ 的作用:
显而易见,$z^0$ 保证了对于 $u$ 的子节点不同的选择方法,进一步展开后能发现选 $\{v1,v2\},\{v1\},\{v2\},\{\varnothing\}$ 的不同方案都被涵盖
对于重链上每个点 $i$ ,将 $i$ 的所有轻儿子 $lson_i$ 的 $F_{lson,z}+z^0$ 做卷积就能考虑所有轻儿子对于该子树的贡献,即
类比于 $F_{i,z}$ 的定义,对于 $h_{i,*}$ 定义 $H_{i,z}$
对于每个点再记录 $LH_{i,z}$ 表示点 $i$ 的每个轻儿子的 $H_{lson_i,z}$ 的和,即
由此,可以用线段树维护每个点的轻边的信息,而求出 $F_{hson,z},H_{hson,z}$ 后就能维护父亲重链的信息
对于一条重链,设重链上点深度从小到大为 $p_1,…,p_c$ ,那么有:
那么能得到矩阵转移:
这个 $3\times 3$ 的矩阵转移会导致要做 $27$ 次生成函数乘法,考虑如何优化
猫老师告诉我们,矩阵乘法对形如 $\begin{bmatrix}a & b & 0 \\ 0 & 1 & 0 \\ c & d & 1\end{bmatrix}$ 的矩阵是封闭的,即:
这样就优化为了 $4$ 次生成函数乘法
至此,这道 树剖后矩阵乘法卷积维护前缀和转多项式生成函数套个 $FWT$ 后上线段树 的题就完成了。。。吗?
树剖在洛谷上被卡掉了qwq,$80$ 分走人
1 |
|