单调栈

单调栈是一种特殊的栈,特殊之处在于栈内的元素都保持一个单调性,可能为单调递增,也可能为单调递减。

性质:

  1. 单调栈里的元素具有单调性
  2. 元素加入栈前,会在栈顶端把破坏栈单调性的元素都删除
  3. 使用单调栈可以找到元素向左遍历第一个比他小的元素,也可以找到元素向左遍历第一个比他大的元素。
  4. 单调栈的维护是 O(n) 级的时间复杂度,因为所有元素只会进入栈一次,并且出栈后再也不会进栈了。

由于单调栈只能对栈顶位置进行操作 所以一般应用于只有对数组有一边有限制的地方

实现用STL的栈实现即可 模拟栈也行

初步来总结一下单调栈吧,单调栈其实是一个看似原理简单,但是可以变得很难的解法。线性的时间复杂度是其最大的优势,每个数字只进栈并处理一次,而解决问题的核心就在处理这块,当前数字如果破坏了单调性,就会触发处理栈顶元素的操作,而触发数字有时候是解决问题的一部分,比如在 Trapping Rain Water 中作为右边界。有时候仅仅触发作用,比如在 Largest Rectangle in Histogram 中是为了开始处理栈顶元素,如果仅作为触发,可能还需要在数组末尾增加了一个专门用于触发的数字。另外需要注意的是,虽然是递增或递减栈,但里面实际存的数字并不一定是递增或递减的,因为我们可以存坐标,而这些坐标带入数组中才会得到递增或递减的数。所以对于玩数组的题,如果相互之间关联很大,那么就可以考虑考虑单调栈能否解题。

单调队列

性质:

单调队列和单调栈很像,就是一个维护了单调性的队列数据结构,可以是单调递增的,也可以是单调递减的。

单调队列满足两个性质

1.单调队列必须满足从队头到队尾的严格单调性。

2.排在队列前面的比排在队列后面的要先进队。

元素进队列的过程对于单调递增队列,对于一个元素a 如果 a > 队尾元素 那么直接将a扔进队列 如果 a <= 队尾元素 则将队尾元素出队列 知道满足 a 大于队尾元素即可;

实现用 stl 的双端队列即可。

由于双端队列即可以在队头操作也可以在队尾操作那么这样的性质就弥补了单调栈只能在一遍操作的不足可以使得其左边也有一定的限制。

https://blog.csdn.net/zhelong3205/article/details/77624699

https://blog.csdn.net/u011893609/article/details/78806089

https://www.cnblogs.com/tham/p/8038828.html

https://blog.csdn.net/qq_30578131/article/details/80740614


没什么好说的,直接上题

提示:点击题目直达题目提交地址

Largest Rectangle in a Histogram

大致题意:

给定从左到右多个矩形,已知这此矩形的宽度都为1,长度不完全相等。

这些矩形相连排成一排,求在这些矩形包括的范围内能得到的面积最大的矩形,输出该面积。

所求矩形可以横跨多个矩形,但不能超出原有矩形所确定的范围。

算法分析&&具体操作:

借助单调性处理问题的思想在于及时排除不可能的选项,保持策略集合的高度有效性和秩序性

对于此题,我们需要从左向右求出每个矩形向右能够扩展到的最大连续宽度

能够扩展的条件:矩形高度大于等于当前矩形高度

那么我们求完之后算出面积取 max 即可

显然朴素算法是不行的,我们需要用到单调栈

准确的说是:

单调栈维护从起点矩形到当前矩形的高度递增序列

如果当前矩形低于于栈顶矩形,我们就一直将栈中元素弹出,直到遇到低于当前点的矩形,以此来维护栈的递增性,显然此时的点最远可以扩展到当前栈元素的位置top-1,即我们找到了当前点的扩展边界,同时把弹出的矩形合并再压入栈。

建立一个单调(递增)栈,所有元素各进栈和出栈一次。每个元素出栈的时候更新最大的矩形面积。

设栈内的矩形为一个二元组(h, w),h表示矩形的高度,w表示矩形的宽度。

如何入栈并更新呢?

① 如果当前元素比栈顶元素大或者栈为空,则直接压栈(h,1);

② 如果当前元素小于等于栈顶元素,则出栈合并矩形,直到当前元素大于栈顶元素或者栈为空时,合并矩形(h,sum_width)入栈。

