HDU5073

来源:互联网 发布:linux 安装 pv 编辑:程序博客网 时间:2024/06/05 08:57

题意:给定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 50005double 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\n", ans);    }    return 0;}


0 0
原创粉丝点击