TOP > データ構造
スパーステーブル(Sparse-Table)
説明
更新がない場合の区間の最小値を高速に求める。
計算量
- 構築 $O(N \log N)$
- クエリ $O(1)$
実装例
- SparseTable($v$): 配列 $v$ で初期化する。
- rmq($l$, $r$): 区間 $[l, r)$ の最小値を返す。
template< typename T >
struct SparseTable {
vector< vector< T > > st;
vector< int > lookup;
SparseTable(const vector< T > &v) {
int b = 0;
while((1 << b) <= v.size()) ++b;
st.assign(b, vector< T >(1 << b));
for(int i = 0; i < v.size(); i++) {
st[0][i] = v[i];
}
for(int i = 1; i < b; i++) {
for(int j = 0; j + (1 << i) <= (1 << b); j++) {
st[i][j] = min(st[i - 1][j], st[i - 1][j + (1 << (i - 1))]);
}
}
lookup.resize(v.size() + 1);
for(int i = 2; i < lookup.size(); i++) {
lookup[i] = lookup[i >> 1] + 1;
}
}
inline T rmq(int l, int r) {
int b = lookup[r - l];
return min(st[b][l], st[b][r - (1 << b)]);
}
};
検証
SPOJ RMQSQ - Range Minimum Query
int main() {
int N, Q;
scanf("%d", &N);
vector< int > vs(N);
for(int i = 0; i < N; i++) scanf("%d", &vs[i]);
SparseTable< int > table(vs);
scanf("%d", &Q);
while(Q--) {
int x, y;
scanf("%d %d", &x, &y);
printf("%d\n", table.rmq(x, y + 1));
}
}