zoukankan      html  css  js  c++  java
  • Codeforces 939E Maximize ( 三分 || 二分 )

    题意 : 给出两个操作,① 往一个序列集合(初始为空)里面不降序地添加数字、② 找出当前序列集合的一个子集使得 (子集的最大元素) - (子集的平均数) 最大并且输出这个最大差值

    分析 : 

    首先关注到 ① 操作是有序地添加数

    然后为了回答 ② 的问询,来分析一波

    直觉告诉我们,要最大化差值,选取的子集最大元素应当越大越好

    这一点是对的,具体的证明可以看 CF 的官方题解

    那么也就是说选出的子集里面必定有当前序列集合的最大值元素

    然后为了使(子集的平均数)越小,直觉又告诉我们

    需要贪心地选择小的元素加入子集,这一点是显然的

    仔细一想就能发现,如果我们从小到大地将元素加入子集

    子集的平均数肯定是先减后增,是个凹函数

    又因为是序列有序,所以我们可以去三分序列的前缀和数组寻找凹点

    最后的答案就是 (集合序列最大值) - (凹点的平均值)

    至于二分解法,也同样是和上面一个道理

    我们可以去二分前缀和数组的一个位置,假设为 POS

    如果算出来的平均值比 POS+1 这个位置的元素更大

    说明加入 POS+1 这个元素肯定更优,最后一直二分到合理位置就是答案了

    具体看代码

    二分 1231ms

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    const int maxn = 5e5 + 10;
    vector<LL> arr;
    LL Presum[maxn];
    
    inline void GetAns()
    {
        int L = 0, R = arr.size()-2, idx = 0;
        double avg;
        while(L <= R){
            int mid = (R + L) / 2;
            avg = (double)(arr[arr.size()-1] + Presum[mid]) / (double)(mid + 2);
            if(avg > arr[mid+1]) L = mid + 1;///平均值比后面的元素更大,说明添加进 mid+1 这个元素肯定更优
            else R = mid - 1, idx = mid;
        }
    
        avg = (double)(arr[arr.size()-1] + Presum[idx]) / (double)(idx + 2);
        double ans = (double)arr[arr.size()-1] - avg;
        printf("%.9f
    ", ans);
    }
    
    int main(void)
    {
        int Q;
        scanf("%d", &Q);
        while(Q--){
            int command;
            scanf("%d", &command);
            if(command == 1){
                LL tmp;
                cin>>tmp;
                arr.push_back(tmp);
                Presum[arr.size()-1] = ((arr.size()-2 < 0) ? 0 : Presum[arr.size()-2]) + tmp;
            }else GetAns();
        }
        return 0;
    }
    二分

     三分 514ms

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    const int maxn = 5e5 + 10;
    vector<LL> arr;
    LL Presum[maxn];
    
    double Fun(int pos)
    { return (double)(arr[arr.size()-1] + Presum[pos]) / (double)(pos + 2); }
    
    double GetAns()
    {
        int L = 0, R = arr.size() - 2;
        while(L < R-1){
            int mid = (L + R) / 2;
            int mmid = (mid + R) / 2;
            if( Fun(mid) > Fun(mmid) ) L = mid;
            else R = mmid;
        }
        return (double)arr[arr.size()-1] - Fun(Fun(L) > Fun(R) ? R : L);
    }
    
    int main(void)
    {
        int Q;
        scanf("%d", &Q);
        while(Q--){
            int command;
            scanf("%d", &command);
            if(command == 1){
                LL tmp;
                scanf("%I64d", &tmp);
                arr.push_back(tmp);
                Presum[arr.size()-1] = (arr.size()-2 < 0 ? 0 : Presum[arr.size()-2]) + tmp;
            }else{
                printf("%.9f
    ", GetAns());
            }
        }
        return 0;
    }
    三分
  • 相关阅读:
    angularjs的$on、$emit、$broadcast
    angularjs中的路由介绍详解 ui-route(转)
    ionic入门教程-ionic路由详解(state、route、resolve)(转)
    Cocos Creator 加载使用protobuf第三方库,因为加载顺序报错
    Cocos Creator 计时器错误 cc.Scheduler: Illegal target which doesn't have uuid or instanceId.
    Cocos Creator 构造函数传参警告 Can not instantiate CCClass 'Test' with arguments.
    Cocos Creator 对象池NodePool
    Cocos Creator 坐标系 (convertToWorldSpaceAR、convertToNodeSpaceAR)
    Cocos Creator 常驻节点addPersistRootNode
    Cocos Creator 配合Tiled地图的使用
  • 原文地址:https://www.cnblogs.com/qwertiLH/p/8560102.html
Copyright © 2011-2022 走看看