疯狂学习——DP!

斜率优化

P3648 [APIO2014] 序列分割

可以观察到切的顺序无关,则有 \(f_{i,k}=\max f_{j,k-1}+(s_i-s_j)\times s_j\)

\(f_{j,k-1}-s_j^2=-s_i\times s_j+f_{i,k}\)

决策单调性:分治

P4360 [CEOI2004] 锯木厂选址

预处理 \(w,d\) 前缀和以及 \(v_i\) 表示将全部木头移到 \(i\) 的代价。这样可以快速计算 \(cost(i,j)\) 表示将 \(i\sim j\) 全部木头移到 \(j\) 的代价。

枚举第二个锯木厂的位置,设 \(f_i\) 表示将第二个厂设在 \(i\)\(1\sim i\) 的最小代价。转移有 \(f_j=\min\{v_j+cost(i+1,j)\}\),答案即 \(\min\{f_i+cost(i+1,n+1)\}\)。由于 \(f\) 的转移显然具有决策单调性,分治解决。

CF833B The Bakery

显然具有决策单调性,使用「贡献难算」的技巧做到 \(\mathcal{O}(nk\log n)\)

P5574 [CmdOI2019] 任务分配问题

「贡献难算」+树状数组做到 \(\mathcal{O}(nk\log ^2 n)\)

CF1603D Artistic Partition

第一反应就是 DP,但是注意到 \(k\) 很大,怎么办??要想办法降维,观察到 \(c(l,r)\ge r-l+1\),所以当 \(n<2^k\) 时,直接令 \(x_i=2^{i-1}-1\),即可保证 \(c(l,r)=r-l+1\),此时取到理论最小值。

对于 \(n>2^k\) 的部分,DP。对 \(c(l,r)\) 化简

\[=\sum\limits_{d=l}^r\sum\limits_{l\leq i\leq j \leq r}[\gcd(i,j)=d] \]

\[=\sum\limits_{d=l}^r\sum\limits_{i=1}^{r/d}\varphi(i) \]

\(S(i)=\sum\limits_{j=1}^i\varphi(i)\),那么

\[c(l,r)=\sum\limits_{d=l}^rS\left(\dfrac{r}{d}\right) \]

可以证明其满足四边形不等式。整除分块可以做到 \(\mathcal{O}(n\log ^2 n\sqrt{n})\),已经足以通过。

但如果使用「贡献难算」的技巧,左端点移动时只需增加 \(S\left(\dfrac{r}{l}\right)\),时间复杂度 \(\mathcal{O}(1)\)。右端点移动时需要对于所有 \(\dfrac{r-1}{d}<\dfrac{r}{d}\)\(d\) 增加 \(S\left(\dfrac{r}{d}\right)\),这只有在 \(d\mid r\) 时取到,所以时间复杂度 \(\mathcal{O}(n\log ^3n)\)

决策单调性:二分队列

二分队列用来解决满足决策单调性,转移时的贡献能 \(\mathcal{O}(1)\) 计算的 DP 问题。通常情况下的限制为:贡献函数二阶导恒为非负,求最小值二阶导恒为非正,求最大值

具体的,建立一个储存三元组的队列 \((p,l,r)\) 表示 \(l\sim r\) 的最优决策点是 \(p\),步骤如下:

  • 先判断队首三元组是否过时,若 \(r<i\) 则弹出队首,否则将 \(l\) 赋值为 \(i\)
  • 加入决策,如果 \(i\) 相比于队尾的 \(p\) 转移到 \(l\) 更优,根据决策单调性则 \((p,l,r)\) 就完全无用。重复这样操作。
  • 取出队尾的三元组 \((p,l,r)\),我们要二分出一个位置 \(q\),使得 \(q\) 以前的位置从 \(p\) 转移更优,\(q\) 及其以后的位置从 \(i\) 转移更优。注意二分位置从 \(l\)\(r+1\),若 \(q\leq n\) 那么先将队尾的 \(r\) 改为 \(q-1\),再将 \((i,p,n)\) 压入队列。

P1912 [NOI2009] 诗人小G

转移方程形如 \(f_i=\min f_j+|s_i-s_j+i-j-1-L|^P\),贡献可以快速计算。

P3515 [POI2011] Lightning Conductor

就是对于每个 \(i\) 找到最大的 \(a_j+\sqrt{|i-j}\),因为 \(j\in [1,n]\),所以要正反做一遍二分队列。注意用浮点数储存。

决策单调性:二分栈

二分栈用来解决满足如下的决策单调性的 DP 问题:每个决策点 \(j\) 只会被比它更前的决策点 \(i\,(i<j)\) 反超。通常情况下的限制为:贡献函数二阶导恒为非负,求最大值二阶导恒为非正,求最小值。(与二分队列区分。)

用栈维护决策点,设现在栈顶的两个决策点分别是 \(i,j\,(i<j)\),现在要加入 \(k\)。我们二分出 \(i\) 反超 \(j\) 的时间 \(t_1\)\(j\) 反超 \(k\) 的时间 \(t_2\),如果 \(t_1\leq t_2\),那么 \(j\) 就完全无用了,弹出 \(j\)。重复上述操作,最后压入 \(k\)

当然每次转移前要不断二分出次栈顶反超栈顶的时间,如果小于 \(i\) 就不断弹栈。

P5504 [JSOI2011] 柠檬

\(f_i\) 表示以 \(i\) 结尾的答案。注意到一个关键结论:转移仅会发生在同种大小的贝壳之间。于是对每种贝壳单独 DP,转移函数 \((2st^2)''=2s>0\),且求最大值,于是使用二分队列。

posted @ 2024-04-12 21:45  xishanmeigao  阅读(13)  评论(0编辑  收藏  举报