栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

前缀和&&单调队列:最大子序和

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

前缀和&&单调队列:最大子序和

输入一个长度为 nn 的整数序列,从中找出一段长度不超过 mm 的连续子序列,使得子序列中所有数的和最大。

注意: 子序列的长度至少是 11。

输入格式

第一行输入两个整数 n,mn,m。

第二行输入 nn 个数,代表长度为 nn 的整数序列。

同一行数之间用空格隔开。

输出格式

输出一个整数,代表该序列的最大子序和。

数据范围

1≤n,m≤3000001≤n,m≤300000

输入样例:

6 4
1 -3 5 1 -2 3

输出样例:

7

题解:

这道题可以用for循环,但是当数据量过大时会运行时间过长,所以用到了单调队列。

单调队列的题以及模板如下:

单调队列 —— 模板题 AcWing 154. 滑动窗口
常见模型:找出滑动窗口中的最大值/最小值
int hh = 0, tt = -1;
for (int i = 0; i < n; i ++ )
{
    while (hh <= tt && check_out(q[hh])) hh ++ ;  // 判断队头是否滑出窗口
    while (hh <= tt && check(q[tt], i)) tt -- ;
    q[ ++ tt] = i;
}

 

本题代码如下:

#include 

using namespace std;

typedef long long LL;

const int N = 3e5 + 10;

int n, m;
LL s[N], que[N];

int main()
{
    cin>>n>>m;
    for (int i = 1; i <= n; i ++ )
    {
        cin>>s[i];
        s[i] += s[i - 1];//前缀和
    }
    LL res = -1e18;
    int hh = 0, tt = 0;
    que[0] = 0;
    for (int i = 1; i <= n; i ++ )
    {
        while (hh <= tt && i - que[hh] > m) //单调队列,当队首元素的序列与i相差超过m,队首元素出队
            hh ++ ;
        res = max(res, s[i] - s[que[hh]]);
        while (hh <= tt && s[que[tt]] >= s[i]) //单调队列,当队尾元素大于当前元素s[i],队尾元素出队
            tt -- ;
        que[ ++ tt] = i;//当前元素入队
    }
    cout< 

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/317859.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号