首页 > 代码库 > ACM/ICPM2014鞍山现场赛D Galaxy (HDU 5073)

ACM/ICPM2014鞍山现场赛D Galaxy (HDU 5073)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5073

题意:给定一条线上的点,然后可以去掉其中的m个,使剩下的到重心的距离最小,

由于重心等于距离的平均值,因此也就是求方差最小;

分析:

因为要去掉m个所以一定剩下n-m个,我们枚举这一串点的起始位置从1开始 一直枚举到m,

然后由平方和的公式展开,预处理一下前几项平方和,以及前几项的和即可,复杂度为O(N);

代码如下:

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

const int maxn = 50010;

long long a[maxn];

int main()
{
    int n,m,t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%I64d",&a[i]);
        if(n==m){
            printf("0\n");
            continue;
        }
        sort(a+1,a+n+1);
        long long sum1=0,sum2=0;
        for(int i=1;i<=n-m;i++){
            sum1+=a[i];
            sum2+=a[i]*a[i];
        }
        double mess = sum1*1.0/(n-m);
        double ans = sum2 + (n-m)*mess*mess - 2*sum1*mess;
        for(int i=1;i<=m;i++){
            sum1 = sum1-a[i]+a[n-m+i];
            sum2 = sum2 - a[i]*a[i]+a[n-m+i]*a[n-m+i];
            mess = sum1*1.0/(n-m);
            ans = min(ans,sum2 + (n-m)*mess*mess - 2*sum1*mess);
        }
        printf("%.10lf\n",ans);
    }
    return 0;
}
/***
100
3 2
-1 0 1
4 2
-2 -1 1 2
****/


ACM/ICPM2014鞍山现场赛D Galaxy (HDU 5073)