单调栈以及单调队列
Posted fonddream
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单调栈以及单调队列相关的知识,希望对你有一定的参考价值。
单调栈:
-
定义:
栈内的元素,按照某种方式排列下(单调递增或者单调递减),如果新入栈的元素破坏了单调性,就弹出栈内元素,直至满足单调性。
-
作用:单调栈可以找到从左/右遍历第一个比它大/小的元素的位置。时间复杂度为O(N);
-
实现方式:(以维护单调递增栈为例)
进栈操作:每次进入栈时,先检验栈顶元素和进栈元素的大小,如果小于,那么直接入栈;否则,大于等于进栈元素的出栈,直到栈空或者栈顶元素小于入栈元素。
例如:3 8 2 3 1
- 初始时刻栈为空,3入栈。.....................................栈内元素(3);
- 8要进栈,8比3大,直接入栈。..............................栈内元素(3,8);
- 2要进栈,2比8小,全部弹出,2入栈。.................栈内元素(2);
- 3要进栈,3比2大,直接入栈。..............................栈内元素(2,3);
- 1要进栈,1比3小,全部弹出,1入栈。.................栈内元素(1);
根据此时求出从左往右第一个比它小的元素。
3 8 2 3 1
0 3 0 2 0
代码:
stack<int>s; for(int i=1;i<=n;i++) { while(s.size()&&s.top()>=a[i]) { s.pop(); } if(s.empty()) l[i]=0; else l[i]=s.top(); s.push(a[i]); }
stack<int>s; for(int i=1;i<=n;i++) { while(s.size()&&s.top()>=a[i]) { s.pop(); } if(s.empty()) l[i]=0; else l[i]=s.top(); s.push(a[i]); }
例题:poj 2559
题意:给出一个柱形统计图,它的每个项目的宽是1,高度和具体问题有关,现在编辑求出这个柱形图中的最大面积的长方形(n<=le5)
例如:2,1,4,5,1,3,3
面积为8。
分析:
- 我们首先想到的是逐个考虑每个项目,求出每个项目被包含的长方形。
- 求出每个被包含的长方形,那么左右两边的高度不能比项目本身的高度低,就是向左右两边延展。
- 那么用单调栈,时间复杂度是2N:
- 求出两边比项目第一个小的位置。为什么不是取两边比项目第一个大的位置呢?因为如果是大的位置,它们之间可能包含比项目本身要小值,就不能达到连续。
- 分别对项目进行左右延伸。
单调队列:
-
定义:
队列中元素之间的关系具有单调性,而且,队首和队尾都可以进行出队操作,只有队尾可以进行入队操作。
-
作用:
对于维护好的单调队列,单调队列是有序的,那么取出最大值(最小值)的复杂度是O(1);
可以拿来优化DP;
-
操作:
- 插入:若新元素从队尾插入后会破坏单调性,则删除队尾元素,直至插入后不再破坏单调性为止,在将其插入单调队列。这和单调栈的插入一样。
- 获取最优值:访问首尾元素。
- 定长连续子区间的最值问题
例题:
题意:给定一个长度为n的数列,求长度为k的定长连续子区间{a1,a2,a3,a4............,ak-1,ak}...............中每个区间的最大值和最小值。
分析:
- 当我们看到这个第一个想法应该是枚举起始元素ax,然后再求ax到ak-1+x的最大(小)值,那么区间的复杂度为O(nk);
- al,al+1,al+2....................ar-1,ar,ar+1,以最大值为例:
- 当我们求区间(l,r)最大值时:=max{al,max(al+1,al+2..........ar-1,ar)};
- 当我们求区间(l+1,r+1)最大值时:=max{ar+1,max(al+1,al+2..........ar-1,ar)};
- 那么再求区间(l+1,r+1)时,我们完全没必要在重新扫描一次。只有当最值在al才需要重新扫描。
- 那么如果在区间(l,r)求最大值时,l<i<j<r,如果ai<aj,那么在向右移动的过程中ai就失去了效果,这就与单调队列弹出所不符合单调的元素性质一样。
- 当我们将区间从(l,r)移动到(l+1,r+1)时,我们将ar+1插入单调队列中,若队首元素不在(l,r)区间中,那么说明最大值不是(l,r)区间的数,清除队首元素(出队);
例如:4 1 3 2 7 5 6 n=7,k=3;求长度为k的连续子序列的最大值。
- 初始队列为空,4入队.....................................................队列元素(4);
- 进队元素为1,1比4小,直接入队...................................队列元素(4,1);
- 进队元素为3,3比1大,弹出1,3入队...........................队列元素(4,3);那么最大值为4;
- 进队元素为2,2比3小,直接入队...................................队列元素(4,3,2);因为4不在a2~a4元素中,所有要先弹出4元素,此时最大值为3,队列元素(3,2);
- 进队元素为7,7比4大,全部弹出...................................队列元素(7);此时最大值为7;
- 进队元素为5,5比7小,直接入队...................................队列元素(7,5);此时最大值为7;
- 进队元素为6,6比5大,弹出5,6入队...........................队列元素(7,6);此时最大值为7;
以上是关于单调栈以及单调队列的主要内容,如果未能解决你的问题,请参考以下文章