疯狂学习——DP!

斜率优化

P3648 [APIO2014] 序列分割

可以观察到切的顺序无关,则有 fi,k=maxfj,k1+(sisj)×sj

fj,k1sj2=si×sj+fi,k

决策单调性:分治

P4360 [CEOI2004] 锯木厂选址

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

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

CF833B The Bakery

显然具有决策单调性,使用「贡献难算」的技巧做到 O(nklogn)

P5574 [CmdOI2019] 任务分配问题

「贡献难算」+树状数组做到 O(nklog2n)

CF1603D Artistic Partition

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

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

=d=lrlijr[gcd(i,j)=d]

=d=lri=1r/dφ(i)

S(i)=j=1iφ(i),那么

c(l,r)=d=lrS(rd)

可以证明其满足四边形不等式。整除分块可以做到 O(nlog2nn),已经足以通过。

但如果使用「贡献难算」的技巧,左端点移动时只需增加 S(rl),时间复杂度 O(1)。右端点移动时需要对于所有 r1d<rdd 增加 S(rd),这只有在 dr 时取到,所以时间复杂度 O(nlog3n)

决策单调性:二分队列

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

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

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

P1912 [NOI2009] 诗人小G

转移方程形如 fi=minfj+|sisj+ij1L|P,贡献可以快速计算。

P3515 [POI2011] Lightning Conductor

就是对于每个 i 找到最大的 aj+|ij,因为 j[1,n],所以要正反做一遍二分队列。注意用浮点数储存。

决策单调性:二分栈

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

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

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

P5504 [JSOI2011] 柠檬

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

posted @   xishanmeigao  阅读(21)  评论(0编辑  收藏  举报
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示