子序列的平均值

给定一个长度为n的非负序列A,请你找出一个长度不小于L的子段(子段是序列A中一些连续的元素构成的集合),使得子段中数值的平均值最大。最终输出这个最大的平均值。

输入格式:

第一行两个整数n,L(1<=L<=n<=100,000)

以下n行,每行一个非负整数,表示序列A中每个元素的值。

输出格式:

一个整数,欲求的最大平均值乘以1000后的结果(注意不要四舍五入,直接输出)

输入样例:

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

输出样例:

6500

源码 

#include <bits/stdc++.h>
using namespace std;

int n = 0, L = 0;
double elements[100001] = {0};
double maxElement = 0, minElement = 1e9;

void myRead()
{
    cin >> n >> L;

    for (int i = 1; i <= n; ++i)
    {
        cin >> elements[i];
        maxElement = max(elements[i], maxElement);
        minElement = min(elements[i], minElement);
        // maxElement = maxElement < elements[i] ? elements[i] : maxElement;
        // minElement = minElement > elements[i] ? elements[i] : minElement;
    }
}

bool myCheck(double average)
{
    bool flag = false;

    double sum[100001] = {0};
    for (int i = 1; i <= n; ++i)
    {
        sum[i] = sum[i - 1] + (elements[i] - average);
    }

    // for (int i = 0; i < n; ++i)
    // {
    //     cout << i + 1 << " : " << sum[i] << endl;
    // }

    double fronts = 1e9;
    for (int i = L; i <= n; ++i)
    {
        fronts = min(fronts, sum[i - L]);
        if (sum[i] - fronts > 0)
        {
            flag = true;
            break;
        }
    }

    return flag;
}
int main()
{
    myRead();

    double low = minElement, high = maxElement, answer = (low + high) / 2;
    while (high - low > 1e-5)
    {
        // cout << "answer = " << answer << ", high = " << high << ", low = " << low << endl;
        if (myCheck(answer))
        {
            low = answer;
        }
        else
        {
            high = answer;
        }

        answer = (low + high) / 2;
        // cout << "---------------------" << endl;
    }

    // cout << "answer = " << answer << ", high = " << high << ", low = " << low << endl;
    cout << (int)(high * 1000);

    return 0;
}

心路历程

初体验

刚读完题目,感觉这道题熟悉,因为之前好像做过类似的题目,但是又想不起来是哪一道题。而且读完之后是想不到解题方法的,所以就去网上搜了别人的代码。看代码第一感觉是看不懂,别人的思路看不懂,代码也看不懂,看了好几篇,都很蒙,最终发现了其他人的文章中大多数都提到了二分答案这个词,这个词在之前没听说过,只听过二分查找,猜测是个算法名称,所以就去b站搜了关键字。

二分答案

二分答案是个算法。

首先先明白它适合什么问题:求最值问题(答案有一定的范围,并且明确的知道一对上下界)。

其次看看二分答案是什么:当一个求最值问题的求最值过程不好求解或者不会求解的时候,我们可以试着去猜答案,比如说这个最值问题的答案会出现在a到b之间,当我们猜c,发现c小了,那么下一步就可以猜一个c到b之间的数........直到猜到答案为止,有点像枚举,但又不是暴力枚举。

抽象的讲,二分答案法是把一个最值问题转化成了一个判断问题。

回归这道题

其实这道题就是求最大平均值,只不过有一个约束条件就是这组数要连续且长度不能小于L。先抛开约束条件不谈,平均值的范围一定是在这组数的最小值和最大值之间的,所以这就自然而然有了范围,正向解也不会解,所以就试试二分答案。 

该吃饭了 不想写了.... 

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罗马尼亚硬拉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值