ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

DP优化

2022-05-18 21:02:19  阅读:168  来源: 互联网

标签:队列 min cdot 斜率 DP 单调 优化 dp


一、单调队列优化

很简单,对于 \(dp_i=\min (A_j+B_i)\) 的状态转移方程,可以丢进单调队列,时间复杂度 \(O(n)\)。

二、斜率优化

如果是对于 \(dp_i=\min(A_i\cdot B_j+C_i+D_j)\) 的状态转移方程,就单调队列不了了,因为有一项同时存在 \(i\) 和 \(j\)。

我们考虑把不和 \(j\) 有关的都丢到等式右边,那左边要么就只和 \(j\) 有关,要么和 \(i\)、\(j\) 都有关。

考虑这样的一次函数 \(y=k\cdot x+b\),稍微移项可得 \(b=y-k\cdot x\),所以我们把只跟 \(i\) 有关的都看做 \(b\),只跟 \(j\) 有关的看做 \(y\),同时跟 \(i\) 和 \(j\) 有关的看做 \(k\cdot x\)。

对于上面那个式子,我们先写成 \(f_i-C_i=\min(A_i\cdot B_j+D_j)\),所以 \(b=dp_i-C_i\),\(x=B_j\),\(y=D_j\),\(k=A_i\)。因为 \(C_i\) 是定值,所以使 \(dp_i\) 最小即使 \(b\) 最小,图像如下:

image

也就是你每次确定一个 \(k_i\) 以后,需要寻找一个过某个点的该斜率的线,使得截距 \(b\) 最小,观察图像,这条线必然过是两条斜率分别小于 \(k_i\) 和大于 \(k_i\) 的直线的交点,用个单调队列维护这个凸包即可。

具体维护方法:

设第 \(i\) 个点和第 \(j\) 个点连接的直线方程斜率为 \(k(i,j)\)。

1、对于队首元素,由于维护的是一个凸包,所以 \(k\) 随着 \(i\) 的增加是单调的,把 \(k(q_j,q_{j+1})<k_i\) 的 \(j\) 都弹出;

2、这条直线最先碰到的必然是最下面那个点,即队首的点,用队首转移即可;

3、对于队尾元素,同样的,因为维护的是一个凸包,所以凹进去的部分要弹出去,即弹出所有 \(k(q_{j-1},q_j)>k(q_{j},q{j+1})\) 的 \(j\) 即可。

e.g. [HNOI2008] 玩具装箱

三、WQS二分

对于有限制的 \(dp\),比如 [Luogu P4983] 忘情

状态转移方程很容易得到,即 \(dp_i=\min(dp_j+(s_i-s_j+1)^2)\),\(s\) 表示 \(a\) 数组的前缀和,很显然如果没有只能分 \(m\) 段的限制,这就是个斜率优化的简单题,然而这里有一个限制,我们画出分成的段数与 \(ans\) 的图像,很显然在 \(m\) 取到最值时,这个图像是个凸的(否则你可以随便合并两个嘛),并且最高点得是 \(m\),考虑画图分析。

image

我们画一些斜率为 \(k\) 的线,观察每一条线 \(y=k\cdot x+b\),移项得 \(b=y-k\cdot x\),那么我们要使得 \(x=m\) 时截距 \(b\) 最大,然后我们惊奇地发现,\(b_i\) 只是 \(y_i\) 即 \(dp_i\) 减去了 \(x\) 个 \(k\),也就是把转移式改成 \(dp_i=\min(dp_j+(s_i-s_j+1)^2)-k\) 即可。

我们二分 \(k\),便可以得到答案。

标签:队列,min,cdot,斜率,DP,单调,优化,dp
来源: https://www.cnblogs.com/vegtable-foraino/p/16286263.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有