C++单调队列详解

单调队列原理与C++实现详解 单调队列是一种特殊的队列数据结构,通过维护元素的单调性(递增或递减)实现高效极值查询。其核心原理是在插入新元素时动态剔除破坏单调性的元素,从而保证队列头部始终是当前窗口的最值。这种数据结构在算法优化中具有重要价值,能够将滑动窗口类问题的时间复杂度从O(nk)优化到O(n)。典型应用场景包括滑动窗口最大值计算、股票价格分析、实时数据流处理等。本文以C++实现为例,详细解析了单调队列的底层数据结构选择、模板化实现方法以及工程实践中的性能优化技巧,帮助开发者掌握这一高效的算法优化工具。 阅读详情

单调队列到底是什么呢?

简单地按照字面意思来说,单调队列是一种队列(踢飞)

但是这种队列和普通的队列有着很大的区别,怎么说呢:

它的队首和普通的队列一样,只能删除元素。

而它的队尾既可以添加元素也可以删除元素。

通常来说也可以叫做输入受限的双端队列(栈)。


单调队列是做什么用的呢?

简单来说就是用来维护一段区间内的单调上升/下降性质,导出性质就是也可以用来维护一个区间内的最值。

我们先来看一道例题:poj 2823

题目大意

给你n个数字和一个长度k,让你从前到后输出每个长度为k的区间内的最小值/最大值。

思路

1.暴力 

从前到后每个区间遍历一遍,复杂度是O(n*k),铁定超时了

2.线段树维护区间最值

n的范围是10^6,线段树需要4*10^6的空间貌似不会爆,时间复杂度是O(nlogn),可以接受

但是对这道题而言,单调队列显然是优于线段树的另一种思路,先来了解一下它的

工作原理

假设现在我们维护一个递减(最大值)的单调队列,当一个数据想要入队时,需要执行以下操作:

①从队尾到队首开始遍历,如果碰到元素比待入队元素要小,那么这个元素便失去了作用(因为维护的是最大值,如果有一个比当前值小,那它一定不是最大的),将其出队。直到碰到一个比当前值大的元素,跳出循环;

②从队首开始清除已经不符合条件的元素(比如已经“过时”即不在当前区间内的元素,视题目而定);

在执行①之后,队列中所有之前元素都比当前元素大

执行②之后,队列中不再有“过时”元素,即此时队列中只有在区间内而且队首元素就是最大值。

复杂度

因为每个元素都只会入队一次和出队一次,所以复杂度为O(n)。

然后这道题目就可以成功地套上板子做出来了~~

不知道为什么c++提交就可以过,g++会超时,总之poj上还有好多奇怪的问题。。。。

#include<iostream>
#include<cstdio>
#include<vector>
#include<set>
#include<map>
#include<string.h>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#define LL long long
#define mod 1000000007
#define inf 0x3f3f3f3f
#define sqr(a) (a)*(a)
#define lan(a,b) memset(a,b,sizeof(a))

using namespace std;

int a[1000010];
int num1[1000010];
int num2[1000010];
int b[1000010];

int c[1000010];
int d[1000010];

int main()
{
    int n,k;
    while(~scanf("%d%d",&n,&k))
    {
        lan(a,0);
        lan(b,0);
        lan(c,0);
        lan(d,0);
        lan(num1,0);
        lan(num2,0);
        int h1=0,t1=0;
        int h2=0,t2=0;
        for(int i=1;i<=n;i++)
        {
            int tem;
            scanf("%d",&tem);
            while(h1<t1&&a[t1-1]>tem) t1--;
            a[t1++]=tem;
            num1[t1-1]=i;
            while(i-num1[h1]+1>k) h1++;
            if(i>=k)
                c[i]=a[h1];
            while(h2<t2&&b[t2-1]<tem) t2--;
            b[t2++]=tem;
            num2[t2-1]=i;
            while(i-num2[h2]+1>k) h2++;
            if(i>=k)
                d[i]=b[h2];
        }
        for(int i=k;i<=n;i++)
        {
            if(i==n)
                printf("%d\n",c[i]);
            else
                printf("%d ",c[i]);
        }
         for(int i=k;i<=n;i++)
        {
            if(i==n)
                printf("%d\n",d[i]);
            else
                printf("%d ",d[i]);
        }
    }
    return 0;
}


