AcWing

题目链接
  题目要求我们求出满足条件的最大值,因为(f)的长度不是固定的,所以如果直接求解的话,非常麻烦。但是,如果我们用二分判定答案的话,问题就变得简单了。但是二分必须要区间具有单调性,我们怎么让区间具有单调性呢?对于一个平均值,如果它偏大的话,那么这个区间里面任意长度的序列的平均值都取不到这个值,换句话说,如果让他们的平均值与二分的平均值比较,结果肯定是负的,同理,对于一个偏小的平均值,一定可以在序列里面找到一个连续子序列,它的平均值大于二分的平均值。
  但是这时候又会有一个问题出现了,我们怎么在最短的时间内找到一个序列判断它的平均值是否大于小于我们二分的平均值呢?这里,我们不需要把所有的可能全都枚举出来。我们先让整个序列全都减去我们二分的平均值(实现起来并不需要这么麻烦,这里只是方便理解),然后我们所要做的就是找一个连续子区间,它的区间和大于(0)。这个问题还能进一步转化为我们找一个从(1)开始以(k)结尾的区间(区间长度大于(f),而且(kleq n)),然后判断在这个区间内有没有一个以(l)结尾的区间((lleq k-l)),这样的话,我们只要对这个区间做一个前缀和来处理一下就行了

//https://www.cnblogs.com/shuitiangong/
#include<set>
#include<map>
#include<list>
#include<stack>
#include<queue>
#include<cmath>
#include<cstdio>
#include<cctype>
#include<string>
#include<vector>
#include<climits>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define endl '
'
#define rtl rt<<1
#define rtr rt<<1|1
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
#define zero(a) memset(a, 0, sizeof(a))
#define INF(a) memset(a, 0x3f, sizeof(a))
#define IOS ios::sync_with_stdio(false)
#define _test printf("==================================================
")
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
typedef pair<ll, ll> P2;
const double pi = acos(-1.0);
const double eps = 1e-7;
const ll MOD =  1000000009;
const int INF = 0x3f3f3f3f;
template<typename T> void read(T &x){
    x = 0;char ch = getchar();ll f = 1;
    while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
    while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
const int maxn = 1e5+10;
double cow[maxn];
int n, f;
bool checker(double mid) {
    double minn = 0;
    for (int i = f; i<=n; ++i) {
        if (cow[i-f]-mid*(i-f) < minn) minn = cow[i-f]-mid*(i-f);
        if (cow[i]-mid*i>minn || fabs(cow[i]-mid*i-minn)<eps) return true;
    }
    return false;
}
int bysh() {
    double l = 1.0, r = 2000.0;
    while(l+eps<r) {
        double mid = (l+r)/2.0;
        if (checker(mid)) l = mid;
        else r = mid;
    }
    return int(r*1000);
    //return int((l+eps)*1000); 上面和这个都行,但是下面这个不行 
    //return int(l*1000); 因为精度问题,l可能小于我们取到的值
}
int main(void) {
    while(~scanf("%d%d", &n, &f)) {
        for (int i = 1; i<=n; ++i) {
            scanf("%lf", &cow[i]);
            cow[i] += cow[i-1];
        }
        printf("%d
", bysh());
    }
    return 0;
}
原文地址:https://www.cnblogs.com/shuitiangong/p/12550732.html