-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy pathmonotonic_queue_using_stacks.cpp
89 lines (75 loc) · 1.81 KB
/
monotonic_queue_using_stacks.cpp
1
2
3
4
5
6
7
8
9
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include <bits/stdc++.h>
using namespace std;
#define F first
#define S second
/**
* Monotonic queue to keep track of the minimum and/or the maximum
* elements so far in the queue in O(1).
*/
template<class T>
class monotonic_queue {
stack<pair<T, pair<T, T>>> s1, s2;
void add(stack<pair<T, pair<T, T>>>& s, T v) {
T mx = std::max(v, s.top().S.F);
T mn = std::min(v, s.top().S.S);
s.push({ v, { mx, mn } });
}
void flip() {
if (s2.size() > 1) {
return;
}
while (s1.size() > 1) {
add(s2, s1.top().F);
s1.pop();
}
}
public:
/**
* Constructs a new monotonic queue.
*/
monotonic_queue() {
s1.push({ numeric_limits<T>::min(), { numeric_limits<T>::min(), numeric_limits<T>::max() } });
s2.push({ numeric_limits<T>::min(), { numeric_limits<T>::min(), numeric_limits<T>::max() } });
}
/**
* Pushes a new element to the end of this queue.
*
* @param v the new element to be pushed.
*/
void push(T v) {
add(s1, v);
}
/**
* Pops the front element from the queue.
* If the queue is empty, an exception is thrown.
*/
void pop() {
flip();
s2.pop();
}
/**
* @return the front element of the queue.
*/
T front() const {
flip();
return s2.top().F;
}
/**
* @return the maximum element of the queue.
*/
T max() const {
return std::max(s1.top().S.F, s2.top().S.F);
}
/**
* @return the minimum element of the queue.
*/
T min() const {
return std::min(s1.top().S.S, s2.top().S.S);
}
/**
* @return the size of the queue.
*/
size_t size() const {
return s1.size() + s2.size() - 2;
}
};