ACM/ICPM2014鞍山現場賽D Galaxy (HDU 5073)

bigbigship發表於2014-10-23

題目連結: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
****/


相關文章