单调栈和单调队列
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
为什么要学习单调栈:
• 它可以很方便地求出某个数的左边或者右边第一个比它大或者小的 元素,而且总时间复杂度O(N)。
如何维护单调栈:(以维护单调递增栈为例)
进栈操作:每次入栈前先检验栈顶元素和进栈元素(x)的大小,如果小于x, 就让x直接入栈。如果栈顶元素大于等于x,那么出栈,直到栈空或者栈顶元 素小于x
区间最值问题:我们想到了啥?线段树?RMQ?
新姿势!!单调队列!O(n)!!!!
O(nlog(n))!!!!
分 析
以得到最小值为例:
• 我们维护一个单增的队列,那么每次滑动窗口入队之后就要得到 一个区间最小值,按照刚才的理论,直接取队首元素就可以了? ??
• 具体做法:每次滑动窗口要得到最小值的时候,判断队首元素 是否过期,,如果过期,就从队首出队,继续找ຫໍສະໝຸດ 最大值做法同上:维护一个单减队列。
例 题
POJ 2559
题意:给出一个柱形统计图(histogram), 它的每个项目的宽度是1, 高度和具体 问题有关。 现在编程求出在这个柱形图中的最大面积的长方形(n<=1e5)
例如:2, 1, 4, 5, 1, 3, 3
最大面积:8
那么问题来了:如何算?
分 析
• 逐个考虑每个项目,那么如何得到每个项目被包含的长方形了? • 假设考虑到项目x,通过简单的思考,我们可以得出结论,x的左 右两边的项目高度都不能比x低,那么如何求项目x的两边延伸 长度? • 我们想到了单调栈 ???????为什么 (以求x左边延伸长度为例)
定义:
• 单调队列:队列中元素之间的关系具有单调性,而且,队首和 队尾都可以进行出队操作,只有队尾可以进行入队操作。
为什么要学习单调队列 :
• 对于维护好的单调队列,对内元素是有序的,那么取出最大值(最 小值)的复杂度是O(1) • 可以拿来优化DP(然而弱不会)
如何维护单调队列:
队尾入队的时候维护单调性。
实 现 方 式
void get_min() { int tail=0,head=1; for(int i=1;i<k;i++) { while(head<=tail&&q[tail]>=a[i]) --tail; q[++tail]=a[i]; p[tail]=i; } for(int i=k;i<=n;i++) { while(head<=tail&&q[tail]>=a[i]) --tail; q[++tail]=a[i]; p[tail]=i; while(p[head]<i-k+1) ++head; mi[i-k+1]=q[head]; } }
Special
head
tail
我们发现,每次从尾部入队前都会比较大小---->注意对象 是队内元素,但是队内元素都是按次序入队,即队内元素都是 比当前要入队的次序小,所以单调队列里的元素都是有次序的 (由小到大)所以,我们要查找某个id的时候,也可以二分。
最后练习的六道题目已经在VJ上挂出来了,欢迎AC
假设我们建立一个单调递增栈,那么我们可以轻松地求得x左边比x小的第一 个数的位置。 那么问题来了:为什么是单调递增栈,为什么是比x小? 求x右边延伸相同处理
方 式
实 现
• 栈(以求x的向左延伸为例) int top=0,s[maxn]; for(int i=1;i<=n;i++) while(top&&h[s[top]]>=h[i]) --top; L[i]=(top==0?1:s[top]+1); s[++top]=i; • 并查集 L[1]=1; for(inti=2;i<=n;i++) int pos=i; while(pos-1>=1&&h[i]<=h[pos-1]) pos=L[pos-1]; L[i]=pos;
whilephead注意对象是队内元素但是队内元素都是按次序入队即队内元素都是比当前要入队的次序小所以单调队列里的元素都是有次序的由小到大所以我们要查找某个id的时候也可以二分
单调栈和单调队列
by
Tisuama
定义:
• 单调栈:栈内的元素,按照某种方式排序下(单调递增或者单调递减) 如果新入栈的元素破坏了单调性,就弹出栈内元素,直到满足单调性
例如:1 4 3 6 0
• 初始时刻栈空,1入栈。----------------------栈内元素(1) • 4要进栈,4大于1,所以直接进栈.-----------栈内元素(1,4)
• 3要进栈,3小于4,4出栈,3进栈.-----------栈内元素(1 3)
• 6要进栈,6大于3,6直接进栈。-------------栈内元素(1,3,6) • 0要入栈,1,3,6都出栈,-------------------栈内元素(0)
例 题
POJ 2823 给定一个大小已知的数组以及一个大小已知的滑动窗口,窗口每个时刻向 后移动一位,求出每个时刻窗口中数字的最大值和最小值。(n<=1e6) 例如: input 83 1 3 -1 -3 5 3 6 7 output: -1 -3 -3 -3 3 3 335567
如何解啊如何解?
谢谢观赏