一.题目链接:

POJ-2018

二.题目大意:

农场主有 n 块连续的田地,第 i 块地上有 a[i] 头牛

求在田地长度不小于 f 的情况下,子段的平均值的最大值.

三.分析:

实数域上二分答案.

现假定二分到 mid,则只需要检查是否存在长度 ≥ f,且平均值 >mid 的子段.

欲求长度 ≥ f 的子段只需要枚举终止点,即 f ~ n.

欲求平均值 >mid 的子段,需要知道子段长度

但由于子段长度不易统计,所以我们可以把每一个数都减去 mid

然后打出前缀和表,检查   是否>0 即可.

详见代码.

四.代码实现:

#include <set>
#include <map>
#include <ctime>
#include <queue>
#include <cmath>
#include <stack>
#include <vector>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define eps 1e-6
#define pi acos(-1.0)
#define ll long long int
using namespace std;

const int M = (int)1e6;
const int inf = 0x3f3f3f3f;
const int mod = 1000000000;

double a[M + 5];
double sum[M + 5];

int main()
{
    int n, f;
    scanf("%d %d", &n, &f);
    for(int i = 1; i <= n; ++i)
        scanf("%lf", &a[i]);
    double l = -inf * 1.0;
    double r = inf * 1.0;
    while(r - eps > l)
    {
        double mid = (l + r) / 2.0;
        for(int i = 1; i <= n; ++i)
            sum[i] = sum[i - 1] + a[i] - mid;
        double Min = inf * 1.0;
        double ans = -inf * 1.0;
        for(int i = f; i <= n; ++i)
        {
            Min = min(Min, sum[i - f]);
            ans = max(ans, sum[i] - Min);
        }
        if(ans >= 0)
            l = mid;
        else
            r = mid;
    }
    printf("%d\n", (int)(r * 1000));
    return 0;
}