HDU5073

题意:给定n个数轴上的点xi,di是xi到中心mid的距离,可以移动K个到中心mid,求 wi*di^2的和的最小值。

因为wi是1,所以我们可以简化成下面的公式:

I=min(sum(di^2))

 =min(sum(xi-mid)^2)

 =min(sum(xi^2-2*xi*mid+mid^2)

 =min(sum(xi^2) - 2*mid*sum(xi^2) + mid^2)    sum下标(0~(n-k))

用前缀和维护xi^2和xi ,时间复杂度是o(n).

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 50005
double x[maxn];    //注意一定是double,如果是int会WA.
int main()
{
   // freopen("in.txt", "r", stdin);
    int T, k, i, j, n;
    double mid, sum1, sum2, ans;
    scanf("%d", &T);
    while(T--)
    {
        sum1 = sum2 = 0;
        scanf("%d%d", &n, &k);
        for(i = 0; i < n; i++) scanf("%lf", &x[i]);
        ans = 0;
        if(n != k)
        {
            sort(x, x+n);
            for(i = 0; i < n-k; i++)
            {
                    sum1 += x[i]*x[i];
                    sum2 += x[i];
            }
            mid = sum2/(n-k);
            ans = sum1 - 2*mid*sum2 + mid*mid*(n-k);
            for(i = 1, j = n-k; j < n; i++, j++)
            {
                sum1 -= x[i-1]*x[i-1];
                sum1 += x[j]*x[j];
                sum2 -= x[i-1];
                sum2 += x[j];
                mid = sum2/(n-k);
                ans = min(ans, (sum1 - 2*mid*sum2 + mid*mid*(n-k)));

            }
        }
        printf("%.10f
", ans);
    }

    return 0;
}


原文地址:https://www.cnblogs.com/lzq1126/p/5596847.html