③在出栈的过程中更新最大面积和累积宽度

那么重复上述①~③操作,我们可以线性O(n)求出每一组数据的解

注意事项:

单调栈要维护两个信息,一个是高度,另一个是宽度(便于计算矩形面积)

同时令H[n+1]=0,以保证所有矩形全部弹出栈 (最后没有矩形剩余在栈中)

 #include <stdio.h>
#include <string.h>
#include <algorithm>
#include <string>
#include <vector>
#include <map>
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
int h[];//定义矩形(rectangle)高度h
int w[];//定义矩形(rectangle)宽度w
int stack[];//数组模拟矩形的高度单调栈
int top;
int n; void solve()//单调栈算法
{
long long ans=;
for(int i=;i<n+;i++)//1~n+1个矩形扫描一遍
{
if(h[i]>stack[top])//如果当前矩形高于栈顶直接入栈,宽度为1(符合高度单调递增性质)
{
stack[++top]=h[i];
w[top]=;
}
else//否则就持续弹出栈顶矩形合并
{
int widthsum=;//弹出的栈顶矩形合并总宽度
while(stack[top]>h[i])//不满足高度单调递增继续弹出
{
widthsum+=w[top];//累计宽度
ans=max(ans,(long long)widthsum*stack[top]);//面积取max
top--;//弹出堆顶矩形
}
stack[++top]=h[i];//把合并好的新矩形入栈(高为H[i],宽为width+1)
w[top]=widthsum+;
}
}
printf("%lld\n",ans);
} int main()
{
while(scanf("%d",&n)&&n)//多组数据
{
memset(h,,sizeof(h));//初始化
memset(w,,sizeof(w));
memset(stack,,sizeof(stack));
top=;
for(int i=;i<n;i++)//读入每个矩形高度
{
scanf("%d",&h[i]);
}
solve();
}
return ;
}

下面是用了STL的代码

 #include<cstdio>
#include<stack>
#include <iostream>
#include <algorithm>
#include<cstring>
using namespace std;
inline long long read(){
long long x=,f=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return f*x;
}//很伤心呢,看错范围了,最初没改成long long 类型的,爆了几次才发现QWQ
struct node{
int h,w;
};//一个存高度,一个存宽度。
long long s[],ans=;
int main(){
while(){
int n=read();
if(n==)return ;
for(int i=;i<=n;i++){
s[i]=read();
}
stack<node>st;
s[n+]=;
for(int i=;i<=n+;i++){
long long W=;
while(!st.empty()&&s[i]<st.top().h){//单调栈!单调递增!
W=W+st.top().w;
ans=max(ans,W*st.top().h);
st.pop();
}
st.push((node){s[i],W+});
}
cout<<ans<<endl;
ans=;
}
}

题目列表:

1047: [HAOI2007]理想的正方形

接雨水

Sliding Window

Max Chunks To Make Sorted II

Trapping Rain Water

Largest Rectangle in Histogram

Remove K Digits

最大子序和

Description

输入一个长度为n的整数序列,从中找出一段不超过M的连续子序列,使得整个序列的和最大。

