题目描述
为了响应国家的号召,司令官PIPI决定在大学里面征集一批同学进入部队。计划开启后,CSU有M位同学参加报名,司令官PIPI想在里面选出N位同学。由于部队对身高有严格要求,PIPI要求这N位同学的身高尽可能接近,即选出的同学身高方差尽可能小,请你帮帮PIPI。
PS:
对于序列x1,x2,…xn,序列方差为:
s2=[(x1-k)2+(x2-k)2+…(xn-k)2]/n
其中k为序列x1,x2,…xn的均值。
输入
输入包含多组测试样例(case≤10)。
对于每组测试样例,第一行输入两个数字M,N,含义如题面所示(0<N≤M≤1e5)。
第二行输入M个数字,ai 代表第i个同学的身高(0<ai≤1e5)。
输出
对于每组测试用例,输出最小方差*N的整数部分(即向下取整)。
样例输入
5 3
1 2 3 4 5
样例输出
2
题解如下:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+7;
double a[N];
double pre_1[N],pre_2[N];
int main(){
int n,m;
while(~scanf("%d%d",&m,&n)){
for(int i=1;i<=m;i++){
scanf("%lf",&a[i]);
}
sort(a+1,a+1+m);
for(int i=1;i<=m;i++){ ///前缀和预处理
pre_1[i] = pre_1[i-1]+a[i];
pre_2[i] = pre_2[i-1]+a[i]*a[i];
}
double ans = 1e18;
for(int l=1;l+n-1<=m;l++){ ///这样写防止越界
int r = l+n-1;
double x = (pre_1[r]-pre_1[l-1])/n; ///均值
double s = (pre_2[r]-pre_2[l-1]) - 2*(pre_1[r]-pre_1[l-1])*x + n*x*x; ///方差*n
ans = min(ans,s);
}
printf("%lld\n",(long long)ans);
}
return 0;
}