BZOJ 2439: [中山市選2011] 序列
阿新 • • 發佈:2018-11-15
沒人寫過題解?(其實貼吧那個啟發性就夠了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;
}