zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", 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
    ");
    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
    ", ans);
    125     }
    126     return 0;
    127 }
  • 相关阅读:
    剑指 Offer 25. 合并两个排序的链表
    53. 最大子序和 动态规划
    121. 买卖股票的最佳时机
    20. 有效的括号
    centos7 常用操作
    树莓派
    golang 学习笔记
    并发 线程 进程
    连接内网问题
    Lamp 高并发优化
  • 原文地址:https://www.cnblogs.com/moonbay/p/4044739.html
Copyright © 2011-2022 走看看