hdu5073 简单枚举+精度处理

其实这题还是挺简单的,因为移动k个星球后,这k个星球的权值就可以变为0,所以只有剩下的本来就是连着的才是最优解,也就是说要动也是动两端的,那么就O(N)枚举一遍动哪些就好了。

我是在杭电oj题目重现的比赛上做这题,因为之前听人说现场赛时有人用n^2的算法蹭过了,所以我不断蹭,蹭了一个小时都没蹭过。。。~!@#¥%……

先贴一份乱七八糟想蹭过的代码

/*

 * Author    : ben

 */

#include <cstdio>

#include <cstdlib>

#include <cstring>

#include <cmath>

#include <ctime>

#include <iostream>

#include <algorithm>

#include <queue>

#include <set>

#include <map>

#include <stack>

#include <string>

#include <vector>

#include <deque>

#include <list>

#include <functional>

#include <numeric>

#include <cctype>

using namespace std;

typedef long long LL;

const double eps = 1e-9;

int get_int() {

    int res = 0, ch;

    while (!((ch = getchar()) >= '0' && ch <= '9')) {

        if (ch == EOF)

            return 1 << 30;

    }

    res = ch - '0';

    while ((ch = getchar()) >= '0' && ch <= '9')

        res = res * 10 + (ch - '0');

    return res;

}

//输入整数(包括负整数),用法int a = get_int2();

int get_int2() {

    int res = 0, ch, flag = 0;

    while (!((ch = getchar()) >= '0' && ch <= '9')) {

        if (ch == '-')

            flag = 1;

        if (ch == EOF)

            return 1 << 30;

    }

    res = ch - '0';

    while ((ch = getchar()) >= '0' && ch <= '9')

        res = res * 10 + (ch - '0');

    if (flag == 1)

        res = -res;

    return res;

}

const int MAXN = 50100;

int N, K, data[MAXN];

int ndata[MAXN];

LL sum[MAXN];

double ans;



inline double getCenter(int s, int e) {

    LL su = sum[e];

    if (s > 0) {

        su -= sum[s - 1];

    }

    double ret = su / (e - s + 1.0);

    return ret;

}



void comput(int s, int e, double c) {

    double ret = 0;

    for (int i = s; i <= e; i++) {

        ret += (data[i] - c) * (data[i] - c);

        if (ret > ans) {

            return;

        }

    }

    if (ret < ans) {

        ans = ret;

    }

}



double comput(double c) {

    double ret = 0;

    for (int i = 0; i < N; ) {

        ret += (data[i] - c) * (data[i] - c) * ndata[i];

        i += ndata[i];

    }

    return ret;

}



void work() {

    double cen = getCenter(0, N - 1);

//    printf("cen = %f\n", cen);

    ans = comput(cen);

    for (int a = K; a >= 0; a--) {

        if (ans < eps) {

            break;

        }

        int e = N + a - K - 1;

        double tmpc = getCenter(a, e);

        comput(a, e, tmpc);

    }

}



void treat() {

    for (int i = 0; i < N; i++) {

        int d = data[i];

        int j = i + 1;

        while (j < N && data[j] == d) {

            j++;

        }

        int num = j - i;

        for (j--; j >= i; j--) {

            ndata[j] = num - j + i;

        }

    }

}



int main() {

    int T = get_int();

    while (T--) {

        N = get_int();

        K = get_int();

        for (int i = 0; i < N; i++) {

            data[i] = get_int2();

        }

        sort(data, data + N);

        treat();

        sum[0] = data[0];

        for (int i = 1; i < N; i++) {

            sum[i] = sum[i - 1] + data[i];

        }

        work();

        printf("%.10lf\n", ans);

    }

    return 0;

}

 

下面是正常做法,其实相对于上面的代码也就只有一处改进,因为上面那份代码求解(xi-x)^2的时候是依次计算累加的,可以通过展开公式,通过预存前n项平方和的方式来计算,把这个计算过程从O(N)变成O(1),就可以过了。

