【NOIP模拟】平均数

Description

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

Solution

一看到求什么最大最小值什么的就要想到用二分答案。
然后是平均数,要求他要大于某个数,那么我们就把这些数同时减去这个平均数,最后如果满足长度大于m的子串和不小于0就成立。

那么我们怎样保证长度大于m

我们循环从m到n循环,然后用1到i的和减去最小的前缀和。
然后就可以O(n)搞定这一结果。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
typedef double db;
using namespace std;
const int maxn=300007;
int i,j,k,t,n,m;
db ans,l,r,mid,f[maxn],a[maxn],b[maxn];
bool pan(int x){
    int i,l=0,p=-0x7fffffff;
    db k=0,j=0;
    fo(i,m,n){
        if(b[i]-k>=0)return 1;
        if(b[i-m+1]<k)k=b[i-m+1];
    }
    return 0;
}
int main(){
    freopen("average.in","r",stdin);
    freopen("average.out","w",stdout);
    scanf("%d%d",&n,&m);
    fo(i,1,n){
        scanf("%lf",&a[i]);
        r+=a[i];
    }
    while(r-l>1e-5){
        mid=(l+r)/2;b[0]=0;
        fo(i,1,n)a[i]-=mid,b[i]=b[i-1]+a[i];
        if(pan(mid))l=mid;else r=mid;
        fo(i,1,n)a[i]+=mid;
    }
    printf("%.5lf\n",l);
}

你可能感兴趣的:(动态规划,贪心,平均数,noip,二分答案)