Best Cow Fences POJ - 2018 二分

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_41280600/article/details/102708277

一、内容

题意:给定正整数数列A,求一个平均数最大的、长度不小于L的字段。

二、思路

  • 我们选取一段连续的数的和 sum / 土地数量 n = ans 转化为 sum = ans * n
  • 我们把每一个数都减去ans(二分枚举的答案),然后转化为求某一段不小于L的区间最大和
  • 我们用一个min_val记录每次前面区间的最小值,这样我们只需要让sum[i] - min_val即可获取区间最大和了。

三、代码

#include <cstdio>
#define min(a, b) (a > b ? b : a)
#define max(a, b) (a > b ? a : b)
const int N = 1e5 + 5;
int n, f;
double a[N], b[N], sum[N];
int main() {
	scanf("%d%d", &n, &f);
	for (int i = 1; i <= n; i++) {
		scanf("%lf", a + i);
	}
	double l = 0, r = 2000;
	double eps = 1e-5;
	while (r - l > eps) {
		double mid = (l + r) / 2;
		//所有数减去mid 
		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;
		}
	} 
	//由于653.666 答案是653因为654就不满足结果了所以必须向下取整 
	printf("%d\n", int(r * 1000));
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_41280600/article/details/102708277