模板

template<typename T, T (*op)(T, T), int N = 32>
struct sparse_table {
    std::vector<T> st[N + 1], lg;

    sparse_table() = default;
    sparse_table(size_t size, std::vector<T>& a) : lg(size + 1, 0) {
        for (int i = 0; i <= N; i++) {
            st[i].resize(size + 1, 0);
        }
        for (int i = 1; i <= size; i++) {
            if (i == 1) lg[i] = 0;
            else lg[i] = lg[i >> 1] + 1;
            st[0][i] = a[i];
        }
        for (int i = 1; i <= lg[size]; i++) {
            for (int j = 1; j + (1 << (i - 1)) <= size; j++) {
                st[i][j] = op(st[i - 1][j], st[i - 1][j + (1 << (i - 1))]);
            }
        }
    }

    T query(int l, int r) {
        int x = lg[r - l + 1];
        return op(st[x][l], st[x][r - (1 << x) + 1]);
    }
};

使用

初始化

int op(int a, int b) {
    return std::max(a, b);
}
sparse_table<int, op, 22> st(n, a)

模板第一个参数为值类型,第二个参数为函数指针(合并信息的操作函数),第三个参数必须为常数,是倍增层数的值(有默认值32, 所以第三参数可以省略)。

第一个构造参数是区间大小,第二个构造参数是数列的值。

查询

query(l, r) 查询区间 \([l, r]\)

其他

P3865 【模板】ST 表

OI-wiki