• [贪心][前缀和] Jzoj P4256 平均数


    Description

    给出包含一个N个整数的数组A。找出一段长度至少为K的连续序列,最大化它的平均值。
    请注意:一段子序列的平均值是子序列中所有数的和除以它的长度。
     

    Input

    第一行包含两个整数N(1<=N<=300000),K(1<=K<=N)。
     第二行包含N个整数,代表数组A,1<=ai<=10^6。

    Output

    一行一个实数,代表最大的平均值。允许在0.001以内的绝对误差。
     

    Sample Input

    输入1:
    4 1
    1 2 3 4
    输入2:
    4 2
    2 4 3 4
    输入3:
    6 3
    7 1 2 1 3 6

    Sample Output

    输出1:
    4.000000
    输出2:
    3.666666
    输出3:
    3.333333
     

    Data Constraint

    对于30%的数据,N<=5000。
    对于100%的数据,1<=N<=300000, 1<=K<=N, 1<=Ai<=1000000。

    题解

    • 先二分出来一个平均值,然后将序列里的所有数减去二分出来的数
    • 然后求一遍前缀和直接判断就好了

    代码

     1 #include <cstdio>
     2 #include <cstring>
     3 #define N 300010
     4 using namespace std;
     5 int n,k;
     6 double l,r,mid,a[N],b[N],eps=1e-5;
     7 bool check(int x)
     8 {
     9     double p=0;
    10     for (int i=k;i<=n;i++)
    11     {
    12         if (b[i]-p>=0) return 1;
    13         if (b[i-k+1]<p) p=b[i-k+1];
    14     }
    15     return 0;
    16 }
    17 int main()
    18 {
    19     freopen("average.in","r",stdin),freopen("average.out","w",stdout),scanf("%d%d",&n,&k);
    20     for (int i=1;i<=n;i++) scanf("%lf",&a[i]),r+=a[i];
    21     while (r-l>eps)
    22     {
    23         double mid=(l+r)/2.0; b[0]=0;
    24         for (int i=1;i<=n;i++) a[i]-=mid,b[i]=b[i-1]+a[i];
    25         if (check(mid)) l=mid; else r=mid;
    26         for (int i=1;i<=n;i++) a[i]+=mid;
    27     }
    28     printf("%.5lf",l);
    29 }
  • 相关阅读:
    HTTP解析
    Java设计模式8:迭代器模式
    Java设计模式7:适配器模式
    Sharepoint 开启发布功能的PowerShell
    How to Limit NodeRunner.exe High Memory, CPU Usage
    sharepoint 2013 网站集解锁
    SharePoint Set-SPUser 命令拒绝访问
    SharePoint 列表视图修改多行文本字段显示长度
    SharePoint 修改项目的new图标显示天数
    SharePoint 压缩打包文件代码分享
  • 原文地址:https://www.cnblogs.com/Comfortable/p/10358964.html
Copyright © 2020-2023  润新知