AlgoPlus v0.1.0
Loading...
Searching...
No Matches
rmq_sparse_table.h
1#ifndef RMQ_SEGMENT_TREE_H
2#define RMQ_SEGMENT_TREE_H
3
4#ifdef __cplusplus
5#include <cassert>
6#include <iostream>
7#include <vector>
8#endif
9
10#ifndef count_leading_zeroes
11#if defined(_MSC_VER)
12#if defined(_M_ARM) || defined(_M_ARM64)
13#define count_leading_zeroes(x) _CountLeadingZeros(x);
14#else
15#define count_leading_zeroes(x) __lzcnt(x);
16#endif
17#else
18#define count_leading_zeroes(x) __builtin_clz(x);
19#endif
20#endif
21
26template <typename T, bool maximum_mode = false> struct RMQ {
27 static int highest_bit(unsigned x) { return x == 0 ? -1 : 31 - count_leading_zeroes(x); }
28
29 int n = 0;
30 std::vector<T> values;
31 std::vector<std::vector<int>> range_low;
32
33 RMQ(const std::vector<T>& _values = {}) {
34 if (!_values.empty())
35 build(_values);
36 }
37
38 // Note: when `values[a] == values[b]`, returns b.
39 // Need to change this if you want to return a instead of b
40 int better_index(int a, int b) const {
41 return (maximum_mode ? values[b] < values[a] : values[a] < values[b]) ? a : b;
42 }
43
44 void build(const std::vector<T>& _values) {
45 values = _values;
46 n = int(values.size());
47 int levels = highest_bit(n) + 1;
48 range_low.resize(levels);
49
50 for (int k = 0; k < levels; k++)
51 range_low[k].resize(n - (1 << k) + 1);
52
53 for (int i = 0; i < n; i++)
54 range_low[0][i] = i;
55
56 for (int k = 1; k < levels; k++)
57 for (int i = 0; i <= n - (1 << k); i++)
58 range_low[k][i] =
59 better_index(range_low[k - 1][i], range_low[k - 1][i + (1 << (k - 1))]);
60 }
61
62 // Note: breaks ties by choosing the largest index.
63 int query_index(int a, int b) const {
64 assert(0 <= a && a < b && b <= n);
65 int level = highest_bit(b - a);
66 return better_index(range_low[level][a], range_low[level][b - (1 << level)]);
67 }
68
69 T query_value(int a, int b) const { return values[query_index(a, b)]; }
70};
71
72#endif