【C++】单调队列 详解 今天我们来讲一下单调队列与栈。 这两种数据结构虽然没有在c++的stl中有直接的实现,但是在做题过程中,很容易有单调队列(栈)的使用,尤其是在一些比较难的题目中。 目录单调队列1.1 单调队列介绍1.2 单调队列的应用1.2.1 滑动窗口最大值1.2.1.1 题目描述1.2.1.2 结题思路方法一(优先队列)方法二 (单调队列)1.3 单调队列的模拟实现1.4 其他例题 单调队列 1.1 单调队列介绍 单调队列 是 队列中元素之间的关系具有单调性,而且,队首和队尾都可以进行出队操作,只有队尾可以进行入队 阅读详情

相关推荐

滑动窗口最小值问题:单调队列算法详解与C++实现

在算法与数据结构领域,区间查询和滑动窗口是处理序列数据的核心概念。其基本原理在于高效地维护一个动态变化的数据子集,并快速响应关于该子集的查询请求。从技术价值看,这直接关系到算法的时间复杂度优化,是解决大规模数据处理问题的关键。在工程实践中,这类技术广泛应用于实时监控、流数据处理、性能分析及动态规划优化等场景。本文以信息学竞赛经典题目P2251“质量检测”为例,深入剖析了利用单调队列这一数据结构,在O(N)时间复杂度内高效求解滑动窗口最小值问题的完整方案,并提供了清晰的C++代码实现与调试技巧,帮助读者掌握这

weixin_33762130的博客 402

【c++】单调队列(超详细)

完结撒花!!!

bhffvhjbjjikiffg的博客 2500

信奥赛C++提高组csp-s之单调队列详解

信奥赛C++提高组csp-s之单调队列详解

王老师青少年编程 825

单调队列(C/C++)

单调队列是一种非常有用的数据结构,可以高效地解决需要维护窗口内最值的问题。使用单调队列的时间复杂度为O(n),其中n为输入数组的长度。t=N7T8t=N7T8t=N7T879. 滑动窗口的最大值 - AcWing题库高质量的算法题库https://www.acwing.com/problem/content/description/75/滑动窗口 /【模板】单调队列 - 洛谷https://www.luogu.com.cn/problem/P1886。

闻道有先后,术业有专攻 4725

Docker 磁盘占用过多问题处理过程记录

Docker 磁盘爆满问题处理

MR.骑士道 3553

模拟ic入门——设计一个带隙基准Bandgap(三)高阶温度补偿与启动电路设计

本节我们来介绍高阶温度补偿,以及一些启动电路的设计,附上一些经典的论文供大家学习

qq_64956710的博客 1万+

单调队列详解[C/C++]

单调队列是一-个限制只能队尾插入,但是可以两端删除的双端队列。单调队列存储的元素值,是从队首到队尾弹调性的(要么单调递增,要么单调递减)。对于求解最大值的问题,则需要维护-个单调递减的队列。如图所际,⑨为原先的队首元素,执行队首删除(出队)操作以后,⑥成为新的队元素;而在队尾执行插入④这个元素的时候,为为保持单调性,要将①②依次从队尾删除;当队尾执行插入②这个元素的时候,满足单调性。

EQUINOX1的博客 699

告别玄学:用Multisim或LTspice仿真带你直观理解PFC的三种工作模式(CCM/DCM/CrM)

本文通过Multisim和LTspice仿真工具,详细解析了PFC(功率因数校正)的三种工作模式(CCM、DCM、CrM)的本质差异。从波形捕捉到参数优化,提供了实用的仿真技巧和工程实践策略,帮助工程师直观理解并优化PFC电路设计,提升THD和功率因数。

weixin_30363285的博客 394

c++算法之数据结构篇(提高) - 单调队列

单调队列是一种高效维护滑动窗口最值的双端队列结构。它通过保持队列元素单调有序(递增或递减),在O(n)时间内解决滑动窗口最大值等问题。核心操作包括:队尾删除破坏单调性的元素、添加新元素,以及移除过期元素。相比暴力解法的O(nk)复杂度,单调队列显著提升效率。典型应用包括求滑动窗口最值、最大子序和变体等场景。实现时建议存储索引而非值,便于处理窗口边界和重复元素。与优先队列相比,单调队列更适合固定窗口的最值问题,具有线性时间复杂度的优势。掌握这一数据结构对解决各类区间最值问题至关重要。

巴巴博一巴巴博一巴巴博一 873

大疆OcuSync vs 传统2.4GHz:深度拆解无人机图传射频模块的硬件差异

