单调栈与单调队列.ppt

  1. 1、本文档共12页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
单调栈 单调栈和单调队列 by Tisuama 定义: 单调栈:栈内的元素,按照某种方式排序下(单调递增或者单调递减) 如果新入栈的元素破坏了单调性,就弹出栈内元素,直到满足单调性 为什么要学习单调栈: 它可以很方便地求出某个数的左边或者右边第一个比它大或者小的元素,而且总时间复杂度O(N)。 如何维护单调栈:(以维护单调递增栈为例) 进栈操作:每次入栈前先检验栈顶元素和进栈元素(x)的大小,如果小于x,就让x直接入栈。如果栈顶元素大于等于x,那么出栈,直到栈空或者栈顶元素小于x 例如: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 2559 题意:给出一个柱形统计图(histogram), 它的每个项目的宽度是1, 高度和具体问题有关。 现在编程求出在这个柱形图中的最大面积的长方形(n=1e5) 例如:2, 1, 4, 5, 1, 3, 3 最大面积:8 那么问题来了:如何算? 分析 逐个考虑每个项目,那么如何得到每个项目被包含的长方形了? 假设考虑到项目x,通过简单的思考,我们可以得出结论,x的左右两边的项目高度都不能比x低,那么如何求项目x的两边延伸长度? 我们想到了单调栈 ???????为什么 (以求x左边延伸长度为例) 假设我们建立一个单调递增栈,那么我们可以轻松地求得x左边比x小的第一个数的位置。 那么问题来了:为什么是单调递增栈,为什么是比x小? 求x右边延伸相同处理 实现方式 栈(以求x的向左延伸为例) int top=0,s[maxn]; for(int i=1;i=n;i++) while(toph[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=1h[i]=h[pos-1]) pos=L[pos-1]; L[i]=pos; 定义: 单调队列:队列中元素之间的关系具有单调性,而且,队首和队尾都可以进行出队操作,只有队尾可以进行入队操作。 为什么要学习单调队列: 对于维护好的单调队列,对内元素是有序的,那么取出最大值(最小值)的复杂度是O(1) 可以拿来优化DP(然而弱不会) 如何维护单调队列: 队尾入队的时候维护单调性。 例题 POJ 2823 给定一个大小已知的数组以及一个大小已知的滑动窗口,窗口每个时刻向后移动一位,求出每个时刻窗口中数字的最大值和最小值。(n=1e6) 例如: input 8 3 1 3 -1 -3 5 3 6 7 output: -1 -3 -3 -3 3 3 3 3 5 5 6 7 如何解啊如何解? 区间最值问题:我们想到了啥?线段树?RMQ? 新姿势!!单调队列!O(n)!!!! O(nlog(n))!!!! 分析 以得到最小值为例: 我们维护一个单增的队列,那么每次滑动窗口入队之后就要得到一个区间最小值,按照刚才的理论,直接取队首元素就可以了??? 具体做法:每次滑动窗口要得到最小值的时候,判断队首元素是否过期,,如果过期,就从队首出队,继续找。 最大值做法同上:维护一个单减队列。 实现方式 void get_min() { int tail=0,head=1; for(int i=1;ik;i++) { while(head=tailq[tail]=a[i]) --tail; q[++tail]=a[i]; p[tail]=i; } for(int i=k;i=n;i++) { while(head=tailq[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 我们发现,每次从尾部入队前都会

文档评论(0)

xuefei111 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档