斜率优化题。
基础方程很容易就推了出来:
f[i]=max{f[j]+a(s[i]−s[j])2+b(s[i]−s[j])+c}
推斜率
设k<j<i
若选j优于选
f[j]+a(s[i]−s[j])2+b(s[i]−s[j])+c≥f[k]+a(s[i]−s[k])2+b(s[i]−s[k])+c
化啊化啊化
f[k]−f[j]+a×s[k]2−a×s[j]2−b×s[k]+b×s[j]s[k]−s[j]≥2×a×s[i]
代码呼之欲出
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long n,a,b,c,f[1000010],q[1000010],s[1000010];
double slp(long long k,long long j)
{
return (double)(f[k]-f[j]+a*s[k]*s[k]-a*s[j]*s[j]-b*s[k]+b*s[j])/(s[k]-s[j]);
}
int main()
{
scanf("%lld%lld%lld%lld",&n,&a,&b,&c);
s[0]=0;
for(long long i=1;i<=n;i++)
{
long long x;
scanf("%lld",&x);
s[i]=s[i-1]+x;
}
long long st=0,ed=1;
q[0]=0;
f[0]=0;
for(long long i=1;i<=n;i++)
{
while(st+1<ed&&slp(q[st],q[st+1])>2*a*s[i])
st++;
long long j=q[st];
f[i]=f[j]+a*(s[i]-s[j])*(s[i]-s[j])+b*(s[i]-s[j])+c;
while(st+1<ed&&slp(q[ed-2],q[ed-1])<slp(q[ed-1],i))
ed--;
q[ed++]=i;/*
for(long long j=0;j<i;j++)
f[i]=max(f[i],f[j]+a*(s[i]-s[j])*(s[i]-s[j])+b*(s[i]-s[j])+c);*/
}
printf("%lld",f[n]);
}

464

被折叠的 条评论
为什么被折叠?