本文深度对比了大疆OcuSync与传统2.4GHz无人机图传射频模块的硬件差异,涵盖芯片组、天线系统、PCB设计、散热方案及生产测试等核心环节。重点解析OcuSync的全定制SoC芯片、智能MIMO天线阵列及精密PCB布局如何实现革命性性能提升,为无人机图传技术发展提供专业参考。

u5v6w7的博客 806

S32K344 Flash Driver实战:手把手教你实现任意字节写入与扇区解锁(含C40_Ip避坑指南)

本文深入解析S32K344微控制器的Flash驱动开发,重点解决C40_Ip驱动库的8字节对齐限制和扇区保护锁问题。通过实战案例和代码示例,详细介绍了如何实现任意字节写入、扇区解锁及性能优化策略,为Bootloader和OTA升级等应用提供可靠解决方案。

weixin_33713707的博客 431

单调队列(例题详解+模板cpp)

蓝桥杯算法复习:单调队列基本知识与例题讲解+模板c++

ylh的博客 1130

2025华为od机试真题B卷【版本管理】Python实现

在 软件版本管理中,版本号由点分割的数字组成,例如 1.2.3 和 2.8。现在,你需要编写一个函数,计算两个版本号之间的可用版本号个数。这里的可用版本号指的是所有满足 version1<x<version2的版本号x的个数。若 version1 >=version2 返回0.,

MISAYAONE的博客 643

C++ 入门单调队列的应用及心得 —— 例题详解 最大矩形面积

单调队列——最大矩形面积 目录 单调队列——最大矩形面积 题目描述:最大矩形面积  分析 思路 易错点 代码 题目描述:最大矩形面积 直方图是由在公共基线处对齐的一系列矩形组成的多边形。矩形具有相等的宽度,但可以具有不同的高度。例如,左边的图显示了由高度为2,1,4,5,1,3,3的矩形组成的直方图,以单位为单位测量,其中1是矩形的宽度:  通常,直方图用于表示离散分布,...

qq_44013342的博客 1085

【GLM5】手把手教你在openclaw中白嫖英伟达羊毛

openclaw很强,但是也很贵,每一次请求都会消耗大量的token。而英伟达平台正好可以白嫖免费的模型,于是,我们一拍即合。

Science prince的博客 3820

DAB协议解读ETSI TS 103 461

数字信号广播( Digital Audio Broadcasting 简称DAB)是继AM、FM传统模拟广播之后的第三代广播--数字信号广播,它提供了接近CD质量的声音,广播及商机无限的附加数据服务,具有抗噪声、抗干扰、抗电波传播衰落、适合高速移动接收等优点,保证固定、携带及移动时接收信号的质量。DAB的原始版本使用MP2音频编解码器。该系统的升级版本于2007年2月发布,称为DAB+,它使用基于改进的离散余弦变换(MDCT)的HE-AACv2(AAC+)音频编解码器。

qflook的博客 4477

C++ 单调队列入门应用——例题详解 滑动窗口

滑动窗口 关于这道题,首先会想到暴搜,但数据太大,绝对超时。用暴搜的思路来说,就是一个一个枚举,再在当中找出最大最小值,会发现,每次都在重复枚举,那有没有什么方法可以保存之前的值? 这就引出主题了——单调队列 单调队列,就是一个队列,但有单调性,就是队列里的元素是递增或递减的 例如 1 2 3 4 5 6 7 8...

qq_44013342的博客 1524

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

每日c/c++题 备战蓝桥杯(洛谷P1440 求m区间内的最小值 详解(单调队列优化))

本文详细介绍了如何通过单调队列优化洛谷P1440题目的解法,将时间复杂度从O(nm)优化至O(n)。文章首先分析了暴力解法的缺陷,随后引入单调队列的核心思想,并提供了完整的C++代码实现。通过维护一个双端队列,确保队列元素严格单调递增,队首元素始终为当前窗口的最小值下标,并自动清理失效元素。文章还讨论了关键优化点,如输入优化、数组下标处理和空间优化,并通过示例详细解释了算法流程。最后,文章总结了单调队列的应用场景和核心操作,强调了其在解决滑动窗口类问题中的重要性。

m0_74096349的博客 1658

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

双端队列与单调队列详解

本篇主要只是讲解该数据结构以及简单应用,具体例题可以自行探索。

2301_79114877的博客 325

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

【单调队列】滑动窗口最大值

