zoukankan      html  css  js  c++  java
  • CF939E:Maximize! ——题解

    http://codeforces.com/problemset/problem/939/E

    https://vjudge.net/problem/CodeForces-939E

    给一个集合,每次两个操作:

    1 a:将一个大于集合所有数的a添加进集合。

    2:查询集合中所有子集的最大值-平均值的最大值。

    有一个结论:最大值所在的子集一定包含集合最大值,我们用感性证明证明一下。

    我们假设结论为假,那么我们已经选定了一个子集,设其最大值为x,我们在集合里还有一个数为x+1,则如果将x换成x+1,平均值只会加上一个小于1的数,而最大值却加1,显然要比原先的值大,所以x+1更优。

    同理x与x+2比较可以看成x+1与x+2比较,以此类推。

    所以结论必为真。

    那么既然我们能固定一个最大值,我们还有一个显然成立的结论,就是子集一定为最小的前k个数和最大的数x构成。因为太显然了就不证了。

    既然这样,那么显然答案是一个单峰函数,可以三分求解。

    (第一次碰这个题的时候前几个步骤都想到了三分愣是没想到……我是真的蠢,看样子题刷少了)

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef double dl;
    typedef long long ll;
    const int Q=5e5+5;
    ll sum[Q],maxx;
    int len=0;
    inline dl suan(int k){
        return 1.0*(maxx*k-sum[k])/(k+1);
    }
    dl sanfen(int l,int r){
        int mid1,mid2;
        while(l<=r){
            if(r-l<3){
                dl ans=suan(r);
                for(int i=l;i<r;i++)ans=max(ans,suan(i));
                return ans;
            }
            mid1=l+(r-l)/3,mid2=mid1+(r-l)/3;
            if(suan(mid1)>suan(mid2))r=mid2;
            else l=mid1;
        }
    }
    int main(){
        int q,op;
        scanf("%d",&q);
        while(q--){
            scanf("%d",&op);
            if(op==1){
                scanf("%lld",&maxx);
                sum[++len]=sum[len-1]+maxx;
            }
            else printf("%.10lf
    ",sanfen(0,len-1));
        }
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

     +本文作者:luyouqi233。               +

     +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    异步初体验
    ASPNET登陆总结
    14年最后一天了
    个人阅读作业
    软工个人博客-week7
    软工结对编程作业-人员
    软工结对编程作业-(附加题)
    软工结对编程作业-(非附加题)
    个人博客作业Week3
    软工个人作业-博客作业-WEEK2
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/8456439.html
Copyright © 2011-2022 走看看