题目链接: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
****/