dp优化瞎吹
dp优化瞎吹
众所周知,我们在dp的转移过程中,可以用一些方法,优化它的转移复杂度。
由于我这边的资料不多,并且例题要么很简单,要么很难,所以我学的脑子有点乱,东西也乱,抱歉啊
前言
对于dp的优化,我个人有些浅显的理解,不知恰当不恰当
我感觉它大概就是,我先写一个dp,再想办法把它变得更快。
怎样更快呢?我可以优化状态数,也可以优化转移。
对于状态数的优化,在dp基础那一篇里有些许提到。而这里主要是针对转移的优化。
转移可以怎么优化呢?我可以 打表 观察转移点的规律,减少转移数;也可以用数据结构,直球的加速转移。
数据结构优化
最直白的一种。这种直接对着转移做就行了。
如果转移是一段 前缀/后缀的和/min/max/积/啥别的, 我们可以使用前缀和优化。这种非常傻逼,例题略。
如果转移是一段区间的min/max/啥别的,还要带修改,那估计得上线段树优化。当然,有一种特殊的:我们的区间长成一段滑动窗口,并且求min/max,我们可以使用单调队列优化,少一个log
然后就是,对于 \(f_i+...\rightarrow f_{i+1}\) 这样的转移,发现它是一个区间平移操作,可以利用平衡树的插入操作支持,因为插入相当于自带一个“让位置”。
以下是例题。
线段树优化:CF833B
很容易写出暴力dp:\(f(k,i)\) 表示分了 \(k\) 段,选到 \(i\) 位置,最大的价值和。
那么 \(f(k,i)=\max\ f(k-1,j)+w(j+1,i)\),\(w(l,r)\) 表示 \([l,r]\) 里面不同种类数。
然后我们发现这个东西可以用pre数组贡献出来:对于 \([j+1,i]\) 中的位置,如果它 \(pre\le j\) ,那就贡献 \(1\)。
枚举 \(k\) ,然后枚举 \(i\)。线段树维护:对于每个 \(j\),当前取 \(j\) 位置转移,权值 \(f(k-1,j)+w(j+1,i)\) 能取到多少。首先用 \(f(k-1,*)\) 作为权值建一颗数,对于每个新来的 \(i\),对于 \((pre_i,i]\) 区间内的 \(j\),可以多一个贡献出来,给它权值 \(+1\) 就行。我们发现它很明显可以线段树维护:区间+1,区间求max。
然后就搞一遍,复杂度 \(O(nk\log n)\)
平衡树优化:CF809D
就拿LIS的那个dp做,发现是一个区间平移的形式,啪的一下打完平衡树,很快啊,哎,就A掉了
另见:这里,这边主要讲的是做dp的思维方法,更加详细一些
决策单调性
对于 \(f_i\),我们要选一个 \(j<i\),使得 \(g(j)+w(j,i)\) 最优化(可能是min/max)。
设 \(p_i\) 表示 \(i\) 这个位置的最优决策点。如果这个 \(p\) 是递增的,这个就叫 决策单调性
如果有这个性质,咋搞呢?我们可以分治,设 calc(l,r,L,R)
表示,要求区间 \([l,r]\) 的dp值,当前的转移位置区间确定在 \([L,R]\) 中。设 \(mid\) 为 \(l,r\) 中点,暴力找到它的最优位置 \(p\),然后由决策单调性递归确定左右两边的转移位置,递归调用 calc(l,mid-1,L,p),calc(mid+1,r,p,R)
即可。复杂度一个 \(\log\)。
除此之外,有些决策单调性的题目也可以在单调栈上二分。不过复杂度一样,并且适用的范围完全被包含了,所以我没有去学,也不太会。
那如何发现这个性质呢?如果足够聪明,你可以脑子里想到几个东西,然后推一推,很快就可以推出来这个性质。如果你不够聪明,像我一样,就可以使用打表,发现这个 \(p\) 好像增。多造点数据,assert一波,发现确实没问题,诶↑,单调性来了。
我们也可以取观摩一下 FlashHu的博客,然后根据函数的交点数/导数等性质,判断它是否满足决策单调性。
以下是例题。
POI2011
LightningUZ Conductor (幻视)
首先转换为 \(p\ge a_j-a_i+\sqrt{|i-j|}\)。那就变成对于每个 \(i\),求 \(j\) 使得后面那一坨最大。把 \(j<i\) 和 \(j>i\) 分开做,最后合并一下即可。现考虑 \(j<i\)
可以用一个dp,\(f(i)=\max\left(a_j+\sqrt{|i-j|}\right)-a_i\)
我们可以用数学方法推式子来证明它的决策单调性,也可以观察打表,发现它的决策单调性。
然后就随便做一波就行了。
CF868F
首先,我们使用理性证明 打表,百度,谷歌 等方法发现了决策单调性。证明详见上面FlashHu的博客。
然后用分治算就行了。
过程中,我们发现,我们需要一个够快的方法来支持区间权值的询问。可以考虑像莫队一样增/减一个位置来移动区间。我们又发现,同一层里面,区间 \(l,r\) 都是递增的,所以区间移动 不会增加 分治决策单调性的复杂度
斜率优化
见 这里
四边形不等式
对于一个区间dp,枚举一个中间断点转移的那种,我们可以观察它的最优转移点取在哪。然后有的时候,我们就会发现一个和决策单调性有点类似的性质。设 \(p(l,r)\) 表示 \(l,r\) 的转移点,那么: \(p(l,r-1)\le p(l,r)\le p(l+1,r)\)。此时我们可以用一个和决策单调性类似的继承转移位置的策略,我们不从 \(l\) 开始,而是直接从以前确定好的 \(p\) 开始,看哪个点最优。容易证明这个复杂度是均摊 \(O(n^2)\) 的。
经典例题如石子合并,可以做到 \(O(n^2)\)。
如果用另一种算法结合平衡树,可以做到 \(O(n\log n)\),我不说是哪个
那么四边形不等式是什么呢?
定义:若二元函数 \(f(x,y)\) 对于 \(l\le l'\le r'\le r\),有:\(f(l,r)+f(l',r')\ge f(l,l')+f(r,r')\),则称 \(f\) 满足 四边形不等式
若有一个dp,形如:\(f(l,r)=w(l,r)+\max\{(l,k)+f(k+1,r)\}\),则以下三个命题等价:
- \(f\) 满足四边形不等式
- \(w\) 满足四边形不等式
- \(f\) 的最优转移位置 \(p\),满足 \(p(l,r-1)\le p(l,r)\le p(l+1,r)\)
证明:我不会,可以感性理解,领悟它的正确性(
更多例题:我不清楚
原文地址:https://www.cnblogs.com/LightningUZ/p/15115066.html
- Go语言struct类型详解
- spark1.x升级spark2如何升级及需要考虑的问题
- 使用 kubeadm 创建一个 kubernetes 集群
- Oracle 12c 多租户专题|CDB元数据内幕
- 深入分析golang多值返回以及闭包的实现
- Hadoop3.0扩展Yarn资源模型详解2:资源Profiles说明
- hdu------(1525)Euclid's Game(博弈决策树)
- Go语言指针访问结构体的方法
- Spring Boot & Spring Cloud 应用内存管理
- hdu----(1849)Rabbit and Grass(简单的尼姆博弈)
- 10分钟让你明白MySQL是如何利用索引的
- 扩展Yarn资源模型详解1
- hdu-------(1848)Fibonacci again and again(sg函数版的尼姆博弈)
- go语言实现将重要数据写入图片中
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Linux shell中这7种运算命令值得掌握!
- 快速掌握shell脚本数组,看这篇
- 详解shell脚本的环境、普通、特殊变量
- 玩转zabbix之超详细的二进制安装
- 玩转zabbix之源码编译安装,添加主机监控
- 总结一篇shell调试技巧及常见的脚本错误
- 备战金九银十:当你裸辞遇到了面试难,你需要了解一下这些面试题
- 看完这7个测试常见问题总结,你的面试就成功了80%
- geant4入门讲解篇-2
- Geant4-怎样设置你的粒子源--精简注释+收藏版
- Geant4--一次编译,运行多个Run,极大提升模拟效率
- Geant4--是怎样使用的?--(1.信息抽取)
- ROOT-数据读取-直方图-Roofit拟合基本流程-(入门实用)
- 最简单的基于FFmpeg的直播系统开发移动端例子:IOS 视频解码器
- 哇塞哇塞--一行命令搞定视频截取和gif制作!