bzoj 1911斜率优化

这个题为什么有个*???
关于斜率优化又有了新的感悟

对于次优解的排除:假设对于i来说l是次优解。即满足k(q[l],q[l+1])<=k(i)时,l+1比l更优
k(q[l],q[l+1])表示这两个点连成一条线的斜率,k(i)表示在i处那根线的斜率,这个很容易就可以证明

对于提前排除不可能的解:假设r是考虑排除的点,now是考虑放入的点,即满足k(q[r-1],q[r])>=k(q[r],now)时,应该提前排除r
这个证明也特别简单,就是不等式换算一下

为什么要这样呢?因为这样两个式子都要计算k,把它封装成一个函数,那么代码量相对于上一篇博客那种写法来说就会小很多,而且思路看起来更加清晰,如果写错了更好修改。


二更:前面的话纯属放屁,有的斜率优化的题如果用k判断的话会有精度损失(转double)然后导致不能ac。应该只用乘法不用除法,最好写个x(i)宏和y(i)宏,不要使用k。

#include <cstdio>
#include <iostream>
#include <iomanip>
#include <string>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <map>
#include <algorithm>
#include <cmath>
#include <stack>

#define INF 0x3f3f3f3f
#define IMAX 2147483646
#define LINF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define uint unsigned int

using namespace::std;

const int maxn = 1111111;
ll n, a, b, c, q[maxn];
ll aa[maxn],sum[maxn], f[maxn];
#define k(x,y) ((double)(f[y] - f[x] + a * sum[y] * sum[y] - a * sum[x] * sum[x] - b * sum[y] + b * sum[x]) / (a * (sum[y] - sum[x]) * 2))

int main() {
	scanf("%lld%lld%lld%lld", &n, &a, &b, &c);
	for (int i = 1; i <= n; i++)
		scanf("%lld", aa + i), sum[i] = aa[i] + sum[i - 1];
	int l = 1, r = 1;
	for (int i = 1; i <= n; i++) {
		while (l < r && k(q[l], q[l + 1]) <= sum[i]) ++l;
		f[i] = f[q[l]] + a * (sum[i] - sum[q[l]]) * (sum[i] - sum[q[l]]) + b * (sum[i] - sum[q[l]]) + c;
		while (l < r && k(q[r - 1], q[r]) >= k(q[r], i)) --r;
		q[++r] = i;
	}
	printf("%lld\n", f[n]);
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值