zoukankan      html  css  js  c++  java
  • 黑客的平均数

    离开了老久,终于又回机房了,有点小激动,发誓要好好学习了,相信在将近四个月的平静后我不会再像之前那么水了,花了一个小时写了这道题,而且是看题解的,没事慢慢来不着急。

    题面:

       给出长度为n的序列,求长度不小于k的连续子序列,且这个子序列的平均值为最大。

       输出这个最大平均值(保留六位小数)

    题解:

      1)低配版 (n,k<=5000)  枚举左右端点找最大值

      2)高配版(n,k<=1e5, a[ i ] < 5000)   二分  

        对于每个二分值mid进行check,如果存在更优解,则:

                

        那我们把每个a[i]减去一个mid,所以检查时建立个aa[i]=a[i]-mid,b[i]=b[i-1]+aa[i],

        问题就转化为:是否存在一个长度满足要求的区间和不等于0。

        可以建立一个f数组实现,f[i]表示以i结尾的连续子序列的最大平均值,从左往右扫一遍的过程中更新 f[i] 和 ans,如果ans大于0,则存在更优解。

        

    #include <bits/stdc++.h>
    using namespace std;
    inline double read()
    {
        char ch=getchar();
        int s=0,f=0;
        while(!(ch<='9'&&ch>='0')) {f|=ch=='-';ch=getchar();}
        while(ch<='9'&&ch>='0') {s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
        return f?-s:s;
    }
    int n, k;
    double l=1e9, r=-1e9, ans, mid;
    double f[10004],aa[10004],b[10004],a[10004];
    bool check(double x)
    {
        ans = -1e9; 
        for(int i=1;i<=n;i++)
            aa[i] = a[i]-x, b[i] = b[i-1]+aa[i];
        
        memset(f,-10,sizeof(f));
        for(int i=k;i<=n;i++)//枚举右端点,f[i]表示以i结尾的连续子序列的最大平均值
            f[i] = max(f[i-1]+aa[i],b[i]-b[i-k]),ans = max(ans,f[i]);
            
        if(ans>=0) return true;
        else return false;
        
    } 
    int main()
    {
        n = read(); k = read();
        for(int i=1;i<=n;i++)
            a[i] = read(), l = min(l,a[i]), r = max(r,a[i]);
        //找到答案的范围l,r
        while(fabs(r-l)>1e-10)
        {
            mid = (r+l)/2;
            if(check(mid)) l = mid;
            else r = mid; 
        }
        printf("%.6lf
    ",l);
        
        return 0;
    }
  • 相关阅读:
    centOS 6 服务管理与服务脚本
    centOS 6启动流程
    shell脚本之流程控制
    centOS7网络配置(nmcli,bonding,网络组)
    模拟主机跨路由通信实验
    网络配置之基本网络配置(cenos6)
    网络基础之IP地址与子网划分
    网络基础之网络层
    我的BO之数据保护
    我的BO之强类型
  • 原文地址:https://www.cnblogs.com/lyflalala/p/11323330.html
Copyright © 2011-2022 走看看