一.题目链接:
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;
}