Solution
1.dp
变化后的每一个值肯定是等于原来序列的某个值(不会证)
(a为原序列,b为排序后的序列),方程的意思是,把序列前i个数变为非递减序列并且以不超过b[j]的值结尾的最小花费,那么它要么是以不超过b[j-1]结尾的最小花费,或者是刚好以b[j]结尾的最小花费
#include<bits/stdc++.h>
using namespace std;
int n,a[5003],i,j,b[5003],x,y=1;
long long f[2][5003];
int main(){
cin>>n;
for (i=1;i<=n;i++) scanf("%d",&a[i]);
memcpy(b,a,sizeof(a));
sort(b+1,b+n+1);
for (i=1;i<=n;i++,x^=1,y^=1){
memset(f[y],1,sizeof(f[y]));
for (j=1;j<=n;j++) f[y][j]=min(f[y][j-1],f[x][j]+abs(a[i]-b[j]));
}
cout<<f[x][n];
}
2.贪心
用与Codeforces867E. Buy Low Sell High的方法,把大于小于号什么的改一下就好了(也不会证)
#include<bits/stdc++.h>
using namespace std;
int i,x,n;
long long ans;
priority_queue<int>q;
inline char gc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int rd(){
int x=0,fl=1;char ch=gc();
for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
for (;48<=ch&&ch<=57;ch=gc())x=(x<<3)+(x<<1)+(ch^48);
return x*fl;
}
int main(){
n=rd();
for (i=0;i<n;i++){
x=rd();
if (q.empty() || x>=q.top()) q.push(x);
else ans+=q.top()-x,q.pop(),q.push(x),q.push(x);
}
printf("%lld",ans);
}
据说还有斜率的做法,如果找到了会加上