POJ - 2018 Best Cow Fences 实数域上的二分

题目描述

给定一个长度为n的序列,求其中平均值最大长度不少于L的序列
将平均值*1000输出

样例

Sample Input
10 6
6 
4
2
10
3
8
5
9
4
1
Sample Output
6500

思路
二分答案,存在一个数mid使序列上所有的数减去mid, 此时将原问题转换成了求一个序列长度不少于L,他的和不少于0,此时我们用sum数组存下减去mid后序列的前缀和,即是求在下标L以后的点x,sum[x]-min(sum[1~x-L]),
就是sum[x] 减去 下标1到x-L的的前缀和里面最小的一个数,就是满足条件的最大解,如果这个值大于0,就是往大于mid的一边扩展。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>

using namespace std;

const int N = 100010;
const double eps = 1e-8;

double a[N], d[N], sum[N];
int n, L;

int main()
{
	scanf("%d%d", &n, &L);
	for (int i = 1; i <= n; i++)
		scanf("%lf", a + i);
	double l = -1e6;
	double r = 1e6;
	while (r - l > eps)
	{
		double mid = (r + l) / 2;
		for (int i = 1; i <= n; i++)
			d[i] = a[i] - mid;
		for (int i = 1; i <= n; i++)
			sum[i] = d[i] + sum[i - 1];

		double ans = -1e10;
		double min_val = 1e10;

		for (int i = L; i <= n; i++)
		{
			min_val = min(min_val, sum[i - L]);
			ans = max(ans, sum[i] - min_val);
		}
		if (ans >= 0)
			l = mid;
		else
			r = mid;
	}
	int res = int(r * 1000);
	printf("%d\n", res);
	return 0;
}
发布了118 篇原创文章 · 获赞 221 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_45432665/article/details/104840991
今日推荐