单调栈and单调队列(此文太多坑了,以后再填)
单调栈
单调栈是一种特殊的栈,特殊之处在于栈内的元素都保持一个单调性,可能为单调递增,也可能为单调递减。
性质:
单调栈里的元素具有单调性
元素加入栈前,会在栈顶端把破坏栈单调性的元素都删除
使用单调栈可以找到元素向左遍历第一个比他小的元素,也可以找到元素向左遍历第一个比他大的元素。
单调栈的维护是 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]理想的正方形
接雨水
Largest Rectangle in Histogram
最大子序和
Description
输入一个长度为n的整数序列,从中找出一段不超过M的连续子序列,使得整个序列的和最大。
单调栈and单调队列(此文太多坑了,以后再填)的更多相关文章
- DP的各种优化(动态规划,决策单调性,斜率优化,带权二分,单调栈,单调队列)
前缀和优化 当DP过程中需要反复从一个求和式转移的话,可以先把它预处理一下.运算一般都要满足可减性. 比较naive就不展开了. 题目 [Todo]洛谷P2513 [HAOI2009]逆序对数列 [D ...
- POJ 2559 Largest Rectangle in a Histogram(单调栈) && 单调栈
嗯... 题目链接:http://poj.org/problem?id=2559 一.单调栈: 1.性质: 单调栈是一种特殊的栈,特殊之处在于栈内的元素都保持一个单调性,可能为单调递增,也可能为单调递 ...
- 数据结构录 之 单调队列&单调栈。
队列和栈是很常见的应用,大部分算法中都能见到他们的影子. 而单纯的队列和栈经常不能满足需求,所以需要一些很神奇的队列和栈的扩展. 其中最出名的应该是优先队列吧我觉得,然后还有两种比较小众的扩展就是单调 ...
- 数据结构录 之 单调队列&单调栈。(转)
http://www.cnblogs.com/whywhy/p/5066306.html 队列和栈是很常见的应用,大部分算法中都能见到他们的影子. 而单纯的队列和栈经常不能满足需求,所以需要一些很神奇 ...
- 单调栈&单调队列入门
单调队列是什么呢?可以直接从问题开始来展开. Poj 2823 给定一个数列,从左至右输出每个长度为m的数列段内的最小数和最大数. 数列长度:\(N <=10^6 ,m<=N\) 解法① ...
- 单调队列&单调栈
单调队列 例题: Poj 2823给定一个数列,从左至右输出每个长度为m的数列段内的最小数和最大数.数列长度:N<=106,m<=N 对于单调队列,我们这样子来定义: 1.维护区间最值 2 ...
- 小结:单调栈 & 单调队列
概要: 对于维护信息具有单调性的性质或者问题可以转化为具有单调性质的模型的题,我们可以考虑用单调栈或单调队列. 技巧及注意: 技巧很多,只要能将问题转化为单调性问题,就好解决了. 当维护固定长度的单调 ...
- 单调队列&单调栈归纳
单调队列 求长度为M的区间内的最大(小)值 单调队列的基本操作,也就是经典的滑动窗口问题. 求长度为M的区间内最大值和最小值的最大差值 两个单调队列,求出长度为M的区间最大最小值的数组,分别求最大最小 ...
- 单调栈&单调队列
最近打了三场比赛疯狂碰到单调栈和单调队列的题目,第一,二两场每场各一个单调栈,第三场就碰到单调队列了.于是乎就查各种博客,找单调栈,单调队列的模板题去做,搞着搞着发现其实这两个其实是一回事,只不过利用 ...
随机推荐
- SAP_ABAP常用事务代码
ST05: 性能跟踪(Performance Trace) SE30/SAT: ABAP对象性能分析 ST12: 单个对象性能分析(Single transaction analysis)
- Tensorflow学习教程------过拟合
Tensorflow学习教程------过拟合 回归:过拟合情况 / 分类过拟合 防止过拟合的方法有三种: 1 增加数据集 2 添加正则项 3 Dropout,意思就是训练的时候隐层神经元每次随机 ...
- JavaSE--Arrays.copyof
背景: 想偷懒一次数组赋值下面多个例子复制下数组就好了.. 以为 Arrays.copyof(Arrays.copyof内部调用的是 System.copy, 所以同 Arrays.copy)拷贝出来 ...
- BZOJ 4855 [Jsoi2016]轻重路径
题解:用树链剖分来维护树链剖分 令d[x]=size[heavyson[x]]-size[lightson[x]] 当d[x]<0时轻重儿子关系改变 用数据结构维护d[x]并找到这些位置改变即可 ...
- 传输层上的TCP和UDP
参考: 知乎 传输层概述 “三次握手,四次挥手”你真的懂吗? 传输层上的TCP和UDP TCP/IP协议是一个协议簇.里面包括很多协议的,UDP只是其中的一个, 之所以命名为TCP/IP协议,因为TC ...
- 委托、Action、Func使用
参考 using System; using System.Collections.Generic; using System.Linq; using System.Text; using Syste ...
- SoapUI substring
- git clone与git pull区别
从远程服务器克隆一个一模一样的版本库到本地,复制的是整个版本库,叫做clone.(clone是将一个库复制到你的本地,是一个本地从无到有的过程)从远程服务器获取到一个branch分支的更新到本地,并更 ...
- Python 安装modules问题及import问题
>>>modules问题 在学习Python的数据可视化时,安装了matplotlib,在安装完成后还特意在终端测试了一下,结果显示能正常import 但是在sublime Text ...
- zabbix几个配置的关系