LeetCode The Hard Way

Sparse Table

Range Queries finding min, max, gcd, lcm, and etc. The array cannot be changed between two queries.

template<typename it, typename bin_op>
struct sparse_table {
    using T = typename remove_reference<decltype(*declval<it>())>::type;
    vector<vector<T>> t; bin_op f;

    sparse_table(it first, it last, bin_op op) : t(1), f(op) {
        int n = distance(first, last);
        t.assign(32 - __builtin_clz(n), vector<T>(n));
        t[0].assign(first, last);
        for (int i = 1; i < t.size(); i++)
            for (int j = 0; j < n - (1 << i) + 1; j++)
                t[i][j] = f(t[i - 1][j], t[i - 1][j + (1 << (i - 1))]);
    }

    // returns f(a[l .. r]) in O(1) time
    T query(int l, int r) {
        int h = floor(log2(r - l + 1));
        return f(t[h][l], t[h][r - (1 << h) + 1]);
    }
};

Usage: Range Queries finding min, max, gcd, lcm, and etc. The array cannot be changed between two queries.

void main() {
	sparse_table g(a.begin(), a.end(), [](int x, int y){
		return gcd(x, y);
	});
	cout << g.query(j, i) << "\n";
}