单调栈是一种栈,但栈里面的元素是具有单调性的,所以被称为单调栈
单调栈解决最经典的问题是每个位置都求
- 当前位置左边最近且小于(大于)当前位置的元素的位置
- 当前位置右边最近且小于(大于)当前位置的元素的位置
单调栈模板
#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