diff --git a/data_structures/sparse_table.cpp b/data_structures/sparse_table.cpp index e1cef3a4a..e40d84296 100644 --- a/data_structures/sparse_table.cpp +++ b/data_structures/sparse_table.cpp @@ -1,6 +1,6 @@ -#include /// for IO operations -#include /// for assert -#include /// for std::array +#include /// for std::array +#include /// for assert +#include /// for IO operations /** * * @file @@ -9,122 +9,122 @@ * @author [manncodes](https://github.com/manncodes) * * @details - * Sparse Table is a data structure, that allows answering range queries. + * Sparse Table is a data structure, that allows answering range queries. * It can answer most range queries in O(logn), but its true power is answering - * range minimum queries (or equivalent range maximum queries). For those queries - * it can compute the answer in O(1) time. The only drawback of this data structure is, - * that it can only be used on immutable arrays. This means, that the array cannot be - * changed between two queries. - * - * If any element in the array changes, the complete data structure has to be recomputed. + * range minimum queries (or equivalent range maximum queries). For those + * queries it can compute the answer in O(1) time. The only drawback of this + * data structure is, that it can only be used on immutable arrays. This means, + * that the array cannot be changed between two queries. * - * @warning this sparse table is made for min(a1,a2,...an) duplicate invariant function. - * This implementation can be changed to other functions like gcd(),lcm(),max() by changing - * few lines of code. + * If any element in the array changes, the complete data structure has to be + * recomputed. + * + * @warning this sparse table is made for min(a1,a2,...an) duplicate invariant + * function. This implementation can be changed to other functions like + * gcd(),lcm(),max() by changing few lines of code. */ - /** * @namespace data_structures * @brief Data Structures algorithms */ namespace data_structures { - + /** * @namespace sparse_table * @brief Implementation of Sparse Table for function : min() - * + * */ namespace sparse_table { +/** + * @brief A struct to represent sparse table + * + */ +struct Sparse_table { + // N : the maximum size of the array. + // M : ceil(log2(N)). + const static int N = 12345, M = 14; + + // The array to compute its sparse table. + int n; + std::array a; + + // + // Sparse table related variables. + // + // ST[j][i] : the sparse table value (min, max, ...etc) in the interval [i, + // i + (2^j) - 1]. LOG[i] : floor(log2(i)). + std::array, M> ST; + std::array LOG; + /** - * @brief A struct to represent sparse table - * + * + * Builds the sparse table for computing min/max/gcd/lcm/...etc + * for any contiguous sub-segment of the array. + * + * This is an example of computing the index of the minimum value. + * + * Complexity: O(n.log(n)) */ - struct Sparse_table{ - // N : the maximum size of the array. - // M : ceil(log2(N)). - const static int N = 12345, M = 14; + void buildST() { + LOG[0] = -1; - // The array to compute its sparse table. - int n; - std::array a; - - // - // Sparse table related variables. - // - // ST[j][i] : the sparse table value (min, max, ...etc) in the interval [i, i + (2^j) - 1]. - // LOG[i] : floor(log2(i)). - std::array,M> ST; - std::array LOG; - - /** - * - * Builds the sparse table for computing min/max/gcd/lcm/...etc - * for any contiguous sub-segment of the array. - * - * This is an example of computing the index of the minimum value. - * - * Complexity: O(n.log(n)) - */ - void buildST() { - LOG[0] = -1; - - for (int i = 0; i < n; ++i) { - ST[0][i] = i; - LOG[i + 1] = LOG[i] + !(i & (i + 1)); - } - - for (int j = 1; (1 << j) <= n; ++j) { - for (int i = 0; (i + (1 << j)) <= n; ++i) { - int x = ST[j - 1][i]; - int y = ST[j - 1][i + (1 << (j - 1))]; - - ST[j][i] = (a[x] <= a[y] ? x : y); - } - } + for (int i = 0; i < n; ++i) { + ST[0][i] = i; + LOG[i + 1] = LOG[i] + !(i & (i + 1)); } - /** - * Queries the sparse table for the value of the interval [l, r] - * (i.e. from l to r inclusive). - * - * Complexity: O(1) - * - * @param l the left index of the range (inclusive). - * @param r the right index of the range (inclusive). - * - * @return the computed value of the given interval. - */ - int query(int l, int r) { - int g = LOG[r - l + 1]; - int x = ST[g][l]; - int y = ST[g][r - (1 << g) + 1]; - return (a[x] <= a[y] ? x : y); + for (int j = 1; (1 << j) <= n; ++j) { + for (int i = 0; (i + (1 << j)) <= n; ++i) { + int x = ST[j - 1][i]; + int y = ST[j - 1][i + (1 << (j - 1))]; + + ST[j][i] = (a[x] <= a[y] ? x : y); + } } - }; -} // namespace sparse_table -} // namespace data_structures + } + + /** + * Queries the sparse table for the value of the interval [l, r] + * (i.e. from l to r inclusive). + * + * Complexity: O(1) + * + * @param l the left index of the range (inclusive). + * @param r the right index of the range (inclusive). + * + * @return the computed value of the given interval. + */ + int query(int l, int r) { + int g = LOG[r - l + 1]; + int x = ST[g][l]; + int y = ST[g][r - (1 << g) + 1]; + return (a[x] <= a[y] ? x : y); + } +}; +} // namespace sparse_table +} // namespace data_structures /** * @brief testcase for sparse_table */ -static void test(){ - std::array testcase = {1,2,3,4,5,6,7,8,9,10}; - int testcase_size = sizeof(testcase)/sizeof(testcase[0]); +static void test() { + std::array testcase = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + int testcase_size = sizeof(testcase) / sizeof(testcase[0]); data_structures::sparse_table::Sparse_table st{}; // copying testcase to the struct - std::copy(std::begin(testcase),std::end(testcase),std::begin(st.a)); + std::copy(std::begin(testcase), std::end(testcase), std::begin(st.a)); st.n = testcase_size; - //precomputing sparse tree + // precomputing sparse tree st.buildST(); // pass queries of form [l,r] - assert(st.query(1,9) == 1); // as 1 is smallest from 1..9 - assert(st.query(2,6) == 2); // as 2 is smallest from 2..6 - assert(st.query(3,8) == 3); // as 3 is smallest from 3..8 + assert(st.query(1, 9) == 1); // as 1 is smallest from 1..9 + assert(st.query(2, 6) == 2); // as 2 is smallest from 2..6 + assert(st.query(3, 8) == 3); // as 3 is smallest from 3..8 std::cout << "Testcase passed!" << std::endl; } @@ -135,7 +135,7 @@ static void test(){ * @param argv commandline array of arguments (ignored) * @returns 0 on exit */ -int main(int argc, char *argv[]){ - test(); // execute the tests +int main(int argc, char *argv[]) { + test(); // execute the tests return 0; }