没人写过题解?(其实贴吧那个启发性就够了233
f[i]表示把1~i改为递增的最小代价,g[i]表示把i~n改为递减的最小代价。
不难求出f和g数组(而且他们是满足可减性的)。
然后考虑固定一个中点,左边和右边答案分别是什么
比如说把1~i改成一个倒V的最小代价是
(2 < j < i)
i~n的也同理啊。
然后发现这个各自的决策是有单调性的,画画图就知道了,然后扫一扫就好..
实在不懂就看代码?(又短又快呢 现在是最快的233
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+3;
char O[1<<14],*S=O,*T=O;
#define gc (S==T&&(T=(S=O)+fread(O,1,1<<14,stdin),S==T)?-1:*S++)
inline int read(){
int x=0,f=1; char ch=gc;
while(ch<'0' || ch>'9'){if(ch=='-')f=-1; ch=gc;}
while(ch>='0' && ch<='9'){x=(x<<1)+(x<<3)+(ch^48); ch=gc;}
return x*f;
}
LL g[N],f[N],L[N],R[N]; int a[N];
int main(){
int n=read(),i,u;
for(i=1;i<=n;++i) a[i]=read(); a[0]=-1;
for(i=1;i<=n;++i) f[i]=f[i-1]+max(a[i-1]-a[i]+1,0);
for(i=n;i>=1;--i) g[i]=g[i+1]+max(a[i+1]-a[i]+1,0);
u=2;
for(i=3;i<n-1;++i){
while(u<i-1 && max(f[u+1],g[u+1]-g[i])<=max(f[u],g[u]-g[i]) )
++u;
L[i]=max(f[u],g[u]-g[i]);
}
u=n-1;
for(i=n-2;i>2;--i){
while(u>i+1 && max(g[u-1],f[u-1]-f[i])<=max(g[u],f[u]-f[i]) )
--u;
R[i]=max(g[u],f[u]-f[i]);
}
LL ans=(1ll<<60);
for(i=3;i<n-1;++i) ans=min(ans,L[i]+R[i]);
printf("%lld\n",ans);
return 0;
}