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组模拟1T1 最长公共回文子序列(dfs)