单调栈

前言

单调栈即栈的一种。

单调栈的定义

既然是来学单调栈的,我相信进来看的都是理解栈的定义的人,所以关于栈是什么我就不多说了。单

调栈,顾名思义,就是存进栈的数是以单调递增或者单调递减的形式存在的,并不是严格的单调递增

或递减,是可以等于的。

下面举个例子:{1 ,2 ,3 ,4 ,4 ,5 ,5 ,6} 假使这些数按这个顺序存放在栈里面,他是完全按

从小到大的顺序,也就是升序,就是单调栈。反之,降序也是单调栈。

单调栈的性质

1.单调栈里的元素具有单调性(即递增或递减)

2.元素加入栈前,会在栈顶端把破坏栈单调性的元素都删除

3.使用单调栈可以找到元素向左遍历第一个比他小的元素,也可以找到元素向左遍历第一个比他大的

元素。

4.单调栈的维护是 O(n) 级的时间复杂度,因为所有元素只会进入栈一次,并且出栈后再也不会进栈

了。

单调栈的应用

单调栈一般是用来找大序列里面的每个子序列。

例题:

题目: 直方图周最大的矩形

在这里插入图片描述

输入格式

输入包含几个测试用例。

每个测试用例占据一行,用以描述一个直方图,并以整数n开始,表示组成直方图的矩形数目。

然后跟随n个整数h1,…,hnh1,…,hn。

这些数字以从左到右的顺序表示直方图的各个矩形的高度。

每个矩形的宽度为1。

同行数字用空格隔开。

当输入用例为n=0时,结束输入,且该用例不用考虑。

输出格式

对于每一个测试用例,输出一个整数,代表指定直方图中最大矩形的区域面积。

每个数据占一行。

请注意,此矩形必须在公共基线处对齐。

数据范围

1≤n≤1000001≤n≤100000,
0≤hi≤1000000000

输入样例:
7 2 1 4 5 1 3 3
4 1000 1000 1000 1000
0
输出样例:
8
4000

题解:

首先讲一下样例一:2 1 4 5 1 3 3
在这里插入图片描述
这里首先找2,2的右边为1比它矮,左边没有他的长度也就最大可能就为1,所以面积为2*1=2

然后找1,它往左边延长和右边延长,可以看到它延长过后就是7,所以它的面积是7*1=7

再找4,它不能往左延长,因为左边第一个就比它矮,它可以往右延长一位,所以面积是2*4=8

再找5,它左右都延长不了,所以他的组成最大矩形是5*1=8

然后这个1和前面的1一样也是7

这个3和后面的3都可以以上述思想证明组成的面积最大为6

所以前面所述的矩形最大面积就为4组成的矩形,就为8。

找到每一个矩形就是找每一个数的左右俩边和他一样高或者比他高的长度有多长,再乘以他的高就是

以他为宽的高度,在此,我们就可以利用单调性的性质来做此题,即如果满足进栈数大于栈顶就一直

进栈,如果不满足进栈数大于栈顶就直接出栈,因为此时进栈数即右边的数比左边这个子序列要矮所

以右边这个数此时不计算即现在进栈的数此时不计算一直计算比进栈数高的栈里面的数直到可以进栈

或者到栈底,即本栈变为空栈时,算的时候还需要将一样高或者比他高的数累加起来。

上代码:
#include<stdio.h>
#include<math.h>
long long int max(long long int a,long long int b)//比较大小
{
	 return a>b?a:b;
}
long long int num[100010],zhan[100010],a[100010];
int main()
{
	 long long int i,k,n,ans;
	 while(scanf("%lld",&n))
	 {
		 if(n==0)break;
		 for(i=0;i<n;i++)scanf("%lld",a+i);//输入
		 i=k=ans=a[n]=0;//将最后一个的后面那个赋值为0,所以肯定到最后的后面那个时要出栈就能算完
		 while(i<=n)
		 {
			if(k==0||a[i]>=zhan[k-1])
		 	{//如果进栈的数字比栈顶大就入栈并默认左右边一样高的个数为1
		 		zhan[k]=a[i];
	    	 		num[k]=1;
	    	 		k++;
	   	 	}
	   		else
	   		{//出栈的同时计算矩形的长度
		    		long long int lon=0;
		    		while(k>0&&a[i]<zhan[k-1])
		   		{//一直重复出栈的操作,出去一个即比进栈数大的有一个,拿变量lon存入
		     			lon+=num[k-1];
		     			ans=max(ans,zhan[k-1]*lon);//记住最大的矩形面积
		    			k--;
		    		}
		    		zhan[k]=a[i];
		    		num[k]=lon+1;
		    		k++;
		  	}
		   	i++;
	  	}
	  	printf("%lld\n",ans); 
	 }
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
单调栈是一种常用的数据结构,用于解决一类特定的问题,其中最常见的问题是找到数组中每个元素的下一个更大或更小的元素。在Codeforces编程竞赛中,单调栈经常被用于解决一些与数组相关的问题。 下面是单调栈的一般思路: 1. 创建一个空栈。 2. 从左到右遍历数组元素。 3. 对于每个元素,将其与栈顶元素进行比较。 - 如果当前元素小于等于栈顶元素,则将当前元素入栈。 - 如果当前元素大于栈顶元素,则将栈顶元素弹出,并将当前元素入栈。 4. 重复步骤3,直到遍历完所有元素。 这样,最后剩下的栈中元素就是没有下一个更大或更小元素的元素。在使用单调栈求解具体问题时,我们可以根据需要进行一些特定的操作。 例如,如果要找到一个数组中每个元素的下一个更大的元素,可以使用单调递减栈。具体操作如下: 1. 创建一个空栈和一个空结果数组。 2. 从左到右遍历数组元素。 3. 对于每个元素,将其与栈顶元素进行比较。 - 如果当前元素小于等于栈顶元素,则将当前元素入栈。 - 如果当前元素大于栈顶元素,则将栈顶元素弹出,并将其在结果数组中的位置记录为当前元素的下一个更大元素的索引。 4. 将当前元素入栈。 5. 重复步骤3和4,直到遍历完所有元素。 6. 结果数组中没有下一个更大元素的位置,可以设置为-1。 以下是一个使用单调递减栈求解下一个更大元素问题的示例代码: ```cpp #include <iostream> #include <stack> #include <vector> std::vector<int> nextGreaterElement(std::vector<int>& nums) { int n = nums.size(); std::vector<int> result(n, -1); std::stack<int> stack; for (int i = 0; i < n; i++) { while (!stack.empty() && nums[i] > nums[stack.top()]) { result[stack.top()] = i; stack.pop(); } stack.push(i); } return result; } int main() { std::vector<int> nums = {1,3, 2, 4, 5, 1}; std::vector<int> result = nextGreaterElement(nums); for (int i = 0; i < result.size(); i++) { std::cout << "Next greater element for " << nums[i] << ": "; if (result[i] != -1) { std::cout << nums[result[i]]; } else { std::cout << "None"; } std::cout << std::endl; } return 0; } ``` 以上代码将输出: ``` Next greater element for 1: 3 Next greater element for 3: 4 Next greater element for 2: 4 Next greater element for 4: 5 Next greater element for 5: None Next greater element for 1: None ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值