templates/monotonic-stack.cpp
compilable
$cat templates/monotonic-stack
Monotonic Stack
Next/previous greater/smaller element queries in O(n) using a monotonic stack.
#monotonic-stack#next-greater#next-smaller#stack
Log in to track progress, save custom versions, and organize into collections.Log In
$cat source_code/
cpp
#include <bits/stdc++.h>
using namespace std;
vector<int> nextGreater(vector<int>& a, bool strict = true) {
int n = a.size();
vector<int> res(n, n);
stack<int> st;
for (int i = n - 1; i >= 0; i--) {
while (!st.empty() && (strict ? a[st.top()] <= a[i] : a[st.top()] < a[i]))
st.pop();
if (!st.empty()) res[i] = st.top();
st.push(i);
}
return res;
}
vector<int> prevGreater(vector<int>& a, bool strict = true) {
int n = a.size();
vector<int> res(n, -1);
stack<int> st;
for (int i = 0; i < n; i++) {
while (!st.empty() && (strict ? a[st.top()] <= a[i] : a[st.top()] < a[i]))
st.pop();
if (!st.empty()) res[i] = st.top();
st.push(i);
}
return res;
}
vector<int> nextSmaller(vector<int>& a, bool strict = true) {
int n = a.size();
vector<int> res(n, n);
stack<int> st;
for (int i = n - 1; i >= 0; i--) {
while (!st.empty() && (strict ? a[st.top()] >= a[i] : a[st.top()] > a[i]))
st.pop();
if (!st.empty()) res[i] = st.top();
st.push(i);
}
return res;
}
vector<int> prevSmaller(vector<int>& a, bool strict = true) {
int n = a.size();
vector<int> res(n, -1);
stack<int> st;
for (int i = 0; i < n; i++) {
while (!st.empty() && (strict ? a[st.top()] >= a[i] : a[st.top()] > a[i]))
st.pop();
if (!st.empty()) res[i] = st.top();
st.push(i);
}
return res;
}54 linesutf-8
$cat explanation_notes.md
notes_viewer --renderedmarkdown (math enabled)
Monotonic Stack
Four functions for next/previous greater/smaller element index queries, all in .
Functions
nextGreater(a) — for each , smallest with (returns if none)prevGreater(a) — for each , largest with (returns if none)nextSmaller(a) — for each , smallest with prevSmaller(a) — for each , largest with How It Works
strict parameter controls vs comparison