2024.12.20 dp 讲课笔记

最小斯坦纳树

允许新加点的最小生成树

目前只有非多项式复杂度解法

模板题:P6192 【模板】最小斯坦纳树

代码

例:QOJ # 5175. 翻修道路

给定 \(n\) 个点 \(m\) 边的有向图,每条边 \(u\rightarrow v\) 有边权 \(a\),可经过一次操作使其变为 \(b\),对于每个 \(0\le x\le m\),求出至多操作 \(x\) 次后,\(\max_{i=1}^k dis(1,p_i)\) 的最小值,\(n,m\le100,k\le8\)

显然 \(1\)\(p_i\) 的最短路的并一定构成以 \(1\) 为根的外向树

建出原图的 反图,则构成内向树

\(dp_{S,i,j}\) 表示考虑内向树的子树 \(i\),其包含 \(p_{1\sim k}\) 的子集 \(S\),其中一共操作了 \(j\) 条边,在此情况下,\(S\) 中点到 \(i\) 的最短路的最大值的最小值

显然 \(\forall1\le i\le k,dp_{\{p_i\},p_i,0}=0\),最终 \(x\) 的答案为 \(\min_{i=0}^x\left(dp_{\{p_1,p_2,\cdots,p_k\},1,x}\right)\)

转移则外层枚举 \(S\)

一种情况是将两个子树合并,转移为

\[dp_{S,u,i+j}\gets max(dp_{S/T,u,i},dp_{T,u,j})(T\subsetneq S,T\ne\emptyset) \]

对于相同的 \(S\)\(u\),显然 \(dp_{S,u,i}\)\(i\) 增加而单调不升

因此对于 \(S\),枚举 \(u,T,i\),指针找到 \(dp_{S/T,u,i}\le dp_{T,u,j}\) 的最大的 \(j\),用其转移一定比用 \(j\) 更大的转移更优

另一种情况是在内向树上向根移动一步,可以操作或不操作那条边,转移为

\[dp_{S,v,i}\gets dp_{S,u,i}+a(u,v) \]

\[dp_{S,v,i+1}\gets dp_{S,u,i}+b(u,v) \]

转移有后效性,需要用 \(dijkstra\) 辅助

总时间复杂度 \(O(3^knm+2^knm\log nm)\)

代码

SOSDP

例 1. [ARC100E] Or Plus Max

对于每个 \(0\le u<2^k\),求出 \(\max_{i\ne j,i|j\le u}a_i+a_j\)

考虑先对于每个 \(0\le u<2^k\),求出 \(dp_u=\max_{i\ne j,(i|j)\subseteq u}a_i+a_j\)

这样原本的 \(\max_{i\ne j,i|j\le u}a_i+a_j\) 可以转化为 \(\max_{0\le i\le u}dp_u\),在输出时前缀 \(\max\) 一下即可

\((i|j)\subseteq u\) 等价于 \(i\subseteq u\)\(j\subseteq u\),又 \(i\ne j\),因此选择 \(\{a_s\mid s\subseteq u\}\) 中最大次大值一定最优

则每个 \(dp\) 为一个二元组,表示最大次大值,初始最大值为其对应 \(a_i\),次大值为 \(-\infty\)

然后对其高维前缀和,其中 \(op\) 为合并两组最大次大求出新的最大次大

时间复杂度 \(O(k2^k)\)

code

例 2:QOJ # 9611. 木桶效应

\(m\)\(1\sim n\) 的排列 \(p_{1\sim m,1\sim n}\),其中 \(q\) 个位置值确定(保证有解),求所有可能方案的 \(\prod_{i=1}^n\min_{j=1}^m p_{j,i}\) 之和取模,\(n\le50,m< MOD(998244353),q\le 10\)

将有确定位置的行前移,设 \(1\sim c_0\) 行有确定位置,其余 \(m-c_0\) 行无确定位置

将有确定位置的列左移,设 \(1\sim c_1\) 列有确定位置,其余 \(n-c_1\) 列无确定位置

显然这样不改变答案

