单调队列
来源:互联网 发布:著名 淘宝店主 90后 编辑:程序博客网 时间:2024/06/07 00:13
预备知识介绍:
1. 队列
- 队列 (queue) 是一种特殊的线性表,是符合“先进先出”(first in first out)原则的基本数据结构,因此也常被称作 FIFO 队列或公平队列。
- 一个队列由队首 (front)、队尾 (rear) 和储存元素的线性表构成。当元素入队时,队尾后移并向线性表中添加新元素;当元素出队时,删除线性表中队首指向的元素,队首后移。一般地,只在队尾入队,在队首出队。对队中元素的讨论都必须建立在队列非空的基础上,否则没有意义。
- C++ STL 中内置了 queue 容器,实现了普通队列的基本操作,使用时需引用 头文件。
2. 双端队列
- 双端队列 (deque) 打破了队列的出入队位置限制,允许元素从队首入队或从队尾出队。类似地,在 C++ STL 中内置了 deque 容器,实现了双端队列。
3. 单调队列
- 单调队列 (monotonic queue) 是指一种所储存的元素具有单调性的特殊双端队列,可根据具体的元素单调性分为单调递增队列、单调递减队列、单调不增队列、单调不减队列四种。前两种要求元素间具有严格的大小关系,不允许相等的元素同时出现在队列中,而后两者允许。
- 单调队列常常用于维护一个具有特殊性质的区间,求区间极值。一般会对区间长度或其他因素进行限制,因此队列中的元素常常为
(pos,val) 的二元组。在任意时刻,队列中元素的两个值都分别具有单调性,但其性质可能不同。如pos 一般为单调上升,而val 则四种情况都有可能。 - 新元素入队时,为了维护队列的单调性,要不断将队尾元素出队,直到当前元素入队后不会破坏队列单调性为止。取值计算时,为了保证对区间的限制是合法的,要将队首元素不断出队,直到队首元素满足对区间的限制为止。出队和入队的顺序可以调换。详见下面的例子。
- 在竞赛中单独考察单调队列的情况极少出现,但往往会配合动态规划,对其时间复杂度进行优化。近年来,NOI 系列赛事和部分省选都考察过。
举例分析
下面试举一例,分析单调队列的具体题目中的应用。
给定 n
朴素的算法为枚举所有待求的 max(a_i, a_{i+1}, \ldots, a_{i+k-1})
我们发现,求 max(a_1, a_2, \ldots, a_k)
其实我们的任务是维护一个长度为
我们不妨维护这样一个单调队列
- 队尾的
pos 减去队首的pos 都必须小于k - 队中的
val 保持单调递减(为什么不用单调不增?)
以
,(1,8),(2,7)){当前的 (3,12),(4,5),(5,4),(6,2)){ ,(4,5),(5,4),(6,2)) {当前的 ,(7,16),(8,9)) {
在这个过程中,可以发现队列
因此作为合法的单调递减队列,任意时刻处理完之后队首元素的
下面来思考上面的问题,为什么不使
后来仔细想想,其实也是可以的,但单调递减会更好。不妨这样考虑:有元素
因为我们要求的是最大值,看上去
顺便提一句,类似于单调队列,还有一种单调栈,原理和单调队列极其相似,只是通常情况下少了对于区间的限制,如 RQNOJ“诺诺的队列”一题。
为了方便理解,甚至可以把单调栈看成单调队列的一个特殊版本,只允许在队尾出入队。
最后来考虑时间复杂度的问题。
我最初在小学阶段学习单调队列的时候在担心一个问题:对于每一个新元素,维护单调队列都要进行一定的出入队操作,会不会出现最坏情况导致很慢?
其实是不可能的。因为每个元素是被按照一定的顺序依次考虑的,最多入队一次,出队一次,总的时间复杂度其实是
相比于线段树、胜者树、堆等传统的维护最值数据结构,单调队列具有其独特的优点:编程复杂度、时间复杂度和空间复杂度都比较低。但是其短处也是不可不考虑的,即单调队列是离线的,无法像上述数据结构一样支持动态操作。
当然有时候也可以通过灵活使用单调队列,发挥出很大的作用。总的来说,在具体的题目中,还是应该具体考虑,分析题目的特点,选择最合适的方法。熟练掌握各种常用数据结构的特点及编写对 NOIp 提高组及以上级别的选手还是很有必要的。
参考文献
- 应用单调队列求解指定区间的最值. 湖南省醴陵市第一中学: 曾妞妞.
- 论单调队列在高效动态规划算法中的应用. 绵阳中学: 李青林.
- 单调栈 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 集合类与IO
- Vector的用法
- KD树详解及KD树最近邻算法
- cf Star sky
- Hypersizer Pro 5.3 (复合材料分析与结构优化)\
- 单调队列
- PX4(PIXHAWK)源码开发人员文档(二)——Hello Sky
- nao机器人之void ALMotionProxy::moveTo()
- 解决Java连接MongoDB数据库"Authentication failed"问题
- Java 并发编程:核心理论
- image object detection
- JavaScript 使用
- 红黑树讲解(逻辑思路透彻清晰)
- linux常用命令