用线段树代替单调栈,常数大,但简单一点
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define mid ((l+r)/2)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-'){f=-1;}ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0',ch=getchar();}return x*f;}
void write(int x){if(x<0){putchar('-'),x=-x;}if(x>9){write(x/10);} putchar(x%10+'0');return;}
const int N=2e5+5,M=105,inf=1e14,mod=123456789;
int n,L;
int c[N],sum[N],dp[N];
struct Tree{
int t[N<<2],lazy[N<<2];
void pushup(int now){
t[now]=max(t[ls(now)],t[rs(now)]);
}
void pushdown(int now,int l,int r){
if(lazy[now]!=-inf){
lazy[ls(now)]=lazy[now];
lazy[rs(now)]=lazy[now];
t[ls(now)]=lazy[now];
t[rs(now)]=lazy[now];
lazy[now]=-inf;
}
}
void build(int now,int l,int r){
lazy[now]=-inf;
if(l==r){t[now]=0;return;}
build(ls(now),l,mid);
build(rs(now),mid+1,r);
pushup(now);
}
void in(int now,int l,int r,int ql,int qr,int val){
if(ql<=l&&r<=qr){t[now]=val,lazy[now]=val;return;}
pushdown(now,l,r);
if(ql<=mid)in(ls(now),l,mid,ql,qr,val);
if(qr>mid)in(rs(now),mid+1,r,ql,qr,val);
pushup(now);
}
int out(int now,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return t[now];
pushdown(now,l,r);
int sum=0;
if(ql<=mid)sum+=out(ls(now),l,mid,ql,qr);
if(qr>mid)sum+=out(rs(now),mid+1,r,ql,qr);
return sum;
}
}t;
int cal(int i,int j){
return dp[i]+(j-(i+1)+sum[j]-sum[i]-L)*(j-(i+1)+sum[j]-sum[i]-L);
}
signed main(){
cin>>n>>L;
t.build(1,1,n);
for(int i=1;i<=n;i++){
cin>>c[i];
sum[i]=sum[i-1]+c[i];
}
dp[1]=(c[1]-L)*(c[1]-L);
for(int i=1;i<=n;i++){
if(i>1)dp[i]=cal(t.out(1,1,n,i,i),i);
int l=i+1,r=n,ret=-1;
while(l<=r){
if(cal(i,mid)<cal(t.out(1,1,n,mid,mid),mid)){
ret=mid;
r=mid-1;
}
else{
l=mid+1;
}
}
if(ret!=-1){t.in(1,1,n,ret,n,i);}
// cout<<"决策表"<<i<<":";for(int j=1;j<=n;j++){cout<<t.out(1,1,n,j,j)<<" ";}cout<<"\n";
}
// cout<<"dp:";for(int i=1;i<=n;i++){cout<<dp[i]<<' ';}
cout<<dp[n];
return 0;
}