\(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