单调栈就是具有单调性的栈,他依旧是一个栈结构,只不过里面的数据是递增或递减的(严格的增或减)
模板如下:
#include <iostream>
#include <stack>
using namespace std;
const int N = 3e6 + 10;
int a[N];
int n;
void test1()
{
stack<int> st;// 维护一个单调递增的栈
for(int i = 1; i <= n; i++)
{
//栈里面大于等于a[i] 的元素全部出栈
while(st.size() && st.top() >= a[i]) st.pop();
st.push(a[i]);
}
}
void text2()
{
stack<int> st; // 维护一个单调递减的栈
for(int i = 1; j<= n; i++)
{
//栈里面小于等于a[i] 的元素全部出栈
while(st.size() && st.top() <= a[i]) st.pop();
st.push(a[i]);
}
}
int main()
{
text1();
text2();
return 0;
}
单调栈解决的问问题
寻找当前元素左侧,理它最近,并且比他大的元素在哪;
寻找当前元素左侧,理它最近,并且比他小的元素在哪;
寻找当前元素右侧,理它最近,并且比他大的元素在哪;
寻找当前元素右侧,理它最近,并且比他大的元素在哪;
寻找当前元素左侧,理它最近,并且比他大的元素在哪;
寻找当前元素左侧,理它最近,并且比他大的元素在哪;
从左往右遍历元素,构造一个单调递减的栈,插入当前我位置的元素
如果栈为空,则左侧不存在比当前元素大的元素;
如果栈为非空,则插入当前位置时的栈顶元素就是所要找的元素;
注意:因为我们要找的是最终结果,因此,栈里面存在每个元素的下标
代码的实现:
单调递减的栈 左边
const int n = 1e5 + 10;
int n;
int a[N];
int ret[N];
void test()
{
stack<int> st; // 单调递减的栈
for(int i = 1; i <= n; i++)
{
while(st.size() && a[st.top()] <= a[i]) st.pop();
if(st.size()) ret[i] = st.top(); //下标
st.push(i);
}
for(int i = 1; i <= n; i++)
cout << ret[i] << " ";
cout << endl;
}
int mian()
{
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> a[i];
}
test();
return 0;
}
单调递增的栈 左边
#include <iostream>
#include <stack>
using namespace std;
const int n = 1e5 + 10;
int n;
int a[N];
int ret[N];
void test()
{
stack<int> st; // 单调递增的栈
for(int i = 1; i <= n; i++)
{
while(st.size() && a[st.top()] >= a[i]) st.pop();
if(st.size()) ret[i] = st.top(); //下标
st.push(i);
}
for(int i = 1; i <= n; i++)
cout << ret[i] << " ";
cout << endl;
}
int mian()
{
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> a[i];
}
test();
return 0;
}
右边 单调递减的栈
const int n = 1e5 + 10;
int n;
int a[N];
int ret[N];
void test()
{
stack<int> st; // 单调递减的栈
for(int i = 1; i <= n; i++)
{
while(st.size() && a[st.top()] <= a[i]) st.pop();
if(st.size()) ret[i] = st.top(); //下标
st.push(i);
}
for(int i = n; i >= 1; i--)
cout << ret[i] << " ";
cout << endl;
}
int mian()
{
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> a[i];
}
test();
return 0;
}
右边 单调增的栈
const int n = 1e5 + 10;
int n;
int a[N];
int ret[N];
void test()
{
stack<int> st; // 单调递增的栈
for(int i = 1; i <= n; i++)
{
while(st.size() && a[st.top()] >= a[i]) st.pop();
if(st.size()) ret[i] = st.top(); //下标
st.push(i);
}
for(int i = 1; i <= n; i++)
cout << ret[i] << " ";
cout << endl;
}
int mian()
{
cin >> n;
for(int i = n; i >= 1; i--)
{
cin >> a[i];
}
test();
return 0;
}