原问题的答案可以转化为:有 \(a_{1\sim n}\)\(p_{1\sim m,1\sim n}\),满足 \(\forall 1\le i\le n,1\le j\le m\),有 \(a_i\le p_{j,i}\),且 \(1\le a_i\le n\)\(p\) 中部分位置确定,求合法的 \((a,p)\) 数量

对于确定的 \(a\),设其排序后结果为 \(x\),则其对应的合法 \(p\) 的数量为 \(\left(\prod_{i=1}^n (i-x_i+1)\right)^{m-c_0}\times\prod_{j=1}^{c_0}\prod_{i=1}^n(i-x_i-num_{i,j}+1)\),其中 \(num_{i,j}\) 为第 \(j\) 行前 \(i\) 个数中,已经确定且不小于 \(i\) 的位置的数量

考虑从小到大向 \(a\) 中填数

\(dp_{i,j,S}\) 为仅填了 \(a\) 中值为 \(1\sim i\) 的位置,\(a_{1\sim c_1}\) 中子集为 \(S\) 的部分已填,剩余列中有 \(j\) 个位置已填,在此情况下 \(a\) 的总贡献

\[dp_{i,j,S}=\sum_{T\subseteq S}\sum_{k\le j}dp_{i-1,k,T}\times\binom{n-m-k}{j-k}\times \left(\prod_{t=|T|+k+1}^{|S|+j}(t-i+1)\right)^{m-c_0}\times\prod_{k=1}^{c_0}\prod_{t=|T|+k+1}^{|S|+k}(t-i-num_{t,k}+1) \]

后面三项分别为选择 \(k\) 列的方案数和两种贡献

第三项化简得

\[ dp_{i,j,S}=\sum_{T\subseteq S}\sum_{k\le j}dp_{i-1,k,T}\times\binom{n-m-k}{j-k}\times \left(\frac{(|S|+j-i+1)!}{(|T|+k-i+1)!}\right)^{m-c_0} \times\prod_{k=1}^{c_0}\frac{}{} \prod_{t=|T|+k+1}^{|S|+k}(t-i-num_{t,k}+1) \]

根据 \(|T|\) 分为 \(n\) 类进行 \(SOSDP\) 即可

时间复杂度 \(O(n^32^mm^2)\),应该可以进一步优化

代码

参考

插头 dp

也称为轮廓线 \(dp\)

