templates/monotonic-queue.cpp
compilable
$cat templates/monotonic-queue
Monotonic Queue
Sliding window min/max in O(1) amortized using the two-stack queue pattern.
#monotonic-queue#sliding-window#deque#min-max
Log in to track progress, save custom versions, and organize into collections.Log In
$cat source_code/
cpp
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <bits/stdc++.h>
using namespace std;
int combine(int a, int b) { return max(a, b); }
const int IDENTITY = INT_MIN;
struct MonoStack {
vector<int> st, agg;
MonoStack() { agg.push_back(IDENTITY); }
void push(int x) { st.push_back(x); agg.push_back(combine(agg.back(), x)); }
int pop() { int r = st.back(); st.pop_back(); agg.pop_back(); return r; }
int top() { return st.back(); }
int query() { return agg.back(); }
bool empty() { return st.empty(); }
int size() { return st.size(); }
};
struct MonoQueue {
MonoStack s1, s2;
void push(int x) { s2.push(x); }
void pop() {
if (s1.empty()) while (!s2.empty()) s1.push(s2.pop());
s1.pop();
}
int front() {
if (s1.empty()) while (!s2.empty()) s1.push(s2.pop());
return s1.top();
}
int query() {
if (s1.empty()) return s2.query();
if (s2.empty()) return s1.query();
return combine(s1.query(), s2.query());
}
bool empty() { return s1.empty() && s2.empty(); }
int size() { return s1.size() + s2.size(); }
};36 linesutf-8
$cat explanation_notes.md
notes_viewer --renderedmarkdown (math enabled)
Monotonic Queue
Maintains the aggregate (min/max) of a sliding window in amortized using two monotonic stacks.
How It Works
push(x) appends to while tracking the running aggregatepop() removes from ; when is empty, all of transfers to (reversal preserves order)When to Use
Notes
combine() for different operations: min for sliding min, max for sliding max, __gcd for sliding gcd