题干:
农夫约翰的农场由 N 块田地组成,每块地里都有一定数量的牛,其数量不会少于1头,也不会超过2000头。
约翰希望用围栏将一部分连续的田地围起来,并使得围起来的区域内每块地包含的牛的数量的平均值达到最大。
围起区域内
至少需要包含 F 块地
,其中 F 会在输入中给出。
在给定条件下,计算围起区域内每块地包含的牛的数量的平均值可能的最大值是多少。
1≤N≤100000
思路:
因为要求的是平均值最大,也就是合最大,可以用前缀和快速求出。
但因为求得是至少f块地的平均值最大,具体的地的数量未知,所以普通暴力无从下手。
考虑到牛的总最大数量是
2
∗
10
8
{2*10}^8
2
∗
1
0
8
,然后求得又是平均值,所以我们可以直接二分枚举平均值,然后通过与最大部分和进行比较,得到范围。
这里在算前缀和的时候先减去ave,可以使数据变小,方便使用。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <map>
#include <iostream>
#include <algorithm>
#define ll long long
using namespace std;
const int inf= 1e6;
int n,m,t[100010];
double s[100010];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&t[i]);
}
double r=inf,l=0;
while((r-l)>0.0001)
{
double mid=(r+l)/2;
for(int i=1;i<=n;i++)
s[i]=s[i-1]+(double)t[i]-mid;
double temp=inf,ans=-inf;
for(int i=m;i<=n;i++){
temp=min(temp,s[i-m]);
ans=max(ans,s[i]-temp);
}
//printf("%lf %lf\n",l,r);
if(ans>=0)
l=mid;
else
r=mid;
}
// printf("%lf %lf\n",s[0],s[5]);
printf("%d\n",(int)(r*1000));
return 0;
}