CodeForces - 939E Maximize!

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37129433/article/details/82390794

Maximize!
题 意:给你q个询问,两种操作,1.每次往容器里面加入一个x,保证x一定大于容器里面所有的数。2.输出容器里面的一个子集,求最大的子集的MAX - avg最大。
数据范围:
1<=q<=5e5
1<=x<=1e9
输入样例:

6
1 3
2
1 4
2
1 8
2

输出样例:

0.0000000000
0.5000000000
3.0000000000

思 路:首先这是一个凸函数,这个很好想,我们需要找的就是凸函数的那个MAX点,然后三分就好了。
具体写一下三分的思路
这里写图片描述

也就是一个lmid和一个rmid把l,r等分成三份。
对于凸函数,如果f(lmid) > f(rmid) 的话 那么max一定在l到rmid之间,如果f(lmid) < f(rmid)那么max就一定实在lmid 到r之间。
下面来考虑一下凹函数。
这里写图片描述
如果f(lmid) > f(rmid)的话那么min肯定在r,lmid之间,如果f(rmid) < f(lmid)那么肯定是在l,rmid之间。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5e5+5;
ll sum[maxn];
int a[maxn];
int q,total;
double f(int x){
    return (double)a[total-1] - (double)(sum[x]+a[total-1])/(double)(x+1);
}
int main(){
    scanf("%d",&q);
    total = 1;
    while(q--){
        int ch,x;
        scanf("%d",&ch);
        if(ch == 1){
            scanf("%d",&a[total]);
            sum[total]= sum[total-1]+a[total];
            total++;
        }else{
            int l = 1,r = total-1;
            while(r-l>2){
                int mid = l + (r-l)/3;
                int mmid= r - (r-l)/3;
                if(f(mid) > f(mmid)){
                    r = mmid;
                }else if(f(mid) < f(mmid)){
                    l = mid;
                }else{
                    r = mmid;
                    l = mid;
                }
            }
            double MAX = 0;
            for(int i=l;i<=r;i++){
                MAX = max(MAX,f(i));
            }
            printf("%.10f\n",MAX);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37129433/article/details/82390794
今日推荐