题目描述
农夫约翰的农场由 N 块田地组成,每块地里都有一定数量的牛,其数量不会少于 1 头,也不会超过 2000 头。
约翰希望用围栏将一部分连续的田地围起来,并使得围起来的区域内每块地包含的牛的数量的平均值达到最大。
围起区域内至少需要包含 F 块地,其中 F 会在输入中给出。
在给定条件下,计算围起区域内每块地包含的牛的数量的平均值可能的最大值是多少
第一行输入整数 N 和 F,数据间用空格隔开。
接下来 N 行,每行输入一个整数,第 i+1 行输入的整数代表第 i 片区域内包含的牛的数目。
输出一个整数,表示平均值的最大值乘以 1000 再 向下取整 之后得到的结果。
数据范围
1≤N≤100000
1≤F≤N
样例
10 6
6
4
2
10
3
8
5
9
4
1
输出样例:
6500
算法1
(浮点数二分+前缀和+双指针)
时间复杂度
参考文献
y总
C++ 代码
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,f;
int s[N];
double q[N];
bool ch(double mid){
double Min=0;
for(int i=1;i<=n;i++)
q[i]=q[i-1]+s[i]-mid;//牛数量前缀和减去mid的区间前缀和减去mid求和。
for(int i=0,j=f;i<n,j<=n;j++,i++)//j从f开始,保证了“围起区域内至少需要包含 F 块地”的条件(双指针)
{
Min=min(Min,q[i]);//前i个的最小前缀和
if(q[j]>=Min)//等价于q[j]-Min>=0,如果前j个的前缀和非负,则存在
return true;
}
return false;
}
int main(){
cin>>n>>f;
for(int i=1;i<=n;i++)
cin>>s[i];
double l=0,r=2000;
double mid;
while(r-l>1e-6)//浮点数二分(如果不熟悉的可以看看Y总视频),此处也可写成for(int i=0;i<100;i++)
{ //因为*1000实际上保留3位有效位数,所以写成1e-5,1e-6都可。
mid=(l+r)/2;//将牛的数量进行二分
if(ch(mid))
l=mid;//存在j区间,将左段点移至当前mid处,继续向右找最大值
else
r=mid;//否则将右端点移至当前mid处,继续向左找最大值
}
cout<<int(r*1000);//向下取整
return 0;
}
路过的客官,可否小小的赞一下,鼓励我这个菜鸡一下,嘿嘿。