• Codeforces 939E Maximize! (三分 || 尺取)


    <题目链接>

    题目大意:
    给定一段序列,每次进行两次操作,输入1 x代表插入x元素(x元素一定大于等于之前的所有元素),或者输入2,表示输出这个序列的任意子集$s$,使得$max(s)-mean(s)$表示这个集合的最大值与平均值的最大差值。

    解题分析:
    首先,因为输入的$x$是非递减的,所以要使$max(s)-mean(s)$最大,肯定$max(s)$就是最后一个输入元素的大小。$x$已经确定了,现在就是尽可能的使$mean(s)$尽可能的小。如何使得平均值最小呢?肯定是从最前面的最小的元素开始选,因为最后一个元素是一定要选的(选做最大的元素),所以$mean(s)$函数必然是一个下凹的函数(在开始选小的元素时,平均值会被慢慢的拉低(因为一开始只有一个最大的元素),选到后面比较大的元素时,平均值又会逐渐上升)。所以我们可以用三分寻找max(s)-mean(s)函数的峰值。同时本题也可以用尺取来做,也是用来寻找峰值。

    三分:

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const int N = 5e5+5;
    ll sum[N];
    
    template<typename T>
    inline void read(T&x){
        x=0;int f=1;char c=getchar();
        while(c<'0' || c>'9'){ if(c=='-')f=-1;c=getchar(); }
        while(c>='0' && c<='9'){ x=x*10+c-'0';c=getchar(); }
        x*=f;
    }
    inline double cal(int loc,int x){
        return (double)(sum[loc]+x)/(loc+1);
    }
    int main(){
        int q;read(q);
        int op,x,cnt=0;
        while(q--){
            read(op);
            if(op==1){
                read(x);
                sum[++cnt]=sum[cnt-1]+x;
            }else{
                //对前cnt-1个元素进行三分
                int l=1,r=cnt-1;
                while(l<r){
                    int m1=(l+l+r)/3,m2=(l+r+r)/3;
                    if(cal(m1,x)>=cal(m2,x)){
                        if(l==m1)break;
                        l=m1;
                    }else{
                        if(r==m2)break;
                        r=m2;
                    }
                }
                double ans=(double)(sum[l]+x)*1.0/(l+1);
                for(int i=l;i<=r;i++)ans=min(ans,(double)(sum[i]+x)/(i+1));     //因为最后[l,r]之间可能不只有一个元素 
                printf("%.10lf
    ",x-ans);
            }
        }
    }
    View Code

    尺取:

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const int N = 5e5+5;
    ll sum[N];
    
    template<typename T>
    inline void read(T&x){
        x=0;int f=1;char c=getchar();
        while(c<'0' || c>'9'){ if(c=='-')f=-1;c=getchar(); }
        while(c>='0' && c<='9'){ x=x*10+c-'0';c=getchar(); }
        x*=f;
    }
    inline double cal(int loc,int x){
        return (double)(sum[loc]+x)/(loc+1);
    } 
    int main(){
        int q;read(q);
        int op,x,cnt=0,top=0;
        while(q--){
            read(op);
            if(op==1){
                read(x);
                sum[++cnt]=sum[cnt-1]+x;
            }else{
                while(top<cnt){
                    if(cal(top+1,x)<cal(top,x))top++;
                    else break;
                }
                printf("%.10lf
    ",x-cal(top,x));
            }
        }
    }
    View Code
  • 相关阅读:
    python检测挖矿特征的几种方式
    python检测当前端口是否使用
    matlab界面UI设计资料
    python中struct.pack()函数和struct.unpack()函数
    网络编程:主机字节序和网络字节序
    【原创】python中文编码问题深入分析(三):python2.7文件读写中文编码问题
    【原创】python中文编码问题深入分析(二):print打印中文异常及显示乱码问题分析与解决
    ivew定制主题 less ^3.0 时报错 .bezierEasingMixin(); Inline JavaScript is not enabled. Is it set in your options?
    Vue子组件中 data 从props中动态更新数据
    Vue 自动吸顶
  • 原文地址:https://www.cnblogs.com/00isok/p/10691637.html
Copyright © 2020-2023  润新知