Skip to content

Latest commit

 

History

History
65 lines (48 loc) · 2.04 KB

sparse_table.md

File metadata and controls

65 lines (48 loc) · 2.04 KB

What are sparse tables?

  • Data structure that allows range queries
  • Can answer most queries in O(log N)
  • But can answer Range Minimum Queries in O(1)
    • An idempotent operation can be repeated an arbitrary number of times and the result will be the same as if it had been done only once. In arithmetic, adding zero to a number is idempotent.
  • It can be only used on immutable arrays. If you need any change, whole DS needs to be changed

Intuition

  • Any non negative number can be uniquely represented as a sum of decreasing powers of 2. This is just a variant of binary representation of a number. For number x, there can be at most log2(x) summands
  • So, by the same reasoning, any interval can be represented as a union of intervals with lengths that are decreasing powers of two. Eq.. [2, 14] = [2, 9] U [10, 13] U [14, 14]
  • And hence, also here union consists of at most [log2(length of interval)] many intervals.
  • MAIN IDEA: Pre-compute all answers for range queries with power of 2 length. So, afterwards combining all of them to receive a complete answer.

Precomputation

  • We will maintain a 2D array
  • Where table[i][j] will store the answer for the range [i, i + 2^j - 1] which can be split nicely into ranges
    • [i, i + 2^{j-1} - 1] and [i + 2^(j-1), i + 2^j - 1] both of length 2^{j-1}
    • So, we can generate this table with dynamic programming

K = log2(MAXN) + 1

logarithmic values

int log[MAXN+1];
log[1] = 0;
for (int i = 2; i <= MAXN; i++)
    log[i] = log[i/2] + 1;

computing sparse table

for (int i = 0; i < MAXN; i++)
    table[i][0] = f(array[i]);

for (int j = 1; j <= K; j++)
    for (int i = 0; i + (1 << j) <= MAXN; i++)
        table[i][j] = f(table[i][j-1], table[i + (1 << (j - 1))][j - 1]);

Query

  • for sum (between L and R)
int sum = 0;
for (int j = K; j >= 0; j--) {
    if ((1 << j) <= R - L + 1) {
        sum += table[L][j];
        L += 1 << j;
    }
}
  • for RMQ (Minimum between L and R)
int j = log[R - L + 1];
int minimum = min(table[L][j], table[R - (1 << j) + 1][j]);