每日一题7.22

P10450 [USACO03MAR] Best Cow Fences G - 洛谷

题目描述

原题来自:USACO 2003 Mar. Green

给定一个长度为 n 的非负整数序列 A ,求一个平均数最大的,长度不小于 L 的子段。

输入格式

第一行用空格分隔的两个整数 n 和 L;

第二行为 n 个用空格隔开的非负整数,表示 Ai​。

输出格式

输出一个整数,表示这个平均数的 1000 倍。不用四舍五入,直接输出。

输入输出样例

输入 #1复制

10 6
6 4 2 10 3 8 5 9 4 1

输出 #1复制

6500

说明/提示

1≤n≤105,0≤Ai​≤2000。

很巧妙的使用二分,从0到2000往答案逼近。注释如下。

#include
using namespace std;
#define int long long
double s[100005],a[100005];
double l = 0, r = 2e3;	//从0~2e3往答案逼近
int n, L;
bool check(double x)
{
	for (int i = 1; i <= n; i++)
		s[i] = s[i - 1] + a[i] - x;//s[i]是a[i]的前缀和减去现在的mid
		double minn = 0;
	for (int i = L; i <= n; i++)
	{
		minn=min(minn,s[i-L]);//minn是从s[0]到s[n-l]小于0的最小值
		if (s[i] - minn >= 0)//如果s[i]-minn>0就说明 s[i]到minn这一段的平均值大于mid返回true
			return true;
	}
	return false;
}
void solve()
{

	cin >> n >> L;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
	}
	while (r-l> 1e-4)
	{
		double mid = (l + r) / 2;
		if(check(mid))l = mid;
		else r = mid;
	}//二分模板,寻找合适的答案
	cout<<(int)(r*1000)<> t;
	while (t--)
	{
		solve();
	}
}

你可能感兴趣的:(每日一题7.22)