diff --git a/algorithms/graph/hld.cpp b/algorithms/graph/hld.cpp index 73908ce0699743c5f380c875b979d8c8d4258e14..2d9f871a0947fd4ce43eef80189a2deb72cc0f2f 100644 --- a/algorithms/graph/hld.cpp +++ b/algorithms/graph/hld.cpp @@ -1,5 +1,16 @@ /// Heavy Light Decomposition /// +/// Description: +/// The Heavy Light Decomposition splits a tree into several path so that we +/// can reach the root from any node by traversing at most $\log n$ paths. For +/// every vertice $v$, an edge is called heavy if it leads to a child with the +/// largest subtree size; all other edges are called light. \par +/// The set of disjoint paths containing heavy edges are called the ``heavy +/// chains''. These paths (both heavy and light) can be indexed by a single +/// segment tree, allowing fast queries and updates to edges (or vertices). And +/// also, information about the chains (such as the head), allows for fast +/// traversals from any node to any of its ancestors. +/// /// Time: /// - build: O(n log n) /// - query: O(log^2 n) @@ -7,7 +18,7 @@ /// Space: O(n log n) /// /// Caution: -/// - Modifications are necessary if values are associated to vertices; +/// - Modifications are necessary if values are associated with vertices; /// - Modifications are necerrary if other data structure is used. /// /// Status: Tested (QTREE,URI2887) diff --git a/algorithms/graph/kruskal.cpp b/algorithms/graph/kruskal.cpp index 2f86011a94ce12f60d1404de51dafb67426db106..87c4f68092877111e69835b0025206e3513a1546 100644 --- a/algorithms/graph/kruskal.cpp +++ b/algorithms/graph/kruskal.cpp @@ -15,10 +15,11 @@ struct Kruskal { Kruskal(int N) : N(N), ds(N) {} - int run(vector<iii> &mst) { + // Minimum Spanning Tree: comp = less<int>() + // Maximum Spanning Tree: comp = greater<int>() + int run(vector<iii> &mst, function<bool(int,int)> comp) { sort(all(edges), [&](const iii &a, const iii &b) { - // ('>' for maximum spanning tree) - return a.se < b.se; + return comp(a.se, b.se); }); int size = 0; diff --git a/algorithms/graph/lca.cpp b/algorithms/graph/lca.cpp index d16ddec7782c7f1e1300287459abbb501ad0fba2..2c5da885748122ff831226178cad19180838ac1b 100644 --- a/algorithms/graph/lca.cpp +++ b/algorithms/graph/lca.cpp @@ -4,13 +4,13 @@ /// The LCA between two nodes in a tree is a node that is an ancestor to both /// nodes with the lowest height possible. \par /// The algorithm works by following the path up the tree from both nodes -/// "simultaneously" until a common node is found. The naive approach for that -/// would be $O(n)$ in the worst case. To improve that, this implementation -/// uses "binary lifting" which is a way of figuring out the right number of -/// up-moves needed to find the LCA by following the binary representation of -/// the distance to the destination (similar to the "binary search by jumping"), -/// but, for that, a preprocessing must be done to set every parent at a $2^i$ -/// distance. +/// ``simultaneously'' until a common node is found. The naive approach for +/// that would be $O(n)$ in the worst case. To improve that, this +/// implementation uses ``binary lifting'' which is a way of figuring out the +/// right number of up-moves needed to find the LCA by following the binary +/// representation of the distance to the destination (similar to the ``binary +/// search by jumping''), but, for that, a preprocessing must be done to set +/// every parent at a $2^i$ distance. /// /// Time: /// - preprocess: O(V log V) diff --git a/algorithms/math/big_integer.cpp b/algorithms/math/big_integer.cpp index e2fed1ae433427cf402759cb28cab6686577e200..de456fb68682bb53bfe43949cf00f2554571926a 100644 --- a/algorithms/math/big_integer.cpp +++ b/algorithms/math/big_integer.cpp @@ -2,13 +2,13 @@ /// /// Space: O(n) /// -/// Status: Tested (KRAKOVIA) -// /// Caution: -/// - Just use python. -// +/// - Just use Python if possible. +/// /// Include: /// - math/karatsuba +/// +/// Status: Tested (KRAKOVIA) const int base = 1000000000; const int base_d = 9; diff --git a/algorithms/math/binary_exponentiation.cpp b/algorithms/math/binary_exponentiation.cpp index ca57045ee532f2f2d1ad3f4589205e7f431905dc..818f7dd00075b8ae22fcc1fbe49ab939ea960e80 100644 --- a/algorithms/math/binary_exponentiation.cpp +++ b/algorithms/math/binary_exponentiation.cpp @@ -1,5 +1,13 @@ /// Binary Exponentiation /// +/// Description: +/// Computes fast exponentiation by looking a the binary representation of +/// the exponent. The usage of ``bin\_mul'' is not necessary, but it ensures +/// that no overflow will occur when multiplying two large integers. It is +/// definitely required in order to work with Miller-Rabin and Pollard's +/// Rho implementations (when dealing with numbers that might go up to +/// $10^{18}$. +/// /// Time: O(log n) /// Space: O(1) diff --git a/algorithms/math/legendre.cpp b/algorithms/math/legendre.cpp index d470908d161049f9266b42a289f753c97b7961b4..7be0e3ce634cc3abda321ed3268883ba7c366bae 100644 --- a/algorithms/math/legendre.cpp +++ b/algorithms/math/legendre.cpp @@ -1,5 +1,16 @@ /// Legendre's Formula /// +/// Description: +/// Given an interger $n$ and a prime number $p$, find the largest power of +/// $p$ ($x$) such that $n!$ is divisible by $k^x$. \par +/// Writing $n!$ as $1 \cdot 2 \cdot 3 ... (n-1) \cdot n$ shows that every +/// $k$-th element of the product is divisible by $k$ (i.e. adds $1$ to the +/// answer), the number of such elements is $\lfloor\frac{n}{k}\rfloor$. The +/// same is true for every $k^i$, thus, the answer is given by: +/// \[ \lfloor\frac{n}{k}\rfloor + \lfloor\frac{n}{k^2}\rfloor + ... + +/// \lfloor\frac{n}{k^i}\rfloor \] only approximately the first $log_p n$ +/// elements are greater than zero, therefore the sum is finite. +/// /// Time: O(log_p n) /// Space: O(1) diff --git a/algorithms/math/linear_diophantine_equation.cpp b/algorithms/math/linear_diophantine_equation.cpp index 085d7d7e13a185dd9a0c7194b5d9e9411b512084..e523f2558ea5bfb4693febbb70f0f532e4ebe7b5 100644 --- a/algorithms/math/linear_diophantine_equation.cpp +++ b/algorithms/math/linear_diophantine_equation.cpp @@ -1,7 +1,7 @@ /// Linear Diophantine Equation /// /// Description: -/// A Linear Diophantine Equation is an equation in the form $ax + by = c$. +/// A Linear Diophantine Equation is an equation in the form \[ ax + by = c \] /// A solution of this equation is a pair $(x,y)$ that satisfies the equation. /// The locus of (lattice) points whose coordinates $x$ and $y$ satisfy the /// equation is a straigh line. \par diff --git a/algorithms/math/modular_multiplicative_inverse.cpp b/algorithms/math/modular_multiplicative_inverse.cpp index a06e950382a7db8540c9d620f502159d7e87715e..f1024e2609b9619f1497db8afd1104ad768be86e 100644 --- a/algorithms/math/modular_multiplicative_inverse.cpp +++ b/algorithms/math/modular_multiplicative_inverse.cpp @@ -1,5 +1,10 @@ /// Modular Multiplicative Inverse /// +/// Description: +/// Given integers $a$ and $m$, the modular multiplicative inverse of $a$ is +/// an integer $x$ such that \[ a \cdot x \equiv 1 \pmod{m} \] also denoted as +/// $a^{-1}$. +/// /// Time: O(log m) /// Space: O(1) diff --git a/algorithms/paradigm/ternary_search.cpp b/algorithms/paradigm/ternary_search.cpp index a687284e3c0b4225e0defb745e3fb45cd651f68c..457f407c35cdb56aca1443c253ecdf5d972917ac 100644 --- a/algorithms/paradigm/ternary_search.cpp +++ b/algorithms/paradigm/ternary_search.cpp @@ -1,30 +1,33 @@ /// Ternary Search /// +/// Description: +/// Searches for the minimum (or maximum) value of a unimodal function +/// $f(x)$ for $x$ between $l$ and $r$. +/// /// Time: O(log n) /// Space: O(1) +/// +/// Caution: +/// - f must be a unimodal function -// Unimodal function -double f(double x) { - return x * x; -} - -double ternary_search(double l, double r) { - double rt, lt; +// Minimum of f: comp = less<T>() +// Maximum of f: comp = greater<T>() +template <typename T, class F = function<T(T)>> +T ternary_search(T l, T r, F f, function<bool(T,T)> comp) { + T rt, lt; for (int i = 0; i < 500; ++i) { if (fabs(r - l) < EPS) - return (l + r) / 2.0; + return (l + r) / 2; - lt = (r - l) / 3.0 + l; - rt = ((r - l) * 2.0) / 3.0 + l; + lt = (r - l) / 3 + l; + rt = ((r - l) * 2) / 3 + l; - // '<' for minimum of f, - // '>' for maximum of f - if (f(lt) < f(rt)) + if (comp(f(lt), f(rt))) l = lt; else r = rt; } - return (l + r) / 2.0; + return (l + r) / 2; } diff --git a/algorithms/string/booth.cpp b/algorithms/string/booth.cpp index ca072deea1dcf2dfb2351ee95b9fef03bf485953..19a684e232044c0d8fb7588eee1d3c2958284bb2 100644 --- a/algorithms/string/booth.cpp +++ b/algorithms/string/booth.cpp @@ -9,7 +9,9 @@ /// Time: O(n) /// Space: O(n) -string booth(string s) { +// Maximal: func = greater<char>() +// Minimal: func = less<char>() +string booth(string s, function<bool(char,char)> func) { string S = s + s; vector<int> f(S.size(), -1); @@ -19,13 +21,13 @@ string booth(string s) { int i = f[j - k - 1]; while (i != -1 && sj != S[k+i+1]) { - if (sj < S[k + i + 1]) // >: maximal + if (func(sj, S[k + i + 1])) k = j - i - 1; i = f[i]; } if (sj != S[k+i+1]) { - if (sj < S[k]) // >: maximal + if (func(sj, S[k])) k = j; f[j-k] = -1; diff --git a/algorithms/structure/mo_algorithm.cpp b/algorithms/structure/mo_algorithm.cpp index c174c545fdf5d7e38ff06789f388f2b8275922b5..64803b3910424fb04a3d24c885615a14264dd5da 100644 --- a/algorithms/structure/mo_algorithm.cpp +++ b/algorithms/structure/mo_algorithm.cpp @@ -2,6 +2,9 @@ /// /// Time: O((n + q) * sqrt{n}) /// Space: O(n + q) +/// +/// Caution: +/// - Remember to implement add, remove, and get\_ans functions. struct Query { int l, r, idx; diff --git a/algorithms/structure/trie.cpp b/algorithms/structure/trie.cpp index a5053daeb4da554b4cbd30c4d1e8b0765cc0c711..6952a693689e9ccd5464615e19eab939e0f63da6 100644 --- a/algorithms/structure/trie.cpp +++ b/algorithms/structure/trie.cpp @@ -4,6 +4,9 @@ /// - insert: O(M) /// - search: O(M) /// Space: O(alph * N) +/// +/// Caution: +/// - If Trie stores integers, remember to check order of bits (most/least significant first). template <typename T> struct Trie { diff --git a/caderno.pdf b/caderno.pdf index 9e2f1bbe431a7791d341b4676e517309295b6130..9ff400bb0e5ec636c3703ff24aae3ac55aaf119c 100644 Binary files a/caderno.pdf and b/caderno.pdf differ diff --git a/notebook/gen_latex.py b/notebook/gen_latex.py index 01a79e8825fbbff5d28765507559695407b9e1b2..e42019db71aa5baa65d54784814bf370e45bae5a 100644 --- a/notebook/gen_latex.py +++ b/notebook/gen_latex.py @@ -117,7 +117,7 @@ class LatexGenerator: def to_big_o(expr): expr = expr.replace('O', '\\mathcal{O}') expr = expr.replace('log', '\\log') - expr = expr.replace('*', '\\times') + expr = expr.replace('*', '\\cdot') expr = expr.replace('sqrt', '\\sqrt') return expr