斜率优化总结

Posted 123789456ye

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了斜率优化总结相关的知识,希望对你有一定的参考价值。

斜率优化dp
考虑一类(dp)方程

[dp[i]=min_{L(i)le jle R(i)}{f(j)+val(i,j)} ]

(min)改成(max)也是可以的
其中(val)中含有(ij)乘积这一项
例题:任务安排
转移方程

[dp[i]=min_{0le j<i}{dp[j]+sumt[i]*(sumf[i]-sumf[j])+s*(sumf[n]-sumf[j])} ]

把式子拆开,把(dp[j])放到左边,(dp[i])放到右边作为截距中的一项

[dp[j]=(s+sumt[i])*sumf[j]+(dp[i]-sumt[i]*sumf[i]-s*sumf[n]) ]

对于每一个确定的(i),截距都是(dp[i]+C),其中(C)只与(i)有关
所以我们要最小化截距,于是我们维护一个点集为((sumf[i],dp[i]))的下凸包
由于这道题斜率一定,所以我们相当于是用一条斜率为(s+sumt[i])的直线去切这个凸包
所以我们找到(kle s+sumt[i])(k)最大的点即可,这个(k)是表示这一个点和前一个点之间的斜率(具体可以画个图)
维护凸包,并且横坐标递增,斜率递增,直接上单调队列即可

#include<bits/stdc++.h>
using namespace std;
inline void read(int& x)
{
	x = 0; char c = getchar();
	while (!isdigit(c)) c = getchar();
	while (isdigit(c)) x = x * 10 + c - ‘0‘, c = getchar();
}
#define maxn 5005
int t[maxn], f[maxn], q[maxn], dp[maxn], n, s;
inline int dy(int x, int y) { return dp[y] - dp[x]; }
inline int dx(int x, int y) { return f[y] - f[x]; }
int main()
{
	read(n), read(s);
	for (int i = 1; i <= n; ++i) read(t[i]), read(f[i]), t[i] += t[i - 1], f[i] += f[i - 1];
	for (int l = 1, r = 1, i = 1; i <= n; ++i)
	{
		while (l < r && dy(q[l], q[l + 1]) <= 1ll * (s + t[i]) * dx(q[l], q[l + 1])) ++l;
		dp[i] = dp[q[l]] - (s + t[i]) * f[q[l]] + t[i] * f[i] + s * f[n];
		while (l < r && 1ll * dx(q[r - 1], q[r]) * dy(q[r], i) < 1ll * dx(q[r], i) * dy(q[r - 1], q[r])) --r;
		q[++r] = i;
	}
	printf("%d
", dp[n]);
	return 0;
}

以及如果两个都不单调,就要上平衡树/cdq,比如这个

以上是关于斜率优化总结的主要内容,如果未能解决你的问题,请参考以下文章

以前的空间斜率优化的一点点总结

斜率优化DP

斜率优化(DP)

总结DP的常用优化

总结DP优化

斜率优化系列——训练记录