本文介绍了LeetCode 239题"滑动窗口最大值"的解法,重点分析了使用单调队列的两种实现方式。题目要求在长度为n的数组中,找出所有大小为k的滑动窗口中的最大值。 解法核心在于使用单调队列维护窗口内元素的顺序: 维护数组下标法:队列存储元素下标,保证队头始终是当前窗口最大值。通过判断下标范围确保元素在窗口内,新元素入队时移除破坏单调性的元素。 维护元素值法:队列直接存储元素值,同样保持单调递减。需额外判断队头元素是否仍在窗口范围内。 两种方法时间复杂度均为O(n),相比暴力解法

lirendada的博客 1111

从优先队列到单调队列:C++中滑动窗口问题的性能优化之旅

本文深入探讨了C++中解决滑动窗口极值问题的性能优化路径。从直观但存在性能瓶颈的优先队列(std::priority_queue)解法出发,逐步引出了时间复杂度更优的单调队列方案。文章详细对比了两种方法的时间与空间复杂度,并提供了单调队列的C++实现及其泛化应用,旨在帮助开发者根据场景在实现便捷性与极致性能间做出最佳选择。

peace的博客 405

算法基础篇:(二十二)数据结构之单调队列:滑动窗口问题的 “最优解” 神器

本文深入解析单调队列这一高效解决滑动窗口问题的数据结构。首先介绍单调队列的核心特性:双端操作、严格单调性和存储下标机制,通过面试官选人的生动比喻阐明其淘汰无效元素的原理。接着详细拆解维护单调性的入队和出队操作步骤,并配以可视化演示。文章提供滑动窗口最大值/最小值的经典模板题完整代码实现,重点解析加速输入输出、下标存储等关键技巧。最后通过洛谷P2251质量检测题展示实战应用,并总结存储数值而非下标、单调性维护不彻底等常见坑点,帮助读者从原理到实践全面掌握单调队列。

2301_79248256的博客 1849

C++单调队列实战:5分钟搞定滑动窗口最大值(附完整代码)

本文详细解析了如何使用C++单调队列高效解决滑动窗口最大值问题。通过清晰的算法步骤拆解和完整代码实现,展示了如何将时间复杂度优化至O(n),并提供了边界处理、通用类封装及常见应用场景,是提升算法与数据结构能力的实战指南。

yog99的博客 869

c++的单调队列

顾名思义,单调队列的重点分为「单调」和「队列」。「单调」指的是元素的「规律」——递增(或递减)。「队列」指的是元素只能从队头和队尾进行操作。Ps. 单调队列中的 "队列" 与正常的队列有一定的区别,稍后会提到。

c++爱好者 960

C++滑动窗口最大值:单调队列从原理到实战

在算法面试中,滑动窗口是一类高频题型,而高效维护窗口内的最值往往需要合适的数据结构。从最基础的暴力遍历出发,当数据规模增大时,O(nk) 的复杂度会迅速失效,因此需要引入单调队列来在线性时间内维护候选最大值。单调队列利用双端队列(deque)两端 O(1) 操作的特点,淘汰不可能成为最大值的旧元素,并自动处理过期索引,从而将整体复杂度降为 O(n)。这一思想不仅适用于 LeetCode 第239题这类滑动窗口最大值问题,也能迁移到最长无重复子串、绝对差限制等变体场景。本文以 C++ 为例,结合代码实现与边界

weixin_33600816的博客 115

滑动窗口与单调队列优化:从暴力到O(n²)解决二维区间最值问题

在算法与数据结构中,滑动窗口是一种处理数组或序列上连续区间问题的核心技巧,常用于高效求解固定长度子区间的统计量,如最大值、最小值或和值。其原理在于通过动态维护一个窗口,在遍历过程中以O(1)复杂度更新窗口信息,避免重复计算,从而将暴力解法的O(n²)或O(n³)复杂度优化至O(n)。实现这一优化的关键技术是单调队列,它能在O(n)时间内维护窗口内的单调性,确保快速获取当前窗口的最值。这种技术价值巨大,是算法竞赛和工程实践中优化时间复杂度的利器,广泛应用于实时数据流处理、图像处理中的局部特征计算以及动态规划的

weixin_33883104的博客 231
上一篇: poj 1651 Multiplication Puzzle(区间DP)
下一篇: hdu 3507 斜率优化DP-详解
Dale_zero
博客等级 码龄9年 10粉丝 174原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值