1. 程式人生 > >BZOJ 2439: [中山市選2011] 序列

BZOJ 2439: [中山市選2011] 序列

沒人寫過題解?(其實貼吧那個啟發性就夠了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; }