定义:S(i)为长度前缀和
易得:
由于L是常数L++
令K为当前最优解
则
展开
定义新函数
带回原式
转为斜率式
完毕
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1e5+1000;
typedef int INT;
#define int long long
int L,n;
double S[N];
int F[N];
int l,r;
int Q[N];
double Snow;
double Y(int k){
return (double)F[k]+S[k]*S[k]+2*S[k]*L;
}
double X(int Id){
return S[Id];
}
double Slope(int k,int t){
return (Y(t)-Y(k))/(X(t)-X(k));
}
INT main(){
// freopen("1995.in","r",stdin);
scanf("%lld%lld",&n,&L);L++;
l=r=1;
Q[1]=0;
for(int i=1;i<=n;i++){
scanf("%lf",&S[i]);
S[i]+=S[i-1];
}
for(int i=1;i<=n;i++)S[i]+=i;
for(int i=1;i<=n;i++){
while(l<r&&Slope(Q[l],Q[l+1])<2*(S[i]))l++;
int Id=Q[l];
// cout<<i<<" "<<Id<<'\n';
F[i]=F[Id]+(S[i]-S[Id]-L)*(S[i]-S[Id]-L);
while(l<r&&Slope(Q[r-1],Q[r])>Slope(Q[r],i))r--;Q[++r]=i;
}
cout<<F[n];
}