由于是随机数据,用分块加乱搞就可以水过。
详情参见大佬的博客:题解
贴个代码:
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<algorithm>
using namespace std;
#define MAXN 50500
#define MAXM 250
int A[MAXN],n,k;
const int inf=0x3c3c3c3c;
void _r(int& x)
{
char c=getchar();
while(c<'0'||c>'9')
{
c=getchar();
}
for(x=0;c>='0'&&c<='9';c=getchar())
{
x=(x<<1)+(x<<3)+c-'0';
}
return ;
}
#define lowbit(x) (x&-x)
int tr[MAXN];
void modify(int x,int d)
{
for(;x<=n;x+=lowbit(x))
{
tr[x]=min(tr[x],d);
}
return ;
}
int get(int x)
{
int an=inf;
for(;x;x-=lowbit(x))
{
an=min(an,tr[x]);
}
return an;
}
int size,dis[MAXN][MAXM],st[MAXN],top,num;
int F[MAXN][MAXM*4+50];
vector<int>P[MAXN];
int cc=0;
void work(int pos,int nn,int lim,int& an)
{
int up=min(nn*size,n),tmp;
for(int i=lim;i<=up;i++)
{
tmp=abs(A[pos]-A[i]);
if(tmp>0&&tmp<an)
{
an=tmp;
if(an<get(i))
{
modify(i,an);
//printf("%d %d %d\n",++cc,pos,i);
P[i].push_back(pos);
}
}
}
return ;
}
int main()
{
freopen("r.in","r",stdin);
freopen("w.out","w",stdout);
_r(n);
_r(k);
for(size=1;size*size<=n;++size);
num=(n-1)/size+1;
for(int i=1;i<=n;i++)
{
_r(*(A+i));
}
memset(tr,0x3c,(n+1)<<2);
memset(dis,0x3c,sizeof(dis));
int l,r;
for(int i=1;i<=num;i++)
{
l=(i-1)*size+1;
r=min(i*size,n);
top=0;
for(int j=l;j<=r;j++)
{
*(st+(++top))=A[j];
}
sort(st+1,st+1+top);
l=0;
r=1;
for(int j=1;j<=n;j++)
{
while(l<top&&*(st+l+1)<j)
{
++l;
}
while(r<=top&&*(st+r)<=j)
{
++r;
}
if(l>0)
{
dis[j][i]=min(dis[j][i],j-st[l]);
}
if(r<=top)
{
dis[j][i]=min(dis[j][i],st[r]-j);
}
}
}
int pos,tmp;
for(int i=n;i>=1;i--)
{
pos=(i-1)/size+1;
tmp=inf;
for(int j=pos;j<=num;j++)
{
if(dis[A[i]][j]<tmp)
{
work(i,j,max(i,(pos-1)*size+1),tmp);
}
}
}
memset(F,0x3c,sizeof(F));
F[0][0]=0;
for(int i=1;i<=n;i++)
{
F[i][0]=0;
for(int j=1;j<=k;j++)
{
F[i][j]=F[i-1][j];
for(int p=0;p<(int)P[i].size();p++)
{
F[i][j]=min(F[i][j],F[P[i][p]-1][j-1]+abs(A[i]-A[P[i][p]]));
}
/*if(F[i][j]==inf)
{
break;
} */
}
}
printf("%d\n",F[n][k]);
return 0;
}