for O(1) LCA, no clue how it works
template <typename T, typename Combine>
class SparseTable {
private:
int n, log2dist;
Combine combine;
vector<vector<T>> st;
public:
SparseTable(const vector<T> &v, Combine combine) : combine(combine) {
n = v.size();
log2dist = 1 + (int) log2(n);
st.resize(log2dist);
st[0] = v;
for (int i = 1; i < log2dist; i++) {
st[i].resize(n - (1 << i) + 1);
for (int j = 0; j + (1 << i) <= n; j++) {
st[i][j] = combine(st[i - 1][j], st[i - 1][j + (1 << (i - 1))]);
}
}
}
T range(int l, int r) {
int i = (int) log2(r - l + 1);
return combine(st[i][l], st[i][r - (1 << i) + 1]);
}
};