不过我还是wa了几发,原因是一开始忘了对N==K和N-1==K的情况作特殊处理了,因为我后面的代码这个地方没单独考虑。

  1 /*

  2  * Author    : ben

  3  */

  4 #include <cstdio>

  5 #include <cstdlib>

  6 #include <cstring>

  7 #include <cmath>

  8 #include <ctime>

  9 #include <iostream>

 10 #include <algorithm>

 11 #include <queue>

 12 #include <set>

 13 #include <map>

 14 #include <stack>

 15 #include <string>

 16 #include <vector>

 17 #include <deque>

 18 #include <list>

 19 #include <functional>

 20 #include <cctype>

 21 using namespace std;

 22 typedef long long LL;

 23 const double eps = 1e-9;

 24 const int MAXN = 50100;

 25 int N, K;

 26 LL data[MAXN], sum[MAXN], sum2[MAXN];

 27 double ans;

 28 int get_int() {

 29     int res = 0, ch;

 30     while (!((ch = getchar()) >= '0' && ch <= '9')) {

 31         if (ch == EOF)

 32             return 1 << 30;

 33     }

 34     res = ch - '0';

 35     while ((ch = getchar()) >= '0' && ch <= '9')

 36         res = res * 10 + (ch - '0');

 37     return res;

 38 }

 39 

 40 //输入整数(包括负整数),用法int a = get_int2();

 41 int get_int2() {

 42     int res = 0, ch, flag = 0;

 43     while (!((ch = getchar()) >= '0' && ch <= '9')) {

 44         if (ch == '-')

 45             flag = 1;

 46         if (ch == EOF)

 47             return 1 << 30;

 48     }

 49     res = ch - '0';

 50     while ((ch = getchar()) >= '0' && ch <= '9')

 51         res = res * 10 + (ch - '0');

 52     if (flag == 1)

 53         res = -res;

 54     return res;

 55 }

 56 inline LL getSum(int from, int to) {

 57     LL ret = sum[to];

 58     if (from > 0) {

 59         ret -= sum[from - 1];

 60     }

 61     return ret;

 62 }

 63 

 64 inline LL getSum2(int from, int to) {

 65     LL ret = sum2[to];

 66     if (from > 0) {

 67         ret -= sum2[from - 1];

 68     }

 69     return ret;

 70 }

 71 

 72 inline double getCenter(int s, int e) {

 73     LL su = sum[e];

 74     if (s > 0) {

 75         su -= sum[s - 1];

 76     }

 77     double ret = su / (e - s + 1.0);

 78     return ret;

 79 }

 80 

 81 inline double comput(int s, int e, double c) {

 82     LL s1 = getSum(s, e);

 83     LL s2 = getSum2(s, e);

 84     double ret = s2 + (e - s + 1.0) * c * c - 2.0 * c * s1;

 85     return ret;

 86 }

 87 

 88 void work() {

 89     double cen = getCenter(0, N - 1);

 90     ans = comput(0, N - 1, cen);

 91     for (int a = 0; a <= K; a++) {

 92         int e = N + a - K - 1;

 93         double tmpc = getCenter(a, e);

 94         double ret = comput(a, e, tmpc);

 95         if (ret < ans) {

 96             ans = ret;

 97         }

 98     }

 99 }

100 

101 int main() {

102 #ifndef ONLINE_JUDGE

103     freopen("data.in", "r", stdin);

104 #endif

105     int T= get_int();

106     while (T--) {

107         N = get_int();

108         K = get_int();

109         for (int i = 0; i < N; i++) {

110             data[i] = get_int2();

111         }

112         if (K == N || N - 1 == K) {

113             printf("0\n");

114             continue;

115         }

116         sort(data, data + N);

117         sum[0] = data[0];

118         sum2[0] = data[0] * data[0];

119         for (int i = 1; i < N; i++) {

120             sum[i] = sum[i - 1] + data[i];

121             sum2[i] = sum2[i - 1] + data[i] * data[i];

122         }

123         work();

124         printf("%.10lf\n", ans);

125     }

126     return 0;

127 }

 

你可能感兴趣的:(HDU)