题目:
农夫约翰的农场由 NN 块田地组成,每块地里都有一定数量的牛,其数量不会少于1头,也不会超过2000头。
约翰希望用围栏将一部分连续的田地围起来,并使得围起来的区域内每块地包含的牛的数量的平均值达到最大。
围起区域内至少需要包含 FF 块地,其中 FF 会在输入中给出。
在给定条件下,计算围起区域内每块地包含的牛的数量的平均值可能的最大值是多少。
输入格式
第一行输入整数 N和 F ,数据间用空格隔开。
接下来 N 行,每行输出一个整数,第i+1i+1行输出的整数代表,第ii片区域内包含的牛的数目。
输出格式
输出一个整数,表示围起区域内每块地包含的牛的数量的平均值可能的最大值乘以1000得到的数值。
数据范围
1≤N≤1000
00
1≤F≤N
输入样例:
10 6
6
4
2
10
3
8
5
9
4
1
输出样例:
6500
解题报告:
这道题要求解的就是某一长度大于等于L的区间的最大平均值,输出这个最大平均值*1000.
开始的时候除了想暴力双重for循环求解之外毫无想法,但是时间复杂度不满足,就很难受,后来又看了课本,才对这个题目想起来二分的思路,需要转变一下思路,就是之前咱们是要去求解的是最大的平均值,现在咱们就可以处理一下将每次的所求数组全部-mid(这个mid是咱们二分的数值),然后对这个数组进行一下最大子段和非负判断就可以。
ac代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn= 1e5+10;
double a[maxn];
double b[maxn];
double sum[maxn];
int n,f;
int main()
{
cin>>n>>f;
for(int i=1;i<=n;i++)
cin>>a[i];
double l=-1e6,r=1e6;
double eps=1e-6;
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;
}
cout<<int(r*1000)<<endl;
}