【POJ2018 Best Cow Fences】二分卡精度+前缀和

题目链接

题意:

给定一个正整数数列,求一个平均数最大的,长度不小于L的子段

分析:

咱们可以二分子段的平均值然后检查一下是否有平均值比它大的子段,如果有的话就l = mid,如果没有的话就r = mid,最后二分出来的结果就是答案,题目中说了牛的数量是0-2000,所以边界就可以设置为0~2000,check函数的话就是写一个前缀和,一边找最小前缀一边检查这一子段是否满足题意, 具体请看代码:

#include
#include
#include
using namespace std;
const int N = 100010;
double a[N],b[N],pre[N];
int n,m;
bool check(double x){
	for(int i=1;i<=n;i++) b[i] = a[i] - x,pre[i] = pre[i-1] + b[i];
	double minleft = 1e11;
	for(int i=m;i<=n;i++){
		minleft = min(minleft,pre[i-m]);
		if(pre[i] - minleft >= 0) return true;
	}
	return false;
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	double l = 0,r = 2000;
	while(r-l>1e-6){
		double mid = (l + r) / 2;
		if(check(mid)) l = mid;
		else r = mid;
	}
	printf("%d\n",(int)(r*1000));//注意这个地方一定是r,因为求的是最大值
	return 0;
} 

你可能感兴趣的:(学习日记,算法题目,动态规划,算法,图论,c++)