|
1 | 1 | #pragma once |
2 | 2 | //! https://codeforces.com/blog/entry/125371?#comment-1173604 |
3 | 3 | //! @code |
4 | | -//! linear_rmq rmq1(a, less());//right-most min |
5 | | -//! linear_rmq rmq2(a, less_equal());//left-most min |
6 | | -//! linear_rmq rmq3(a, greater());//right-most max |
7 | | -//! linear_rmq rmq4(a, greater_equal());//left-most max |
| 4 | +//! linear_rmq rmq1(a, less()); //right-most min |
| 5 | +//! linear_rmq rmq2(a, less_equal()); //left-most min |
| 6 | +//! linear_rmq rmq3(a, greater()); //right-most max |
| 7 | +//! linear_rmq rmq4(a, greater_equal()); //left-most max |
8 | 8 | //! linear_rmq rmq5(a, [&](auto& x, auto& y) { |
9 | 9 | //! return x < y; |
10 | 10 | //! }); |
11 | 11 | //! @endcode |
12 | 12 | //! @time O(n + q) |
13 | 13 | //! @space O(n) |
14 | 14 | template<class T, class F> struct linear_rmq { |
| 15 | + int n; |
15 | 16 | vector<T> a; |
16 | 17 | F cmp; |
17 | | - vi head; |
18 | | - vector<array<int, 2>> t; |
| 18 | + vi asc, in, head; |
19 | 19 | linear_rmq(const vector<T>& a, F cmp): |
20 | | - a(a), cmp(cmp), head(sz(a) + 1), t(sz(a)) { |
| 20 | + n(sz(a)), a(a), cmp(cmp), asc(n), in(n), head(n + 1) { |
21 | 21 | vi st{-1}; |
22 | | - for (int i = 0; i <= sz(a); i++) { |
| 22 | + rep(i, 0, n + 1) { |
23 | 23 | int prev = -1; |
24 | 24 | while (st.back() != -1 && |
25 | | - (i == sz(a) || !cmp(a[st.back()], a[i]))) { |
| 25 | + (i == n || !cmp(a[st.back()], a[i]))) { |
26 | 26 | if (prev != -1) head[prev] = st.back(); |
27 | | - int pw2 = 1 << __lg((end(st)[-2] + 1) ^ i); |
28 | | - t[st.back()][0] = prev = i & -pw2; |
| 27 | + int pw2 = bit_floor((end(st)[-2] + 1u) ^ i); |
| 28 | + in[st.back()] = prev = i & -pw2; |
29 | 29 | st.pop_back(); |
30 | | - t[st.back() + 1][1] |= pw2; |
| 30 | + asc[st.back() + 1] |= pw2; |
31 | 31 | } |
32 | 32 | if (prev != -1) head[prev] = i; |
33 | 33 | st.push_back(i); |
34 | 34 | } |
35 | | - rep(i, 1, sz(a)) t[i][1] = |
36 | | - (t[i][1] | t[i - 1][1]) & -(t[i][0] & -t[i][0]); |
| 35 | + rep(i, 1, n) asc[i] = |
| 36 | + (asc[i] | asc[i - 1]) & -(in[i] & -in[i]); |
37 | 37 | } |
38 | | - int query_idx(int l, int r) { // [l, r] |
39 | | - if (unsigned j = t[l][0] ^ t[r][0]; j) { |
40 | | - j = t[l][1] & t[r][1] & -bit_floor(j); |
41 | | - if (unsigned k = t[l][1] ^ j; k) |
42 | | - k = bit_floor(k), l = head[(t[l][0] & -k) | k]; |
43 | | - if (unsigned k = t[r][1] ^ j; k) |
44 | | - k = bit_floor(k), r = head[(t[r][0] & -k) | k]; |
| 38 | + int idx(int l, int r) { // [l, r] |
| 39 | + if (unsigned j = in[l] ^ in[r]; j) { |
| 40 | + j = asc[l] & asc[r] & -bit_floor(j); |
| 41 | + if (unsigned k = asc[l] ^ j; k) |
| 42 | + k = bit_floor(k), l = head[(in[l] & -k) | k]; |
| 43 | + if (unsigned k = asc[r] ^ j; k) |
| 44 | + k = bit_floor(k), r = head[(in[r] & -k) | k]; |
45 | 45 | } |
46 | 46 | return cmp(a[l], a[r]) ? l : r; |
47 | 47 | } |
48 | | - T query(int l, int r) { return a[query_idx(l, r)]; } |
| 48 | + T query(int l, int r) { return a[idx(l, r)]; } |
49 | 49 | }; |
0 commit comments