学习笔记——斜率优化dp
注:文中全部图片均为手绘,不喜勿喷
总论
斜率优化是dp优化中极其常用的一种手法
第一点,先要懂什么是凸包与单调队列
先来看看凸多边形是什么样
接着再是斜率及斜率优化
一、凸包及凸多边形
凸多边形
就像这样
这就不是
即所有角都 ≤ 180 \leq180 ≤180°
凸包
一条折线,满足斜率(定义看下面)单调递增或递减,例如
二、 单调队列
请看下图
三、斜率
进入正题
什么是斜率?
严谨一点讲:
斜率 k = Δ y Δ x k=\frac{\Delta y}{\Delta x} k=ΔxΔy
其中, Δ x \Delta x Δx 与 Δ y \Delta y Δy 表示横坐标差与纵坐标差
在 Δ x \Delta x Δx 为 0 的时候,即该直线与 y y y 轴平行,该直线斜率不存在或认为趋向于 ∞
一次函数中, f ( x ) = a x + b f(x)=ax+b f(x)=ax+b,a就是其函数影像的斜率
一篇博客少不了一道题
例题——斜率
输入格式
第一行两个整数 n n n 和 m m m 。
接下来 n n n 行,每行两个整数,表示一个点的坐标。
接下来 m m m 行,每行一个整数,表示一条直线的斜率。
输出格式
对于每个斜率 k k k ,输出 k x + y kx+y kx+y 的最大值, 其中 ( x , y ) (x,y) (x,y) 是给出的 n n n 个点中的一个。
样例
输入
5 4
-1 1
1 2
3 4
4 3
5 6
-2
3
-5
10
输出
3
21
6
56
数据范围与提示
n , m n,m n,m 的范围 [ 1 , 1 0 5 ] [1,10^5] [1,105]; x , y , k x,y,k x,y,k 的范围 [ − 1 0 9 , 1 0 9 ] [-10^9,10^9] [−109,109] 。
思路
一看这题的数据范围,暴力绝对挂,必须考虑优化
首先,暴力的思想是:
a n s = max { x i k + y i } ( 1 ≤ i ≤ n ) ans=\max\{x_ik+y_i\}(1\leq i\leq n) ans=max{xik+yi}(1≤i≤n)
我们考虑舍去多余的判断
不妨先将节点按x轴排序
当 ( x j , y j ) (x_j,y_j) (xj,yj) 比 ( x i , y i ) ( i < j ) (x_i,y_i)~(i<j) (xi,yi) (i<j) 更优时候,有
k x i + y i < k x j + y j kx_i+y_i< kx_j+y_j kxi+yi<kxj+yj
k ( x j − x i ) > y i − y j k(x_j-x_i)> y_i-y_j k(xj−xi)>yi−yj
− k < y i − y j x i − x j = k j ↔ i -k<\frac{y_i-y_j}{x_i-x_j}=k_{j\leftrightarrow i} −k<xi−xjyi−yj=kj↔i
k x ↔ y k_{x\leftrightarrow y} kx↔y 表示连接 x x x 和 y y y 的线的斜率
显然,一个点只有比两侧的点更优,才可能是最优决策点
则对于每次询问的 k k k ,若点 i i i 是决策点,一定存在 k i ↔ i − 1 ≥ − k > k i + 1 ↔ i k_{i\leftrightarrow i-1}\geq -k>k_{i+1\leftrightarrow i} ki↔i−1≥−k>ki+1↔i
很明显,后一个的斜率 < < <前一个的斜率,是一个上凸包(如图)
这样,我们的目的变为维护一个上凸包,即斜率递减
可以利用类似单调栈的方法:遇到一个点 i i i先将其与队末连线,如果产生了一个下凸包,则删掉队末……直至满足条件。然后加入 i i i点(是类似单调栈哦!与单调栈还是不同的)
均摊复杂度 O ( 1 ) O(1) O(1)(证明:因为每个数都最多加入一次,删除一次)
循环结束后
对于每个询问,如何求出最优解?
不难发现,对于询问的 k k k,
当 k j − 1 ↔ j > − k k_{j-1\leftrightarrow j}>-k kj−1↔j>−k,则 j j j一定是 [ 1 , j ] [1,j] [1,j]中的最优决策点
当 k j − 1 ↔ j ≤ − k k_{j-1\leftrightarrow j}\leq -k kj−1↔j≤−k,则 j j j一定是 [ j , n ] [j,n] [j,n]中的最优决策点
每次二分答案,可做到 O ( n log n ) O(n\log n) O(nlogn)
当然,可以利用单指针,将k从小到大排序,离线处理
证明:
因为 k k k越大,其答案斜率越小,可以往更后面处理,理论 O ( n log n ) O(n\log n) O(nlogn)或 O ( n + p ) , p = max { k i } ( 1 ≤ i ≤ m ) O(n+p),p=\max\{k_i\}(1\leq i\leq m) O(n+p),p=max{ki}(1≤i≤m)
对于此题,至少 O ( n log n ) O(n\log n) O(nlogn),即快排时间复杂度或计排 + m a p +map +map时间复杂度
二、斜率优化dp
这是斜率的升级版
依然少不了一道题
例题——[SDOI2016] 征途
题目描述
Pine开始了从S地到T地的征途。
从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站。
Pine计划用m天到达T地。除第m天外,每一天晚上Pine都必须在休息站过夜。所以,一段路必须在同一天中走完。
Pine希望每一天走的路长度尽可能相近,所以他希望每一天走的路的长度的方差尽可能小。
帮助Pine求出最小方差是多少。
设方差是v,可以证明, v × m 2 v\times m^2 v×m2是一个整数。为了避免精度误差,输出结果时输出 v × m 2 v\times m^2 v×m2。
输入格式
第一行两个数 n、m。
第二行 n 个数,表示 n 段路的长度
输出格式
一个数,最小方差乘以 m 2 m^2 m2 后的值
样例 #1
样例输入 #1
5 2
1 2 5 8 6
样例输出 #1
36
提示
对于 30 % 30\% 30% 的数据, 1 ≤ n ≤ 10 1 \le n \le 10 1≤n≤10
对于 60 % 60\% 60% 的数据, 1 ≤ n ≤ 100 1 \le n \le 100 1≤n≤100
对于 $100% $ 的数据, 1 ≤ n ≤ 3000 1 \le n \le 3000 1≤n≤3000
保证从 S S S 到 T T T 的总路程不超过 30000 30000 30000 。
思路
- 第一步:方差这个东西好玄乎,拆开来!
- 第二步:欸好像可以滚掉点空间!
- 第三步:时间不够,斜率来凑
第一步
方差 S = 1 m ∑ i = 1 m ( x i − x ‾ ) 2 \texttt{方差}S=\frac{1}{m}\sum_{i=1}^m(x_i-\overline{x})^2 方差S=m1i=1∑m(xi−x)2
可以将 n 2 n^2 n2移至左侧
m 2 S = m ( ∑ i = 1 m x i 2 ) − 2 ( ∑ i = 1 m x i ) 2 + ( ∑ i = 1 m x i ) 2 m^2S=m(\sum_{i=1}^{m}{x_i}^2)-2(\sum^{m}_{i=1}{x_i})^2+(\sum_{i=1}^{m}x_i)^2 m2S=m(i=1∑mxi2)−2(i=1∑mxi)2+(i=1∑mxi)2
m 2 S = m ( ∑ i = 1 m x i 2 ) − ( ∑ i = 1 m x i ) 2 m^2S=m(\sum_{i=1}^{m}{x_i}^2)-(\sum_{i=1}^{m}x_i)^2 m2S=m(i=1∑mxi2)−(i=1∑mxi)2
这就是我们要输出的东西
可以发现,第二项其实是个常数, m m m也可以最后乘
这样,需要维护的东西成了平方和
记 s i = ∑ j = 1 i x j s_i=\sum_{j=1}^{i}x_j si=∑j=1ixj
d p dp dp式子就是 d p i , l = min { d p j , l − 1 + ( s i − s j ) 2 } ( i < j ) dp_{i,l}=\min\{dp_{j,l-1}+(s_i-s_j)^2\}(i<j) dpi,l=min{dpj,l−1+(si−sj)2}(i<j)
第二步(此步可省略)
可以发现,我们能够不按常理出牌,先枚举 l l l,这样可以滚掉 l l l这一层,但要倒序枚举
伪代码:
for i=1->m:for j=n->1:for k=1->j-1:dp[j]=minimum(dp[j],dp[k]+(s[j]-s[k])^2)
第三步
重中之重到了!!!
我们还要继续拆式子(悲)
( s i − s j ) 2 = ( s j 2 − 2 s j s i ) + s i 2 (s_i-s_j)^2=(s_j^2-2s_js_i)+s_i^2 (si−sj)2=(sj2−2sjsi)+si2
带进 d p dp dp式子内,得
d p i = min { d p j + s j 2 − 2 s j s i + s i 2 } dp_i=\min\{dp_j+s_j^2-2s_js_i+s_i^2\} dpi=min{dpj+sj2−2sjsi+si2}
斜率优化有个套路,就是先提再构
提
即提出常数项
d p i = min { d p j + s j 2 − 2 s j s i } + s i 2 dp_i=\min\{dp_j+s_j^2-2s_js_i\}+s_i^2 dpi=min{dpj+sj2−2sjsi}+si2
构
构造一个只与 j j j有关的函数
f ( j ) = d p j + s j 2 f(j)=dp_j+s_j^2 f(j)=dpj+sj2
d p i = min { f ( j ) − 2 s j s i } + s i 2 dp_i=\min\{f(j)-2s_js_i\}+s_i^2 dpi=min{f(j)−2sjsi}+si2
接着是斜率的老套路
一个 j 1 j_1 j1比 j 2 j_2 j2优且 j 2 < j 1 j_2<j_1 j2<j1,仅当
f ( j 1 ) − 2 s j 1 s i > f ( j 2 ) − 2 s j 2 s i f(j_1)-2s_{j_1}s_i>f(j_2)-2s_{j_2}s_i f(j1)−2sj1si>f(j2)−2sj2si
f ( j 1 ) − f ( j 2 ) > 2 s i ( j 1 − j 2 ) f(j_1)-f(j_2)>2s_i(j_1-j_2) f(j1)−f(j2)>2si(j1−j2)
f ( j 1 ) − f ( j 2 ) 2 ( j 1 − j 2 ) < s i \frac{f(j_1)-f(j_2)}{2(j_1-j_2)}<s_i 2(j1−j2)f(j1)−f(j2)<si
这样与第一题截然相反,是要维护一个下凸包
但二分还是一样的
理论复杂度 O ( n log n ) O(n\log n) O(nlogn)
与官方博文或参考文献对照,可更好理解
参考文献:https://www.luogu.com.cn/blog/aben-blog/xie-shuai-you-hua-dp
最新消息!最近发起活动,请选出其中最小的图片,有奖竞猜!(其实就是把名字写上去)
学习笔记——斜率优化dp相关推荐
- APIO2010 特别行动队 斜率优化DP算法笔记
做完此题之后 自己应该算是真正理解了斜率优化DP 根据状态转移方程$f[i]=max(f[j]+ax^2+bx+c),x=sum[i]-sum[j]$ 可以变形为 $f[i]=max((a*sum[j ...
- HDU-3507Print Article 斜率优化DP
学习:https://blog.csdn.net/bill_yang_2016/article/details/54667902 HDU-3507 题意:有若干个单词,每个单词有一个费用,连续的单词组 ...
- 【总结】斜率优化DP
于是,XSC062开始写总结. 斜率优化DP 前置芝士 单调队列优化DP(夹带私货) 正文 我们以一道题为例. 打印文章 双倍经验 三倍经验 Solution 明显DP. 那么DP式就是: f i = ...
- NOI2007 货币兑换 - CDQ分治斜率优化dp
斜率优化dp维护一个凸壳.如果\(x, y\)坐标都递增,可以用单调队列,如果只有\(x\)递增,可以在凸壳上二分斜率,如果\(x, y\)都不递增,则需要在凸包中插入,可以用平衡树或cdq分治维护. ...
- CF-311B Cats Transport(斜率优化DP)
题目链接 题目描述 小S是农场主,他养了 \(M\)只猫,雇了 \(P\) 位饲养员. 农场中有一条笔直的路,路边有 \(N\) 座山,从 \(1\) 到 \(N\)编号. 第 \(i\) 座山与第 ...
- 【洛谷3648】[APIO2014] 序列分割(斜率优化DP)
点此看题面 大致题意: 你可以对一个序列进行\(k\)次分割,每次得分为两个块元素和的乘积,求总得分的最大值. 区间\(DPor\)斜率优化\(DP\) 这题目第一眼看上去感觉很明显是区间\(DP\) ...
- 深度学习笔记:优化方法总结(BGD,SGD,Momentum,AdaGrad,RMSProp,Adam)
深度学习笔记(一):logistic分类 深度学习笔记(二):简单神经网络,后向传播算法及实现 深度学习笔记(三):激活函数和损失函数 深度学习笔记:优化方法总结 深度学习笔记(四):循环神经 ...
- HDU 3507 Print Article(斜率优化DP)
题目链接 题意 : 一篇文章有n个单词,如果每行打印k个单词,那这行的花费是,问你怎么安排能够得到最小花费,输出最小花费. 思路 : 一开始想的简单了以为是背包,后来才知道是斜率优化DP,然后看了网上 ...
- HDU 2993 MAX Average Problem(斜率优化DP)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2993 题目大意:给定一个长度为n(最长为10^5)的正整数序列,求出连续的最短为k的子序列平均值的最大 ...
最新文章
- 使用MASM04 - Win32汇编语言012
- android查询竞价处理,公平可靠的竞价方式,应对越来越高的流量获取成本,如何解决推广费用过高的问题可能是...
- 函 float *search(float(*pointer)[4],int n)
- 计算机视觉与深度学习 | ORB特征匹配:基于OpenCV+Python(暴力匹配、FLANN)
- 程序人生:提高代码运行效率的9个技巧
- discuz x2.5用户注册后邮箱认证后无法收到邮件或者直接进垃圾箱
- 记一次Task抛异常,调用线程处理而引发的一些随想
- 中科院自动化所与华为联合提出!视觉目标检测大模型GAIA
- arcgis不闭合线转面_地理工具学习--arcgis篇(15):CAD和SHP的简单转换
- fastjson转换包含date类型属性的对象时报错com.alibaba.fastjson.JSONException: For input string 解决方法
- 你们是不是很缺大数据工程师?
- 六石编程学:方便调试输出的标准C代码
- 【AI PC端算法优化】七,RGB和YUV图像颜色空间互转SSE优化
- html中的js代码测试,w3school JS测验
- 1357. 路径总和 II
- 华为云HMS Core 助力鸿蒙开发
- win10新建计算机账户,Windows10系统创建microsoft帐户的方法
- 企业微信如何快速高效添加好友?
- 计算机英语测试,计算机专业英语测试
- PCB与设备外壳接地问题