-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathrmq.cpp
34 lines (33 loc) · 1.22 KB
/
rmq.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
// @brunomaletta
template <typename T>
struct rmq {
vector<T> v;
int n;
static const int b = 30;
vector<int> mask, t;
int op(int x, int y) { return v[x] <= v[y] ? x : y; }
int msb(int x) { return __builtin_clz(1) - __builtin_clz(x); }
int small(int r, int sz = b) { return r - msb(mask[r] & ((1 << sz) - 1)); }
rmq() {}
rmq(const vector<T>& v_) : v(v_), n(v.size()), mask(n), t(n) {
for (int i = 0, at = 0; i < n; mask[i++] = at |= 1) {
at = (at << 1) & ((1 << b) - 1);
while (at and op(i - msb(at & -at), i) == i) at ^= at & -at;
}
for (int i = 0; i < n / b; i++) t[i] = small(b * i + b - 1);
for (int j = 1; (1 << j) <= n / b; j++)
for (int i = 0; i + (1 << j) <= n / b; i++)
t[n / b * j + i] =
op(t[n / b * (j - 1) + i], t[n / b * (j - 1) + i + (1 << (j - 1))]);
}
int index_query(int l, int r) {
if (r - l + 1 <= b) return small(r, r - l + 1);
int x = l / b + 1, y = r / b - 1;
if (x > y) return op(small(l + b - 1), small(r));
int j = msb(y - x + 1);
int ans = op(small(l + b - 1),
op(t[n / b * j + x], t[n / b * j + y - (1 << j) + 1]));
return op(ans, small(r));
}
T query(int l, int r) { return v[index_query(l, r)]; }
};