单调栈及其应用

单调栈就是一个栈内的元素满足一定的单调性,要么单增、要么单减。
例如一个栈
{1,3,6,9}
满足上升条件,就说是一个单调栈
同样
{9,6,3,1}是一个单调递减的栈
关于栈内元素重复,例如{1,3,3,6,9},这样是否符合一个单调栈的特性,主要看题目要求。
关于单调栈的大致原理,无非就是循环遍历数组元素,不停的维护栈的单调性。
例如我要维护一个单调递增的栈,如果现在数组中下表为 i 的元素 a[i]大于栈顶的元素,即符合单调递增的特性。就直接把元素 a[i] 放到栈中去,如果不符合单调递增的特性,就每次从栈顶取走一个元素,删掉,继续比对下一个,直到在栈中找到一个满足条件的元素,然后压栈,或者删除直到栈为空,直接压栈。

这就是单调栈的基本原理。

那么这样做有什么用呢?

首先,可以求解数组中一个元素向左或者向右遍历第一个比自己小或者比自己大的元素。
代码如下

//求解一个数组中某一位置对应元素向左遍历第一个比自己小的值的位置
#include<bits/stdc++.h>
using namespace std;
int a[]={4,3,6,7,8,4,2,9};
int res[110];
nt main()
{
	stack<int> c;
	for(int i=0;i<8;i++){
		while(!c.empty()&&a[c.top()]>=a[i])c.pop();
		if(c.empty())res[i]=0;
		else res[i]=c.top();
		c.push(i);
	}
	for(int i=0;i<8;i++)cout<<res[i]<<" ";
	return 0;
}

也许会有人跟我一样,看懂代码了,直到原理了,知道用处了,不知道怎么用。
其实用的最多的是另一个应用场景,大体上和上面的应用一样。

求解以一个数组中某一位置对应元素为最大或者最小值的最大区间,也就是求一个子序列要求以要求的元素为最大或最小值,求序列的最大长度。

这个应用可以映射到一个题目上

Description

A histogram is a polygon composed of a sequence of rectangles aligned at a common base line. The rectangles have equal widths but may have different heights. For example, the figure on the left shows the histogram that consists of rectangles with the heights 2, 1, 4, 5, 1, 3, 3, measured in units where 1 is the width of the rectangles:

Usually, histograms are used to represent discrete distributions, e.g., the frequencies of characters in texts. Note that the order of the rectangles, i.e., their heights, is important. Calculate the area of the largest rectangle in a histogram that is aligned at the common base line, too. The figure on the right shows the largest aligned rectangle for the depicted histogram.

Input

The input contains several test cases. Each test case describes a histogram and starts with an integer n, denoting the number of rectangles it is composed of. You may assume that 1<=n<=100000. Then follow n integers h1,…,hn, where 0<=hi<=1000000000. These numbers denote the heights of the rectangles of the histogram in left-to-right order. The width of each rectangle is 1. A zero follows the input for the last test case.

Output

For each test case output on a single line the area of the largest rectangle in the specified histogram. Remember that this rectangle must be aligned at the common base line.

在这里插入图片描述
输入

7 2 1 4 5 1 3 3

输出

8

大致题目意思就是,求给定的柱形图中完全包含在图形内的的最大矩形面积。
第一个输入的数字,对应上面的7,表示柱形图的宽度,后面的7个数表示每个位置上的高度。

这个问题可以看作是求以某一个高度为最小高度的最大的区间,求面积只需要在每一个这样的区间里面各自求一下面积,取最大值就行了。

#include<bits/stdc++.h>
using namespace std;
struct p{//结构体中的 l , r 分别表示以 i 位置上面对应的值为最小值的最大区间的左端点和右端点
	int l,r;
	p(){
		
	}
	p(int l,int r){
		this->l=l;
		this->r=r;
	}
};
p a[110];
int arr[]={2,1,5,5,4,3,2};//样例
stack<int> c;
int main()
{
	for(int i=0;i<7;i++){
		while(!c.empty()&&arr[c.top()]>=arr[i]){
			a[c.top()].r=i;//如果一个 i 位置的数字让你出栈了,说明它向左遍历的时候,你比他大,无法压栈,也就是说 i 位置就是弹出元素的右端点
			c.pop();
		}
		if(c.empty()){
			a[i].l=0;
		}
		else{
			a[i].l=c.top()+1;//如果栈不空,那么栈顶的元素就比 i 位置的元素小,也就是向左遍历第一个比 i 位置元素小的位置
		}
		c.push(i);
	}
	while(!c.empty()){
		a[c.top()].r=7;
		c.pop();
	}
	int res=-1;
	for(int i=0;i<7;i++){
		res=max(res,(a[i].r-a[i].l)*arr[i]);
	}
	cout<<res;
	return 0;
}

如果暴力模拟的话,首先要枚举起点,还有枚举终点,还要一个循环求区间内的最小值,复杂度为O(n ^ 3),即便ST优化一下也需要O(n ^ 2),但是用单调栈,可以O(n)求出每一个高度的最大区间,再O(n)的求出每一个高度的最大面积,整体复杂度为O(n)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值