首页 > 其他分享 >单调栈

单调栈

时间:2024-01-20 15:56:41浏览次数:21  
标签:位置 int 元素 栈顶 stack 单调 size

单调栈是一种栈,但栈里面的元素是具有单调性的,所以被称为单调栈

单调栈解决最经典的问题是每个位置都求

  1. 当前位置左边最近且小于(大于)当前位置的元素的位置
  2. 当前位置右边最近且小于(大于)当前位置的元素的位置   

单调栈模板   

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <stdbool.h>
#define u unsigned
#define ll long long
#define sc scanf
#define pr printf 
#define fr(i, j, n) for (int i = j; i < n; i++)
#define N 1000000

int a[N];//元素数组 
int stack[N];//单调栈 
int ans[N][2];//ans[i][0]存放a[i]位置左边小于a[i]离a[i]最近的位置,ans[i][1]存放a[i]位置右边小于a[i]离a[i]最近的位置 
int size;//栈里面有多少元素 

int main(int argc, char* argv[])
{
	int len = 0;//数组的长度 

	sc("%d", &len);//读入数组的长度 

	//读入数组 
	for (int i = 0; i < len; i++) { 
		sc("%d", a + i);
	}

	for (int i = 0; i < len; i++) {//遍历每一个数组元素 
 		if (size == 0 || a[i] > a[stack[size - 1]]) {//如果栈为空或者当前数组元素大于栈顶元素,那么就把数组元素的下标压入到单调栈 
			stack[size++] = i;//是下标,不是值 
		}
		else {//a[i] <= stack[top] 
			while (size > 0 && a[stack[size -  1]] >= a[i]) {//如果栈不为空,并且栈顶元素大于等于当前数组元素 
				ans[stack[size - 1]][1] = i;//因为被一个小于的数破坏了单调性所以每一个被弹出的栈顶元素右边最近且小于栈顶元素的就是i下标的位置 
				ans[stack[size - 1]][0] = (size == 1 ? -1 : stack[size - 2]);//如果栈里面只有一个元素了,那么就没有左边小于栈顶元素且最近的位置,所以是-1
				//栈弹出之后还有元素,那么在栈顶元素下面的那个元素就是左边小于且最近的位置 
				size--;//弹出了元素,所以栈的大小减一 
			}
			stack[size++] = i;//把a[i]的下标压入单调栈 
		}
	}

	while (size) {//如果遍历完了之后,栈不为空,就处理栈里面剩余的元素 
		ans[stack[size - 1]][1] = -1;//因为遍历完了还没有碰到小于栈顶元素的,代表右边没有小于栈顶元素且最近的位置 
		ans[stack[size - 1]][0] = size == 1 ? -1 : stack[size - 2];//如果弹出栈顶元素后栈不为空,那么左边小于且离栈顶元素最近就是栈弹出之后的栈顶元素
		//如果栈为空,代表左边没有小于栈顶元素且最近的位置 
		size--;//弹出了元素,所以栈的大小减一 
	}

	//如果有数组中有重复值 
	for (int i = len - 1; i >= 0; i--) {//从后面遍历数组,当然可以从len - 2开始因为最后一个元素的右边肯定是-1 
		if (ans[i][1] != -1 && a[i] <= a[ans[i][1]]) {//只要有位置并且a[i] <= a[i]右边小于a[i]且离a[i]最近的位置,就代表这个ans[i][1]是到等于a[i]的位置 
			ans[i][1] = ans[ans[i][1]][1];//所以要拿上一个等于a[i]的位置的最右的位置,这也是为什么要从后面遍历数组 
		}
	}

	for (int i = 0; i < len; i++) {
		pr("%d %d\n", ans[i][0], ans[i][1]);
	}

	return 0;
}

 求大于的最近位置,只要让栈里面的元素是小压大就可以了                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   

标签:位置,int,元素,栈顶,stack,单调,size
From: https://www.cnblogs.com/lwj1239/p/17975125

