这题斜率优化即可。
由此式子可得:
k<j<i,且j比k更优:
此处的x[i]表示原x[1~i]的和。
上标:
#include<cstdio>
#define N 1000010
#define ll long long
#define db double
using namespace std;
int n,a,b,c,len=0,l=0;
ll f[N],x[N],g[N];
inline int read()
{
int x=0,f=0; char c=getchar();
while (c<'0' || c>'9') f=(c=='-') ? 1:f,c=getchar();
while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return f ? -x:x;
}
db solve(int j,int k)
{
return (db)((f[j]+a*x[j]*x[j]-b*x[j])-(f[k]+a*x[k]*x[k]-b*x[k]))/(2*a*(x[j]-x[k]));
}
int main()
{
// freopen("P3628.in","r",stdin);
// freopen("P3628.out","w",stdout);
n=read(),a=read(),b=read(),c=read();x[0]=0;
for (int i=1;i<=n;i++) x[i]=read()+x[i-1];
for (int i=1;i<=n;i++)
{
if (l>len) l=len;
while (l<len && solve(g[l+1],g[l])<=x[i]) l++;
f[i]=f[g[l]]+a*(x[i]-x[g[l]])*(x[i]-x[g[l]])+b*(x[i]-x[g[l]])+c;
while (len && solve(g[len],g[len-1])>=solve(i,g[len])) len--;
g[++len]=i;
}
printf("%lld
",f[n]);
return 0;
}