ST表

\(n\)表示数组长度,\(lg[i]\)表示\(log_2i\),\(st[i][j]\)表示区间\([i, i+2^j-1]\)的询问值。

构造函数中预处理出\(lg\)和\(st\),时间复杂度:\(O(nlogn)\)。

\(query(l,r)\)表示求区间\([l,r]\)的询问值,时间复杂度:\(O(logn)\)。

支持高效区间查询,不支持区间修改。

C++ 复制代码
template <typename T>
class SparseTable 
{
public:
    using func_type = function<T(const T &, const T &)>;
    int n;
    vector<vector<T>> st;
    vector<int> lg;
    static T default_func(const T &a, const T &b) {return max(a, b);}
    func_type op;
    SparseTable(const vector<T> &v, func_type _func = default_func) 
    {
        n = v.size() - 1, op = _func;
        lg.assign(n + 1, 0);
        st.assign(n + 1, vector<T>(20));
        for (int i = 0; 1 << i <= n; i++) lg[1 << i] = i;
        for (int i = 1; i <= n; i++) 
        {
            if (!lg[i]) lg[i] = lg[i - 1];
            st[i][0] = v[i];
        }
        for (int j = 1; 1 << j <= n; j++)
            for (int i = 1; i + (1 << j) - 1 <= n; i++)
                st[i][j] = op(st[i][j - 1], st[i + (1 << j - 1)][j - 1]);
    }

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

应用

多次求区间询问值(需满足可重复贡献和结合律,如最值,按位与值,按位或值,\(gcd\)值,代码中默认为最大值)。

例题

Set To Max