相关文章

  • 单调栈
    概述栈中元素满足单调性的线性数据结构板子题P5788【模板】单调栈-洛谷|计算机科学教育新生态(luogu.com.cn)题意即求每一个数的下一个更大数的下标。思路维护一个单调递减的栈。每次插入元素与栈顶进行比较大于等于栈顶栈顶不停出栈,直到该元素小于栈顶或栈......
  • 滑动窗口的最大值 239 单调队列初识
    最开始做的时候,暴力解法结果不管怎么剪枝,还是超时了。后来看到了卡哥的方法,学到了单调队列,其实就是自定义队列。用deque来实现。有三个关键点:pop,push,front.pop,如果遍历的元素等于队头元素,则头删。push,把比遍历元素小的都进行尾部删。front,就是普通的查找队头。循环遍历的时......
  • CF-514-D-单调队列
    514-D题目大意给定\(n\)个人,每个人有\(m\)个属性,第\(i\)个人的第\(j\)个属性值为\(a[i][j]\)。最多可以执行\(k\)次操作,每次操作选定一个属性,把所有人的该属性减\(1\),求一段最长的区间,满足执行所有操作之后该区间中所有人的所有属性全部为\(0\)。Solution转换一下思考方向,求......
  • dp优化-决策单调性 / 四边形不等式
    前言这种优化我以前“听”过了很多次,但是好像都没学会qwq。四边形不等式:对于二元组\(w_{x,y}\),如果在定义域上任取四个点\(a\leb\lec\led\),满足:\[w_{a,b}+w_{c,d}\gew_{a,c}+w_{b,d}\]则称\(w_{x,y}\)满足四边形不等式。你会想这鬼东西怎么记?反正我也不想记。......
  • elixir erlang 简单调用学习
    实际上基于elixir的mix进行erlang以及elixir的互调用开发处理是很方便的,mix直接就包含了构建erlang代码同时对于代码的互调用,只要使用符合语言格式要求就行了,以下是一个简单的互调用学习项目准备项目结构 ├──README.md├──lib│├──a.ex│└──er_app......
  • elixir erlang 简单调用学习
    实际上基于elixir的mix进行erlang以及elixir的互调用开发处理是很方便的,mix直接就包含了构建erlang代码同时对于代码的互调用,只要使用符合语言格式要求就行了,以下是一个简单的互调用学习项目准备项目结构 ├──README.md├──lib│├──a.e......
  • 单调栈
    单调栈是一种下标单调、元素单调的栈使用场景若干区间内找最值,转化为枚举每个最值找区间寻找每个元素\(a[i]\)向右(左)第一个比\(a[i]\)大(小)的位置如何寻找\(a[i]\)右边第一个大于\(a[i]\)的位置?枚举下标\(i\),\(a[i]\)与栈顶循环比较,若a[i]>a[stk.top()],则R[stk.top()]=i,stk......
  • 单调栈分类、封装和总结
    作者推荐map|动态规划|单调栈|LeetCode975:奇偶跳通过枚举最小(最大)值不重复、不遗漏枚举所有子数组C++算法:美丽塔O(n)解法单调栈左右寻找第一个小于maxHeight[i]的left,right,[left,right]直接的高度都是maxHeight[i]可以用封装的类,可以理解为枚举山顶这个子数组【单调栈]LeetCode8......
  • map|动态规划|单调栈|LeetCode975:奇偶跳
    作者推荐【贪心算法】【中位贪心】.执行操作使频率分数最大涉及知识点单调栈动态规划map题目给定一个整数数组A,你可以从某一起始索引出发,跳跃一定次数。在你跳跃的过程中,第1、3、5…次跳跃称为奇数跳跃,而第2、4、6…次跳跃称为偶数跳跃。你可以按以下方式从索引i向后跳转......
  • 浅谈单调栈
    单调栈,顾名思义,具有单调性的栈。单调,指满足一个序列是一个从小到大的序列或从大到小的序列。栈(\(stack\))是以一种线性存储结构,它具有以下特点:栈中的数据元素遵守“先进后出(\(First\in\Last\out\))”的原则,简称FILO结构;限定只能在栈顶进行插入和删除操作。所以,何为单......