例 1:P4262 [Code+#3] 白金元首与莫斯科

\(n\times m\) 的网格,其中若干位置有障碍,对于每个没有障碍的位置,求出若在该位置放置障碍,有多少种方式在无障碍的格子内放置 \(1\times 2\)\(2\times 1\) 的物体,满足其互不重叠(可以不放满),\(n,m\le17\)

\(dp_{i,j,S}\) 表示仅考虑 \(1\sim {i-1}\) 行和第 \(i\) 行前 \(j\) 格的范围,轮廓线状态为 \(S\) 时总方案数,其中 \(S\)\(m+1\) 位的二进制数,依次表示 \(m+1\) 段的状态,编号如下:

@                    j+1 ...  m   @
@                     |       |   @
@              col j  v       v   @
@               +---+--+--+--+--+ @
@ line          |cur|             @
@   i           |blk|<- j         @
@   +--+--+--+--+---+             @
@    ^  ^        ^                @
@    |  |        |                @
@    0  1 ...   j-1               @

若对应位为 \(1\) 则表示有 \(1\times 2\)\(2\times 1\) 的物体跨过这一段轮廓线,反之为没有跨过的

转移需要一定的分类讨论,具体见代码

需要注意一些边界情况

这样可以在 \(O(nm2^m)\) 内解决没有新增障碍的情况

若在 \((i,j)\) 位置新增一个障碍,则可以看做将 \(dp\) 数组和反向 \(dp\) 数组拼起来,需要一定讨论

+-------------------+
|    正向 dp        |
|                   |
|       +---+-------+
|       |i,j|       |
+-------+---+       |
|                   |
|        反向 dp    |
+-------------------+

时间复杂度 \(O(nm2^m)\),常数较大

代码

例 2:P5056 【模板】插头 DP

\(n\times m\) 的矩形上有一些位置为障碍,要用在其余格子铺线,形成一条闭合回路,求总铺法,\(n,m\le12\)

用括号匹配的方式处理回路相交的问题

同样用 \(m+1\) 位数字表示轮廓线状态,但是每一位为 \(0/1/2\),分别表示无穿过的,穿过的为左括号,穿过的为右括号

转移同样需要一定分讨,具体见代码。需要在最后一个非障碍位置处闭合曲线,统计答案

发现有效位置较少,因此用 unordered_map 保存下非 \(0\)\(dp\)

总时间复杂度 \(O(nm^23^m)\),常数极大,但完全跑不满

代码

例 3:P3886 [JLOI2009] 神秘的生物

给定 \(n\times n\) 的矩阵,求其所有联通块中最大的权值和(至少选一格),\(n\le9\)

对于一条轮廓线,显然最多只有 \(5\) 个联通块

将其状压为长 \(n+1\)\(8\) 进制数,使用最小表示法(所有能表示当前状态的 \(8\) 进制数中字典序最小的一个),直接分讨转移即可

理论时间复杂度 \(O(nm6^m)\),常数极大,若使用 unordered_map 优化则完全跑不满

代码

dp 套 dp

内层 \(dp\) 求出外层 \(dp\) 转移到的新状态,外层 \(dp\) 对内层 \(dp\) 计数

例 1:P4590 [TJOI2018] 游园会

求长为 \(n\),字符集为 \(N,O,I\),不含子串 \(NOI\),且与给定串 \(t\)\(LCS\)\(i\) 的字符串数量(对于每个 \(i\) 都求解),\(n\le1000,|t|\le 15\)

外层 \(dp\) 处理不含子串 \(NOI\) 的显著,内层 \(2^{|t|}\) 状压 \(LCS\)\(dp\) 过程

时间复杂度 \(O(nk2^k)\),可优化到 \(O(n2^k+k2^k)\)

代码

例 2:P8352 [SDOI/SXOI2022] 小 N 的独立集

给定 \(n\) 个节点的树,每个点赋 \(1\sim k\) 的权值,对于每个 \(1\le i\le nk\) 求出最大独立集为 \(i\) 的赋值方案数取模,\(n\le1000,k\le5\)

内层 \(dp\) 显然令 \(f_{i,0/1}\) 表示 强制不选节点 \(i\) / 不限制节点 \(i\) 选择情况 的答案,有 \(f_{i,0}\gets f_{i,0}+\max(f_{j,0},f_{j,1})\)\(f_{i,1}\gets f_{i,1}+f_{j,0}\),显然 \(f_{i,1}-k\le f_{i,0}\le f_{i,1}\)

外层 \(dp\)\(dp_{i,j,l}\) 表示节点 \(i\) 处内层 \(dp\)\(f_{i,0}=j\)\(f_{i,1}=j+l\) 时的方案数,显然 \(j=O(nk),l=O(k)\),转移则将其每个儿子依次拼接上去

时间复杂度 \(O(n^2k^4)\),若只转移不为 \(0\) 的位置,则完全跑不满

代码

加强版:QOJ # 8670. 独立

求独立集的期望取模,\(n\le2000,k\le10^8\)

根号分治

例 1:P6189 [NOI Online #1 入门组] 跑步

求和为 \(n\) 的递增序列数量取模,\(n\le10^5\),模数不一定为质数

设立阈值 \(B\),不超过 \(B\) 的完全背包,超过的部分每次加入一个 \(B\),或整体加一

\(B=\sqrt n\),则时间复杂度 \(O(n\sqrt n)\)

代码

例 2:QOJ # 5097. 小 P 爱学习

给定 \(n\times m\) 个互不相同的数,将其分为若干组,满足每组大小都是 \(m\) 的倍数,一种分组方法的权值为每组内数之和的乘积,求所有可能方案的权值和取模,\(n\le1500,m\le100\)

拆贡献,等价于将其划分为若干大小为 \(m\) 倍数的组,从每组中选出一个数,求所有方案选出数的乘积的总和

\(f_i\) 表示从中选出 \(i\) 个数,选出数的乘积的总和,令 \(g_i\) 表示将 \(nm-i\) 本数划分为 \(i\) 个集合(集合之间无序,每个集合大小为 \(km-1\))的方案数,则答案为 \(\sum_{i=1}^n f_i\times g_i \times i!\)

\(f\) 数组容易背包 \(O(n^2m)\) 求,常数不大

根据定义

\[\begin{aligned} g_t=&\sum_{s_{1\sim t}\mid \forall 1\le i< t,s_i\le s_{i+1},\sum s_i = n,s_i\in\Bbb N^+}\binom{nm-t}{s_1m-1,s_2m-1,\cdots,s_tm-1}\\ =&(nm-t)!\sum_{s_{1\sim t}\mid \forall 1\le i< t,s_i\le s_{i+1},\sum s_i = n,s_i\in\Bbb N^+}\;\prod_{i=1}^t\frac1{s_im-1}\\ \end{aligned}\]

\(w_i=\frac1{im-1}\),考虑求出

\[H_t=\sum_{s_{1\sim t}\mid \forall 1\le i< t,s_i\le s_{i+1},\sum s_i = n,s_i\in\Bbb N^+}\;\prod_{i=1}^t w_{s_i} \]

考虑根号分治,设定阈值 \(B\)

\[F_{t,x}=\sum_{s_{1\sim t}\mid \sum s_i = x,s_i\in\Bbb N^+,s_i\le B}\;\prod_{i=1}^t w_{s_i} \]

\[G_{t,x}=\sum_{s_{1\sim t}\mid \sum s_i = x,s_i\in\Bbb N^+,s_i> B}\;\prod_{i=1}^t w_{s_i} \;(t\le\frac nB) \]

(此处值相同但值的下标不同的 \(s\) 不同,即若交换 \(s\) 中值相同的两个位置,\(s\) 变化)

\[H_t=\sum_{a+b=t,A+B=n} F_{a,A} G_{b,B}\times\frac1{a!b!} \]

(由于 \(b\) 不超过 \(\frac nB\),因此此处合并的时间复杂度为 \(O(n^2\cdot\frac nB)\)

\(F\)\(G\) 的边界条件为 \(F_{0,0}=G_{0,0}=1\),转移为

\[F_{t,x}=\sum_{v\le B} F_{t-1,x-v} w_v \]

\[G_{t,x}=\sum_{v> B} G_{t-1,x-v} w_v \]

这部分时间复杂度 \(O(n^2(B+\frac nB))\),取 \(B=\sqrt n\) 最优,为 \(O(n^2\sqrt n)\)

总时间复杂度 \(O(n^2(\sqrt n+m))\)

代码

例 3:QOJ # 9608. 皮鞋的多项式

给定一棵 \(n\) 节点的树,每个节点 \(i\) 有长为 \(k_i\) 的多项式 \(P_i\),令 \(F_x=\prod_{u\in\operatorname{subtree}(x)}P_u\)\(q\) 次询问每次给定 \(l,r,x\),查询 \(\sum_{i=l}^r[x^i] F_x\) 取模,强制在线,\(n\le10^5,q\le10^5,\sum k_i\le2\times10^5\)

设立阈值 \(B\)

每个节点维护两个多项式 \(R_u,S_u\),满足 \(R_u\times S_u=F_u\)\(S_u\) 长度不超过 \(B\)

初始令 \(S_u=P_u\),然后依次将每个儿子的 \(R,S\) 分别与当前处理节点的 \(R_u,S_u\) 相乘,若某时刻 \(S_u\) 长度超过 \(B\),则令 \(R_u\gets R_u\times S_u\) 并令 \(S=1\)

其中 \(S\) 部分的乘法可以暴力实现,令 \(N=\sum k_i\),可证时间复杂度不超过 \(O(N\times B)\)

可证本质不同\(R_i\)(即需要用类似引用计数的方式,相同的直接引用而不是拷贝)数量不超过 \(O(\frac NB)\),因此 \(R_i\) 相关的乘法用 \(NTT\) 即可,这部分总时间复杂度 \(O(\frac NB N\log N)\)

对每个本质不同的 \(R_i\) 做前缀和后,每个询问 \(x,l,r\) 枚举 \(S_x\) 的下标,得到 \(R_x\) 中的下标范围,可 \(O(B)\) 回答

总时间复杂度 \(O(NB+\frac NBN\log N+NB)\)(假定 \(N,q\) 同级)

\(B=\sqrt{N\log N}\),则复杂度为 \(O(N\sqrt{N\log N})\),实际建议取 \(B=\sqrt{2N\log N}\)

代码

分治、闵可夫斯基和

例 1:[ABC383G] Bar Cover

给定 \(a_{1\sim n}\)\(K\),对于每个 \(1\le i\le\lfloor\frac nK\rfloor\),求出从 \(a_{1\sim n}\) 中选出恰好 \(i\) 个长为 \(K\) 的不交区间时,选出数的总和的最大值,\(K\le n\le 2\times 10^5,K\le 5,|a_i|\le10^9\)

考虑分治

在分治树上,令 \(f_{k,l,r,c}\) 为节点 \(k\) 对应区间中,左侧至少 \(l\) 个位置没选,右侧至少 \(r\) 个位置没选,选择了 \(c\) 个位置的总和的最大值,令 \(dp_{k,l,r,c}=f_{k,l,r,c}-f_{k,l,r,c-1}\)(实现时只保存 \(dp\)\(dp_{k,l,r}\) 为一个 vector,以下将 \(dp_{k,l,r}\) 作为转移的单位)(\(0\le l,r<K\)

则答案为 \(dp_{rt,0,0,0\sim\lfloor\frac nk\rfloor-1}\) 的前缀和数组

令节点 \(k\) 对应区间为 \(a[L(k),R(k)]\),中点为 \(M(k)\),左右儿子为 \(lp(k),rp(k)\),其中左儿子对应 \(a[L(k),M(k)]\),右儿子对应 \(a[M(k)+1,R(k)]\)

\(R(k)-L(k)+1<K\),则所有 \(dp_{k,l,r}\) 都为空,因为无法选择

定义 \(\max(a,b)\)(其中 \(a,b\) 为数组)为 \(a\)\(b\) 的前缀和数组补为相同长度(补极小值)后对应项取 \(\max\) 的差分数组

定义数组 \(a\)\(b\)合并数组为满足 \(c_t=\max_{x+y=t}(a_x+b_y)\) 的数组 \(c\),定义 \(\operatorname{mrg}(a,b)\)\(a,b\) 的前缀和数组的合并数组的差分数组

\(A\)\(a\) 的前缀和数组

则转移为

\[dp_{k,l,r}=\max(dp_{k,l,r},\max_{x+y=K,x\ge 1,y\ge 1}\operatorname{mrg}(dp_{lp(k),l,a},dp_{rp(k),b,r},\{A_{M(k)+b}-A_{M(k)-a}\})) \]

可以证明所有 \(f_{k,l,r}\) 都是凸的,因此 \(dp_{k,l,r}\) 为单调的,\(\operatorname{mrg}\) 可用归并实现

总时间复杂度 \(O(k^3\times\frac nk\log\frac nk)=O(nk^2\log\frac nk)\)

代码

可以用 \(slope\;trick\) 做到 \(O(n\log^2n)\)

例 2:gym103202 L. Forged in the Barrens

给定 \(a_{1\sim n}\),对于每个 \(1\le i\le n\),求出将 \(a\) 划分为 \(i\) 个子段后极差总和的最大值,\(n\le2\times10^5\)

等价于将 \(a_{1\sim n}\) 划分为 \(i\) 段,每段选择一个数减,一个数加,两数可以相同,求最大的总和

分治,令 \(dp_{k,0/1/2,0/1/2,c}\) 表示节点 \(k\) 带代表的区间,中间划分为 \(c\) 个完整的段,左侧散段没选 / 选了加上的 / 选了减去的,右侧散段没选 / 选了加上的 / 选了减去的,此时的最大总权值(代码中保存了其差分数组)

叶子处的 \(dp\) 数组取值可以分类讨论该位置不选 / 自成一段 / 加 / 减

合并时枚举分界点所属段的情况即可,需要特殊处理左半段内没有分割点或右半段内没有分割点的情况

可证 \(dp_{k,l,r}\) 为凸的,归并即可

时间复杂度 \(O(n\log n)\),常数较大

代码

杂项

例 1:P2900 [USACO08MAR] Land Acquisition G

给定 \(n\) 个矩形,大小为 \(x_i\times y_i\;(1\le i\le n)\),选择一个子集的代价为子集中最大的 \(x\) 乘以最大的 \(y\),求将全集划分为若干子集的最小总代价,\(n\le5\times10^4,x,y\le10^6\)

相当于平面上有若干点 \((x_i,y_i)\),定义点 \(A\) 覆盖点 \(B\)\(A\)\(x,y\) 坐标都比 \(B\) 大,定义一个点的权值为其两坐标之积,要选择一个点集覆盖所有点,最小化总权值

先移除已经被别的给定点覆盖的点,这样剩下的点可排列为 \(x\) 严格递增,\(y\) 严格递减

最优情况下一个选择的点一定覆盖一个区间

\(f_i\) 表示选择了 \(1\sim i\) 的代价(移除并排序后,令 \(n\) 为剩余点数),则转移为 \(f_i=\min_{0\le j<i}f_j+x_iy_{j+1}\)

可以斜率优化或用李超树

时间复杂度 \(O(n\log n)\)\(O(n\log V)\)

代码

例 2:P5298 [PKUWC2018] Minimax

一棵 \(n\) 点的二叉树,叶子的权值给定且互不相同,非叶子节点 \(i\)\(p_i\) 的概率为其所有儿子的权值的最大值,\(1-p_i\) 的概率为其所有儿子的权值的最小值(\(0<p_i<1\)),设根的权值有 \(m\) 种可能,分别为 \(v_{1\sim m}\),概率分别为 \(p_{1\sim m}\),求出 \(\sum_i iv_ip_i^2\)\(n\le3\times10^5\)

由于 \(0<p_i<1\),根可以取遍所有叶子的权值

因此 \(m\) 等于树的叶子数,\(v_{1\sim m}\) 为每个叶子权值排序后的结果

将叶子的权值离散化为一个 \(1\sim m\) 的排列

\(dp_{u,i}\) 表示节点 \(u\) 的权值为 \(i\)(离散化后)的概率

对于叶子 \(u\),设其离散化后的权值为 \(w_u\),则 \(dp_{u,i}=[i=w_u]\)

对于只有一个儿子 \(w\) 的节点 \(u\)\(dp_{u,i}=dp_{w,i}\)

对于有两个儿子 \(v,w\) 的节点 \(u\),有

\[dp_{u,i}=dp_{w,i}\left(p_u\sum_{j\le i}dp_{v,j}+(1-p_u)\sum_{j\ge i}dp_{v,j}\right)+dp_{v,i}\left(p_u\sum_{j<i}dp_{w,j}+(1-p_u)\sum_{j>i}dp_{w,j}\right) \]

答案式子中的 \(p_i\) 即为 \(dp_{1,i}\)

通过前缀和优化可做到 \(O(n^2)\) \(\quad\) 代码

考虑进一步优化

对于每个 \(dp_{u,\ast}\) 建立一棵动态开点线段树

叶子和只有一个儿子的情况容易处理,考虑如何处理两个儿子合并的情况

考虑修改线段树合并的过程

递归到某个区间 \([l,r]\) 时,维护 \(dp_{v,1\sim l-1}\)\(dp_{v,l+1\sim m}\)\(dp_{w,1\sim l-1}\)\(dp_{w,l+1\sim m}\) 的和(作为参数传入)

若两棵树对应区间都不为空则递归下去,若都为空则直接返回

若有一颗为空,假设是 \(dp_{v,\ast}\) 对应位置为空,记之前四个前后缀和分别为 \(vl,vr,wl,wr\),则对于该区间内的 \(dp_{u,i}\),转移为

\[dp_{u,i}=dp_{w,i}(p_u vl+(1-p_u)vr) \]

因此在 \(dp_{w,\ast}\) 的基础上区间乘以 \(p_u vl+(1-p_u)vr\) 即可

线段树需要维护区间和,支持区间乘

时间复杂度 \(O(n\log^2 n)\)

代码

参考

例 3:P2605 [ZJOI2010] 基站选址

\(n\) 个点坐标为 \(d_{1\sim n}\)\(d_1=0\)),选择一个大小不超过 \(k\) 的子集 \(S\),称一个点 \(i\) 被覆盖当且仅当 \((\exists u\in S)\,\,d_u\in[d_i-s_i,d_i+s_i]\),令被覆盖的点集为 \(T\),最小化 \(\sum_{u\in S} c_u+\sum_{u\notin T}w_u\)\(n\le2\times10^4,k\le100,d_i,s_i\le10^9,c_i,w_i\le10^4\)

\(n,k\) 都加一,并令增加后的 \(d_n=w_n=\infty,c_n=s_n=0\),这样相当于强制令最后一个点必选,且其不影响前面的点,答案显然不变

\(f_{i,j}\) 表示 \(1\sim j\) 中选择不超过 \(i\) 个点,其中点 \(j\) 强制选,该情况下 \(1\sim j\) 内选择点的 \(c_x\) 和未覆盖点的 \(w_x\) 之和

边界为 \(f_{1,i}=c_i+\sum_{j<i}[d_j+s_j<d_i]w_j\),容易预处理后 \(O(n)\) 全部求出,答案为 \(f_{k,n}\)

\(w(i,j)\) 表示选择了 \(i\)\(j\)\(i\)\(j\) 之间没有被覆盖的点的 \(w_x\) 之和(若 \(i\ge j\) 则为 \(0\)

则转移为

\[f_{i,j}=c_j+\min_{1\le l<j}f_{i-1,l}+w(l,j) \]

暴力实现为 \(O(n^2k)\) 的,状态难以优化,考虑优化转移

对于第 \(i\) 层的转移,在枚举 \(j\) 的同时维护一个数组 \(T\),其中 \(T_l=f_{i-1,l}+w(l,j)\),忽略 \(l\ge j\) 的部分,初始 \(T_j=f_{i-1,j}\)

每个转移相当于求 \(T\) 的前缀最小值

\(j\) 加一时,枚举 \(R_u=j\)\(u\)(加一之前的 \(j\)),则 \(T_{1\sim L_u-1}\) 会增加 \(w_u\)(对应范围内点 \(u\) 不再被覆盖)

转化为求前缀最小值,前缀加,线段树维护即可

时间复杂度 \(O(kn\log n)\)

代码

参考

例 4:P5364 [SNOI2017] 礼物

\(f_1=1\)\(f_i=i^k+\sum_{j=1}^{i-1}f_j\),求 \(f_n\)\(n\le10^{18},k\le10\)

维护向量 \([i^0 \,\, i^1 \,\, i^2 \,\, \cdots \,\, i^k \,\, f_i]\),转化为矩阵快速幂

时间复杂度 \(O(k^3\log n)\)

代码

例 5:CF809D Hitchhiking in the Baltic States

给定 \(l_{1\sim n},r_{1\sim n}\),求出 所有 \(a_{1\sim n}\) 满足 \(l_i\le a_i\le r_i\) 的最长严格上升子序列长度的最大值,\(n\le3\times10^5\)\(l_i,r_i\le10^9\)

考虑 \(dp\),令 \(f_{i,j}\) 表示 \(1\sim i\) 中长为 \(j\) 的最长严格上升子序列最后一项的最小值

初始 \(f_{0,\ast}=\infty\)

\(l_i-1\le f_{i-1,j-1}\le r_i-1\) 时,可以在后面追加一个恰好大一的值,此时 \(f_{i-1,j-1}+1\to f_{i,j}\)

\(f_{i-1,j-1}\le l_i-1\) 时,可以追加一个 \(l_i\),此时 \(l_i\to f_{i-1,j}\),而 \(f_{i-1,j-1}=l_i-1\) 时已经被前一种情况覆盖,因此这里只要考虑 \(f_{i-1,j-1}< l_i-1\) 的情况

\(i\) 位置不选择,则 \(f_{i-1,j}\to f_{i,j}\)

显然每个 \(f_{i,\ast}\) 都是严格不降的,因此用一棵平衡树维护

第一种转移相当于找到值在 \([l_i-1,r_i-1]\) 内的区间,全部加一并向后移一位

第二种转移相当于把第一个 \(<l_i-1\) 位置的后一个位置改为 \(l_i\)

两者结合,相当于找到值在 \([l_i-1,r_i-1]\) 内的区间,区间内的数整体加一,区间前面插入一个 \(l_i\),删去区间后面的第一个数(如果存在)

最终答案为平衡树的大小

时间复杂度 \(O(n\log n)\)

代码

例 6:CF1715E Long Way Home

给定一张无向图,节点 \(u\) 和节点 \(v\) 之间有长为 \((u-v)^2\) 的额外边,对于每个 \(i\) 求出 \(1\)\(i\) 经过不超过 \(k\) 条额外边的最短路,\(n\le10^5,k\le20\)

\(dp_{i,j}\) 表示 \(1\)\(j\) 经过不超过 \(i\) 条额外边的最短路

显然 \(dp_{0,1}=0\),答案即为 \(dp_{k,1\sim n}\)

定义 \(dp_{i,\ast}\) 为第 \(i\) 层,则同一层内的可以通过 \(\operatorname{dijkstra}\) 优化,这部分时间复杂度为 \(O(kn\log n)\)

\(i-1\) 层到第 \(i\) 层的转移为

\[dp_{i-1,u}+(u-v)^2\to dp_{i,v} \]

暴力实现为 \(O(n^2k)\)

显然可以斜率优化做到 \(O(nk)\)

总时间复杂度 \(O(kn\log n)\)

代码

例 7:CF1889C2 Doremy's Drying Plan (Hard Version)

给定 \(m\)\([1,n]\) 内的线段,删除至多 \(k\) 条,最大化没有被线段覆盖的整点数量,\(k\le m\le2\times10^5,k\le 10,n\le2\times10^5\)

\(f_{i,j}\) 表示删去 \(i\) 条的情况下 \(1\sim j\) 中没有被覆盖的整点数量的最大值,则 \(f_{i,0}=0\),答案为 \(f\) 的最大值

\(w(k,i)=\sum_{t=1}^n [k<l_t\le i\le r_t]\)

则转移为

\[f_{i,j}=1+\max_{k=0}^{i-1} f_{k,j-w(k,i)} \]

暴力实现可做到 \(O(n^2k)\)

由于 \(w(\ast,i)\) 单调不降,可以将 \([0,i)\) 划分为 \(O(k)\) 个连续子段,每段内 \(w(\ast,i)\) 值相同,转化为 \(O(k)\) 个关于 \(f\)\(\operatorname{RMQ}\),可以通过动态 \(\operatorname{ST}\) 维护

问题转化为快速分段

\(a_{i,j}\) 表示 将所有覆盖位置 \(i\) 的区间的左端点从大到小排序后第 \(j\) 大的值(可重)\(j\le k\)),容易 \(O(kn+m\log m)\) 预处理

则对于 \(i\),有 \(\forall a_{i,c+1}\le x< a_{i,c}\)\(w(x,i)=c\)

总时间复杂度 \(O(kn+m\log m)\)

代码

参考

vjudge 练习

dp,pw:tang

题单,pw:tanger

luogu 题单

DP 优化

参考

动态规划.pdf by cyfff

posted @ 2025-01-29 10:32  Hstry  阅读(43)  评论(0)    收藏  举报