2021.8.9提高B组模拟1T3 平均数(二分)(贪心)

Posted SSL_LKJ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021.8.9提高B组模拟1T3 平均数(二分)(贪心)相关的知识,希望对你有一定的参考价值。

平均数

题目大意

给出包含一个N个整数的数组A。找出一段长度至少为K的连续序列,最大化它的平均值。
请注意:一段子序列的平均值是子序列中所有数的和除以它的长度。

输入样例

第一行包含两个整数N(1<=N<=300000),K(1<=K<=N)。
第二行包含N个整数,代表数组A,1<=ai<=10^6。

1.

4 1
1 2 3 4

2.

4 2
2 4 3 4

3.

6 3
7 1 2 1 3 6

输出样例

一行一个实数,代表最大的平均值。允许在0.001以内的绝对误差。

1.

4.000000

2.

3.666666

3.

3.333333

题目数据

对于30%的数据,N<=5000。
对于100%的数据,1<=N<=300000, 1<=K<=N, 1<=Ai<=1000000。

解题思路

这题就是二分求出答案mid(平均值)

a数组分别减去mid,并求前缀和

如果 某一段长度>k 的子序列和>=0,则说明这个mid合法,增大 l

AC代码

#include<iostream>
#include<cstdio>
using namespace std;
int n,k;
double l,r,mid,a[300005],f[300005];
bool check(double mid)//判断是否合法
{
	double x=0.0;
	f[0]=0.0;
	for(int i=1;i<=n;i++)//求前缀和
	 f[i]=f[i-1]+a[i]-mid*1.0;
	for(int i=k;i<=n;i++)
	{
		if(f[i]-x>=0.0)return true;
		x=min(x,f[i-k+1]);
	}
	return false;
}
int main()
{
	freopen("average.in","r",stdin);
	freopen("average.out","w",stdout);
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)
	{
		scanf("%lf",&a[i]);
		r=1.0*max(a[i],r);
	}
	l=1.0;
	while(l+0.000001<r)//二分
	{
		double mid=(l+r)/2;
		if(check(mid))l=mid;
		else r=mid-0.000001;
	}  
	printf("%0.6lf",l);
	return 0;
}

谢谢

以上是关于2021.8.9提高B组模拟1T3 平均数(二分)(贪心)的主要内容,如果未能解决你的问题,请参考以下文章

2021.7.12提高B组模拟1T3 最长公共子串(记忆化搜索)

2021.8.9提高B组模拟1T4 着色(组合数学)

2021.8.9提高B组模拟1T1 最长公共回文子序列(dfs)

2021.8.9提高B组模拟1T4 着色(组合数学)

2021.8.9提高B组模拟1T1 最长公共回文子序列(dfs)

2021.8.9提高B组模拟1T2 QYQ在艾泽拉斯(Tarjan强连通分量)(并查集)