显然 $dp$,首先设 $f[i][j]$ 表示当前考虑到第 $i$ 个电线杆,高度为 $j$ 时的最小代价
那么有转移 $f[i][j]=f[i-1][k]+cost+C(j-k)$,其中 $j>=k$,$cost$ 为把电线杆 $i$ 增高到 $j$ 的代价,$i,j$ 固定时为常数
对于 $i,j$ 的最优转移 $k$,$i,j+1$ 时小于 $j$ 的所有转移代价同时增加 $C$,所有对于 $k<j$ 的位置只有 $k$ 有机会贡献
当 $k>j$ 时也同理,动态维护即可
其实直接维护前缀 $f[i][j]-Ck$ 最小值会好写很多...
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
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<<1)+(x<<3)+(ch^48); ch=getchar(); }
return x*f;
}
const int N=1e5+7,M=107;
const ll INF=1e18;
int n,C,h[N],H;
ll f[2][M],ans=INF;
inline ll calc(int i,int j,int k) { return f[(i&1)^1][k]+(j-h[i])*(j-h[i])+C*abs(j-k); }
int main()
{
n=read(),C=read();
for(int i=1;i<=n;i++) h[i]=read(),H=max(H,h[i]);
for(int i=h[1];i<=H;i++) f[1][i]=(i-h[1])*(i-h[1]);
for(int i=2;i<=n;i++)
{
int pre=h[i-1],p=i&1;
for(int j=0;j<=H;j++) f[p][j]=INF;
for(int k=pre+1;k<h[i];k++) if(calc(i,h[i],pre)>calc(i,h[i],k)) pre=k;
for(int j=max(h[i],h[i-1]);j<=H;j++)
{
if(calc(i,j,pre)>calc(i,j,j)) pre=j;
f[p][j]=calc(i,j,pre);
}
pre=H;
for(int j=H-1;j>=h[i];j--)
{
if(j+1>=h[i-1] && calc(i,j,pre)>calc(i,j,j+1)) pre=j+1;
f[p][j]=min(f[p][j],calc(i,j,pre));
}
}
for(int i=h[n];i<=H;i++) ans=min(ans,f[n&1][i]);
printf("%lld\n",ans);
return 0;
}