http://poj.org/problem?id=3666
很明显B序列非严格递增和B序列非严格递减处理方式是相同的,分别处理取最小值即可
下面以B序列非严格递增为例:
一个直观的想法是 设 为确定了b序列前i个数,第i个数的值为j是所得的最小值
这么一看时间复杂度是的,需要进行优化
首先发现,对于一个i,随着j的增加,可选取的决策点k是只增不减的,即j每次加1时,可选取的k的个数也会加1
由此看出j每次加1时,要是再从头到尾循环k就造成了时间上的浪费
所以对于一个i,记录一个mn,表示循环到j的时候的决策点 的前缀最小值,直接利用mn实现转移,而每次更新mn时只需考虑新加入的
,就能做到O(1)更新mn
到这里复杂度就降到了,但ai的范围是1e9,还需要继续优化
这时候就有一个猜想,貌似B的取值在1e9这个范围内会有很多是无用的,再进一步地说,B的取值会不会是A序列出现的数字的集合的子集,也就是B的取值不会出现A中没有出现的数字
可以尝试证明一下,这里用数学归纳法:
(1)当N=1时显然成立
(2)当N>1时,假设前Bn-1项取得最优解且满足上述条件,此时Bn>=Bn-1
1.若Bn-1>=An,则令Bn=Bn-1即可,贪心地想,尽可能地让Bn往小了选,这样之后B序列能选择的数范围更广,与A序列更“接近”
2.反之,又分为两种情况
1.若选取的Bn>=An(>=Bn-1),按照上面贪心的思想,直接令Bn取An即可
2.否则的话,假设Bn-1=Bn-2=...=Bn-k (0<=k<=n-1),对于A序列和B序列这2k个点来说,就已经转化成了 “ 在数轴上取一个点,让这个点到其他指定的点的距离和最小” 问题,就像这样:
Bn-1=Bn-2=...=Bn-k肯定是取在这些A点的中位数上
然后发现,再往里插入An时,它肯定在Bn-1=Bn-2=...=Bn-k这个点的右侧,这时候无论A点个数是奇是偶,中位数始终不变的
所以接下来取Bn的时候,也直接把它放在中位数的位置上,也就是Bn=Bn-1,这样就保证了最优解
综上,Bn的取值一定是A序列出现的数的集合的子集,然后离散化处理A序列即可,这样复杂度就降到了
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define db double
#define rep(x,a,b) for(int x=(a);x<=(b);x++)
#define per(x,a,b) for(int x=(a);x>=(b);x--)
#define reP(x,a,b) for(int x=(a);x<(b);x++)
#define Per(x,a,b) for(int x=(a);x>(b);x--)
#define scf(a) scanf("%d",&a)
#define scfll(a) scanf("%lld",&a)
#define scfdb(a) scanf("%lf",&a)
#define ptf(a) printf("%d",a)
#define ptfll(a) printf("%lld",a)
#define ptfdb(x,a) printf("%x.lf",a)
#define ptfsp(a) printf("%d ",a)
#define ptfllsp(a) printf("%lld ",a)
#define ptfdbsp(x,a) printf("%x.lf ",a)
#define pli(a,b) make_pair(a,b)
#define pb push_back
#define el puts("")
#define ls pos<<1
#define rs pos<<1|1
#define pi 3.1415926
//ios::sync_with_stdio(false);
using namespace std;
const ll mod=1e9+7;
const int maxn=2e3+5;
ll f[maxn][maxn];
map<int,int>mp;
int a[maxn],b[maxn];
int main(){
int n;scf(n);
rep(i,1,n) scf(a[i]),mp[a[i]]=1;
int cnt=0;
for(auto &x:mp) x.second=++cnt,b[cnt]=x.first;
ll ans=1e18;
//for(int j=1;j<=cnt;j++) cout<<b[j]<<" ";el;
rep(i,1,n)
rep(j,1,cnt)
f[i][j]=1e18;
rep(j,1,cnt) f[0][j]=0;
rep(i,1,n){
ll mn=1e18;
rep(j,1,cnt){
mn=min(mn,f[i-1][j]);
f[i][j]=min(f[i][j],mn+abs(b[j]-a[i]));
}
}
rep(j,1,cnt) ans=min(ans,f[n][j]);
rep(i,1,n)
rep(j,1,cnt)
f[i][j]=1e18;
rep(j,1,cnt) f[0][j]=0;
rep(i,1,n){
ll mn=1e18;
per(j,cnt,1){
mn=min(mn,f[i-1][j]);
f[i][j]=min(f[i][j],mn+abs(b[j]-a[i]));
}
}
rep(j,1,cnt) ans=min(ans,f[n][j]);
cout<<ans;
}