CodeForces - 939E Maximize!

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值