码迷,mamicode.com
首页 > 其他好文 > 详细

CF939E:Maximize! ——题解

时间:2018-02-21 12:48:30      阅读:140      评论:0      收藏:0      [点我收藏+]

标签:scanf   blog   添加   mes   net   lan   target   查询   https   

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\n",sanfen(0,len-1));
    }
    return 0;
}

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

 +本文作者:luyouqi233。               +

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

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

CF939E:Maximize! ——题解

标签:scanf   blog   添加   mes   net   lan   target   查询   https   

原文地址:https://www.cnblogs.com/luyouqi233/p/8456439.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!