(F[i]=min{ F[j]+(lis[i]-lis[j]+i-j-1-L)^2 })
(f(i)=lis[i]+i,g(i)=f(i)+L+1)
(F[i]=F[j]+(f(i)-g(j))^2)
(F[i]=F[j]+f(i)^2-2f(i)g(j)+g(j)^2)
(F[j]=2f(i)g(j)+(F[i]-f(i)^2-g(j)^2))
以(g(j))为横坐标,则直线斜率为(2f(i))
单调队列维护下凸壳即可
#include"cstdio"
#include"cstring"
#include"iostream"
#include"algorithm"
using namespace std;
const int MAXN=5e4+5;
int n,L;
int q[MAXN];
long long lis[MAXN],F[MAXN];
long long get(int x){return lis[x]+L+x+1;}
long long got(int x){return F[x]+get(x)*get(x);}
bool cqr(int x1,int x2,int x3)
{
long long y3=lis[x3]+x3<<1ll;
return (got(x2)-got(x1))<=y3*(get(x2)-get(x1));
}
bool cqt(int x1,int x2,int x3)
{
return (got(x2)-got(x1))/(get(x2)-get(x1))*(get(x3)-get(x1))>=(got(x3)-got(x1));
}
int main()
{
scanf("%d%d",&n,&L);
for(int i=1;i<=n;++i) scanf("%lld",&lis[i]),lis[i]+=lis[i-1];
int hd=1,tl=1;
for(int i=1;i<=n;++i){
while(hd<tl&&cqr(q[hd],q[hd+1],i)) ++hd;
long long tmp=lis[i]-lis[q[hd]]+i-q[hd]-1-L;
F[i]=F[q[hd]]+tmp*tmp;
while(hd<tl&&cqt(q[tl-1],q[tl],i)) --tl;
q[++tl]=i;
}printf("%lld
",F[n]);
return 0;
}