Range Minimum Query

For the range minimum query (RMQ) problem, we are given an array $A$ of size $n$ and two indices $i$ and $j$ with $0 \leq i \leq j < n$. We then want to determine the smallest element in $\bigl \lbrace A[i], A[i + 1], \ldots, A[j] \bigr \rbrace$. The program implements different RMQ algorithms. They are mostly taken from [1].

The algorithms all have two parts to it: a pre-processing and query. The pre-processing processes the given array A and then stores results that allow for a faster query. The query then determines the minimum in the specified rang with the help of the pre-processing results. Subsequently, these algorithms have two runtimes. We write that the runtime of an algorithm is in $\bigl \langle \mathcal{O} \bigl( f(n) \bigr), \mathcal{O} \bigl( g(n) \bigr) \bigr \rangle$ time if the pre-processing runs in $\mathcal{O} \bigl( f(n) \bigr)$ time, and a single query runs in $\mathcal{O} \bigl( g(n) \bigr)$ time.

Implemented Algorithms

Lowest Common Ancestor

We also implemented an algorithm that computes the lowest common ancestor of two nodes in a tree. The algorithm uses an Euler tour of the given tree and then performs a RMQ on that tour as described in [1]. For that it can use any of the RMQ algorithms described above.

Rust Implementation

The original implementation was in C++. I also started a reimplementation in Rust which can be found in the RMQ.rs repository.

References

[1] M.A. Bender, M. Farach-Colton: The LCA Problem Revisited. LATIN 2000, LNCS 1776, 88-94, 2000.

[2] M.A. Bender, E.D. Demaine, M. Farach-Colton: Cache-Oblivious B-Trees. SIAM J. Comput. 35(2), 341-358, 2005.

[3] H. Prokop: Cache-oblivious algorithms. Master’s thesis, MIT, June 1999.