TOP > データ構造 スパーステーブル(Sparse-Table) 2018/04/16 • ei1333 説明 更新がない場合の区間の最小値を高速に求める。 計算量 構築 $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)); } }