Farmer John's farm consists of a long row of N (1 <= N <= 100,000)fields. Each field contains a certain number of cows, 1 <= ncows <= 2000.
FJ wants to build a fence around a contiguous group of these fields in order to maximize the average number of cows per field within that block. The block must contain at least F (1 <= F <= N) fields, where F given as input.
Calculate the fence placement that maximizes the average, given the constraint.
Input
* Line 1: Two space-separated integers, N and F.
* Lines 2..N+1: Each line contains a single integer, the number of cows in a field. Line 2 gives the number of cows in field 1,line 3 gives the number in field 2, and so on.
Output
* Line 1: A single integer that is 1000 times the maximal average.Do not perform rounding, just print the integer that is 1000*ncows/nfields.
Sample Input
10 6
6
4
2
10
3
8
5
9
4
1
Sample Output
6500
题目描述:给定一个正整数数列A,求一个平均数最大的、长度不小于L的子段。
分析:二分答案,判定是否存在一个长度不小于L的子段,平均数不小于二分的值。如果把数列中的每个数都减去二分的值,就转换为判定“是否存在一个长度不小于L的子段,子段和非负”。
求一个子段,它的和最大,子段的长度不小于L。
子段和可以转换为前缀和相减的形式,即设sumj表示Ai~Aj的和,
则有:max{A[j+1]+A[j+2].......A[i] } ( i-j>=L ) = max{ sum[i] - min{ sum[j] }(0<=j<=i-L) }(L<=i<=n)
仔细观察上面的式子可以发现,随着i的增长,j的取值范围 0~i-L 每次只会增大1。换言之,每次只会有一个新的取值进入 min{sumj} 的候选集合,所以我们没必要每次循环枚举j,只需要用一个变量记录当前的最小值,每次与新的取值 sum[i-L] 取min 就可以了。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int maxn=100005;
double a[maxn],b[maxn],sum[maxn];
int main(){
int N,F;
scanf("%d %d",&N, &F);
for(int i=1; i <= N; i++)
scanf("%lf", &a[i]);
double eps=1e-5;
double l=-1e6, r=1e6;
while(r - l > eps) {
double mid = (l + r) / 2;
for(int i=1; i <= N; i++)
b[i] = a[i] - mid;
for(int i = 1; i <= N; i++)
sum[i] = sum[i-1] + b[i];
double ans = -1e10;
double min_val = 1e10;
for(int i = F; i <= N; i++){
min_val = min(min_val, sum[i-F]);
ans = max(ans, sum[i]-min_val);
}
if(ans >= 0) l = mid;
else r = mid;
}
printf("%d\n",int(r*1000));
return 0;
}