差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

両方とも前のリビジョン前のリビジョン
次のリビジョン
前のリビジョン
次のリビジョン両方とも次のリビジョン
programming_algorithm:data_structure:sparse_table [2019/12/05] ikatakosprogramming_algorithm:data_structure:sparse_table [2019/12/05] – [±1-RmQ] ikatakos
行 94: 行 94:
 $A=\{A_0,A_1,...,A_{N-1}\}$ の要素が、必ず「左の値から1増えるか1減るかのどちらか」で変化していく配列の最小値/最大値を求める場合。 $A=\{A_0,A_1,...,A_{N-1}\}$ の要素が、必ず「左の値から1増えるか1減るかのどちらか」で変化していく配列の最小値/最大値を求める場合。
  
-この場合、実装はちょっとややこしくなるが、事前計算量と空間を $O(N\log{N})$ から $O(N)$ に落とすことができる。+この場合、実装はちょっとややこしくなるが、クエリ応答は $O(1)$ のまま、事前計算量と空間を $O(N\log{N})$ から $O(N)$ に落とすことができる。
  
 なかなか特殊な条件に見えるが、木の最小共通祖先だったり、たまに使える。 なかなか特殊な条件に見えるが、木の最小共通祖先だったり、たまに使える。
行 108: 行 108:
   * ブロックを1要素として、SparseTableを構築する   * ブロックを1要素として、SparseTableを構築する
   * クエリに対して、完全に覆われるブロック内の最小値はSparseTableで求められる   * クエリに対して、完全に覆われるブロック内の最小値はSparseTableで求められる
-  * はみ出る部分は個別に計算するが、変化パターンが+1か-1のみなので、どのパターンが事前計算して持っておいても大したサイズにならない+  * はみ出る部分は個別に計算するが、変化パターンが限られるので、事前計算して持っておいても大したサイズにならない
  
       | 1  2  3 | 4  5  6 | 7  8  9 | 10 11 12 | 13 14 15 | 16 17 18 | 19 20 21 | 22 23 24 | 25 26 27 | 28 29 30 |       | 1  2  3 | 4  5  6 | 7  8  9 | 10 11 12 | 13 14 15 | 16 17 18 | 19 20 21 | 22 23 24 | 25 26 27 | 28 29 30 |
行 124: 行 124:
 ブロック内の変化は、今回1ブロック3要素なので、%%「++」「+-」「-+」「--」%%の4通りしかない。 ブロック内の変化は、今回1ブロック3要素なので、%%「++」「+-」「-+」「--」%%の4通りしかない。
  
-ブロック内パターン区間 $[l, r]$ の最小値配列は、事前計算で作っておいても間に合う容量であるブロックサイズを $s$ とすると $s^22^{s-1}$+なので、全変化パターン・全区間 $[l, r]$ の最小値配列事前計算で作っても、現実的な容量で間に合う。 
 +ブロックサイズを $s$ とすると $s^22^{s-1}$ の計算量とメモリがかかる。 
 + 
 +先頭要素が0だったとして、最小値を計算しておく。
  
   [++]           [+-]           [-+]           [--]   [++]           [+-]           [-+]           [--]
行 144: 行 147:
 $\displaystyle \frac{\log_2{N}}{2}$ が良いとされている。端数はどちらでもよいが、とりあえず切り上げとする。 $\displaystyle \frac{\log_2{N}}{2}$ が良いとされている。端数はどちらでもよいが、とりあえず切り上げとする。
  
-というのも、こうするとブロックの個数は $\displaystyle \frac{2N}{\log_2{N}}$ となる。+こうするとSparseTable, 個別計算のいずれも事前計算とメモリが $O(N)$ に収まる。 
 + 
 +SparseTableの方は、ブロックの個数が $\displaystyle \frac{2N}{\log_2{N}}$ となる。
 この要素数でSparseTableを構築すると、$\displaystyle \frac{2N}{\log{N}} \log {\frac{2N}{\log{N}}}=O(N)$ となる。 この要素数でSparseTableを構築すると、$\displaystyle \frac{2N}{\log{N}} \log {\frac{2N}{\log{N}}}=O(N)$ となる。
  
行 150: 行 155:
  
 また、個別計算の方も、$\displaystyle \frac{\log{N}}{2}^2 2^{\frac{\log{N}}{2}-1}=O(\log^2{N}\sqrt{N})$ となり、$O(N)$ より小さくなる。 また、個別計算の方も、$\displaystyle \frac{\log{N}}{2}^2 2^{\frac{\log{N}}{2}-1}=O(\log^2{N}\sqrt{N})$ となり、$O(N)$ より小さくなる。
 +
 +=== 拡張性 ===
 +
 +必ずしも±1で遷移する場合に限定しなくても、ブロック内全区間の事前計算テーブルのパターン数が $2^s$ 程度で収まる場合、同じ理由で活用できそう。具体的にあるかは知らんけど。
  
  
  
programming_algorithm/data_structure/sparse_table.txt · 最終更新: 2023/10/13 by ikatakos
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0