第一反应肯定是dp啦,然后就会愉快的T成一头象拔蚌。
那么,说说正解吧。
显然,选取的区间一定可以是两头为差值最小的。那就好办了,只需要预处理出所有的这样的区间,再dp即可,由于数据是随机生成的,所以这样的区间不会太多,有人验证了,好像是O(n)级别的。
预处理怎么搞?分块优化,pre[i][j]表示在第i块内的数,与j差值的最小值。每一块内的数取出来排序,两个下标跟着动就行了。
然后把那些区间搞出来,从a[n]到a[1],先暴力处理自身所在的块内的。然后在看后面的块,如果最小值更有,那就再暴力处理这个块。得出的区间要注意,如果有区间被完全包含并且最小值还小于这个区间,那么这个区间显然可以舍去,最小值可以用树状数组来维护。
把右端点相同的区间链起来,一次非常简单的dp就得出答案了。
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<queue>
//#include<ctime>
#define N 50005
#define ll long long
using namespace std;
const int block=210;
const int inf=0x3f3f3f3f;
template <typename T>
inline void _read(T& x){
char t=getchar();bool sign=true;
while(t<'0'||t>'9'){if(t=='-')sign=false;t=getchar();}
for(x=0;t>='0'&&t<='9';t=getchar())x=x*10+t-'0';
if(!sign)x=-x;
}
int n,m,tot,top;
int a[N],Pre[255][N],q[N],f[N][1005];
struct node{
int l,r,d;
node(){}
node(int L,int R,int D){l=L;r=R;d=D;}
};
vector<node> tra[N];
int c[N];
int lowbit(int x){return x&(-x);}
void modify(int x,int d){
for(int i=x;i<=50000;i+=lowbit(i)){
c[i]=min(c[i],d);
}
}
int getmin(int x){
int temp=inf;
for(int i=x;i;i-=lowbit(i)){
temp=min(temp,c[i]);
}
return temp;
}
bool check(int x){return (x>=1&&x<=n);}
void pre(){
int i,j,k,l,r,p1,p2;
for(i=1;i<=tot;i++){
top=0;
l=(i-1)*block+1;r=min(n,i*block);
for(j=l;j<=r;j++)q[++top]=a[j];
sort(q+1,q+1+top);
p1=p2=1;
for(j=1;j<=n;j++){
Pre[i][j]=inf;
while(p1<top&&q[p1+1]<j)p1++;
while(p2<top&&q[p2]<=j)p2++;
if(check(p1)&&q[p1]<j)Pre[i][j]=min(Pre[i][j],j-q[p1]);
if(check(p2)&&q[p2]>j)Pre[i][j]=min(Pre[i][j],q[p2]-j);
}
}
/*for(i=1;i<=tot;i++){
for(j=1;j<=10;j++){
cout<<Pre[i][j]<<" ";
}
cout<<endl;
}*/
}
int temp;
void work(int x,int st,int num){
int i,j,k,r;
r=min(n,num*block);
for(i=st;i<=r;i++){
int t=abs(a[i]-a[x]);
if(t&&t<temp){
temp=t;
int p=getmin(i);
if(temp<p){
modify(i,temp);
tra[i].push_back(node(x,i,temp));
}
}
}
}
int main(){
int i,j,k,st;
cin>>n>>m;
tot=(n-1)/block+1;
for(i=1;i<=n;i++)_read(a[i]);
for(i=0;i<=50000;i++)c[i]=inf;
pre();
top=0;
for(i=n;i;i--){
temp=inf;
int bel=(i-1)/block+1;
work(i,i+1,bel);
for(j=bel+1;j<=tot;j++){
if(Pre[j][a[i]]<temp){
work(i,(j-1)*block+1,j);
}
}
}
for(i=0;i<=n;i++){
for(j=0;j<=m;j++){
f[i][j]=inf;
}
}
f[0][0]=0;
int ans=inf;
for(i=1;i<=n;i++){
f[i][0]=0;
for(j=1;j<=m;j++){
f[i][j]=min(f[i][j],f[i-1][j]);
for(k=0;k<tra[i].size();k++){
f[i][j]=min(f[i][j],f[tra[i][k].l-1][j-1]+tra[i][k].d);
}
}
}
cout<<f[n][m];
}