CodeForces 572D Minimization(DP)


题意翻译

给定数组AAA 和值kkk ,你可以重排AAA 中的元素,使得∑i=1n−k∣Ai−Ai+k∣\displaystyle\sum_{i=1}^{n-k} |A_i-A_{i+k}|i=1∑n−k​∣Ai​−Ai+k​∣ 最小。输出最小值。
题目描述

You've got array A A A , consisting of n n n integers and a positive integer k k k . Array A A A is indexed by integers from 1 1 1 to n n n .

You need to permute the array elements so that value

became minimal possible. In particular, it is allowed not to change order of elements at all.
输入输出格式
输入格式:

The first line contains two integers n,k n,k n,k ( 2<=n<=3⋅105 2<=n<=3·10^{5} 2<=n<=3⋅105 , 1<=k<=min(5000,n−1) 1<=k<=min(5000,n-1) 1<=k<=min(5000,n−1) ).

The second line contains n n n integers A[1],A[2],...,A[n] A[1],A[2],...,A[n] A[1],A[2],...,A[n] ( −109<=A[i]<=109 -10^{9}<=A[i]<=10^{9} −109<=A[i]<=109 ), separate by spaces — elements of the array A A A .

输出格式:

Print the minimum possible value of the sum described in the statement.

输入输出样例
输入样例#1: 复制

3 2
1 2 4

输出样例#1: 复制

1

输入样例#2: 复制

5 2
3 -5 3 -5 3

输出样例#2: 复制

0

输入样例#3: 复制

6 3
4 3 4 3 2 5

输出样例#3: 复制

3

说明

In the first test one of the optimal permutations is $ 1 4 2 $ .

In the second test the initial order is optimal.

In the third test one of the optimal permutations is $ 2 3 4 4 3 5 $ .

题解:首先显然如果把i,i+k,i+2×k等排列起来,这将是一条链,而且会有k条链。

链长可能有两种情况:n/k,n/k+1

显然同一条链中如果数字固定,单调的话链的贡献最小

显然如果单调的话,取连续的几个贡献最小

所以我们现将全部数字放到同一条链里,接着将这条长链断成k条长度为n/k,n/k+1的链,此时贡献需要减掉两条链之间的差值

于是问题转化成了求减掉差值的和的最大值

令i表示长边数量,j表示短边的数量

dp[i][j]=max(dp[i][j-1]+det1,dp[i-1][j]+det2)

因为只有两种边长,所以分割点所在的位置可以直接根据i和j推出

总贡献减去dp[cnt1][cnt2]即为答案

 

代码如下:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define int long long
using namespace std;

int n,k,a[300030];
int dp[5010][5010];
int ans;

signed main()
{
    scanf("%lld%lld",&n,&k);
    int cnt1=n%k;
    int cnt2=k-cnt1;
    int len1=n/k+1;
    int len2=n/k;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
    }
    sort(a+1,a+n+1);
    for(int i=2;i<=n;i++)
    {
        ans+=a[i]-a[i-1];
    }
    for(int i=2;i<=cnt1;i++)
    {
        dp[i][0]=dp[i-1][0]+a[i*len1-len1+1]-a[i*len1-len1];
    }
    for(int i=2;i<=cnt2;i++)
    {
        dp[0][i]=dp[0][i-1]+a[i*len2-len2+1]-a[i*len2-len2];
    }
    for(int i=1;i<=cnt1;i++)
    {
        for(int j=1;j<=cnt2;j++)
        {
            dp[i][j]=max(dp[i][j-1]+a[i*len1+j*len2-len2+1]-a[i*len1+j*len2-len2],dp[i-1][j]+a[i*len1+j*len2-len1+1]-a[i*len1+j*len2-len1]);
        }
    }
    printf("%lld",ans-dp[cnt1][cnt2]);
}

 

posted @ 2018-09-07 15:06  Styx-ferryman  阅读(260)  评论(0编辑  收藏  举报