Acwing -102. 最佳牛围栏(二分)
原创
©著作权归作者所有:来自51CTO博客作者不想悲伤到天明的原创作品,请联系作者获取转载授权,否则将追究法律责任
农夫约翰的农场由 N 块田地组成,每块地里都有一定数量的牛,其数量不会少于1头,也不会超过2000头。
约翰希望用围栏将一部分连续的田地围起来,并使得围起来的区域内每块地包含的牛的数量的平均值达到最大。
围起区域内至少需要包含 F块地,其中 F 会在输入中给出。
在给定条件下,计算围起区域内每块地包含的牛的数量的平均值可能的最大值是多少。
输入格式
第一行输入整数 N 和 F ,数据间用空格隔开。
接下来 N 行,每行输出一个整数,第i+1行输出的整数代表,第ii片区域内包含的牛的数目。
输出格式
输出一个整数,表示围起区域内每块地包含的牛的数量的平均值可能的最大值乘以1000得到的数值。
数据范围
1≤N≤100000
1≤F≤N
输入样例:
输出样例:
#include <iostream>
#include <cstdio>
using namespace std ;
const int MAX = 100010 ;
int n , m ;
double cows[MAX] ;
double sum[MAX] ;
bool check(double avg){
// 这里用到一个小技巧
// 就是 对于,问题中是否存在一个长度为 F 连续的子序列,使得他们均值最大
// 等价于每个数都减去 均值,
// 看是否存在一个
// 长度大于等于 F 的连续子序列 之和 大于等于0
for(int i = 1 ; i<=n ; i++ ){
sum[i] = sum[i-1] + cows[i] -avg ;
}
double minn = 0 ;
// i , j 指针 ,他们之间差 F 单位长度
// 由于 cows[i] ... cows[j] 他们的和 可以用 S[j] - S[i-1] 来求
// 所以 S[j] - S[i-1] >=0
// 当然 s[i-1] 越小越好 , 这样不就越远离 0
// i 从 0 开始枚举, j 从 m 开始
for(int i = 0 ,j = m ; j<=n ; j++ , i++){
minn = min(minn,sum[i]) ;
if(sum[j] - minn >= 0 ) return true ;
}
return false ;
}
int main(){
cin >>n >>m ;
double l = 0 , r = 2000 ;
for(int i = 1 ; i<=n ; i ++ ){
cin >>cows[i] ;
r = max(cows[i],r);
}
while(r -l >1e-5){
double mid = (l+r)/2 ;
if(check(mid)){
l = mid ;
}
else{
r = mid ;
}
}
printf("%d\n",(int)(r*1000));
return 0 ;
}