单调栈and单调队列(此文太多坑了,以后再填)的更多相关文章

  1. DP的各种优化(动态规划,决策单调性,斜率优化,带权二分,单调栈,单调队列)

    前缀和优化 当DP过程中需要反复从一个求和式转移的话,可以先把它预处理一下.运算一般都要满足可减性. 比较naive就不展开了. 题目 [Todo]洛谷P2513 [HAOI2009]逆序对数列 [D ...

  2. POJ 2559 Largest Rectangle in a Histogram(单调栈) && 单调栈

    嗯... 题目链接:http://poj.org/problem?id=2559 一.单调栈: 1.性质: 单调栈是一种特殊的栈,特殊之处在于栈内的元素都保持一个单调性,可能为单调递增,也可能为单调递 ...

  3. 数据结构录 之 单调队列&单调栈。

    队列和栈是很常见的应用,大部分算法中都能见到他们的影子. 而单纯的队列和栈经常不能满足需求,所以需要一些很神奇的队列和栈的扩展. 其中最出名的应该是优先队列吧我觉得,然后还有两种比较小众的扩展就是单调 ...

  4. 数据结构录 之 单调队列&单调栈。(转)

    http://www.cnblogs.com/whywhy/p/5066306.html 队列和栈是很常见的应用,大部分算法中都能见到他们的影子. 而单纯的队列和栈经常不能满足需求,所以需要一些很神奇 ...

  5. 单调栈&单调队列入门

    单调队列是什么呢?可以直接从问题开始来展开. Poj 2823 给定一个数列,从左至右输出每个长度为m的数列段内的最小数和最大数. 数列长度:\(N <=10^6 ,m<=N\) 解法① ...

  6. 单调队列&单调栈

    单调队列 例题: Poj 2823给定一个数列,从左至右输出每个长度为m的数列段内的最小数和最大数.数列长度:N<=106,m<=N 对于单调队列,我们这样子来定义: 1.维护区间最值 2 ...

  7. 小结:单调栈 & 单调队列

    概要: 对于维护信息具有单调性的性质或者问题可以转化为具有单调性质的模型的题,我们可以考虑用单调栈或单调队列. 技巧及注意: 技巧很多,只要能将问题转化为单调性问题,就好解决了. 当维护固定长度的单调 ...

  8. 单调队列&单调栈归纳

    单调队列 求长度为M的区间内的最大(小)值 单调队列的基本操作,也就是经典的滑动窗口问题. 求长度为M的区间内最大值和最小值的最大差值 两个单调队列,求出长度为M的区间最大最小值的数组,分别求最大最小 ...

  9. 单调栈&单调队列

    最近打了三场比赛疯狂碰到单调栈和单调队列的题目,第一,二两场每场各一个单调栈,第三场就碰到单调队列了.于是乎就查各种博客,找单调栈,单调队列的模板题去做,搞着搞着发现其实这两个其实是一回事,只不过利用 ...

随机推荐

  1. ansible下载文件的多种方式

    对于ansible来说,下载文件是一个很重要的课题,这是build或者deploy的第一步,通常来讲由于不同项目的差异,可能我们的代码包或者资源文件保存在于http,github,nexus,ftp, ...

  2. 201771010123汪慧和《面向对象程序设计Java》第十八周实验总结

    一.总复习纲要 1. Java语言特点与开发环境配置(第1章.第2章) 2. Java基本程序结构(第3章) 3. Java面向对象程序结构(第4章.第5章.第6章) 4. 类.类间关系.类图 5. ...

  3. java多线程之volatile关键字

    public class ThreadVolatile extends Thread { public boolean flag=true; @Override public void run() { ...

  4. 学习Github必须要会的知识

    目的     托管项目代码 基本概念 仓库Respository   存放项目代码,每个项目对应一个仓库,多个开源项目则有多个仓库. 收藏Star   收藏项目,方便下次查看. 复制克隆项目Fork ...

  5. Unity获取游戏对象详解

    我觉得Unity里面的Transform 和 GameObject就像两个双胞胎兄弟一样,这俩哥们很要好,我能直接找到你,你也能直接找到我.我看很多人喜欢在类里面去保存GameObject对象.解决G ...

  6. cmd 进入指定文件夹

    1.通常情况下,我们要进入其他盘符下的任意目录,需要在CMD窗口运行两次命令:第一次,进入盘符,第二次进入指定目录 #进入D盘 d: #进入D盘下的anaconda目录 cd anacond 2.通过 ...

  7. UML-UML工具与UML蓝图

    1.UML应用场景 1).UML作为草图 2).UML作为蓝图. UML生成java代码(前向工程) java代码生成UML(逆向工程) 2.如果绘制了UML草图,如何在编码后更新该图形? 逆向工程, ...

  8. JS获取当前时间往后一天的时间

    (图片来自W3school) let myDate = new Date(); myDate.setDate(myDate.getDate() + 1); let year = myDate.getF ...

  9. IDEA抽取方法的快捷键

    正常的话是 ctrl+alt+m 如果快捷键占用或者修改过,在写代码的地方右键->refactor->extract->method

  10. CVPR2019 | 超越Mask R-CNN!华科开源图像实例分割新方法MS R-CNN

    安妮 乾明 发自 凹非寺 本文转载自量子位(QbitAI) 实习生又立功了! 这一次,亮出好成绩的实习生来自地平线,是一名华中科技大学的硕士生. 他作为第一作者完成的研究Mask Scoring R- ...