http://acm.hdu.edu.cn/showproblem.php?pid=5073

这题的关键是要把p点减重心位置 的 平方的那个式子展开,就可以O(n),开始ans初始化为1e18一直wa,改成1e19就A了

最大的部分是连续的,头尾指针一起移动就可以

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

typedef __int64 ll;

ll a[50005], sum[50005], sum2[50005];

int main(){
    int T;
    scanf("%d", &T);
    while(T--){
        ll n, k;
        scanf("%I64d %I64d", &n, &k);
        for(int i = 1; i <= n; i++)
            scanf("%I64d", &a[i]); 
        if(n == k || k == n - 1){
            printf("0.0000000000\n");
            continue;
        }
        sort(a + 1, a + n + 1);
        memset(sum, 0, sizeof(sum));
        memset(sum2, 0, sizeof(sum2)); 
        sum[1] = a[1]; 
        sum2[1] = a[1] * a[1]; 
        for(int i = 2; i <= n; i++){
            sum[i] = sum[i - 1] + a[i];
            sum2[i] = sum2[i - 1] + a[i] * a[i]; 
        }
        double ans = 1e19; 
        for(int front = 1, rear = n - k; rear <= n; front++, rear++){
            ll av = sum[rear] - sum[front - 1]; 
            double res=  (n - k) * (sum2[rear] - sum2[front - 1]) + 1.0 * av * av - 2.0 * av * (sum[rear] - sum[front - 1]); 
            ans = min(ans, res); 
        }
        printf("%.10lf\n", ans / (n - k));
    }
    return 0;
}
View Code