http://poj.org/problem?id=3016 (题目链接)
给出一个数列,将一个数${a_i}$更改为${b_i}$的代价为${|a_i-b_i|}$。求将数列改为不递减的最小代价
话说我现在还没弄得明白→_→
左转题解:http://www.cnblogs.com/wenruo/p/5798801.html
// poj3016 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<vector> #include<cstdio> #include<cmath> #define LL long long #define inf 1<<30 #define Pi acos(-1.0) #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); using namespace std; const int maxn=2010; struct heap {int l,r,val,sz;}q[maxn]; int num[maxn],rt[maxn],a[maxn],b[maxn],c[maxn]; int cnt,n,K,in[maxn][maxn],de[maxn][maxn],f[maxn][maxn]; int newq(int val) { q[++cnt].val=val; q[cnt].l=q[cnt].r=0;q[cnt].sz=1; return cnt; } int merge(int x,int y) { if (x==0 || y==0) return x+y; if (q[x].val<q[y].val) swap(x,y); q[x].r=merge(q[x].r,y); swap(q[x].l,q[x].r); q[x].sz=q[q[x].l].sz+q[q[x].r].sz+1; return x; } int del(int x) { int l=q[x].l,r=q[x].r; return merge(l,r); } void cal(int *a,int u,int v,int *ans) { int res=0,tot=0;cnt=0; for (int i=u;i<=v;i++) { rt[++tot]=newq(a[i]); num[tot]=1; while (tot>1 && q[rt[tot]].val<q[rt[tot-1]].val) { tot--; if (num[tot+1]&1) res+=q[rt[tot]].val-q[rt[tot+1]].val; rt[tot]=merge(rt[tot],rt[tot+1]); num[tot]+=num[tot+1]; while (q[rt[tot]].sz*2>num[tot]+1) rt[tot]=del(rt[tot]); } ans[i]=res; } } int main() { while (scanf("%d%d",&n,&K)!=EOF && n && K) { for (int i=1;i<=n;i++) { scanf("%d",&a[i]); c[i]=-a[i]-i; b[i]=a[i]-i; } for (int i=1;i<=n;i++) { cal(c,i,n,de[i]); cal(b,i,n,in[i]); } for (int i=1;i<=n;i++) f[0][i]=inf; for (int i=1;i<=K;i++) { f[i][0]=0; for (int j=1;j<=n;j++) { f[i][j]=inf; for (int k=0;k<j;k++) f[i][j]=min(f[i][j],f[i-1][k]+min(in[k+1][j],de[k+1][j])); } } printf("%d\n",f[K][n]); } return 0; }
原文:http://www.cnblogs.com/MashiroSky/p/6268698.html