\(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\)值,代码中默认为最大值)。
例题