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;
    }
  • 相关阅读:
    Linux内核RPC请求过程
    二分图
    Java实现 蓝桥杯 算法提高 合并石子
    Java实现 蓝桥杯 算法提高 合并石子
    Java实现 蓝桥杯 算法提高 摩尔斯电码
    Java实现 蓝桥杯 算法提高 摩尔斯电码
    Java实现 蓝桥杯 算法提高 文本加密
    Java实现 蓝桥杯 算法提高 文本加密
    Java蓝桥杯 算法提高 九宫格
    Java蓝桥杯 算法提高 九宫格
  • 原文地址:https://www.cnblogs.com/lyflalala/p/11323330.html
Copyright © 2011-2022 走看看