第五届华中区程序设计邀请赛暨武汉大学第十四届校赛 Problem 1603 - Minimum Sum



链接:戳这里


Problem 1603 - Minimum Sum
Time Limit: 2000MS   Memory Limit: 65536KB   
Total Submit: 589  Accepted: 165  Special Judge: No
Description
There are n numbers A[1] , A[2] .... A[n], you can select m numbers of it A[B[1]] , A[B[2]] ... A[B[m]]  ( 1 <= B[1] < B[2] .... B[m] <= n ) such that Sum as small as possible.

Sum is sum of abs( A[B[i]]-A[B[j]] ) when 1 <= i < j <= m.

Input
There are multiple test cases.
First line of each case contains two integers n and m.( 1 <= m <= n <= 100000 )
Next line contains n integers A[1] , A[2] .... A[n].( 0 <= A[i] <= 100000 )
It's guaranteed that the sum of n is not larger than 1000000.
Output
For each test case, output minimum Sum in a line.
Sample Input
4 2
5 1 7 10
5 3
1 8 6 3 10
Sample Output
2
8


题意:给定n个整数ai,从中任选m个数  使得sum of abs( A[B[i]]-A[B[j]] ) when 1 <= i < j <= m.最小


思路:因为是任意选m个数,所以我直接排序,然后选择连续的m个数才尽可能的是sum小  这个应该很好理解

接下来我们要分析的是取那一段m,首先我们简单分析下

想象成滚动长度为m的序列,当前的第i个数要加进长m的序列,那么第i-m就需要出去

计算贡献,当前的i加进去对于序列产生的价值是s1=(a[i]-a[i-1]+a[i]-a[i-2]+...+a[i]-a[i-m+1])

当前i-m删出去对于队列产生的价值是s2= -(a[i-1]-a[i-m]+a[i-2]-a[i-m]+..+a[i-m+1]-a[i-m])

s1+s2=(m-1)*(a[i]+a[i-m])-2*(sum[i-1]-sum[i-m])  sum代表前缀和


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include <ctime>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<iomanip>
#include<cmath>
#define mst(ss,b) memset((ss),(b),sizeof(ss))
#define maxn 0x3f3f3f3f
#define MAX 1000100
///#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef unsigned long long ull;
#define INF (1ll<<60)-1
using namespace std;
int n,m;
ll sum[1000100];
int a[1000100];
int main(){
    while(scanf("%d%d",&n,&m)!=EOF){
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        sort(a+1,a+n+1);
        a[0]=sum[0]=0;
        for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i];
        ll ans=INF,s=0;
        int num=0;
        for(int i=1;i<=n;i++){
            if(num<m) {
                s+=(ll)a[i]*(i-1)-sum[i-1];
                num++;
            }
            else {
                s+=(ll)(m-1)*(a[i]+a[i-m])-2*(sum[i-1]-sum[i-m]);
            }
            if(num==m) ans=min(ans,s);
        }
        printf("%lld\n",ans);
    }
    return 0;
}


你可能感兴趣的:(第五届华中区程序设计邀请赛暨武汉大学第十四届校赛 Problem 1603 - Minimum Sum)