From bb54e83c8b49cf51f3865bf2772f21de62c79961 Mon Sep 17 00:00:00 2001 From: Carlos Javier Blanco Date: Sun, 22 Jan 2023 09:03:13 -0500 Subject: [PATCH 001/590] Update fibonacci-numbers.md Adding two algorithms for calculating fibonacci sequence, one in O(n) time, and one in O(log n) time with matrix exponentiation. Plus three new issues to the list. --- src/algebra/fibonacci-numbers.md | 75 ++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/src/algebra/fibonacci-numbers.md b/src/algebra/fibonacci-numbers.md index 3653d4bd0..fd3561a74 100644 --- a/src/algebra/fibonacci-numbers.md +++ b/src/algebra/fibonacci-numbers.md @@ -74,6 +74,26 @@ The encoding of an integer $n$ can be done with a simple greedy algorithm: To decode a code word, first remove the final $1$. Then, if the $i$-th bit is set (indexing from 0 from the leftmost to the rightmost bit), sum $F_{i+2}$ to the number. +### Fibonacci O(N) time + +We can start from an iterative approach, to take advantage of the use of the formula Fn = Fn-1 + Fn-2, therefore, we will simply precalculate those values in an array. Taking into account the base cases for F(0) and F(1). + +```cpp +int fib(int n) { + + int fibNumbers[n+1]; + fibNumbers[0] = 0; + fibNumbers[1] = 1; + + for(int i=2;i<=n;i++) { + fibNumbers[i] = fibNumbers[i-1] + fibNumbers[i-2]; + } + return fibNumbers[n]; +} +``` + +In this way, we obtain a linear solution, **O(N) time**, saving all the values prior to **N** in the sequence. + ## Formulas for the $n^{\text{th}}$ Fibonacci number { data-toc-label="Formulas for the -th Fibonacci number" } The $n$-th Fibonacci number can be easily found in $O(n)$ by computing the numbers one by one up to $n$. However, there are also faster ways, as we will see. @@ -106,6 +126,58 @@ $$\begin{pmatrix}F_n & F_{n+1} \cr\end{pmatrix} = \begin{pmatrix}F_0 & F_1 \cr\e Thus, in order to find $F_n$, we must raise the matrix $P$ to $n$. This can be done in $O(\log n)$ (see [Binary exponentiation](binary-exp.md)). +### Matrix exponentiation + +The method is based on the relationship: + +$$\begin{pmatrix} 1 & 1 \cr 1 & 0 \cr\end{pmatrix} ^ n = \begin{pmatrix} F_{n+1} & F_{n} \cr F_{n} & F_{n-1} \cr\end{pmatrix}$$ + +``` cpp +typedef long long ll; +const ll mod = 100000007; + +struct matrix{ + ll mat[2][2]; + matrix friend operator *(const matrix &a, const matrix &b){ + matrix c; + for(int i = 0; i < 2; i++) + for(int j = 0; j < 2; j++){ + c.mat[i][j] = 0; + for(int k = 0; k < 2; k++){ + c.mat[i][j] += (a.mat[i][k]*b.mat[k][j]); + } + } + return c; + } +}; + +matrix matpow(matrix base, ll n){ + matrix ans; + for(int i = 0; i < 2; i++) + for(int j = 0; j < 2; j++) + ans.mat[i][j] = (i==j); + while(n){ + if(n&1) + ans = ans*base; + base = base*base; + n >>= 1; + } + return ans; +} + +void solution(int n) { + + matrix base, ans; + base.mat[0][0] = base.mat[0][1] = base.mat[1][0] = 1; + base.mat[1][1] = 0; + + ans = matpow(base, n); +} + +``` + +Note that in many problems, you will have to calculate Fn % m, since Fn could be quite large, you will only have to apply modular arithmetics. + ### Fast Doubling Method Using above method we can find these equations: @@ -153,4 +225,7 @@ We now choose two pairs of identical remainders with the smallest indices in the * [Project Euler - Even Fibonacci numbers](https://www.hackerrank.com/contests/projecteuler/challenges/euler002/problem) * [DMOJ - Fibonacci Sequence](https://dmoj.ca/problem/fibonacci) * [DMOJ - Fibonacci Sequence (Harder)](https://dmoj.ca/problem/fibonacci2) +* [DMOJ UCLV - Numbered sequence of pencils](https://dmoj.uclv.edu.cu/problem/secnum) +* [DMOJ UCLV - Fibonacci 2D](https://dmoj.uclv.edu.cu/problem/fibonacci) +* [DMOJ UCLV - fibonacci calculation](https://dmoj.uclv.edu.cu/problem/fibonaccicalculatio) From 4333252d8e3efe893f72913894729ccb74b53ec8 Mon Sep 17 00:00:00 2001 From: Carlos Javier Blanco Date: Wed, 22 Feb 2023 07:50:29 -0500 Subject: [PATCH 002/590] Update fibonacci-numbers.md --- src/algebra/fibonacci-numbers.md | 67 ++++++++++++-------------------- 1 file changed, 25 insertions(+), 42 deletions(-) diff --git a/src/algebra/fibonacci-numbers.md b/src/algebra/fibonacci-numbers.md index fd3561a74..ccc984d10 100644 --- a/src/algebra/fibonacci-numbers.md +++ b/src/algebra/fibonacci-numbers.md @@ -74,25 +74,6 @@ The encoding of an integer $n$ can be done with a simple greedy algorithm: To decode a code word, first remove the final $1$. Then, if the $i$-th bit is set (indexing from 0 from the leftmost to the rightmost bit), sum $F_{i+2}$ to the number. -### Fibonacci O(N) time - -We can start from an iterative approach, to take advantage of the use of the formula Fn = Fn-1 + Fn-2, therefore, we will simply precalculate those values in an array. Taking into account the base cases for F(0) and F(1). - -```cpp -int fib(int n) { - - int fibNumbers[n+1]; - fibNumbers[0] = 0; - fibNumbers[1] = 1; - - for(int i=2;i<=n;i++) { - fibNumbers[i] = fibNumbers[i-1] + fibNumbers[i-2]; - } - return fibNumbers[n]; -} -``` - -In this way, we obtain a linear solution, **O(N) time**, saving all the values prior to **N** in the sequence. ## Formulas for the $n^{\text{th}}$ Fibonacci number { data-toc-label="Formulas for the -th Fibonacci number" } @@ -114,27 +95,37 @@ where the square brackets denote rounding to the nearest integer. As these two formulas would require very high accuracy when working with fractional numbers, they are of little use in practical calculations. -### Matrix form +### Fibonacci fast method -It is easy to prove the following relation: - -$$\begin{pmatrix}F_{n-1} & F_{n} \cr\end{pmatrix} = \begin{pmatrix}F_{n-2} & F_{n-1} \cr\end{pmatrix} \cdot \begin{pmatrix}0 & 1 \cr 1 & 1 \cr\end{pmatrix}$$ +The $n$-th Fibonacci number can be easily found in $O(n)$ by computing the numbers one by one up to $n$. However, there are also faster ways, as we will see. -Denoting $P \equiv \begin{pmatrix}0 & 1 \cr 1 & 1 \cr\end{pmatrix}$, we have: +We can start from an iterative approach, to take advantage of the use of the formula $F_n = F_{n-1} + F_{n-2}$, therefore, we will simply precalculate those values in an array. Taking into account the base cases for $F_0$ and $F_1$. -$$\begin{pmatrix}F_n & F_{n+1} \cr\end{pmatrix} = \begin{pmatrix}F_0 & F_1 \cr\end{pmatrix} \cdot P^n$$ +```cpp +int fib(int n) { + int a = 0; + int b = 1; + for (int i = 0; i < n; i++) { + int tmp = a + b; + a = b; + b = tmp; + } + return b; +} +``` -Thus, in order to find $F_n$, we must raise the matrix $P$ to $n$. This can be done in $O(\log n)$ (see [Binary exponentiation](binary-exp.md)). +In this way, we obtain a linear solution, $O(n)$ time, saving all the values prior to $n$ in the sequence. -### Matrix exponentiation +### Matrix form -The method is based on the relationship: +It is easy to prove the following relation: $$\begin{pmatrix} 1 & 1 \cr 1 & 0 \cr\end{pmatrix} ^ n = \begin{pmatrix} F_{n+1} & F_{n} \cr F_{n} & F_{n-1} \cr\end{pmatrix}$$ +Thus, in order to find $F_n$ in $O(log n)$ time, we must raise the matrix to n. (See [Binary exponentiation](https://github.com/cp-algorithms/cp-algorithms/blob/master/src/algebra/binary-exp.md)) + ``` cpp typedef long long ll; -const ll mod = 100000007; struct matrix{ ll mat[2][2]; @@ -152,10 +143,7 @@ struct matrix{ }; matrix matpow(matrix base, ll n){ - matrix ans; - for(int i = 0; i < 2; i++) - for(int j = 0; j < 2; j++) - ans.mat[i][j] = (i==j); + matrix ans {{{1, 0}, {0, 1}}}; while(n){ if(n&1) ans = ans*base; @@ -165,19 +153,14 @@ matrix matpow(matrix base, ll n){ return ans; } -void solution(int n) { - - matrix base, ans; - base.mat[0][0] = base.mat[0][1] = base.mat[1][0] = 1; - base.mat[1][1] = 0; - - ans = matpow(base, n); +long long fib(int n) { + matrix base {{{1, 1}, {1, 0}}}; + base = matpow(base, n); + return base.mat[0][1]; } ``` -Note that in many problems, you will have to calculate Fn % m, since Fn could be quite large, you will only have to apply modular arithmetics. - ### Fast Doubling Method Using above method we can find these equations: From 94c3ef0ccca87f625d34ad04eabacb34b80eb0ce Mon Sep 17 00:00:00 2001 From: ContronThePanda Date: Wed, 22 Feb 2023 09:43:19 -0500 Subject: [PATCH 003/590] Fix link in binary-exp page --- src/algebra/binary-exp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algebra/binary-exp.md b/src/algebra/binary-exp.md index 05dbacc76..417c391bc 100644 --- a/src/algebra/binary-exp.md +++ b/src/algebra/binary-exp.md @@ -188,7 +188,7 @@ a_{41} & a_ {42} & a_ {43} & a_ {44} \end{pmatrix} = \begin{pmatrix} x' & y' & z' & 1 \end{pmatrix}$$ -(Why introduce a fictitious fourth coordinate, you ask? That is the beauty of (homogeneous coordinates)[https://en.wikipedia.org/wiki/Homogeneous_coordinates], which find great application in computer graphics. Without this, it would not be possible to implement affine operations like the shift operation as a single matrix multiplication, as it requires us to _add_ a constant to the coordinates. The affine transformation becomes a linear transformation in the higher dimension!) +(Why introduce a fictitious fourth coordinate, you ask? That is the beauty of [homogeneous coordinates](https://en.wikipedia.org/wiki/Homogeneous_coordinates), which find great application in computer graphics. Without this, it would not be possible to implement affine operations like the shift operation as a single matrix multiplication, as it requires us to _add_ a constant to the coordinates. The affine transformation becomes a linear transformation in the higher dimension!) Here are some examples of how transformations are represented in matrix form: From c834e68a5ff59fa22db37e8870a1e91912342ca7 Mon Sep 17 00:00:00 2001 From: Pratik Rai Date: Sat, 25 Feb 2023 01:36:49 +0530 Subject: [PATCH 004/590] Update search-for-connected-components.md --- src/graph/search-for-connected-components.md | 43 ++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/graph/search-for-connected-components.md b/src/graph/search-for-connected-components.md index f18779055..86c4c2267 100644 --- a/src/graph/search-for-connected-components.md +++ b/src/graph/search-for-connected-components.md @@ -49,6 +49,49 @@ void find_comps() { } ``` +## Iterative implementation of the code +``` cpp +int n; +vector g[MAXN]; +bool used[MAXN]; +vector comp; + +void dfs(int v) { + stack st; + st.push(v); + + while (!st.empty()) { + int curr = st.top(); + st.pop(); + if (!used[curr]) { + used[curr] = true; + comp.push_back(curr); + for (int i = g[curr].size() - 1; i >= 0; i--) { + int to = g[curr][i]; + st.push(to); + } + } + } +} + +void find_comps() { + for (int i = 0; i < n ; ++i) + used [i] = false; + for (int i = 0; i < n ; ++i) + if (!used[i]) { + comp.clear(); + dfs(i); + cout << "Component:" ; + for (size_t j = 0; j < comp.size(); ++j) + cout << ' ' << comp[j]; + cout << endl ; + } +} + +``` + + + * The most important function that is used is `find_comps()` which finds and displays connected components of the graph. * The graph is stored in adjacency list representation, i.e `g[i]` contains a list of vertices that have edges from the vertex `i`. The constant `MAXN` should be set equal to the maximum possible number of vertices in the graph. From eafd45aacd7f384662da7fe501ac471213ba9930 Mon Sep 17 00:00:00 2001 From: Dev Choganwala Date: Sat, 25 Feb 2023 19:20:38 +0530 Subject: [PATCH 005/590] Inconsistent inequality in segment_tree.md The condition `l < tl` and `tr < r` will never be true in `query`. So only `==` can be checked. --- src/data_structures/segment_tree.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data_structures/segment_tree.md b/src/data_structures/segment_tree.md index 49c0858e7..778aba3e3 100644 --- a/src/data_structures/segment_tree.md +++ b/src/data_structures/segment_tree.md @@ -842,7 +842,7 @@ void update(int v, int tl, int tr, int l, int r, int addend) { int query(int v, int tl, int tr, int l, int r) { if (l > r) return -INF; - if (l <= tl && tr <= r) + if (l == tl && tr == r) return t[v]; push(v); int tm = (tl + tr) / 2; From 0efa8e7a3481223ea259ddefaa4031c2a0e692de Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sat, 25 Feb 2023 23:39:41 +0100 Subject: [PATCH 006/590] formatting + tests for fibonacci --- src/algebra/fibonacci-numbers.md | 87 ++++++++++++++++++++------------ test/test_fibonacci.cpp | 38 ++++++++++++++ 2 files changed, 92 insertions(+), 33 deletions(-) create mode 100644 test/test_fibonacci.cpp diff --git a/src/algebra/fibonacci-numbers.md b/src/algebra/fibonacci-numbers.md index ccc984d10..5dd2c074d 100644 --- a/src/algebra/fibonacci-numbers.md +++ b/src/algebra/fibonacci-numbers.md @@ -77,8 +77,6 @@ To decode a code word, first remove the final $1$. Then, if the $i$-th bit is se ## Formulas for the $n^{\text{th}}$ Fibonacci number { data-toc-label="Formulas for the -th Fibonacci number" } -The $n$-th Fibonacci number can be easily found in $O(n)$ by computing the numbers one by one up to $n$. However, there are also faster ways, as we will see. - ### Closed-form expression There is a formula known as "Binet's formula", even though it was already known by Moivre: @@ -95,13 +93,13 @@ where the square brackets denote rounding to the nearest integer. As these two formulas would require very high accuracy when working with fractional numbers, they are of little use in practical calculations. -### Fibonacci fast method +### Fibonacci in linear time The $n$-th Fibonacci number can be easily found in $O(n)$ by computing the numbers one by one up to $n$. However, there are also faster ways, as we will see. We can start from an iterative approach, to take advantage of the use of the formula $F_n = F_{n-1} + F_{n-2}$, therefore, we will simply precalculate those values in an array. Taking into account the base cases for $F_0$ and $F_1$. -```cpp +```{.cpp file=fibonacci_linear} int fib(int n) { int a = 0; int b = 1; @@ -110,7 +108,7 @@ int fib(int n) { a = b; b = tmp; } - return b; + return a; } ``` @@ -122,29 +120,31 @@ It is easy to prove the following relation: $$\begin{pmatrix} 1 & 1 \cr 1 & 0 \cr\end{pmatrix} ^ n = \begin{pmatrix} F_{n+1} & F_{n} \cr F_{n} & F_{n-1} \cr\end{pmatrix}$$ -Thus, in order to find $F_n$ in $O(log n)$ time, we must raise the matrix to n. (See [Binary exponentiation](https://github.com/cp-algorithms/cp-algorithms/blob/master/src/algebra/binary-exp.md)) - -``` cpp -typedef long long ll; +Thus, in order to find $F_n$ in $O(log n)$ time, we must raise the matrix to n. (See [Binary exponentiation](binary-exp.md)) -struct matrix{ - ll mat[2][2]; +```{.cpp file=fibonacci_matrix} +struct matrix { + long long mat[2][2]; matrix friend operator *(const matrix &a, const matrix &b){ matrix c; - for(int i = 0; i < 2; i++) - for(int j = 0; j < 2; j++){ - c.mat[i][j] = 0; - for(int k = 0; k < 2; k++){ - c.mat[i][j] += (a.mat[i][k]*b.mat[k][j]); - } + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + c.mat[i][j] = 0; + for (int k = 0; k < 2; k++) { + c.mat[i][j] += a.mat[i][k] * b.mat[k][j]; + } + } } return c; } }; -matrix matpow(matrix base, ll n){ - matrix ans {{{1, 0}, {0, 1}}}; - while(n){ +matrix matpow(matrix base, long long n) { + matrix ans{ { + {1, 0}, + {0, 1} + } }; + while (n) { if(n&1) ans = ans*base; base = base*base; @@ -153,26 +153,47 @@ matrix matpow(matrix base, ll n){ return ans; } -long long fib(int n) { - matrix base {{{1, 1}, {1, 0}}}; - base = matpow(base, n); - return base.mat[0][1]; -} - +long long fib(int n) { + matrix base{ { + {1, 1}, + {1, 0} + } }; + return matpow(base, n).mat[0][1]; +} ``` ### Fast Doubling Method -Using above method we can find these equations: - -$$ \begin{array}{rll} - F_{2k} &= F_k \left( 2F_{k+1} - F_{k} \right). \\ - F_{2k+1} &= F_{k+1}^2 + F_{k}^2. -\end{array}$$ +Using expanding the above matrix expression for $n = 2\cdot k$ + +$$ +\begin{pmatrix} +F_{2k+1} & F_{2k}\\ +F_{2k} & F_{2k-1} +\end{pmatrix} += +\begin{pmatrix} +1 & 1\\ +1 & 0 +\end{pmatrix}^{2k} += +\begin{pmatrix} +F_{k+1} & F_{k}\\ +F_{k} & F_{k-1} +\end{pmatrix} +^2 +$$ + +we can find these simpler equations: + +$$ \begin{align} +F_{2k+1} &= F_{k+1}^2 + F_{k}^2 \\ +F_{2k} &= F_k(F_{k+1}+F_{k-1}) = F_k (2F_{k+1} - F_{k})\\ +\end{align}.$$ Thus using above two equations Fibonacci numbers can be calculated easily by the following code: -```cpp +```{.cpp file=fibonacci_doubling} pair fib (int n) { if (n == 0) return {0, 1}; diff --git a/test/test_fibonacci.cpp b/test/test_fibonacci.cpp new file mode 100644 index 000000000..b2d6b5ad6 --- /dev/null +++ b/test/test_fibonacci.cpp @@ -0,0 +1,38 @@ +#include +#include +using namespace std; + +namespace FibLinear { +#include "fibonacci_linear.h" +} + +namespace FibMatrix { +#include "fibonacci_matrix.h" +} + +namespace FibDoubling { +#include "fibonacci_doubling.h" +} + +int main() { + vector expected = { + 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, + 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, + 121393, 196418, 317811, 514229, 832040, 1346269, + 2178309, 3524578, 5702887, 9227465, 14930352, 24157817, + 39088169, 63245986, 102334155 + }; + + for (int i = 0; i < expected.size(); i++) { + assert(FibLinear::fib(i) == expected[i]); + } + + for (int i = 0; i < expected.size(); i++) { + assert(FibMatrix::fib(i) == expected[i]); + } + + for (int i = 0; i < expected.size(); i++) { + assert(FibDoubling::fib(i).first == expected[i]); + } +} + From 9f10a8ff2b3b380c60f7a96094d16798ba89318e Mon Sep 17 00:00:00 2001 From: Md Shamim Ahmmed <56692841+Md-Shamim-Ahmmed@users.noreply.github.com> Date: Sun, 26 Feb 2023 07:24:42 +0600 Subject: [PATCH 007/590] add LightOJ - Number Sequence problem "LightOJ - Number Sequence" is a problem of Fibonacci Sequence. --- src/algebra/fibonacci-numbers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algebra/fibonacci-numbers.md b/src/algebra/fibonacci-numbers.md index 5dd2c074d..629f7a75f 100644 --- a/src/algebra/fibonacci-numbers.md +++ b/src/algebra/fibonacci-numbers.md @@ -232,4 +232,4 @@ We now choose two pairs of identical remainders with the smallest indices in the * [DMOJ UCLV - Numbered sequence of pencils](https://dmoj.uclv.edu.cu/problem/secnum) * [DMOJ UCLV - Fibonacci 2D](https://dmoj.uclv.edu.cu/problem/fibonacci) * [DMOJ UCLV - fibonacci calculation](https://dmoj.uclv.edu.cu/problem/fibonaccicalculatio) - +* [LightOJ - Number Sequence](https://lightoj.com/problem/number-sequence) From a4d6447253754ee75d782183ae69e061a1060ff6 Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sun, 26 Feb 2023 15:54:36 +0100 Subject: [PATCH 008/590] modernize connected component code + add description --- src/graph/search-for-connected-components.md | 73 ++++++++++---------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/src/graph/search-for-connected-components.md b/src/graph/search-for-connected-components.md index 86c4c2267..6c4c5a703 100644 --- a/src/graph/search-for-connected-components.md +++ b/src/graph/search-for-connected-components.md @@ -20,40 +20,53 @@ Given an undirected graph $G$ with $n$ nodes and $m$ edges. We are required to f ``` cpp int n; -vector g[MAXN] ; -bool used[MAXN] ; -vector comp ; +vector> adj; +vector used; +vector comp; void dfs(int v) { used[v] = true ; comp.push_back(v); - for (size_t i = 0; i < (int) g[v].size(); ++i) { - int to = g[v][i]; - if (!used[to]) - dfs(to); + for (int u : adj[v]) { + if (!used[u]) + dfs(u); } } void find_comps() { - for (int i = 0; i < n ; ++i) - used [i] = false; - for (int i = 0; i < n ; ++i) + fill(used.begin(), used.end(), 0); + for (int v = 0; v < n; ++v) { if (!used[i]) { comp.clear(); dfs(i); - cout << "Component:" ; - for (size_t j = 0; j < comp.size(); ++j) - cout << ' ' << comp[j]; + cout << "Component:" ; + for (int u : comp) + cout << ' ' << u; cout << endl ; } + } } ``` +* The most important function that is used is `find_comps()` which finds and displays connected components of the graph. + +* The graph is stored in adjacency list representation, i.e `adj[v]` contains a list of vertices that have edges from the vertex `v`. + +* Vector `comp` contains a list of nodes in the current connected component. + ## Iterative implementation of the code -``` cpp + +Deeply recursive functions are in general bad. +Ever single recursive call will require a little bit of memory in the stack, and per default programs only have a limited amount of stack space. +So when you do a recursive DFS over a connected graph with millions of nodes, you might run into stack overflows. + +It is always possible to translate a recursive program into an iterative program, by manually maintaining a stack data structure. +Since this data structure is allocated on the heap, no stack overflow will occur. + +```cpp int n; -vector g[MAXN]; -bool used[MAXN]; +vector> adj; +vector used; vector comp; void dfs(int v) { @@ -66,38 +79,28 @@ void dfs(int v) { if (!used[curr]) { used[curr] = true; comp.push_back(curr); - for (int i = g[curr].size() - 1; i >= 0; i--) { - int to = g[curr][i]; - st.push(to); + for (int i = adj[curr].size() - 1; i >= 0; i--) { + st.push(adj[curr][i]); } } } } void find_comps() { - for (int i = 0; i < n ; ++i) - used [i] = false; - for (int i = 0; i < n ; ++i) - if (!used[i]) { + fill(used.begin(), used.end(), 0); + for (int v = 0; v < n ; ++v) { + if (!used[v]) { comp.clear(); - dfs(i); + dfs(v); cout << "Component:" ; - for (size_t j = 0; j < comp.size(); ++j) - cout << ' ' << comp[j]; + for (int u : comp) + cout << ' ' << u; cout << endl ; } + } } - ``` - - -* The most important function that is used is `find_comps()` which finds and displays connected components of the graph. - -* The graph is stored in adjacency list representation, i.e `g[i]` contains a list of vertices that have edges from the vertex `i`. The constant `MAXN` should be set equal to the maximum possible number of vertices in the graph. - -* Vector `comp` contains a list of nodes in the current connected component. - ## Practice Problems - [SPOJ: CCOMPS](http://www.spoj.com/problems/CCOMPS/) - [SPOJ: CT23E](http://www.spoj.com/problems/CT23E/) From 1260771f9ec117d1049e44e9bbd073692b3d2b8e Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sun, 26 Feb 2023 16:26:29 +0100 Subject: [PATCH 009/590] add linear construction for fenwick tree closes #1043 --- src/data_structures/fenwick.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/data_structures/fenwick.md b/src/data_structures/fenwick.md index c67044d87..01a49040b 100644 --- a/src/data_structures/fenwick.md +++ b/src/data_structures/fenwick.md @@ -148,7 +148,7 @@ struct FenwickTree { bit.assign(n, 0); } - FenwickTree(vector a) : FenwickTree(a.size()) { + FenwickTree(vector const &a) : FenwickTree(a.size()) { for (size_t i = 0; i < a.size(); i++) add(i, a[i]); } @@ -171,6 +171,24 @@ struct FenwickTree { }; ``` +### Linear construction + +The above implementation requires $O(N \log N)$ time. +It's possible to improve that to $O(N)$ time. + +The idea is, that the number $a[i]$ at index $i$ will contribute to the range stored in $bit[i]$, and to all ranges that the index $i | (i + 1)$ contributes to. +So by adding the numbers in order, you only have to push the current sum further to the next range, where it will then get pushed further to the next range, and so on. + +```cpp +FenwickTree(vector const &a) : FenwickTree(a.size()){ + for (int i = 0; i < n; i++) { + bit[i] += a[i]; + int r = i | (i + 1); + if (r < n) bit[r] += bit[i]; + } +} +``` + ### Finding minimum of $[0, r]$ in one-dimensional array { data-toc-label='Finding minimum of in one-dimensional array' } It is obvious that there is no easy way of finding minimum of range $[l, r]$ using Fenwick tree, as Fenwick tree can only answer queries of type $[0, r]$. From dc9f2d1c75d040bc3ff7f5692a4464f1e3b14986 Mon Sep 17 00:00:00 2001 From: Hoang Ho <40765474+nhuhoang0701@users.noreply.github.com> Date: Sat, 11 Mar 2023 00:41:31 +0100 Subject: [PATCH 010/590] Fix wrong variable names in connected components Variable in the loop in the code for search connected components is supposed to be v, not i --- src/graph/search-for-connected-components.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/graph/search-for-connected-components.md b/src/graph/search-for-connected-components.md index 6c4c5a703..2c61dfaa6 100644 --- a/src/graph/search-for-connected-components.md +++ b/src/graph/search-for-connected-components.md @@ -36,9 +36,9 @@ void dfs(int v) { void find_comps() { fill(used.begin(), used.end(), 0); for (int v = 0; v < n; ++v) { - if (!used[i]) { + if (!used[v]) { comp.clear(); - dfs(i); + dfs(v); cout << "Component:" ; for (int u : comp) cout << ' ' << u; From f2572d2276126c20f3929dced6a01c9ae4523b1d Mon Sep 17 00:00:00 2001 From: SiddharthEEE <99067988+SiddharthEEE@users.noreply.github.com> Date: Fri, 10 Mar 2023 11:35:39 +0530 Subject: [PATCH 011/590] Update sparse-table.md --- src/data_structures/sparse-table.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/data_structures/sparse-table.md b/src/data_structures/sparse-table.md index 79532439f..18372c01c 100644 --- a/src/data_structures/sparse-table.md +++ b/src/data_structures/sparse-table.md @@ -173,3 +173,4 @@ Another one would be the [Sqrt Tree](sqrt-tree.md). * [Codeforces - Map](http://codeforces.com/contest/15/problem/D) * [Codeforces - Awards for Contestants](http://codeforces.com/contest/873/problem/E) * [Codeforces - Longest Regular Bracket Sequence](http://codeforces.com/contest/5/problem/C) +* [Codeforces - Array Stabilization (GCD version)](http://codeforces.com/problemset/problem/1547/F) From b3184faf76da13a76ce7e4d5a249d21dffa678f0 Mon Sep 17 00:00:00 2001 From: Md Shamim Ahmmed <56692841+Md-Shamim-Ahmmed@users.noreply.github.com> Date: Tue, 28 Feb 2023 14:36:58 +0600 Subject: [PATCH 012/590] added some Codeforces Fibonacci Problems --- src/algebra/fibonacci-numbers.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/algebra/fibonacci-numbers.md b/src/algebra/fibonacci-numbers.md index 629f7a75f..a526c111e 100644 --- a/src/algebra/fibonacci-numbers.md +++ b/src/algebra/fibonacci-numbers.md @@ -233,3 +233,7 @@ We now choose two pairs of identical remainders with the smallest indices in the * [DMOJ UCLV - Fibonacci 2D](https://dmoj.uclv.edu.cu/problem/fibonacci) * [DMOJ UCLV - fibonacci calculation](https://dmoj.uclv.edu.cu/problem/fibonaccicalculatio) * [LightOJ - Number Sequence](https://lightoj.com/problem/number-sequence) +* [Codeforces - C. Fibonacci](https://codeforces.com/problemset/gymProblem/102644/C) +* [Codeforces - A. Hexadecimal's theorem](https://codeforces.com/problemset/problem/199/A) +* [Codeforces - B. Blackboard Fibonacci](https://codeforces.com/problemset/problem/217/B) +* [Codeforces - E. Fibonacci Number](https://codeforces.com/problemset/problem/193/E) From a5d0a224a3920b116e098f8ac8f9a5e4980e7ae2 Mon Sep 17 00:00:00 2001 From: SiddharthEEE <99067988+SiddharthEEE@users.noreply.github.com> Date: Sat, 11 Mar 2023 10:12:58 +0530 Subject: [PATCH 013/590] Update phi-function.md --- src/algebra/phi-function.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/algebra/phi-function.md b/src/algebra/phi-function.md index be823cfb0..ac92ea4c1 100644 --- a/src/algebra/phi-function.md +++ b/src/algebra/phi-function.md @@ -200,3 +200,4 @@ $$ x^n \equiv x^{\phi(m)} x^{(n - \phi(m)) \bmod \phi(m)} \bmod m \equiv x^{\phi * [Codeforces - Power Tower](http://codeforces.com/problemset/problem/906/D) * [Kattis - Exponial](https://open.kattis.com/problems/exponial) * [LeetCode - 372. Super Pow](https://leetcode.com/problems/super-pow/) +* [Codeforces - The Holmes Children](http://codeforces.com/problemset/problem/776/E) From 50ad170e37a0e8ed7ab9a79571a2544819ad2190 Mon Sep 17 00:00:00 2001 From: SiddharthEEE <99067988+SiddharthEEE@users.noreply.github.com> Date: Sat, 11 Mar 2023 10:19:35 +0530 Subject: [PATCH 014/590] Update binomial-coefficients.md --- src/combinatorics/binomial-coefficients.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/combinatorics/binomial-coefficients.md b/src/combinatorics/binomial-coefficients.md index 382e16b06..dd27dc3eb 100644 --- a/src/combinatorics/binomial-coefficients.md +++ b/src/combinatorics/binomial-coefficients.md @@ -230,6 +230,7 @@ When $m$ is not square-free, a [generalization of Lucas's theorem for prime powe * [Codeforces - Points, Lines and Ready-made Titles](http://codeforces.com/contest/872/problem/E) * [SPOJ - The Ultimate Riddle](https://www.spoj.com/problems/DCEPC13D/) * [CodeChef - Long Sandwich](https://www.codechef.com/MAY17/problems/SANDWICH/) +* [Codeforces - Placing Jinas](https://codeforces.com/problemset/problem/1696/E) ## References * [Blog fishi.devtail.io](https://fishi.devtail.io/weblog/2015/06/25/computing-large-binomial-coefficients-modulo-prime-non-prime/) From e5ed999fd013267679746976a2f63bda1bd86944 Mon Sep 17 00:00:00 2001 From: SiddharthEEE <99067988+SiddharthEEE@users.noreply.github.com> Date: Sat, 11 Mar 2023 10:24:16 +0530 Subject: [PATCH 015/590] Update inclusion-exclusion.md --- src/combinatorics/inclusion-exclusion.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/combinatorics/inclusion-exclusion.md b/src/combinatorics/inclusion-exclusion.md index cb96ba96d..6abb8aa43 100644 --- a/src/combinatorics/inclusion-exclusion.md +++ b/src/combinatorics/inclusion-exclusion.md @@ -451,3 +451,4 @@ A list of tasks that can be solved using the principle of inclusions-exclusions: * [SPOJ - EASY MATH [difficulty: medium]](http://www.spoj.com/problems/EASYMATH/) * [SPOJ - MOMOS - FEASTOFPIGS [difficulty: easy]](https://www.spoj.com/problems/MOMOS/) * [Atcoder - Grid 2 [difficulty: easy]](https://atcoder.jp/contests/dp/tasks/dp_y/) +* [Codeforces - Count GCD](https://codeforces.com/contest/1750/problem/D) From cf3f3a7999ce1eeb0d89fe0703d735aff0573327 Mon Sep 17 00:00:00 2001 From: Deji Oyerinde Date: Fri, 17 Mar 2023 03:37:02 -0400 Subject: [PATCH 016/590] Update binomial-coefficients.md Spacing for `C++ Implementation` in two instances. I just moved the phrase "C++ Implementation" to a new line for better readability. --- src/combinatorics/binomial-coefficients.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/combinatorics/binomial-coefficients.md b/src/combinatorics/binomial-coefficients.md index 382e16b06..242325714 100644 --- a/src/combinatorics/binomial-coefficients.md +++ b/src/combinatorics/binomial-coefficients.md @@ -85,7 +85,9 @@ int C(int n, int k) { ### Improved implementation -Note that in the above implementation numerator and denominator have the same number of factors ($k$), each of which is greater than or equal to 1. Therefore, we can replace our fraction with a product $k$ fractions, each of which is real-valued. However, on each step after multiplying current answer by each of the next fractions the answer will still be integer (this follows from the property of factoring in). C++ implementation: +Note that in the above implementation numerator and denominator have the same number of factors ($k$), each of which is greater than or equal to 1. Therefore, we can replace our fraction with a product $k$ fractions, each of which is real-valued. However, on each step after multiplying current answer by each of the next fractions the answer will still be integer (this follows from the property of factoring in). + +C++ implementation: ```cpp int C(int n, int k) { @@ -101,6 +103,7 @@ Here we carefully cast the floating point number to an integer, taking into acco ### Pascal's Triangle By using the recurrence relation we can construct a table of binomial coefficients (Pascal's triangle) and take the result from it. The advantage of this method is that intermediate results never exceed the answer and calculating each new table element requires only one addition. The flaw is slow execution for large $n$ and $k$ if you just need a single value and not the whole table (because in order to calculate $\binom n k$ you will need to build a table of all $\binom i j, 1 \le i \le n, 1 \le j \le n$, or at least to $1 \le j \le \min (i, 2k)$). The time complexity can be considered to be $\mathcal{O}(n^2)$. + C++ implementation: ```cpp From 15816f223ffd6891307f517edcea6993404edd01 Mon Sep 17 00:00:00 2001 From: Deji Oyerinde Date: Fri, 17 Mar 2023 03:49:49 -0400 Subject: [PATCH 017/590] Update main_lorentz.md Added a wikipedia link to the master theorem mentioned in the article. I think this is a good choice since the article just uses the result of the theorem for analysis. --- src/string/main_lorentz.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string/main_lorentz.md b/src/string/main_lorentz.md index 2552b9739..c79071dba 100644 --- a/src/string/main_lorentz.md +++ b/src/string/main_lorentz.md @@ -74,7 +74,7 @@ The algorithm finds all repetitions starting in the first half and ending in the This is the essential part of the Main-Lorentz algorithm, and we will discuss it in detail here. The complexity of divide-and-conquer algorithms is well researched. -The master theorem says, that we will end up with an $O(n \log n)$ algorithm, if we can compute the crossing repetitions in $O(n)$ time. +The [master theorem](https://en.wikipedia.org/wiki/Master_theorem_(analysis_of_algorithms)) says, that we will end up with an $O(n \log n)$ algorithm, if we can compute the crossing repetitions in $O(n)$ time. ### Search for crossing repetitions From 543fe351ae3a00307efb70e3aa542069089bd235 Mon Sep 17 00:00:00 2001 From: Michael Hayter Date: Fri, 24 Mar 2023 03:56:46 -0400 Subject: [PATCH 018/590] Update suffix-automaton.md ".length" does not work as the attribute is ".len". Code now compiles and runs. --- src/string/suffix-automaton.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string/suffix-automaton.md b/src/string/suffix-automaton.md index 1fcb07bc4..2ae0771c4 100644 --- a/src/string/suffix-automaton.md +++ b/src/string/suffix-automaton.md @@ -702,7 +702,7 @@ string lcs (string S, string T) { for (int i = 0; i < T.size(); i++) { while (v && !st[v].next.count(T[i])) { v = st[v].link ; - l = st[v].length ; + l = st[v].len; } if (st[v].next.count(T[i])) { v = st [v].next[T[i]]; From 749698bafec9decd3ce0b0dad1cdcee44adf6553 Mon Sep 17 00:00:00 2001 From: Carlos Javier Blanco Date: Tue, 28 Mar 2023 21:54:24 -0500 Subject: [PATCH 019/590] Update and rename all-submasks.md to bit manipulation.md Extending the article, adding the use of bit operators and bit tricks. Plus a bit-on-count algorithm. Changing the name to Bit Manipulation. --- src/algebra/all-submasks.md | 79 ------------ src/algebra/bit manipulation.md | 214 ++++++++++++++++++++++++++++++++ 2 files changed, 214 insertions(+), 79 deletions(-) delete mode 100644 src/algebra/all-submasks.md create mode 100644 src/algebra/bit manipulation.md diff --git a/src/algebra/all-submasks.md b/src/algebra/all-submasks.md deleted file mode 100644 index 9169d23d4..000000000 --- a/src/algebra/all-submasks.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -tags: - - Translated -e_maxx_link: all_submasks ---- - -# Submask Enumeration - -## Enumerating all submasks of a given mask - -Given a bitmask $m$, you want to efficiently iterate through all of its submasks, that is, masks $s$ in which only bits that were included in mask $m$ are set. - -Consider the implementation of this algorithm, based on tricks with bit operations: - -```cpp -int s = m; -while (s > 0) { - ... you can use s ... - s = (s-1) & m; -} -``` - -or, using a more compact `for` statement: - -```cpp -for (int s=m; s; s=(s-1)&m) - ... you can use s ... -``` - -In both variants of the code, the submask equal to zero will not be processed. We can either process it outside the loop, or use a less elegant design, for example: - -```cpp -for (int s=m; ; s=(s-1)&m) { - ... you can use s ... - if (s==0) break; -} -``` - -Let us examine why the above code visits all submasks of $m$, without repetition, and in descending order. - -Suppose we have a current bitmask $s$, and we want to move on to the next bitmask. By subtracting from the mask $s$ one unit, we will remove the rightmost set bit and all bits to the right of it will become 1. Then we remove all the "extra" one bits that are not included in the mask $m$ and therefore can't be a part of a submask. We do this removal by using the bitwise operation `(s-1) & m`. As a result, we "cut" mask $s-1$ to determine the highest value that it can take, that is, the next submask after $s$ in descending order. - -Thus, this algorithm generates all submasks of this mask in descending order, performing only two operations per iteration. - -A special case is when $s = 0$. After executing $s-1$ we get a mask where all bits are set (bit representation of -1), and after `(s-1) & m` we will have that $s$ will be equal to $m$. Therefore, with the mask $s = 0$ be careful — if the loop does not end at zero, the algorithm may enter an infinite loop. - -## Iterating through all masks with their submasks. Complexity $O(3^n)$ - -In many problems, especially those that use bitmask dynamic programming, you want to iterate through all bitmasks and for each mask, iterate through all of its submasks: - -```cpp -for (int m=0; m<(1<>** One bit to the right. Which would be the same as a division by a power of two. + +**<<** One bit to the left. And this would be a multiplication, equally by a power of two. + +Let's see an example. + +Let's say we have a number $N$, which. $N = 4$. + +The binary representation of **4** is: + +$4_2 = 100$ + +If we shift one bit to the left, then we would be adding a bit to the end, in this case a 0. + +$4_2 << 1 = 100 << 1 = 1000$ + +$1000 = 8_2$ and clearly, $4 * 2 = 8$ + +So, for a division by two, it would be exactly the same, but using the operator $<<$. + +$4_2 >> 1 = 100 >> 1 = 10$ + +In this case, we would remove one bit from the end, this is what is called the **least significant bit**, the rightmost bit of the representation. + +Of course, the **most significant bit** is the leftmost bit. + +And then, how could it carry out operations with other powers, greater than two? + +Easy, you just have to remember the exponent of two, to create said power. In other words: + +$4 = 2 ^ 2$, so to do multiplication or division operations with **4**, we must move **2 bits**. + +$8 = 2 ^ 3$, so for **8** it would be **3 bits**. *And so on*. + + +* ## Bitwise operators. + + * **&** : The bitwise AND operator compares each bit of its first operand with the corresponding bit of its second operand. If both bits are 1, the corresponding result bit is set to 1. Otherwise, the corresponding result bit is set to 0. + + * **|** : The bitwise inclusive OR operator compares each bit of its first operand with the corresponding bit of its second operand. If one of the two bits is 1, the corresponding result bit is set to 1. Otherwise, the corresponding result bit is set to 0. + + * **^** : The bitwise exclusive OR (XOR) operator compares each bit of its first operand with the corresponding bit of its second operand. If one bit is 0 and the other bit is 1, the corresponding result bit is set to 1. Otherwise, the corresponding result bit is set to 0. + +Examples: + +``` + 11111111 11110000 +& 00000000 01100011 + _________________ + 00000000 01100000 +``` + +``` + 11111111 11110000 +| 00000000 01100011 + _________________ + 11111111 11110011 +``` + +``` + 11111111 11110000 +^ 00000000 01100011 + _________________ + 11111111 10010011 +``` + +# Useful tricks. + +## Check if a bit is on (to one) + +The bit's value can be obtained by shifting the number to the right x times and then bit AND ( & ) on it: + +``` cpp +bool check(int number, int bit) { + return ((number >> bit) & 1); +} +``` + +## Change the state of a bit n to x + +``` cpp +number ^= (-x ^ number) & (1 << n); +``` + +## Even or Odd + +Function to know if a number is even or odd. + +True if number is odd, false for number is even. + +``` cpp +bool check(int number) { + return (number & 1); +} +``` + +## Check if an integer is a power of 2 + +``` cpp +bool powerTwo = n && !(n & (n - 1)); +``` + +## Brian Kernighan's algorithm. + +The idea is to consider only the set bits of an integer by turning off its rightmost set bit (after counting it), so the next iteration of the loop considers the Next Rightmost bit. + +The expression **n & (n-1)** can be used to turn off the rightmost set bit of a number **n**. This works like the expression **n-1** flips all bits after the rightmost set bit of n, including the rightmost set bit. Therefore, **n & (n-1)** returns the last flipped bit of **n**. + +``` cpp +int countSetBits(int n) +{ + int count = 0; + + while (n) + { + n = n & (n - 1); + count++; + } + + return count; +} +``` + +# Submask Enumeration + +## Enumerating all submasks of a given mask + +Given a bitmask $m$, you want to efficiently iterate through all of its submasks, that is, masks $s$ in which only bits that were included in mask $m$ are set. + +Consider the implementation of this algorithm, based on tricks with bit operations: + +```cpp +int s = m; +while (s > 0) { + ... you can use s ... + s = (s-1) & m; +} +``` + +or, using a more compact `for` statement: + +```cpp +for (int s=m; s; s=(s-1)&m) + ... you can use s ... +``` + +In both variants of the code, the submask equal to zero will not be processed. We can either process it outside the loop, or use a less elegant design, for example: + +```cpp +for (int s=m; ; s=(s-1)&m) { + ... you can use s ... + if (s==0) break; +} +``` + +Let us examine why the above code visits all submasks of $m$, without repetition, and in descending order. + +Suppose we have a current bitmask $s$, and we want to move on to the next bitmask. By subtracting from the mask $s$ one unit, we will remove the rightmost set bit and all bits to the right of it will become 1. Then we remove all the "extra" one bits that are not included in the mask $m$ and therefore can't be a part of a submask. We do this removal by using the bitwise operation `(s-1) & m`. As a result, we "cut" mask $s-1$ to determine the highest value that it can take, that is, the next submask after $s$ in descending order. + +Thus, this algorithm generates all submasks of this mask in descending order, performing only two operations per iteration. + +A special case is when $s = 0$. After executing $s-1$ we get a mask where all bits are set (bit representation of -1), and after `(s-1) & m` we will have that $s$ will be equal to $m$. Therefore, with the mask $s = 0$ be careful — if the loop does not end at zero, the algorithm may enter an infinite loop. + +## Iterating through all masks with their submasks. Complexity $O(3^n)$ + +In many problems, especially those that use bitmask dynamic programming, you want to iterate through all bitmasks and for each mask, iterate through all of its submasks: + +```cpp +for (int m=0; m<(1< Date: Thu, 30 Mar 2023 19:56:00 -0500 Subject: [PATCH 020/590] Update navigation.md Add bit-manipulation.md to the navigation menu. --- src/navigation.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/navigation.md b/src/navigation.md index f080f1dcc..b37bab725 100644 --- a/src/navigation.md +++ b/src/navigation.md @@ -39,6 +39,7 @@ search: - [Balanced Ternary](algebra/balanced-ternary.md) - [Gray code](algebra/gray-code.md) - Miscellaneous + - [Bit manipulation](algebra/bit-manipulation.md) - [Enumerating submasks of a bitmask](algebra/all-submasks.md) - [Arbitrary-Precision Arithmetic](algebra/big-integer.md) - [Fast Fourier transform](algebra/fft.md) From 5eb9a386a32514a750dc92755c2cb5fcaaf04328 Mon Sep 17 00:00:00 2001 From: Carlos Javier Blanco Date: Thu, 30 Mar 2023 21:53:20 -0500 Subject: [PATCH 021/590] Create bit-manipulation.md --- src/algebra/bit-manipulation.md | 184 ++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 src/algebra/bit-manipulation.md diff --git a/src/algebra/bit-manipulation.md b/src/algebra/bit-manipulation.md new file mode 100644 index 000000000..d3215a302 --- /dev/null +++ b/src/algebra/bit-manipulation.md @@ -0,0 +1,184 @@ +# Binary number + +A **binary number** is a number expressed in the base-2 numeral system or binary numeral system, a method of mathematical expression which uses only two symbols: typically "0" (zero) and "1" (one). + +We are talking about a numerical system of great importance in technological development. Among some of the most outstanding applications are the representation of images and texts, in the field of electronics. With the combination of zeros and ones, any number can be represented on a decimal basis, making communication with electronic devices easier for humans. In addition to translating the different programming languages, to a common language where the computer understands. + +**In this article I will not talk about how to convert to binary or decimal. There is a lot of information all over the internet on the subject.** + +# Bit manipulation + +When finding solutions to problems, a very important factor is the simplicity and the execution time. Now, in this bitwise operations are very important and you can take advantage of them. + +# Bit operators + +## Bit shift operators +### Multiplication and division by powers of 2 + +There are two operators for shifting bits. + +$\gg$ One bit to the right. Which would be the same as a division by a power of two. + +$\ll$ One bit to the left. And this would be a multiplication, equally by a power of two. + +Let's see an example. + +Let's say we have a number $N$, which. $N = 4$. + +The binary representation of $4$ is: + +$4 = 100_2$ + +If we shift one bit to the left, then we would be adding a bit to the end, in this case a 0. + +$4 \ll 1 = 100_2 \ll 1 = 1000_2$ + +$1000_2 = 8$ and clearly, $4 * 2 = 8$ + +So, for a division by two, it would be exactly the same, but using the operator $<<$. + +$4 \gg 1 = 100_2 \gg 1 = 10_2$ + +In this case, we would remove one bit from the end, this is what is called the **least significant bit**, the rightmost bit of the representation. + +Of course, the **most significant bit** is the leftmost bit. + +And then, how could it carry out operations with other powers, greater than two? + +Easy, you just have to remember the exponent of two, to create said power. In other words: + +$4 = 2 ^ 2$, so to do multiplication or division operations with **4**, we must move **2 bits**. + +$8 = 2 ^ 3$, so for $8$ it would be **3 bits**. *And so on*. + + +## Bitwise operators. + +``` +& : The bitwise AND operator compares each bit of its first operand with the corresponding bit of its second operand. + If both bits are 1, the corresponding result bit is set to 1. Otherwise, the corresponding result bit is set to 0. + +| : The bitwise inclusive OR operator compares each bit of its first operand with the corresponding bit of its second operand. + If one of the two bits is 1, the corresponding result bit is set to 1. Otherwise, the corresponding result bit is set to 0. + +^ : The bitwise exclusive OR (XOR) operator compares each bit of its first operand with the corresponding bit of its second operand. + If one bit is 0 and the other bit is 1, the corresponding result bit is set to 1. Otherwise, the corresponding result bit is set to 0. +``` + +Examples: + +``` +n = 01011000 +n-1 = 01010111 +-------------------- +n & (n-1) = 01010000 +``` + +``` +n = 01011000 +n-1 = 01010111 +-------------------- +n | (n-1) = 01011111 +``` + +``` +n = 01011000 +n-1 = 01010111 +-------------------- +n ^ (n-1) = 00001111 +``` + +# Useful tricks. + +## A bit is set (1) or cleared (0) + +The value of the $x$-th bit can be by shifting the number $x$ positions to the right, the $x$-th bit is the units place, therefore we can extract it by performing a bitwise & with 1 + +``` cpp +bool check(int number, int x) { + return ((number >> x) & 1); +} +``` + +## Parity of a number + +Function to know if a number is even or odd. + +True if number is odd, false for number is even. + +``` cpp +bool check(int number) { + return (number & 1); +} +``` + +## Check if an integer is a power of 2 + +``` cpp +bool powerTwo = n && !(n & (n - 1)); +``` + +## Clear the most-right set bit + +The expression **n & (n-1)** can be used to turn off the rightmost set bit of a number **n**. This works like the expression **n-1** flips all bits after the rightmost set bit of n, including the rightmost set bit. Therefore, **n & (n-1)** returns the last flipped bit of **n**. + +For example, consider the number 52, which is 00110100 in binary, and has a total set of 3 bits. + +``` +1st iteration of the loop: n = 52 + +00110100 & (n) +00110011 (n-1) +~~~~~~~~ +00110000 +``` + +``` +2nd iteration of the loop: n = 48 + +00110000 & (n) +00101111 (n-1) +~~~~~~~~ +00100000 +``` + +``` +3rd iteration of the loop: n = 32 + +00100000 & (n) +00011111 (n-1) +~~~~~~~~ +00000000 (n = 0) +``` + +## Brian Kernighan's algorithm. + +We can count the number of bits set with the above expression. + +The idea is to consider only the set bits of an integer by turning off its rightmost set bit (after counting it), so the next iteration of the loop considers the Next Rightmost bit. + +``` cpp +int countSetBits(int n) +{ + int count = 0; + + while (n) + { + n = n & (n - 1); + count++; + } + + return count; +} +``` + +Additionally, there are also predefined functions in C++, to count the number of bits in a representation. + +1. ```__builtin_popcount(number)``` number of bits set. +2. ```__builtin_ctz(number)``` number of bits cleared. + +## Practice Problems + +* [Codeforces - Raising Bacteria](https://codeforces.com/problemset/problem/579/A) +* [Codeforces - Fedor and New Game](https://codeforces.com/problemset/problem/467/B) +* [Codeforces - And Then There Were K](https://codeforces.com/problemset/problem/1527/A) From 320a94c8951df32a02ec746523d450d3c8131c1e Mon Sep 17 00:00:00 2001 From: sundaram123krishnan Date: Fri, 14 Apr 2023 18:07:57 +0530 Subject: [PATCH 022/590] added congruence symbol to linear_congruence_equation --- src/algebra/linear_congruence_equation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/algebra/linear_congruence_equation.md b/src/algebra/linear_congruence_equation.md index 520bf65e6..425fef965 100644 --- a/src/algebra/linear_congruence_equation.md +++ b/src/algebra/linear_congruence_equation.md @@ -8,7 +8,7 @@ e_maxx_link: diofant_1_equation This equation is of the form: -$$a \cdot x = b \pmod n,$$ +$$a \cdot x \equiv b \pmod n,$$ where $a$, $b$ and $n$ are given integers and $x$ is an unknown integer. @@ -30,7 +30,7 @@ Then, if $b$ is not divisible by $g$, there is no solution. In fact, for any $x$ If $g$ divides $b$, then by dividing both sides of the equation by $g$ (i.e. dividing $a$, $b$ and $n$ by $g$), we receive a new equation: -$$a^\prime \cdot x = b^\prime \pmod{n^\prime}$$ +$$a^\prime \cdot x \equiv b^\prime \pmod{n^\prime}$$ in which $a^\prime$ and $n^\prime$ are already relatively prime, and we have already learned how to handle such an equation. We get $x^\prime$ as solution for $x$. From a2a8b2f78dd374472a46710e4b404122f4b57e41 Mon Sep 17 00:00:00 2001 From: sundaram123krishnan Date: Fri, 14 Apr 2023 19:06:47 +0530 Subject: [PATCH 023/590] replaced more equal symbols with congruence symbols. --- src/algebra/linear_congruence_equation.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/algebra/linear_congruence_equation.md b/src/algebra/linear_congruence_equation.md index 425fef965..6826e1a0c 100644 --- a/src/algebra/linear_congruence_equation.md +++ b/src/algebra/linear_congruence_equation.md @@ -16,15 +16,15 @@ It is required to find the value $x$ from the interval $[0, n-1]$ (clearly, on t ## Solution by finding the inverse element -Let us first consider a simpler case where $a$ and $n$ are **coprime** ($\gcd(a, n) = 1$). +Let us first consider a simpler case where $a$ and $n$ are **coprime** ($\gcd(a, n) \equiv 1$). Then one can find the [inverse](module-inverse.md) of $a$, and multiplying both sides of the equation with the inverse, and we can get a **unique** solution. -$$x = b \cdot a ^ {- 1} \pmod n$$ +$$x \equiv b \cdot a ^ {- 1} \pmod n$$ Now consider the case where $a$ and $n$ are **not coprime** ($\gcd(a, n) \ne 1$). -Then the solution will not always exist (for example $2 \cdot x = 1 \pmod 4$ has no solution). +Then the solution will not always exist (for example $2 \cdot x \equiv 1 \pmod 4$ has no solution). -Let $g = \gcd(a, n)$, i.e. the [greatest common divisor](euclid-algorithm.md) of $a$ and $n$ (which in this case is greater than one). +Let $g \equiv \gcd(a, n)$, i.e. the [greatest common divisor](euclid-algorithm.md) of $a$ and $n$ (which in this case is greater than one). Then, if $b$ is not divisible by $g$, there is no solution. In fact, for any $x$ the left side of the equation $a \cdot x \pmod n$ , is always divisible by $g$, while the right-hand side is not divisible by it, hence it follows that there are no solutions. @@ -39,15 +39,15 @@ It is clear that this $x^\prime$ will also be a solution of the original equatio However it will **not be the only solution**. It can be shown that the original equation has exactly $g$ solutions, and they will look like this: -$$x_i = (x^\prime + i\cdot n^\prime) \pmod n \quad \text{for } i = 0 \ldots g-1$$ +$$x_i = (x^\prime + i\cdot n^\prime) \pmod n \quad \text{for } i \equiv 0 \ldots g-1$$ -Summarizing, we can say that the **number of solutions** of the linear congruence equation is equal to either $g = \gcd(a, n)$ or to zero. +Summarizing, we can say that the **number of solutions** of the linear congruence equation is equal to either $g \equiv \gcd(a, n)$ or to zero. ## Solution with the Extended Euclidean Algorithm We can rewrite the linear congruence to the following Diophantine equation: -$$a \cdot x + n \cdot k = b,$$ +$$a \cdot x + n \cdot k \equiv b,$$ where $x$ and $k$ are unknown integers. From 4edfa87e4cb7ba2962302b0eb6d45673e17255c0 Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Fri, 14 Apr 2023 15:44:57 +0200 Subject: [PATCH 024/590] equiv only for \pmod --- src/algebra/linear_congruence_equation.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/algebra/linear_congruence_equation.md b/src/algebra/linear_congruence_equation.md index 6826e1a0c..89c598429 100644 --- a/src/algebra/linear_congruence_equation.md +++ b/src/algebra/linear_congruence_equation.md @@ -16,7 +16,7 @@ It is required to find the value $x$ from the interval $[0, n-1]$ (clearly, on t ## Solution by finding the inverse element -Let us first consider a simpler case where $a$ and $n$ are **coprime** ($\gcd(a, n) \equiv 1$). +Let us first consider a simpler case where $a$ and $n$ are **coprime** ($\gcd(a, n) = 1$). Then one can find the [inverse](module-inverse.md) of $a$, and multiplying both sides of the equation with the inverse, and we can get a **unique** solution. $$x \equiv b \cdot a ^ {- 1} \pmod n$$ @@ -24,7 +24,7 @@ $$x \equiv b \cdot a ^ {- 1} \pmod n$$ Now consider the case where $a$ and $n$ are **not coprime** ($\gcd(a, n) \ne 1$). Then the solution will not always exist (for example $2 \cdot x \equiv 1 \pmod 4$ has no solution). -Let $g \equiv \gcd(a, n)$, i.e. the [greatest common divisor](euclid-algorithm.md) of $a$ and $n$ (which in this case is greater than one). +Let $g = \gcd(a, n)$, i.e. the [greatest common divisor](euclid-algorithm.md) of $a$ and $n$ (which in this case is greater than one). Then, if $b$ is not divisible by $g$, there is no solution. In fact, for any $x$ the left side of the equation $a \cdot x \pmod n$ , is always divisible by $g$, while the right-hand side is not divisible by it, hence it follows that there are no solutions. @@ -39,15 +39,15 @@ It is clear that this $x^\prime$ will also be a solution of the original equatio However it will **not be the only solution**. It can be shown that the original equation has exactly $g$ solutions, and they will look like this: -$$x_i = (x^\prime + i\cdot n^\prime) \pmod n \quad \text{for } i \equiv 0 \ldots g-1$$ +$$x_i = (x^\prime + i\cdot n^\prime) \pmod n \quad \text{for } i = 0 \ldots g-1$$ -Summarizing, we can say that the **number of solutions** of the linear congruence equation is equal to either $g \equiv \gcd(a, n)$ or to zero. +Summarizing, we can say that the **number of solutions** of the linear congruence equation is equal to either $g = \gcd(a, n)$ or to zero. ## Solution with the Extended Euclidean Algorithm We can rewrite the linear congruence to the following Diophantine equation: -$$a \cdot x + n \cdot k \equiv b,$$ +$$a \cdot x + n \cdot k = b,$$ where $x$ and $k$ are unknown integers. From 97705b1eb4c193ed38a7d4471673497c4720b151 Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Fri, 14 Apr 2023 15:45:57 +0200 Subject: [PATCH 025/590] equiv for pmod --- src/algebra/linear_congruence_equation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algebra/linear_congruence_equation.md b/src/algebra/linear_congruence_equation.md index 89c598429..c663f523f 100644 --- a/src/algebra/linear_congruence_equation.md +++ b/src/algebra/linear_congruence_equation.md @@ -39,7 +39,7 @@ It is clear that this $x^\prime$ will also be a solution of the original equatio However it will **not be the only solution**. It can be shown that the original equation has exactly $g$ solutions, and they will look like this: -$$x_i = (x^\prime + i\cdot n^\prime) \pmod n \quad \text{for } i = 0 \ldots g-1$$ +$$x_i \equiv (x^\prime + i\cdot n^\prime) \pmod n \quad \text{for } i = 0 \ldots g-1$$ Summarizing, we can say that the **number of solutions** of the linear congruence equation is equal to either $g = \gcd(a, n)$ or to zero. From 833638ad3db087a5e345dba41b846336ddd14383 Mon Sep 17 00:00:00 2001 From: km6102 <35743082+km6102@users.noreply.github.com> Date: Sun, 9 Apr 2023 17:51:39 +0530 Subject: [PATCH 026/590] Update z-function.md Implementation of efficient algorithm has put variables used to store previous calculated inside for loop. It causes them to be reassigned at every iteration and previous calculated value is lost. So, it is better in declare them outside the loop in order to work this implementation correctly. --- src/string/z-function.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/string/z-function.md b/src/string/z-function.md index f1a73da96..b4caee202 100644 --- a/src/string/z-function.md +++ b/src/string/z-function.md @@ -89,7 +89,8 @@ Implementation turns out to be rather laconic: vector z_function(string s) { int n = (int) s.length(); vector z(n); - for (int i = 1, l = 0, r = 0; i < n; ++i) { + int l = 0, r = 0; + for (int i = 1; i < n; ++i) { if (i <= r) z[i] = min (r - i + 1, z[i - l]); while (i + z[i] < n && s[z[i]] == s[i + z[i]]) From 8b99a595770d9d55eb1e014d2c698835317ee3a9 Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Fri, 14 Apr 2023 17:13:09 +0200 Subject: [PATCH 027/590] use half-intervals, clearer implementation i + z[i] < n no longer needed, as s[s.size()] = 0 --- src/string/z-function.md | 66 +++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/src/string/z-function.md b/src/string/z-function.md index b4caee202..1b1c50316 100644 --- a/src/string/z-function.md +++ b/src/string/z-function.md @@ -49,19 +49,19 @@ To obtain an efficient algorithm we will compute the values of $z[i]$ in turn fr For the sake of brevity, let's call **segment matches** those substrings that coincide with a prefix of $s$. For example, the value of the desired Z-function $z[i]$ is the length of the segment match starting at position $i$ (and that ends at position $i + z[i] - 1$). -To do this, we will keep **the $[l, r]$ indices of the rightmost segment match**. That is, among all detected segments we will keep the one that ends rightmost. In a way, the index $r$ can be seen as the "boundary" to which our string $s$ has been scanned by the algorithm; everything beyond that point is not yet known. +To do this, we will keep **the $[l, r)$ indices of the rightmost segment match**. That is, among all detected segments we will keep the one that ends rightmost. In a way, the index $r$ can be seen as the "boundary" to which our string $s$ has been scanned by the algorithm; everything beyond that point is not yet known. Then, if the current index (for which we have to compute the next value of the Z-function) is $i$, we have one of two options: -* $i > r$ -- the current position is **outside** of what we have already processed. +* $i \geq r$ -- the current position is **outside** of what we have already processed. - We will then compute $z[i]$ with the **trivial algorithm** (that is, just comparing values one by one). Note that in the end, if $z[i] > 0$, we'll have to update the indices of the rightmost segment, because it's guaranteed that the new $r = i + z[i] - 1$ is better than the previous $r$. + We will then compute $z[i]$ with the **trivial algorithm** (that is, just comparing values one by one). Note that in the end, if $z[i] > 0$, we'll have to update the indices of the rightmost segment, because it's guaranteed that the new $r = i + z[i]$ is better than the previous $r$. -* $i \le r$ -- the current position is inside the current segment match $[l, r]$. +* $i < r$ -- the current position is inside the current segment match $[l, r)$. Then we can use the already calculated Z-values to "initialize" the value of $z[i]$ to something (it sure is better than "starting from zero"), maybe even some big number. - For this, we observe that the substrings $s[l \dots r]$ and $s[0 \dots r-l]$ **match**. This means that as an initial approximation for $z[i]$ we can take the value already computed for the corresponding segment $s[0 \dots r-l]$, and that is $z[i-l]$. + For this, we observe that the substrings $s[l \dots r)$ and $s[0 \dots r-l)$ **match**. This means that as an initial approximation for $z[i]$ we can take the value already computed for the corresponding segment $s[0 \dots r-l)$, and that is $z[i-l]$. However, the value $z[i-l]$ could be too large: when applied to position $i$ it could exceed the index $r$. This is not allowed because we know nothing about the characters to the right of $r$: they may differ from those required. @@ -69,11 +69,11 @@ Then, if the current index (for which we have to compute the next value of the Z $$ s = "aaaabaa" $$ - When we get to the last position ($i = 6$), the current match segment will be $[5, 6]$. Position $6$ will then match position $6 - 5 = 1$, for which the value of the Z-function is $z[1] = 3$. Obviously, we cannot initialize $z[6]$ to $3$, it would be completely incorrect. The maximum value we could initialize it to is $1$ -- because it's the largest value that doesn't bring us beyond the index $r$ of the match segment $[l, r]$. + When we get to the last position ($i = 6$), the current match segment will be $[5, 7)$. Position $6$ will then match position $6 - 5 = 1$, for which the value of the Z-function is $z[1] = 3$. Obviously, we cannot initialize $z[6]$ to $3$, it would be completely incorrect. The maximum value we could initialize it to is $1$ -- because it's the largest value that doesn't bring us beyond the index $r$ of the match segment $[l, r)$. Thus, as an **initial approximation** for $z[i]$ we can safely take: - $$ z_0[i] = \min(r - i + 1,\; z[i-l]) $$ + $$ z_0[i] = \min(r - i,\; z[i-l]) $$ After having $z[i]$ initialized to $z_0[i]$, we try to increment $z[i]$ by running the **trivial algorithm** -- because in general, after the border $r$, we cannot know if the segment will continue to match or not. @@ -83,22 +83,26 @@ The algorithm turns out to be very simple. Despite the fact that on each iterati ## Implementation -Implementation turns out to be rather laconic: +Implementation turns out to be rather concise: ```cpp vector z_function(string s) { - int n = (int) s.length(); - vector z(n); - int l = 0, r = 0; - for (int i = 1; i < n; ++i) { - if (i <= r) - z[i] = min (r - i + 1, z[i - l]); - while (i + z[i] < n && s[z[i]] == s[i + z[i]]) - ++z[i]; - if (i + z[i] - 1 > r) - l = i, r = i + z[i] - 1; + int n = s.size(); + vector z(n); + int l = 0, r = 0; + for(int i = 1; i < n; i++) { + if(i < r) { + z[i] = min(r - i, z[i - l]); } - return z; + while(s[z[i]] == s[i + z[i]]) { + z[i]++; + } + if(i + z[i] > r) { + l = i; + r = i + z[i]; + } + } + return z; } ``` @@ -106,13 +110,13 @@ vector z_function(string s) { The whole solution is given as a function which returns an array of length $n$ -- the Z-function of $s$. -Array $z$ is initially filled with zeros. The current rightmost match segment is assumed to be $[0; 0]$ (that is, a deliberately small segment which doesn't contain any $i$). +Array $z$ is initially filled with zeros. The current rightmost match segment is assumed to be $[0; 0)$ (that is, a deliberately small segment which doesn't contain any $i$). Inside the loop for $i = 1 \dots n - 1$ we first determine the initial value $z[i]$ -- it will either remain zero or be computed using the above formula. Thereafter, the trivial algorithm attempts to increase the value of $z[i]$ as much as possible. -In the end, if it's required (that is, if $i + z[i] - 1 > r$), we update the rightmost match segment $[l, r]$. +In the end, if it's required (that is, if $i + z[i] > r$), we update the rightmost match segment $[l, r)$. ## Asymptotic behavior of the algorithm @@ -126,29 +130,29 @@ We will show that **each iteration** of the `while` loop will increase the right To do that, we will consider both branches of the algorithm: -* $i > r$ +* $i \geq r$ In this case, either the `while` loop won't make any iteration (if $s[0] \ne s[i]$), or it will take a few iterations, starting at position $i$, each time moving one character to the right. After that, the right border $r$ will necessarily be updated. - So we have found that, when $i > r$, each iteration of the `while` loop increases the value of the new $r$ index. + So we have found that, when $i \geq r$, each iteration of the `while` loop increases the value of the new $r$ index. -* $i \le r$ +* $i < r$ - In this case, we initialize $z[i]$ to a certain value $z_0$ given by the above formula. Let's compare this initial value $z_0$ to the value $r - i + 1$. We will have three cases: + In this case, we initialize $z[i]$ to a certain value $z_0$ given by the above formula. Let's compare this initial value $z_0$ to the value $r - i$. We will have three cases: - * $z_0 < r - i + 1$ + * $z_0 < r - i$ We prove that in this case no iteration of the `while` loop will take place. - It's easy to prove, for example, by contradiction: if the `while` loop made at least one iteration, it would mean that initial approximation $z[i] = z_0$ was inaccurate (less than the match's actual length). But since $s[l \dots r]$ and $s[0 \dots r-l]$ are the same, this would imply that $z[i-l]$ holds the wrong value (less than it should be). + It's easy to prove, for example, by contradiction: if the `while` loop made at least one iteration, it would mean that initial approximation $z[i] = z_0$ was inaccurate (less than the match's actual length). But since $s[l \dots r)$ and $s[0 \dots r-l)$ are the same, this would imply that $z[i-l]$ holds the wrong value (less than it should be). - Thus, since $z[i-l]$ is correct and it is less than $r - i + 1$, it follows that this value coincides with the required value $z[i]$. + Thus, since $z[i-l]$ is correct and it is less than $r - i$, it follows that this value coincides with the required value $z[i]$. - * $z_0 = r - i + 1$ + * $z_0 = r - i$ - In this case, the `while` loop can make a few iterations, but each of them will lead to an increase in the value of the $r$ index because we will start comparing from $s[r+1]$, which will climb beyond the $[l, r]$ interval. + In this case, the `while` loop can make a few iterations, but each of them will lead to an increase in the value of the $r$ index because we will start comparing from $s[r]$, which will climb beyond the $[l, r)$ interval. - * $z_0 > r - i + 1$ + * $z_0 > r - i$ This option is impossible, by definition of $z_0$. From f73e8097f5cc5a9f01bbbd9b445b650081d96555 Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Fri, 14 Apr 2023 17:14:46 +0200 Subject: [PATCH 028/590] i+z[i] < n is not needed since c++11 --- src/string/z-function.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/string/z-function.md b/src/string/z-function.md index 1b1c50316..2d584bc22 100644 --- a/src/string/z-function.md +++ b/src/string/z-function.md @@ -30,11 +30,13 @@ Formal definition can be represented in the following elementary $O(n^2)$ implem ```cpp vector z_function_trivial(string s) { - int n = (int) s.length(); + int n = s.size(); vector z(n); - for (int i = 1; i < n; ++i) - while (i + z[i] < n && s[z[i]] == s[i + z[i]]) - ++z[i]; + for (int i = 1; i < n; i++) { + while (s[z[i]] == s[i + z[i]]) { + z[i]++; + } + } return z; } ``` From 8c7047101819f2b5253488842a2fce24fceb4a21 Mon Sep 17 00:00:00 2001 From: JustAnAverageGuy <68919330+JustAnAverageGuy@users.noreply.github.com> Date: Fri, 14 Apr 2023 19:06:54 +0530 Subject: [PATCH 029/590] Change "number of ... bit" to "index of ... bit" Changed "number of its leading (biggest value) non-zero bit" to "index of its leading (biggest value) non-zero bit" as latter is clearer in its intention. I believe I am not the only one who got confused by whether "number of a bit" is referring to $2^(d-1)$ (i.e. the actual value of the bit) or $d$ --- src/game_theory/sprague-grundy-nim.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game_theory/sprague-grundy-nim.md b/src/game_theory/sprague-grundy-nim.md index 2eb6232c6..99156bae2 100644 --- a/src/game_theory/sprague-grundy-nim.md +++ b/src/game_theory/sprague-grundy-nim.md @@ -85,7 +85,7 @@ If $s \neq 0$, we have to prove that there is a move leading to a state with $t * Let $s \neq 0$. Consider the binary representation of the number $s$. - Let $d$ be the number of its leading (biggest value) non-zero bit. + Let $d$ be the index of its leading (biggest value) non-zero bit. Our move will be on a pile whose size's bit number $d$ is set (it must exist, otherwise the bit wouldn't be set in $s$). We will reduce its size $x$ to $y = x \oplus s$. All bits at positions greater than $d$ in $x$ and $y$ match and bit $d$ is set in $x$ but not set in $y$. From 293858e623ebe3a6f44f1e9d8d7c964ae5c472a8 Mon Sep 17 00:00:00 2001 From: Wiktor Kuchta Date: Fri, 7 Apr 2023 21:31:37 +0200 Subject: [PATCH 030/590] Rename "implicit" to "dynamic" segment tree --- src/data_structures/segment_tree.md | 9 ++++++--- src/sequences/longest_increasing_subsequence.md | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/data_structures/segment_tree.md b/src/data_structures/segment_tree.md index 778aba3e3..cd1be608b 100644 --- a/src/data_structures/segment_tree.md +++ b/src/data_structures/segment_tree.md @@ -1126,11 +1126,14 @@ It is easy to generate lookup tables (e.g. using $\text{map}$), that convert a v -### Implicit segment tree +### Dynamic segment tree + +(Called so because its shape is dynamic and the nodes are usually dynamically allocated. +Also known as _implicit segment tree_ or _sparse segment tree_.) Previously, we considered cases when we have the ability to build the original segment tree. But what to do if the original size is filled with some default element, but its size does not allow you to completely build up to it in advance? - -We can solve this problem by not explicitly creating a segment tree. Initially, we will create only the root, and we will create the other vertexes only when we need them. + +We can solve this problem by creating a segment tree lazily (incrementally). Initially, we will create only the root, and we will create the other vertexes only when we need them. In this case, we will use the implementation on pointers(before going to the vertex children, check whether they are created, and if not, create them). Each query has still only the complexity $O(\log n)$, which is small enough for most use-cases (e.g. $\log_2 10^9 \approx 30$). diff --git a/src/sequences/longest_increasing_subsequence.md b/src/sequences/longest_increasing_subsequence.md index 31ba0e03d..3d24bef61 100644 --- a/src/sequences/longest_increasing_subsequence.md +++ b/src/sequences/longest_increasing_subsequence.md @@ -283,7 +283,7 @@ For instance we can use a [Segment tree](../data_structures/segment_tree.md) or This method has obviously some **shortcomings**: in terms of length and complexity of the implementation this approach will be worse than the method using binary search. -In addition if the input numbers $a[i]$ are especially large, then we would have to use some tricks, like compressing the numbers (i.e. renumber them from $0$ to $n-1$), or use an implicit Segment tree (only generate the branches of the tree that are important). +In addition if the input numbers $a[i]$ are especially large, then we would have to use some tricks, like compressing the numbers (i.e. renumber them from $0$ to $n-1$), or use a dynamic segment tree (only generate the branches of the tree that are important). Otherwise the memory consumption will be too high. On the other hand this method has also some **advantages**: From 2546479b95770befd3d68cf952b8e87e65089e83 Mon Sep 17 00:00:00 2001 From: Gvne <62983467+gvnee@users.noreply.github.com> Date: Fri, 7 Apr 2023 16:05:24 +0800 Subject: [PATCH 031/590] typo --- src/data_structures/sparse-table.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data_structures/sparse-table.md b/src/data_structures/sparse-table.md index 18372c01c..f576da357 100644 --- a/src/data_structures/sparse-table.md +++ b/src/data_structures/sparse-table.md @@ -149,7 +149,7 @@ One of the main weakness of the $O(1)$ approach discussed in the previous sectio I.e. it works great for range minimum queries, but it is not possible to answer range sum queries using this approach. There are similar data structures that can handle any type of associative functions and answer range queries in $O(1)$. -One of them is called is called [Disjoint Sparse Table](https://discuss.codechef.com/questions/117696/tutorial-disjoint-sparse-table). +One of them is called [Disjoint Sparse Table](https://discuss.codechef.com/questions/117696/tutorial-disjoint-sparse-table). Another one would be the [Sqrt Tree](sqrt-tree.md). ## Practice Problems From 8366f0d3d0c951db55f1f092634bdd0a4adc8ba2 Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Fri, 14 Apr 2023 17:26:47 +0200 Subject: [PATCH 032/590] a problem which asks to implement z-function --- src/string/z-function.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/string/z-function.md b/src/string/z-function.md index 2d584bc22..87027e2f0 100644 --- a/src/string/z-function.md +++ b/src/string/z-function.md @@ -204,6 +204,7 @@ The proof for this fact is the same as the solution which uses the [prefix funct ## Practice Problems +* [eolymp - Blocks of string](https://www.eolymp.com/en/problems/1309) * [Codeforces - Password [Difficulty: Easy]](http://codeforces.com/problemset/problem/126/B) * [UVA # 455 "Periodic Strings" [Difficulty: Medium]](http://uva.onlinejudge.org/index.php?option=onlinejudge&page=show_problem&problem=396) * [UVA # 11022 "String Factoring" [Difficulty: Medium]](http://uva.onlinejudge.org/index.php?option=onlinejudge&page=show_problem&problem=1963) From 1359569371fcda2e2efa47614b05dfce6afdb47a Mon Sep 17 00:00:00 2001 From: Michael Hayter Date: Fri, 14 Apr 2023 23:27:23 -0400 Subject: [PATCH 033/590] Integers less than 2 (especially 1) are not prime. I got a wrong answer because I copied this on a contest once. This corrects the error. --- src/algebra/primality_tests.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/algebra/primality_tests.md b/src/algebra/primality_tests.md index 1876c62aa..8491e85c8 100644 --- a/src/algebra/primality_tests.md +++ b/src/algebra/primality_tests.md @@ -20,6 +20,7 @@ If it is a divisor, than $n$ is definitely not prime, otherwise it is. ```cpp bool isPrime(int x) { + if (x<2) return false; for (int d = 2; d * d <= x; d++) { if (x % d == 0) return false; From f86e8b2e095c66e8f9c460aff40e8d4670183650 Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Sun, 16 Apr 2023 11:39:33 +0200 Subject: [PATCH 034/590] Update primality_tests.md --- src/algebra/primality_tests.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/algebra/primality_tests.md b/src/algebra/primality_tests.md index 8491e85c8..dcebf116a 100644 --- a/src/algebra/primality_tests.md +++ b/src/algebra/primality_tests.md @@ -20,12 +20,11 @@ If it is a divisor, than $n$ is definitely not prime, otherwise it is. ```cpp bool isPrime(int x) { - if (x<2) return false; for (int d = 2; d * d <= x; d++) { if (x % d == 0) return false; } - return true; + return x >= 2; } ``` From ccb80aeb00f8e38ac004697aadc50ad7b4e61327 Mon Sep 17 00:00:00 2001 From: Wiktor Kuchta Date: Fri, 7 Apr 2023 20:23:43 +0200 Subject: [PATCH 035/590] aho_corasick: rewording, typos, grammar --- src/string/aho_corasick.md | 102 ++++++++++++++++++++----------------- 1 file changed, 54 insertions(+), 48 deletions(-) diff --git a/src/string/aho_corasick.md b/src/string/aho_corasick.md index d711693f7..644164fcf 100644 --- a/src/string/aho_corasick.md +++ b/src/string/aho_corasick.md @@ -6,8 +6,10 @@ e_maxx_link: aho_corasick # Aho-Corasick algorithm -Let there be a set of strings with the total length $m$ (sum of all lengths). -The Aho-Corasick algorithm constructs a data structure similar to a trie with some additional links, and then constructs a finite state machine (automaton) in $O(m k)$ time, where $k$ is the size of the used alphabet. +The Aho-Corasick algorithm allows us to quickly search for multiple patterns in a text. +The set of pattern strings is also called a _dictionary_. +We will denote the total length of its constituent strings by $m$ and the size of the alphabet by $k$. +The algorithm constructs a finite state automaton based on a trie in $O(m k)$ time and then uses it to process the text. The algorithm was proposed by Alfred Aho and Margaret Corasick in 1975. @@ -21,21 +23,18 @@ The algorithm was proposed by Alfred Aho and Margaret Corasick in 1975. The image by [nd](https://de.wikipedia.org/wiki/Benutzer:Nd) is distributed under CC BY-SA 3.0 license. -Formally a trie is a rooted tree, where each edge of the tree is labeled by some letter. -All outgoing edge from one vertex must have different labels. +Formally, a trie is a rooted tree, where each edge of the tree is labeled with some letter +and outgoing edges of a vertex have distinct labels. -Consider any path in the trie from the root to any vertex. -If we write out the labels of all edges on the path, we get a string that corresponds to this path. -For any vertex in the trie we will associate the string from the root to the vertex. +We will identify each vertex in the trie with the string formed by the labels on the path from the root to that vertex. Each vertex will also have a flag $\text{leaf}$ which will be true, if any string from the given set corresponds to this vertex. -Accordingly to build a trie for a set of strings means to build a trie such that each $\text{leaf}$ vertex will correspond to one string from the set, and conversely that each string of the set corresponds to one $\text{leaf}$ vertex. +Accordingly, a trie for a set of strings is a trie such that each $\text{leaf}$ vertex corresponds to one string from the set, and conversely, each string of the set corresponds to one $\text{leaf}$ vertex. We now describe how to construct a trie for a given set of strings in linear time with respect to their total length. -We introduce a structure for the vertices of the tree. - +We introduce a structure for the vertices of the tree: ```{.cpp file=aho_corasick_trie_definition} const int K = 26; @@ -51,15 +50,15 @@ struct Vertex { vector trie(1); ``` -Here we store the trie as an array of $\text{Vertex}$. -Each $\text{Vertex}$ contains the flag $\text{leaf}$, and the edges in the form of ans array $\text{next}[]$, where $\text{next}[i]$ is the index to the vertex that we reach by following the character $i$, or $-1$, if there is no such edge. -Initially the trie consists of only one vertex - the root - with the index $0$. +Here, we store the trie as an array of $\text{Vertex}$. +Each $\text{Vertex}$ contains the flag $\text{leaf}$ and the edges in the form of an array $\text{next}[]$, where $\text{next}[i]$ is the index of the vertex that we reach by following the character $i$, or $-1$ if there is no such edge. +Initially, the trie consists of only one vertex - the root - with the index $0$. Now we implement a function that will add a string $s$ to the trie. -The implementation is extremely simple: +The implementation is simple: we start at the root node, and as long as there are edges corresponding to the characters of $s$ we follow them. -If there is no edge for one character, we simply generate a new vertex and connect it via an edge. -At the end of the process we mark the last vertex with flag $\text{leaf}$. +If there is no edge for one character, we generate a new vertex and connect it with an edge. +At the end of the process we mark the last vertex with the flag $\text{leaf}$. ```{.cpp file=aho_corasick_trie_add} void add_string(string const& s) { @@ -76,33 +75,33 @@ void add_string(string const& s) { } ``` -The implementation obviously runs in linear time. -And since every vertex store $k$ links, it will use $O(m k)$ memory. +This implementation obviously runs in linear time, +and since every vertex stores $k$ links, it will use $O(m k)$ memory. It is possible to decrease the memory consumption to $O(m)$ by using a map instead of an array in each vertex. -However this will increase the complexity to $O(n \log k)$. +However, this will increase the time complexity to $O(m \log k)$. ## Construction of an automaton Suppose we have built a trie for the given set of strings. Now let's look at it from a different side. -If we look at any vertex. -The string that corresponds to it is a prefix of one or more strings in the set, thus each vertex of the trie can be interpreted as a position in one or more strings from the set. +If we look at any vertex, +the string that corresponds to it is a prefix of one or more strings in the set, thus each vertex of the trie can be interpreted as a position in one or more strings from the set. -In fact the trie vertices can be interpreted as states in a **finite deterministic automaton**. -From any state we can transition - using some input letter - to other states, i.e. to another position in the set of strings. -For example, if there is only one string in the trie $abc$, and we are standing at vertex $2$ (which corresponds to the string $ab$), then using the letter $c$ we can transition to the state $3$. +In fact, the trie vertices can be interpreted as states in a **finite deterministic automaton**. +From any state we can transition - using some input letter - to other states, i.e., to another position in the set of strings. +For example, if there is only one string $abc$ in the dictionary, and we are standing at vertex $ab$, then using the letter $c$ we can go to the vertex $abc$. Thus we can understand the edges of the trie as transitions in an automaton according to the corresponding letter. -However for an automaton we cannot restrict the possible transitions for each state. +However, in an automaton we need to have transitions for each combination of a state and a letter. If we try to perform a transition using a letter, and there is no corresponding edge in the trie, then we nevertheless must go into some state. -More strictly, let us be in a state $p$ corresponding to the string $t$, and we want to transition to a different state with the character $c$. +More precisely, suppose we are in a state corresponding to a string $t$, and we want to transition to a different state using the character $c$. If there is an edge labeled with this letter $c$, then we can simply go over this edge, and get the vertex corresponding to $t + c$. -If there is no such edge, then we must find the state corresponding to the longest proper suffix of the string $t$ (the longest available in the trie), and try to perform a transition via $c$ from there. +If there is no such edge, since we want to maintain the invariant that the current state is the longest partial match in the processed string, we must find the longest string in the trie that's a proper suffix of the string $t$, and try to perform a transition from there. -For example let the trie be constructed by the strings $ab$ and $bc$, and we are currently at the vertex corresponding to $ab$, which is a $\text{leaf}$. -For a transition with the letter $c$, we are forced to go to the state corresponding to the string $b$, and from there follow the edge with the letter $c$. +For example, let the trie be constructed by the strings $ab$ and $bc$, and we are currently at the vertex corresponding to $ab$, which is a $\text{leaf}$. +To transition with the letter $c$, we are forced to go to the state corresponding to the string $b$, and from there follow the edge with the letter $c$.
@@ -112,22 +111,26 @@ For a transition with the letter $c$, we are forced to go to the state correspon Blue arrows are suffix links, green arrows are terminal links.
-A **suffix link** for a vertex $p$ is a edge that points to the longest proper suffix of the string corresponding to the vertex $p$. -The only special case is the root of the trie, the suffix link will point to itself. +A **suffix link** for a vertex $p$ is an edge that points to the longest proper suffix of the string corresponding to the vertex $p$. +The only special case is the root of the trie, whose suffix link will point to itself. Now we can reformulate the statement about the transitions in the automaton like this: -while from the current vertex of the trie there is no transition using the current letter (or until we reach the root), we follow the suffix link. +while there is no transition from the current vertex of the trie using the current letter (or until we reach the root), we follow the suffix link. Thus we reduced the problem of constructing an automaton to the problem of finding suffix links for all vertices of the trie. However we will build these suffix links, oddly enough, using the transitions constructed in the automaton. -Note that if we want to find a suffix link for some vertex $v$, then we firstly have the base case that the root vertex has its suffix link as itself, and all nodes that are immediate children of the root vertex (i.e the vertices associated with prefixes of length one) also have their suffix links as the root vertex. Moreover, the suffix links of all deeper vertices can be evaluated as follows: we can go to the ancestor $p$ of this current vertex (let $c$ be the letter of the edge from $p$ to $v$), then follow its suffix link, and perform the transition with the letter $c$ from there. +The suffix links of the root vertex and all its immediate children point to the root vertex. +For any vertex $v$ deeper in the tree, we can calculate the suffix link as follows: +if $p$ is the ancestor of $v$ with $c$ being the letter labeling the edge from $p$ to $v$, +go to $p$, +then follow its suffix link, and perform the transition with the letter $c$ from there. -Thus the problem of finding the transitions has been reduced to the problem of finding suffix links, and the problem of finding suffix links has been reduced to the problem of finding a suffix link and a transition, except for vertices closer to the root. +Thus, the problem of finding the transitions has been reduced to the problem of finding suffix links, and the problem of finding suffix links has been reduced to the problem of finding a suffix link and a transition, except for vertices closer to the root. So we have a recursive dependence that we can resolve in linear time. Let's move to the implementation. Note that we now will store the ancestor $p$ and the character $pch$ of the edge from $p$ to $v$ for each vertex $v$. -Also at each vertex we will store the suffix link $\text{link}$ (or $-1$ if it hasn't been calculated yet), and in the array $\text{go}[k]$ the transitions in the machine for each symbol (again $-1$ if it hasn't been calculated yet). +Also, at each vertex we will store the suffix link $\text{link}$ (or $-1$ if it hasn't been calculated yet), and in the array $\text{go}[k]$ the transitions in the machine for each symbol (again $-1$ if it hasn't been calculated yet). ```{.cpp file=aho_corasick_automaton} const int K = 26; @@ -185,35 +188,38 @@ int go(int v, char ch) { } ``` -It is easy to see, that due to the memoization of the found suffix links and transitions the total time for finding all suffix links and transitions will be linear. +It is easy to see that thanks to memoization of the suffix links and transitions, +the total time for finding all suffix links and transitions will be linear. For an illustration of the concept refer to slide number 103 of the [Stanford slides](http://web.stanford.edu/class/archive/cs/cs166/cs166.1166/lectures/02/Slides02.pdf). ### BFS-based construction -Instead of computing transitions and suffix links with recursive calls of `go` and `get_link` to each other, it is possible to compute them for all vertices at once with an approach that is similar in nature to the Knuth-Morris-Pratt algorithm (which, in itself, is a special case of Aho-Corasick when the dictionary only contains a single string). +Instead of computing transitions and suffix links with recursive calls to `go` and `get_link`, it is possible to compute them bottom-up starting from the root. +(In fact, when the dictionary consists of only one string, we obtain the familiar Knuth-Morris-Pratt algorithm.) -This approach has some advantages over the one described above as instead of the total length $m$ its running time would depend on the number of vertices $n$ in a trie. Moreover, it is possible to adapt it for large alphabets with persistent array data structure, thus making construction time $O(n \log k)$ instead of $O(mk)$, which is a significant improvement granted that $m$ may go up to $n^2$. +This approach will have some advantages over the one described above as, instead of the total length $m$, its running time depends only on the number of vertices $n$ in the trie. Moreover, it is possible to adapt it for large alphabets using a persistent array data structure, thus making the construction time $O(n \log k)$ instead of $O(mk)$, which is a significant improvement granted that $m$ may go up to $n^2$. -Algorithm is based on mathematical induction and the fact that BFS traverses vertices in order of increasing length. Thus, by induction on the length of the vertex we may assume that when we're in a vertex $v$, its suffix link $u = link[v]$ is already successfully computed, and for all vertices with shorter length transitions from them are also fully computed. +We can reason inductively using the fact that BFS from the root traverses vertices in order of increasing length. +We may assume that when we're in a vertex $v$, its suffix link $u = link[v]$ is already successfully computed, and for all vertices with shorter length transitions from them are also fully computed. Assume that at the moment we stand in a vertex $v$ and consider a character $c$. We essentially have two cases: - -1. $go[v][c] = -1$. In this case, we may assign $go[v][c] = go[u][c]$, which is already known due to induction assumption; -2. $go[v][c] = w$ and $w \neq -1$. In this case, we may assign $link[w] = go[u][c]$. -In this way, we spend $O(1)$ time per each pair of a vertex and a character, making the running time $O(nk)$. Major overhead here comes from the fact that we copy a lot of transitions from $u$, while remaining transitions form a tree and sum up to $n-1$ over all vertices. To avoid the copying of $go[u][c]$, we may use persistent array data structure (for example, implemented with persistent segment tree on top of array of size $k$), using which we initially copy $go[u]$ into $go[v]$ and then only update values for characters in which the transition would differ. This leads to the $O(n \log k)$ algorithm. +1. $go[v][c] = -1$. In this case, we may assign $go[v][c] = go[u][c]$, which is already known by the induction hypothesis; +2. $go[v][c] = w \neq -1$. In this case, we may assign $link[w] = go[u][c]$. + +In this way, we spend $O(1)$ time per each pair of a vertex and a character, making the running time $O(nk)$. The major overhead here is that we copy a lot of transitions from $u$, while the remaining transitions form the trie and sum up to $m-1$ over all vertices. To avoid the copying of $go[u][c]$, we may use a persistent array data structure, using which we initially copy $go[u]$ into $go[v]$ and then only update values for characters in which the transition would differ. This leads to the $O(n \log k)$ algorithm. ## Applications ### Find all strings from a given set in a text -Given a set of strings and a text. +We are given a set of strings and a text. We have to print all occurrences of all strings from the set in the given text in $O(\text{len} + \text{ans})$, where $\text{len}$ is the length of the text and $\text{ans}$ is the size of the answer. We construct an automaton for this set of strings. -We will now process the text letter by letter, transitioning during the different states. -Initially we are at the root of the trie. +We will now process the text letter by letter using the automaton, +starting at the root of the trie. If we are at any time at state $v$, and the next letter is $c$, then we transition to the next state with $\text{go}(v, c)$, thereby either increasing the length of the current match substring by $1$, or decreasing it by following a suffix link. How can we find out for a state $v$, if there are any matches with strings for the set? @@ -236,10 +242,10 @@ Thus we can sum up all matches in $O(\text{len})$. ### Finding the lexicographical smallest string of a given length that doesn't match any given strings A set of strings and a length $L$ is given. -We have to find a string of length $L$, which does not contain any of the string, and derive the lexicographical smallest of such strings. +We have to find a string of length $L$, which does not contain any of the strings, and derive the lexicographically smallest of such strings. We can construct the automaton for the set of strings. -Let's remember, that the vertices from which we can reach a $\text{leaf}$ vertex are the states, at which we have a match with a string from the set. +Recall that the vertices from which we can reach a $\text{leaf}$ vertex are the states at which we have a match with a string from the set. Since in this task we have to avoid matches, we are not allowed to enter such states. On the other hand we can enter all other vertices. Thus we delete all "bad" vertices from the machine, and in the remaining graph of the automaton we find the lexicographical smallest path of length $L$. From 70470762765d9f709b7993a7e4181bb2f14c1ff9 Mon Sep 17 00:00:00 2001 From: Wiktor Kuchta Date: Fri, 7 Apr 2023 20:38:43 +0200 Subject: [PATCH 036/590] aho_corasick: m transitions total --- src/string/aho_corasick.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string/aho_corasick.md b/src/string/aho_corasick.md index 644164fcf..ab4b05cb9 100644 --- a/src/string/aho_corasick.md +++ b/src/string/aho_corasick.md @@ -208,7 +208,7 @@ Assume that at the moment we stand in a vertex $v$ and consider a character $c$. 1. $go[v][c] = -1$. In this case, we may assign $go[v][c] = go[u][c]$, which is already known by the induction hypothesis; 2. $go[v][c] = w \neq -1$. In this case, we may assign $link[w] = go[u][c]$. -In this way, we spend $O(1)$ time per each pair of a vertex and a character, making the running time $O(nk)$. The major overhead here is that we copy a lot of transitions from $u$, while the remaining transitions form the trie and sum up to $m-1$ over all vertices. To avoid the copying of $go[u][c]$, we may use a persistent array data structure, using which we initially copy $go[u]$ into $go[v]$ and then only update values for characters in which the transition would differ. This leads to the $O(n \log k)$ algorithm. +In this way, we spend $O(1)$ time per each pair of a vertex and a character, making the running time $O(nk)$. The major overhead here is that we copy a lot of transitions from $u$, while the remaining transitions form the trie and sum up to $m$ over all vertices. To avoid the copying of $go[u][c]$, we may use a persistent array data structure, using which we initially copy $go[u]$ into $go[v]$ and then only update values for characters in which the transition would differ. This leads to the $O(n \log k)$ algorithm. ## Applications From 3d2d86358d993c8c5c7f521c9cf3fe2562b4c675 Mon Sep 17 00:00:00 2001 From: Wiktor Kuchta Date: Fri, 7 Apr 2023 20:39:55 +0200 Subject: [PATCH 037/590] aho_corasick: fix least string not matching dict --- src/string/aho_corasick.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string/aho_corasick.md b/src/string/aho_corasick.md index ab4b05cb9..2c2b5205e 100644 --- a/src/string/aho_corasick.md +++ b/src/string/aho_corasick.md @@ -245,7 +245,7 @@ A set of strings and a length $L$ is given. We have to find a string of length $L$, which does not contain any of the strings, and derive the lexicographically smallest of such strings. We can construct the automaton for the set of strings. -Recall that the vertices from which we can reach a $\text{leaf}$ vertex are the states at which we have a match with a string from the set. +Recall that $\text{leaf}$ vertices are the states where we have a match with a string from the set. Since in this task we have to avoid matches, we are not allowed to enter such states. On the other hand we can enter all other vertices. Thus we delete all "bad" vertices from the machine, and in the remaining graph of the automaton we find the lexicographical smallest path of length $L$. From f89b720388d0414f4c0bd37919eff29f26b78bf2 Mon Sep 17 00:00:00 2001 From: Wiktor Kuchta Date: Fri, 7 Apr 2023 20:44:15 +0200 Subject: [PATCH 038/590] aho_corasick: rename leaf to output Leaf is confusing --- src/string/aho_corasick.md | 29 +++++++++++++++-------------- test/test_aho_corasick.cpp | 16 ++++++++-------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/string/aho_corasick.md b/src/string/aho_corasick.md index 2c2b5205e..526ac1814 100644 --- a/src/string/aho_corasick.md +++ b/src/string/aho_corasick.md @@ -28,9 +28,10 @@ and outgoing edges of a vertex have distinct labels. We will identify each vertex in the trie with the string formed by the labels on the path from the root to that vertex. -Each vertex will also have a flag $\text{leaf}$ which will be true, if any string from the given set corresponds to this vertex. +Each vertex will also have a flag $\text{output}$ which will be set +if the vertex corresponds to a pattern in the dictionary. -Accordingly, a trie for a set of strings is a trie such that each $\text{leaf}$ vertex corresponds to one string from the set, and conversely, each string of the set corresponds to one $\text{leaf}$ vertex. +Accordingly, a trie for a set of strings is a trie such that each $\text{output}$ vertex corresponds to one string from the set, and conversely, each string of the set corresponds to one $\text{output}$ vertex. We now describe how to construct a trie for a given set of strings in linear time with respect to their total length. @@ -40,7 +41,7 @@ const int K = 26; struct Vertex { int next[K]; - bool leaf = false; + bool output = false; Vertex() { fill(begin(next), end(next), -1); @@ -51,14 +52,14 @@ vector trie(1); ``` Here, we store the trie as an array of $\text{Vertex}$. -Each $\text{Vertex}$ contains the flag $\text{leaf}$ and the edges in the form of an array $\text{next}[]$, where $\text{next}[i]$ is the index of the vertex that we reach by following the character $i$, or $-1$ if there is no such edge. +Each $\text{Vertex}$ contains the flag $\text{output}$ and the edges in the form of an array $\text{next}[]$, where $\text{next}[i]$ is the index of the vertex that we reach by following the character $i$, or $-1$ if there is no such edge. Initially, the trie consists of only one vertex - the root - with the index $0$. Now we implement a function that will add a string $s$ to the trie. The implementation is simple: we start at the root node, and as long as there are edges corresponding to the characters of $s$ we follow them. If there is no edge for one character, we generate a new vertex and connect it with an edge. -At the end of the process we mark the last vertex with the flag $\text{leaf}$. +At the end of the process we mark the last vertex with the flag $\text{output}$. ```{.cpp file=aho_corasick_trie_add} void add_string(string const& s) { @@ -71,7 +72,7 @@ void add_string(string const& s) { } v = trie[v].next[c]; } - trie[v].leaf = true; + trie[v].output = true; } ``` @@ -100,7 +101,7 @@ More precisely, suppose we are in a state corresponding to a string $t$, and we If there is an edge labeled with this letter $c$, then we can simply go over this edge, and get the vertex corresponding to $t + c$. If there is no such edge, since we want to maintain the invariant that the current state is the longest partial match in the processed string, we must find the longest string in the trie that's a proper suffix of the string $t$, and try to perform a transition from there. -For example, let the trie be constructed by the strings $ab$ and $bc$, and we are currently at the vertex corresponding to $ab$, which is a $\text{leaf}$. +For example, let the trie be constructed by the strings $ab$ and $bc$, and we are currently at the vertex corresponding to $ab$, which is a $\text{output}$. To transition with the letter $c$, we are forced to go to the state corresponding to the string $b$, and from there follow the edge with the letter $c$.
@@ -137,7 +138,7 @@ const int K = 26; struct Vertex { int next[K]; - bool leaf = false; + bool output = false; int p = -1; char pch; int link = -1; @@ -161,7 +162,7 @@ void add_string(string const& s) { } v = t[v].next[c]; } - t[v].leaf = true; + t[v].output = true; } int go(int v, char ch); @@ -223,14 +224,14 @@ starting at the root of the trie. If we are at any time at state $v$, and the next letter is $c$, then we transition to the next state with $\text{go}(v, c)$, thereby either increasing the length of the current match substring by $1$, or decreasing it by following a suffix link. How can we find out for a state $v$, if there are any matches with strings for the set? -First, it is clear that if we stand on a $\text{leaf}$ vertex, then the string corresponding to the vertex ends at this position in the text. +First, it is clear that if we stand on a $\text{output}$ vertex, then the string corresponding to the vertex ends at this position in the text. However this is by no means the only possible case of achieving a match: -if we can reach one or more $\text{leaf}$ vertices by moving along the suffix links, then there will be also a match corresponding to each found $\text{leaf}$ vertex. +if we can reach one or more $\text{output}$ vertices by moving along the suffix links, then there will be also a match corresponding to each found $\text{output}$ vertex. A simple example demonstrating this situation can be creating using the set of strings $\{dabce, abc, bc\}$ and the text $dabc$. -Thus if we store in each $\text{leaf}$ vertex the index of the string corresponding to it (or the list of indices if duplicate strings appear in the set), then we can find in $O(n)$ time the indices of all strings which match the current state, by simply following the suffix links from the current vertex to the root. +Thus if we store in each $\text{output}$ vertex the index of the string corresponding to it (or the list of indices if duplicate strings appear in the set), then we can find in $O(n)$ time the indices of all strings which match the current state, by simply following the suffix links from the current vertex to the root. However this is not the most efficient solution, since this gives us $O(n ~ \text{len})$ complexity in total. -However this can be optimized by computing and storing the nearest $\text{leaf}$ vertex that is reachable using suffix links (this is sometimes called the **exit link**). +However this can be optimized by computing and storing the nearest $\text{output}$ vertex that is reachable using suffix links (this is sometimes called the **exit link**). This value we can compute lazily in linear time. Thus for each vertex we can advance in $O(1)$ time to the next marked vertex in the suffix link path, i.e. to the next match. Thus for each match we spend $O(1)$ time, and therefore we reach the complexity $O(\text{len} + \text{ans})$. @@ -245,7 +246,7 @@ A set of strings and a length $L$ is given. We have to find a string of length $L$, which does not contain any of the strings, and derive the lexicographically smallest of such strings. We can construct the automaton for the set of strings. -Recall that $\text{leaf}$ vertices are the states where we have a match with a string from the set. +Recall that $\text{output}$ vertices are the states where we have a match with a string from the set. Since in this task we have to avoid matches, we are not allowed to enter such states. On the other hand we can enter all other vertices. Thus we delete all "bad" vertices from the machine, and in the remaining graph of the automaton we find the lexicographical smallest path of length $L$. diff --git a/test/test_aho_corasick.cpp b/test/test_aho_corasick.cpp index afc1fd927..dd9dd8496 100644 --- a/test/test_aho_corasick.cpp +++ b/test/test_aho_corasick.cpp @@ -34,22 +34,22 @@ void test_automaton() { int v = 0; v = go(v, 'a'); - assert(t[v].leaf == true); + assert(t[v].output == true); v = go(v, 'b'); - assert(t[v].leaf == true); + assert(t[v].output == true); v = go(v, 'c'); - assert(t[v].leaf == true); + assert(t[v].output == true); v = go(v, 'd'); - assert(t[v].leaf == false); + assert(t[v].output == false); assert(v == 0); v = go(v, 'b'); - assert(t[v].leaf == false); + assert(t[v].output == false); v = go(v, 'a'); - assert(t[v].leaf == false); + assert(t[v].output == false); v = go(v, 'a'); - assert(t[v].leaf == true); + assert(t[v].output == true); v = go(v, 'b'); - assert(t[v].leaf == true); + assert(t[v].output == true); } int main() { From cfdaaec24df01583bddbf2db39b6709d2c8c245a Mon Sep 17 00:00:00 2001 From: Wiktor Kuchta Date: Fri, 7 Apr 2023 20:51:53 +0200 Subject: [PATCH 039/590] aho_corasick: lexicographically --- src/string/aho_corasick.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/string/aho_corasick.md b/src/string/aho_corasick.md index 526ac1814..e90e5508d 100644 --- a/src/string/aho_corasick.md +++ b/src/string/aho_corasick.md @@ -240,7 +240,7 @@ If you only want to count the occurrences and not find the indices themselves, y This can be calculated in $O(n)$ time in total. Thus we can sum up all matches in $O(\text{len})$. -### Finding the lexicographical smallest string of a given length that doesn't match any given strings +### Finding the lexicographically smallest string of a given length that doesn't match any given strings A set of strings and a length $L$ is given. We have to find a string of length $L$, which does not contain any of the strings, and derive the lexicographically smallest of such strings. @@ -249,7 +249,7 @@ We can construct the automaton for the set of strings. Recall that $\text{output}$ vertices are the states where we have a match with a string from the set. Since in this task we have to avoid matches, we are not allowed to enter such states. On the other hand we can enter all other vertices. -Thus we delete all "bad" vertices from the machine, and in the remaining graph of the automaton we find the lexicographical smallest path of length $L$. +Thus we delete all "bad" vertices from the machine, and in the remaining graph of the automaton we find the lexicographically smallest path of length $L$. This task can be solved in $O(L)$ for example by [depth first search](../graph/depth-first-search.md). ### Finding the shortest string containing all given strings @@ -261,11 +261,11 @@ initially being in the state $(v = \text{root},~ \text{mask} = 0)$, we want to r When we transition from one state to another using a letter, we update the mask accordingly. By running a [breadth first search](../graph/breadth-first-search.md) we can find a path to the state $(v,~ \text{mask} = 2^n - 1)$ with the smallest length. -### Finding the lexicographical smallest string of length $L$ containing $k$ strings {data-toc-label="Finding the lexicographical smallest string of length L containing k strings"} +### Finding the lexicographically smallest string of length $L$ containing $k$ strings {data-toc-label="Finding the lexicographically smallest string of length L containing k strings"} As in the previous problem, we calculate for each vertex the number of matches that correspond to it (that is the number of marked vertices reachable using suffix links). We reformulate the problem: the current state is determined by a triple of numbers $(v,~ \text{len},~ \text{cnt})$, and we want to reach from the state $(\text{root},~ 0,~ 0)$ the state $(v,~ L,~ k)$, where $v$ can be any vertex. -Thus we can find such a path using depth first search (and if the search looks at the edges in their natural order, then the found path will automatically be the lexicographical smallest). +Thus we can find such a path using depth first search (and if the search looks at the edges in their natural order, then the found path will automatically be the lexicographically smallest). ## Problems From 7c8c0a8b59b8cb600289f9a71339ed502f384cb6 Mon Sep 17 00:00:00 2001 From: Wiktor Kuchta Date: Fri, 14 Apr 2023 20:17:05 +0200 Subject: [PATCH 040/590] aho_corasick: rewording, commmas --- src/string/aho_corasick.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/string/aho_corasick.md b/src/string/aho_corasick.md index e90e5508d..5499c7767 100644 --- a/src/string/aho_corasick.md +++ b/src/string/aho_corasick.md @@ -118,7 +118,7 @@ Now we can reformulate the statement about the transitions in the automaton like while there is no transition from the current vertex of the trie using the current letter (or until we reach the root), we follow the suffix link. Thus we reduced the problem of constructing an automaton to the problem of finding suffix links for all vertices of the trie. -However we will build these suffix links, oddly enough, using the transitions constructed in the automaton. +However, we will build these suffix links, oddly enough, using the transitions constructed in the automaton. The suffix links of the root vertex and all its immediate children point to the root vertex. For any vertex $v$ deeper in the tree, we can calculate the suffix link as follows: @@ -230,8 +230,8 @@ if we can reach one or more $\text{output}$ vertices by moving along the suffix A simple example demonstrating this situation can be creating using the set of strings $\{dabce, abc, bc\}$ and the text $dabc$. Thus if we store in each $\text{output}$ vertex the index of the string corresponding to it (or the list of indices if duplicate strings appear in the set), then we can find in $O(n)$ time the indices of all strings which match the current state, by simply following the suffix links from the current vertex to the root. -However this is not the most efficient solution, since this gives us $O(n ~ \text{len})$ complexity in total. -However this can be optimized by computing and storing the nearest $\text{output}$ vertex that is reachable using suffix links (this is sometimes called the **exit link**). +This is not the most efficient solution, since this results in $O(n ~ \text{len})$ complexity overall. +However, this can be optimized by computing and storing the nearest $\text{output}$ vertex that is reachable using suffix links (this is sometimes called the **exit link**). This value we can compute lazily in linear time. Thus for each vertex we can advance in $O(1)$ time to the next marked vertex in the suffix link path, i.e. to the next match. Thus for each match we spend $O(1)$ time, and therefore we reach the complexity $O(\text{len} + \text{ans})$. From 03d425e369abc15642d770babeeb4b3e6ae504e6 Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Sun, 16 Apr 2023 11:51:15 +0200 Subject: [PATCH 041/590] O(nk) -> O(mk) --- src/string/aho_corasick.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string/aho_corasick.md b/src/string/aho_corasick.md index 5499c7767..1afd251b8 100644 --- a/src/string/aho_corasick.md +++ b/src/string/aho_corasick.md @@ -209,7 +209,7 @@ Assume that at the moment we stand in a vertex $v$ and consider a character $c$. 1. $go[v][c] = -1$. In this case, we may assign $go[v][c] = go[u][c]$, which is already known by the induction hypothesis; 2. $go[v][c] = w \neq -1$. In this case, we may assign $link[w] = go[u][c]$. -In this way, we spend $O(1)$ time per each pair of a vertex and a character, making the running time $O(nk)$. The major overhead here is that we copy a lot of transitions from $u$, while the remaining transitions form the trie and sum up to $m$ over all vertices. To avoid the copying of $go[u][c]$, we may use a persistent array data structure, using which we initially copy $go[u]$ into $go[v]$ and then only update values for characters in which the transition would differ. This leads to the $O(n \log k)$ algorithm. +In this way, we spend $O(1)$ time per each pair of a vertex and a character, making the running time $O(mk)$. The major overhead here is that we copy a lot of transitions from $u$, while the remaining transitions form the trie and sum up to $m$ over all vertices. To avoid the copying of $go[u][c]$, we may use a persistent array data structure, using which we initially copy $go[u]$ into $go[v]$ and then only update values for characters in which the transition would differ. This leads to the $O(n \log k)$ algorithm. ## Applications From 7118f41c9df30455664616a3047e58dcf1bccd9e Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Sun, 16 Apr 2023 11:52:16 +0200 Subject: [PATCH 042/590] n \log k -> m \log k --- src/string/aho_corasick.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string/aho_corasick.md b/src/string/aho_corasick.md index 1afd251b8..2a3e708cb 100644 --- a/src/string/aho_corasick.md +++ b/src/string/aho_corasick.md @@ -209,7 +209,7 @@ Assume that at the moment we stand in a vertex $v$ and consider a character $c$. 1. $go[v][c] = -1$. In this case, we may assign $go[v][c] = go[u][c]$, which is already known by the induction hypothesis; 2. $go[v][c] = w \neq -1$. In this case, we may assign $link[w] = go[u][c]$. -In this way, we spend $O(1)$ time per each pair of a vertex and a character, making the running time $O(mk)$. The major overhead here is that we copy a lot of transitions from $u$, while the remaining transitions form the trie and sum up to $m$ over all vertices. To avoid the copying of $go[u][c]$, we may use a persistent array data structure, using which we initially copy $go[u]$ into $go[v]$ and then only update values for characters in which the transition would differ. This leads to the $O(n \log k)$ algorithm. +In this way, we spend $O(1)$ time per each pair of a vertex and a character, making the running time $O(mk)$. The major overhead here is that we copy a lot of transitions from $u$, while the remaining transitions form the trie and sum up to $m$ over all vertices. To avoid the copying of $go[u][c]$, we may use a persistent array data structure, using which we initially copy $go[u]$ into $go[v]$ and then only update values for characters in which the transition would differ. This leads to the $O(m \log k)$ algorithm. ## Applications From 53a1c7d1f1b7aaf2b159e7d1a85efe5aa8527b49 Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Sun, 16 Apr 2023 11:55:02 +0200 Subject: [PATCH 043/590] clarification --- src/string/aho_corasick.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string/aho_corasick.md b/src/string/aho_corasick.md index 2a3e708cb..75986a3c7 100644 --- a/src/string/aho_corasick.md +++ b/src/string/aho_corasick.md @@ -209,7 +209,7 @@ Assume that at the moment we stand in a vertex $v$ and consider a character $c$. 1. $go[v][c] = -1$. In this case, we may assign $go[v][c] = go[u][c]$, which is already known by the induction hypothesis; 2. $go[v][c] = w \neq -1$. In this case, we may assign $link[w] = go[u][c]$. -In this way, we spend $O(1)$ time per each pair of a vertex and a character, making the running time $O(mk)$. The major overhead here is that we copy a lot of transitions from $u$, while the remaining transitions form the trie and sum up to $m$ over all vertices. To avoid the copying of $go[u][c]$, we may use a persistent array data structure, using which we initially copy $go[u]$ into $go[v]$ and then only update values for characters in which the transition would differ. This leads to the $O(m \log k)$ algorithm. +In this way, we spend $O(1)$ time per each pair of a vertex and a character, making the running time $O(mk)$. The major overhead here is that we copy a lot of transitions from $u$ in the first case, while the transitions of the second case form the trie and sum up to $m$ over all vertices. To avoid the copying of $go[u][c]$, we may use a persistent array data structure, using which we initially copy $go[u]$ into $go[v]$ and then only update values for characters in which the transition would differ. This leads to the $O(m \log k)$ algorithm. ## Applications From ffdf1e5e8b9de0e6bf8f953dfc48a2a373206d7e Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sun, 16 Apr 2023 21:50:51 +0200 Subject: [PATCH 044/590] clean up bitwise manipulation article and add additional infos --- src/algebra/bit-manipulation.md | 205 ++++++++++++++++++-------------- 1 file changed, 113 insertions(+), 92 deletions(-) diff --git a/src/algebra/bit-manipulation.md b/src/algebra/bit-manipulation.md index d3215a302..b61cfbf85 100644 --- a/src/algebra/bit-manipulation.md +++ b/src/algebra/bit-manipulation.md @@ -1,69 +1,60 @@ -# Binary number - -A **binary number** is a number expressed in the base-2 numeral system or binary numeral system, a method of mathematical expression which uses only two symbols: typically "0" (zero) and "1" (one). - -We are talking about a numerical system of great importance in technological development. Among some of the most outstanding applications are the representation of images and texts, in the field of electronics. With the combination of zeros and ones, any number can be represented on a decimal basis, making communication with electronic devices easier for humans. In addition to translating the different programming languages, to a common language where the computer understands. - -**In this article I will not talk about how to convert to binary or decimal. There is a lot of information all over the internet on the subject.** - +--- +tags: + - Original +--- # Bit manipulation -When finding solutions to problems, a very important factor is the simplicity and the execution time. Now, in this bitwise operations are very important and you can take advantage of them. - -# Bit operators - -## Bit shift operators -### Multiplication and division by powers of 2 - -There are two operators for shifting bits. - -$\gg$ One bit to the right. Which would be the same as a division by a power of two. - -$\ll$ One bit to the left. And this would be a multiplication, equally by a power of two. - -Let's see an example. - -Let's say we have a number $N$, which. $N = 4$. - -The binary representation of $4$ is: +## Binary number -$4 = 100_2$ +A **binary number** is a number expressed in the base-2 numeral system or binary numeral system, it is a method of mathematical expression which uses only two symbols: typically "0" (zero) and "1" (one). -If we shift one bit to the left, then we would be adding a bit to the end, in this case a 0. +We say that a certain bit is **set**, if it is one, and **cleared** if it is zero. -$4 \ll 1 = 100_2 \ll 1 = 1000_2$ +The binary number $(a_k a_{k-1} \dots a_1 a_0)_2$ represents the number: -$1000_2 = 8$ and clearly, $4 * 2 = 8$ +$$(a_k a_{k-1} \dots a_1 a_0)_2 = a_k \cdot 2^k + a_{k-1} \cdot 2^{k-1} + \dots + a_1 \cdot 2^1 + a_0 \cdot 2^0.$$ -So, for a division by two, it would be exactly the same, but using the operator $<<$. +For instance the binary number $1101_2$ represents the number $13$: -$4 \gg 1 = 100_2 \gg 1 = 10_2$ +$$\begin{align} +1101_2 &= 1 \cdot 2^3 + 1 \cdot 2^2 + 0 \cdot 2^1 + 1 \cdot 2^0 \\ + &= 1\cdot 8 + 1 \cdot 4 + 0 \cdot 2 + 1 \cdot 1 = 13 +\end{align}$$ -In this case, we would remove one bit from the end, this is what is called the **least significant bit**, the rightmost bit of the representation. +Computers represent integers as binary numbers. +Positive integers (both signed and unsigned) are just represented with their binary digits, and negative signed numbers (which can be positive and negative) are usually represented with the [Two's complement](https://en.wikipedia.org/wiki/Two%27s_complement). -Of course, the **most significant bit** is the leftmost bit. +```cpp +unsigned int unsigned_number = 13; +assert(unsigned_number == 0b1101); -And then, how could it carry out operations with other powers, greater than two? +int positive_signed_number = 13; +assert(positive_signed_number == 0b1101); -Easy, you just have to remember the exponent of two, to create said power. In other words: +int negative_signed_number = -13; +assert(negative_signed_number == 0b1111'1111'1111'1111'1111'1111'1111'0011); +``` -$4 = 2 ^ 2$, so to do multiplication or division operations with **4**, we must move **2 bits**. +CPUs are very fast manipulating those bits with specific operations. +For some problems we can take these binary number representations to our advantage, and speed up the execution time. +And for some problems (typically in combinatorics or dynamic programming) where we want to track which objects we already picked from a given set of objects, we can just use an large enought integer where each digit represents an object and depending on if we pick or drop the object we set or clear the digit. -$8 = 2 ^ 3$, so for $8$ it would be **3 bits**. *And so on*. +## Bit operators +All those introduced operators are instant (same speed as an addition) on a CPU for fixed-length integers. -## Bitwise operators. +### Bitwise operators -``` -& : The bitwise AND operator compares each bit of its first operand with the corresponding bit of its second operand. +- $\&$ : The bitwise AND operator compares each bit of its first operand with the corresponding bit of its second operand. If both bits are 1, the corresponding result bit is set to 1. Otherwise, the corresponding result bit is set to 0. -| : The bitwise inclusive OR operator compares each bit of its first operand with the corresponding bit of its second operand. +- $|$ : The bitwise inclusive OR operator compares each bit of its first operand with the corresponding bit of its second operand. If one of the two bits is 1, the corresponding result bit is set to 1. Otherwise, the corresponding result bit is set to 0. -^ : The bitwise exclusive OR (XOR) operator compares each bit of its first operand with the corresponding bit of its second operand. +- $\wedge$ : The bitwise exclusive OR (XOR) operator compares each bit of its first operand with the corresponding bit of its second operand. If one bit is 0 and the other bit is 1, the corresponding result bit is set to 1. Otherwise, the corresponding result bit is set to 0. -``` + +- $\sim$ : The bitwise complement (NOT) operator flips each bit of a number, if a bit is set the operator will clear it, if it is cleared the operator sets it. Examples: @@ -88,70 +79,79 @@ n-1 = 01010111 n ^ (n-1) = 00001111 ``` -# Useful tricks. +``` +n = 01011000 +-------------------- +~n = 10100111 +``` -## A bit is set (1) or cleared (0) +### Shift operators -The value of the $x$-th bit can be by shifting the number $x$ positions to the right, the $x$-th bit is the units place, therefore we can extract it by performing a bitwise & with 1 +There are two operators for shifting bits. + +- $\gg$ Shifts a number to the right by removing the last few binary digits of the number. + Each shift by one represents an integer division by 2, so a right shift by $k$ represents an integer division by $2^k$. + + E.g. $5 \gg 2 = 101_2 \gg 2 = 1_2 = 1$ which is the same as $\frac{5}{2^2} = \frac{5}{4} = 1$. + For a computer though shifting some bits is a lot faster than doing divisions. + +- $\ll$ Shifts a number to left by appending zero digits. + In similar fashion to a right shift by $k$, a left shift by $k$ represents a multiplication by $2^k$. + + E.g. $5 \ll 3 = 101_2 \ll 3 = 101000_2 = 40$ which is the same as $5 \cdot 2^3 = 5 \cdot 8 = 40$. + + Notice however that for a fixed-length integer that means dropping the most left digits, and if you shift too much you end up with the number $0$. -``` cpp -bool check(int number, int x) { - return ((number >> x) & 1); -} -``` -## Parity of a number +## Useful tricks -Function to know if a number is even or odd. +### Set/flip/clear a bit -True if number is odd, false for number is even. +Using bitwise shifts and some basic bitwise operations we can easily set, flip or clear a bit. +$1 \ll x$ is a number with only the $x$-th bit set, while $\sim(1 \ll x)$ is a number with all bits set except the $x$-th bit. + +- $n ~|~ (1 \ll x)$ sets the $x$-th bit in the number $n$ +- $n ~\wedge~ (1 \ll x)$ flips the $x$-th bit in the number $n$ +- $n ~\&~ \sim(1 \ll x)$ clears the $x$-th bit in the number $n$ + +### Check if a bit is set + +The value of the $x$-th bit can be by shifting the number $x$ positions to the right, the $x$-th bit is the units place, therefore we can extract it by performing a bitwise & with 1 ``` cpp -bool check(int number) { - return (number & 1); +bool is_set(unsigned int number, int x) { + return (number >> x) & 1; } ``` -## Check if an integer is a power of 2 +### Check if an integer is a power of 2 + +A power of two is a number that has only a single bit in it (e.g. $32 = 0010~0000_2$), while the predecessor of that number has that digit not set and all the digits after it set ($31 = 0001~1111_2$). +So the bitwise AND of a number with it's predecessor will always be 0, as they don't have any common digits set. +You can easily check that this only happens for the the power of twos and for the number $0$ which already has no digit set. ``` cpp -bool powerTwo = n && !(n & (n - 1)); +bool isPowerOfTwo(unsigned int n) { + return n && !(n & (n - 1)); +} ``` -## Clear the most-right set bit +### Clear the most-right set bit -The expression **n & (n-1)** can be used to turn off the rightmost set bit of a number **n**. This works like the expression **n-1** flips all bits after the rightmost set bit of n, including the rightmost set bit. Therefore, **n & (n-1)** returns the last flipped bit of **n**. +The expression $n ~\&~ (n-1)$ can be used to turn off the rightmost set bit of a number $n$. +This works because the expression $n-1$ flips all bits after the rightmost set bit of $n$, including the rightmost set bit. +So all those digits are different from the original number, and by doing a bitwise AND they are all set to 0, giving you the original number $n$ with the rightmost set bit flipped. -For example, consider the number 52, which is 00110100 in binary, and has a total set of 3 bits. +For example, consider the number $52 = 0011~0100_2$: ``` -1st iteration of the loop: n = 52 - -00110100 & (n) -00110011 (n-1) -~~~~~~~~ -00110000 -``` - -``` -2nd iteration of the loop: n = 48 - -00110000 & (n) -00101111 (n-1) -~~~~~~~~ -00100000 -``` - -``` -3rd iteration of the loop: n = 32 - -00100000 & (n) -00011111 (n-1) -~~~~~~~~ -00000000 (n = 0) +n = 00110100 +n-1 = 00110011 +-------------------- +n & (n-1) = 00110000 ``` -## Brian Kernighan's algorithm. +### Brian Kernighan's algorithm We can count the number of bits set with the above expression. @@ -161,21 +161,42 @@ The idea is to consider only the set bits of an integer by turning off its right int countSetBits(int n) { int count = 0; - while (n) { n = n & (n - 1); count++; } - return count; } ``` -Additionally, there are also predefined functions in C++, to count the number of bits in a representation. +### Addtional tricks + +- $n ~\&~ (n + 1)$ clears all trailing ones: $0011~0111_2 \rightarrow 0011~0000_2$. +- $n ~|~ (n + 1)$ sets the last cleared bit: $0011~0101_2 \rightarrow 0011~0111_2$. +- $n ~\&~ -n$ extracts the last set bit: $0011~0100_2 \rightarrow 0000~0100_2$. + +Many more can be found in the book [Hacker's Delight](https://en.wikipedia.org/wiki/Hacker%27s_Delight). + +### Language and compiler support + +C++ supports some of those operations since C++20 via the [bit](https://en.cppreference.com/w/cpp/header/bit) standard library: + +- `has_single_bit`: checks if the number is a power of two +- `bit_ceil` / `bit_floor`: round up/down to the next power of two +- `rotl` / `rotr`: rotate the bits in the number +- `countl_zero` / `countr_zero` / `countl_one` / `countr_one`: count the leading/trailing zeros/ones +- `popcount`: count the number of set bits + +Additionally, there are also predefined functions in some compilers that help working with bits. +E.g. GCC defines a list at [Built-in Functions Provided by GCC](https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html) that also work in older versions of C++: + +- `__builtin_popcount(unsigned int)` returns the number of set bits (`__builtin_popcount(0b0001'0010'1100) == 4`) +- `__builtin_ffs(int)` finds the index of the first (most right) set bit (`__builtin_ffs(0b0001'0010'1100) == 3`) +- `__builtin_clz(unsigned int)` the count of leading zeros (`__builtin_clz(0b0001'0010'1100) == 23`) +- `__builtin_ctz(unsigned int)` the count of trailing zeros (`__builtin_ctz(0b0001'0010'1100) == 2`) -1. ```__builtin_popcount(number)``` number of bits set. -2. ```__builtin_ctz(number)``` number of bits cleared. +_Note that some of the operations (both the C++20 functions and the Compiler Built-in ones) might be quite slow in GCC if you don't enable a specific compiler target with `#pragma GCC target("popcnt")`._ ## Practice Problems From c2676eaedeea770a0423ff7bcbca07e6fd7d74fa Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sun, 16 Apr 2023 22:52:24 +0200 Subject: [PATCH 045/590] Fix link of Setun computer image Closes #1075 --- src/algebra/balanced-ternary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algebra/balanced-ternary.md b/src/algebra/balanced-ternary.md index 6e9cdfa73..12e4d4ddc 100644 --- a/src/algebra/balanced-ternary.md +++ b/src/algebra/balanced-ternary.md @@ -6,7 +6,7 @@ e_maxx_link: balanced_ternary # Balanced Ternary -!["Setun computer using Balanced Ternary system"](http://ternary.3neko.ru/photo/setun1_small.jpg) +!["Setun computer using Balanced Ternary system"](https://earltcampbell.files.wordpress.com/2014/12/setun.jpeg?w=300) This is a non-standard but still positional **numeral system**. Its feature is that digits can have one of the values `-1`, `0` and `1`. Nevertheless, its base is still `3` (because there are three possible values). Since it is not convenient to write `-1` as a digit, From b19ce682f3811716e8c4efda0404e3c4a3fc1ba3 Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Mon, 17 Apr 2023 20:50:59 +0200 Subject: [PATCH 046/590] clarification about search on SBT --- .../stern_brocot_tree_farey_sequences.md | 72 ++++++++++++++++--- 1 file changed, 63 insertions(+), 9 deletions(-) diff --git a/src/others/stern_brocot_tree_farey_sequences.md b/src/others/stern_brocot_tree_farey_sequences.md index e0361150b..47f765900 100644 --- a/src/others/stern_brocot_tree_farey_sequences.md +++ b/src/others/stern_brocot_tree_farey_sequences.md @@ -135,22 +135,76 @@ void build(int a = 0, int b = 1, int c = 1, int d = 0, int level = 1) { The search algorithm was already described in the proof that all fractions appear in the tree, but we will repeat it here. The algorithm is a binary search algorithm. Initially we stand at the root of the tree and we compare our target with the current fraction. If they are the same we are done and stop the process. If our target is smaller we move to the left child, otherwise we move to the right child. -Here is an implementation that returns the path to a given fraction $\frac{x}{y}$ as a sequence of `'L'` and `'R'` characters, meaning traversal to the left and right child respectively. This sequence of characters uniquely defines all positive fractions and is called the Stern-Brocot number system. +### Naive search + +Here is an implementation that returns the path to a given fraction $\frac{p}{q}$ as a sequence of `'L'` and `'R'` characters, meaning traversal to the left and right child respectively. This sequence of characters uniquely defines all positive fractions and is called the Stern-Brocot number system. ```cpp -string find(int x, int y, int a = 0, int b = 1, int c = 1, int d = 0) { - int m = a + c, n = b + d; - if (x == m && y == n) - return ""; - if (x*n < y*m) - return 'L' + find(x, y, a, b, m, n); - else - return 'R' + find(x, y, m, n, c, d); +string find(int p, int q) { + int pL = 0, qL = 1; + int pR = 1, qR = 0; + int pM = 1, qM = 1; + string res; + while(pM != p || qM != q) { + if(p * qM < pM * q) { + res += 'L'; + tie(pR, qR) = {pM, qM}; + } else { + res += 'R'; + tie(pL, qL) = {pM, qM}; + } + tie(pM, qM) = pair{pL + pR, qL + qR}; + } + return res; } ``` Irrational numbers in the Stern-Brocot number system corresponds to infinite sequences of characters. Along the endless path towards the irrational number the algorithm will find reduced fractions with gradually increasing denominators that provides increasingly better approximations of the irrational number. So by taking a prefix of the infinite sequence approximations with any desired precision can be achieved. This application is important in watch-making, which explains why the tree was discovered in that domain. +Note that for a fraction $\frac{p}{q}$, the length of the resulting sequence could be as large as $O(p+q)$, for example when the fraction is of form $\frac{p}{1}$. This means that the algorithm above **should not be used, unless this is an acceptable complexity**! + +### Logarithmic search + +Fortunately, it is possible to enhance the algorithm above to guarantee $O(\log (p+q))$ complexity. For this we should note that if the current boundary fractions are $\frac{p_L}{q_L}$ and $\frac{p_R}{q_R}$, then by doing $a$ steps to the right we move to the fraction $\frac{p_L + a p_R}{q_L + a q_R}$, and by doing $a$ steps to the left, we move to the fraction $\frac{a p_L + p_R}{a q_L + q_R}$. + +Therefore, instead of doing steps of `L` or `R` one by one, we can do $k$ steps in the same direction at once, after which we would switch to going into other direction, and so on. In this way, we can find the path to the fraction $\frac{p}{q}$ as its run-length encoding. + +As the directions alternate this way, we will always know which one to take. So, for convenience we may represent a path to a fraction $\frac{p}{q}$ as a sequence of fractions + +$$ +\frac{p_0}{q_0}, \frac{p_1}{q_1}, \frac{p_2}{q_2}, \dots, \frac{p_n}{q_n}, \frac{p_{n+1}}{q_{n+1}} = \frac{p}{q} +$$ + +such that $\frac{p_{k-1}}{q_{k-1}}$ and $\frac{p_k}{q_k}$ are the boundaries of the search interval on the $k$-th step, starting with $\frac{p_0}{q_0} = \frac{0}{1}$ and $\frac{p_1}{q_1} = \frac{1}{0}$. Then, after the $k$-th step we move to a fraction + +$$ +\frac{p_{k+1}}{q_{k+1}} = \frac{p_{k-1} + a_k p_k}{q_{k-1} + a_k q_k}, +$$ + +where $a_k$ is a positive integer number. If you're familiar with [continued fractions](), you would recognize that the sequence $\frac{p_i}{q_i}$ is the sequence of the convergent fractions of $\frac{p}{q}$ and the sequence $[a_1; a_2, \dots, a_{n}, 1]$ represents the continued fraction of $\frac{p}{q}$. + +This allows to find the run-length encoding of the path to $\frac{p}{q}$ in the manner which follows the algorithm for computing continued fraction representation of the fraction $\frac{p}{q}$: + +```cpp +auto find(int p, int q) { + bool right = true; + vector> res; + while(q) { + res.emplace_back(p / q, right ? 'R' : 'L'); + tie(p, q) = pair{q, p % q}; + right ^= 1; + } + res.back().first--; + return res; +} +``` + +However, this approach only works if we already know $\frac{p}{q}$ and want to find its place in the Stern-Brocot tree. + +On practice, it is often the case that $\frac{p}{q}$ is not known in advance, but we are able to check for specific $\frac{x}{y}$ whether $\frac{x}{y} < \frac{p}{q}$. + +Knowing this, we can emulate the search on Stern-Brocot tree by maintaining the current boundaries $\frac{p_{k-1}}{q_{k-1}}$ and $\frac{p_k}{q_k}$, and finding each $a_k$ via binary search. The algorithm then is a bit more technical and potentially have a complexity of $O(\log^2(x+y))$, unless the problem formulation allows you to find $a_k$ faster (for example, using `floor` of some known expression). + ## Farey Sequence The Farey sequence of order $n$ is the sorted sequence of fractions between $0$ and $1$ whose denominators do not exceed $n$. From c6a9ad6fe8586c13367ec45c007c2986b54242b0 Mon Sep 17 00:00:00 2001 From: snymm2 <131008890+snymm2@users.noreply.github.com> Date: Mon, 17 Apr 2023 21:03:31 +0545 Subject: [PATCH 047/590] Typo: "Module Operator" -> "Modulo Operator" --- src/algebra/binary-exp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algebra/binary-exp.md b/src/algebra/binary-exp.md index 417c391bc..595b44e63 100644 --- a/src/algebra/binary-exp.md +++ b/src/algebra/binary-exp.md @@ -96,7 +96,7 @@ Compute $x^n \bmod m$. This is a very common operation. For instance it is used in computing the [modular multiplicative inverse](module-inverse.md). **Solution:** -Since we know that the module operator doesn't interfere with multiplications ($a \cdot b \equiv (a \bmod m) \cdot (b \bmod m) \pmod m$), we can directly use the same code, and just replace every multiplication with a modular multiplication: +Since we know that the modulo operator doesn't interfere with multiplications ($a \cdot b \equiv (a \bmod m) \cdot (b \bmod m) \pmod m$), we can directly use the same code, and just replace every multiplication with a modular multiplication: ```cpp long long binpow(long long a, long long b, long long m) { From 8a0a5dce1898cb4db3cffddeaf9f337ec3c73608 Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Tue, 18 Apr 2023 00:38:07 +0200 Subject: [PATCH 048/590] we don't use these toggles anymore --- src/graph/bridge-searching.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graph/bridge-searching.md b/src/graph/bridge-searching.md index 5195a6376..dc7cf70b4 100644 --- a/src/graph/bridge-searching.md +++ b/src/graph/bridge-searching.md @@ -40,7 +40,7 @@ The implementation needs to distinguish three cases: when we go down the edge in To implement this, we need a depth first search function which accepts the parent vertex of the current node. -C++ implementation Show/Hide +C++ implementation ```cpp int n; // number of nodes From 8ec5eb10ff7a034d8234f8c4407e08f182af53f8 Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Tue, 18 Apr 2023 00:38:52 +0200 Subject: [PATCH 049/590] we don't use toggles anymore --- src/graph/cutpoints.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/graph/cutpoints.md b/src/graph/cutpoints.md index 8d7279612..46f7676b7 100644 --- a/src/graph/cutpoints.md +++ b/src/graph/cutpoints.md @@ -40,8 +40,6 @@ The implementation needs to distinguish three cases: when we go down the edge in To implement this, we need a depth first search function which accepts the parent vertex of the current node. -C++ implementation Show/Hide - ```cpp int n; // number of nodes vector> adj; // adjacency list of graph From aa6959b4a49961bf093cdf3cdbc124859b157772 Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Tue, 18 Apr 2023 00:39:27 +0200 Subject: [PATCH 050/590] no need to announce the implementation --- src/graph/bridge-searching.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/graph/bridge-searching.md b/src/graph/bridge-searching.md index dc7cf70b4..2d6596878 100644 --- a/src/graph/bridge-searching.md +++ b/src/graph/bridge-searching.md @@ -40,8 +40,6 @@ The implementation needs to distinguish three cases: when we go down the edge in To implement this, we need a depth first search function which accepts the parent vertex of the current node. -C++ implementation - ```cpp int n; // number of nodes vector> adj; // adjacency list of graph From ab68c65c43ea8c0148d3d2f1b6113e9e00661447 Mon Sep 17 00:00:00 2001 From: Deji Oyerinde Date: Sat, 18 Mar 2023 18:58:02 -0400 Subject: [PATCH 051/590] Update catalan-numbers.md I wasn't sure why this article said "C++ Implementation Show/Hide". This PR here that I've edited allows for collapsible code sections (which I assume was the intention). However,I've seen other articles that don't have collapsible code sections so I wasn't quite sure if this was wanted here or not. Please let me know! --- src/combinatorics/catalan-numbers.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/combinatorics/catalan-numbers.md b/src/combinatorics/catalan-numbers.md index 8ede5e92c..471983d18 100644 --- a/src/combinatorics/catalan-numbers.md +++ b/src/combinatorics/catalan-numbers.md @@ -47,7 +47,10 @@ You can also think it in this manner. By definition, $C_n$ denotes number of cor $( ) ( ( ) )$ can be divided into $( )$ and $( ( ) )$, but cannot be divided into $( ) ($ and $( ) )$. Again summing over all admissible $k's$, we get the recurrence relation on $C_n$. -#### C++ implementation Show/Hide +#### C++ implementation + +
+Click here to show/hide code ```cpp const int MOD = .... @@ -66,6 +69,7 @@ void init() { } } ``` +
### Analytical formula From a5f0bb9aaa189813e3053d1ec21e780ed26c8d22 Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Tue, 18 Apr 2023 00:35:23 +0200 Subject: [PATCH 052/590] code shouldn't be hidden --- src/combinatorics/catalan-numbers.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/combinatorics/catalan-numbers.md b/src/combinatorics/catalan-numbers.md index 471983d18..02da0128e 100644 --- a/src/combinatorics/catalan-numbers.md +++ b/src/combinatorics/catalan-numbers.md @@ -49,9 +49,6 @@ $( ) ( ( ) )$ can be divided into $( )$ and $( ( ) )$, but cannot be divided int #### C++ implementation -
-Click here to show/hide code - ```cpp const int MOD = .... const int MAX = .... @@ -69,7 +66,7 @@ void init() { } } ``` -
+ ### Analytical formula From 91829087d10285be502398837d7d4c906665b514 Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Tue, 18 Apr 2023 00:36:28 +0200 Subject: [PATCH 053/590] no need for extra newline --- src/combinatorics/catalan-numbers.md | 1 - 1 file changed, 1 deletion(-) diff --git a/src/combinatorics/catalan-numbers.md b/src/combinatorics/catalan-numbers.md index 02da0128e..d3fa1ce64 100644 --- a/src/combinatorics/catalan-numbers.md +++ b/src/combinatorics/catalan-numbers.md @@ -67,7 +67,6 @@ void init() { } ``` - ### Analytical formula $$C_n = \frac{1}{n + 1} {\binom{2n}{n}}$$ From 35ac565880f61bde0828a7787bb7d4d093fc6295 Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Tue, 18 Apr 2023 21:46:11 +0200 Subject: [PATCH 054/590] add new article to front page --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 14a479e48..33501b697 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ Compiled pages are published at [https://cp-algorithms.com/](https://cp-algorith ### New articles +- (18 April 2023) [Bit manipulation](https://cp-algorithms.com/algebra/bit-manipulation.md) - (17 October 2022) [Binary Search](https://cp-algorithms.com/num_methods/binary_search.html) - (17 October 2022) [MEX (Minimum Excluded element in an array)](https://cp-algorithms.com/sequences/mex.html) - (12 May 2022) [Factoring Exponentiation](https://cp-algorithms.com/algebra/factoring-exp.html) From 2b27ef65056dd6915d7e7aa2faf073580161a733 Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Tue, 18 Apr 2023 21:46:11 +0200 Subject: [PATCH 055/590] add new article to front page --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 33501b697..fb01878a9 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Compiled pages are published at [https://cp-algorithms.com/](https://cp-algorith ### New articles -- (18 April 2023) [Bit manipulation](https://cp-algorithms.com/algebra/bit-manipulation.md) +- (18 April 2023) [Bit manipulation](https://cp-algorithms.com/algebra/bit-manipulation.html) - (17 October 2022) [Binary Search](https://cp-algorithms.com/num_methods/binary_search.html) - (17 October 2022) [MEX (Minimum Excluded element in an array)](https://cp-algorithms.com/sequences/mex.html) - (12 May 2022) [Factoring Exponentiation](https://cp-algorithms.com/algebra/factoring-exp.html) From 84821c60b837c85ffa9a7abc25a96ee16c38f988 Mon Sep 17 00:00:00 2001 From: Michael Hayter Date: Thu, 20 Apr 2023 02:12:16 -0400 Subject: [PATCH 056/590] change set to unordered_set making distinct substrings O(n^2) Wasn't sure why we used set rather than unordered_set to store unique hashes. This should lower the runtime from O(n^2*log(n)) to O(n^2). --- src/string/string-hashing.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/string/string-hashing.md b/src/string/string-hashing.md index 11228612b..afa49bf2c 100644 --- a/src/string/string-hashing.md +++ b/src/string/string-hashing.md @@ -142,7 +142,7 @@ By doing this, we get both the hashes multiplied by the same power of $p$ (which Here are some typical applications of Hashing: * [Rabin-Karp algorithm](rabin-karp.md) for pattern matching in a string in $O(n)$ time -* Calculating the number of different substrings of a string in $O(n^2 \log n)$ (see below) +* Calculating the number of different substrings of a string in $O(n^2)$ (see below) * Calculating the number of palindromic substrings in a string. ### Determine the number of different substrings in a string @@ -173,7 +173,7 @@ int count_unique_substrings(string const& s) { int cnt = 0; for (int l = 1; l <= n; l++) { - set hs; + unordered_set hs; for (int i = 0; i <= n - l; i++) { long long cur_h = (h[i + l] + m - h[i]) % m; cur_h = (cur_h * p_pow[n-i-1]) % m; From 3d29232e7d13befe66a931cc219987db72f32133 Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sat, 22 Apr 2023 20:41:47 +0200 Subject: [PATCH 057/590] modernize bellman-ford code --- src/graph/bellman_ford.md | 111 ++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 59 deletions(-) diff --git a/src/graph/bellman_ford.md b/src/graph/bellman_ford.md index 99548f5f5..6f29fc016 100644 --- a/src/graph/bellman_ford.md +++ b/src/graph/bellman_ford.md @@ -20,7 +20,7 @@ Let us assume that the graph contains no negative weight cycle. The case of pres We will create an array of distances $d[0 \ldots n-1]$, which after execution of the algorithm will contain the answer to the problem. In the beginning we fill it as follows: $d[v] = 0$, and all other elements $d[ ]$ equal to infinity $\infty$. -The algorithm consists of several phases. Each phase scans through all edges of the graph, and the algorithm tries to produce relaxation along each edge $(a,b)$ having weight $c$. Relaxation along the edges is an attempt to improve the value $d[b]$ using value $d[a] + c$. In fact, it means that we are trying to improve the answer for this vertex using edge $(a,b)$ and current response for vertex $a$. +The algorithm consists of several phases. Each phase scans through all edges of the graph, and the algorithm tries to produce **relaxation** along each edge $(a,b)$ having weight $c$. Relaxation along the edges is an attempt to improve the value $d[b]$ using value $d[a] + c$. In fact, it means that we are trying to improve the answer for this vertex using edge $(a,b)$ and current response for vertex $a$. It is claimed that $n-1$ phases of the algorithm are sufficient to correctly calculate the lengths of all shortest paths in the graph (again, we believe that the cycles of negative weight do not exist). For unreachable vertices the distance $d[ ]$ will remain equal to infinity $\infty$. @@ -33,28 +33,27 @@ Unlike many other graph algorithms, for Bellman-Ford algorithm, it is more conve The constant $\rm INF$ denotes the number "infinity" — it should be selected in such a way that it is greater than all possible path lengths. ```cpp -struct edge -{ +struct Edge { int a, b, cost; }; int n, m, v; -vector e; +vector edges; const int INF = 1000000000; void solve() { - vector d (n, INF); + vector d(n, INF); d[v] = 0; - for (int i=0; i d (n, INF); + vector d(n, INF); d[v] = 0; - for (;;) - { + for (;;) { bool any = false; - for (int j=0; j d[e[j].a] + e[j].cost) - { - d[e[j].b] = d[e[j].a] + e[j].cost; + for (Edge e : edges) + if (d[e.a] < INF) + if (d[e.b] > d[e.a] + e.cost) { + d[e.b] = d[e.a] + e.cost; any = true; } - if (!any) break; + if (!any) + break; } // display d, for example, on the screen } @@ -98,36 +96,34 @@ Following is an implementation of the Bellman-Ford with the retrieval of shortes ```cpp void solve() { - vector d (n, INF); + vector d(n, INF); d[v] = 0; - vector p (n, -1); + vector p(n, -1); - for (;;) - { + for (;;) { bool any = false; - for (int j = 0; j < m; ++j) - if (d[e[j].a] < INF) - if (d[e[j].b] > d[e[j].a] + e[j].cost) - { - d[e[j].b] = d[e[j].a] + e[j].cost; - p[e[j].b] = e[j].a; + for (Edge e : edges) + if (d[e.a] < INF) + if (d[e.b] > d[e.a] + e.cost) { + d[e.b] = d[e.a] + e.cost; + p[e.b] = e.a; any = true; } - if (!any) break; + if (!any) + break; } if (d[t] == INF) cout << "No path from " << v << " to " << t << "."; - else - { + else { vector path; for (int cur = t; cur != -1; cur = p[cur]) - path.push_back (cur); - reverse (path.begin(), path.end()); + path.push_back(cur); + reverse(path.begin(), path.end()); cout << "Path from " << v << " to " << t << ": "; - for (size_t i=0; iProof: Consider an arbitrary vertex $a$ to which there is a path from the starting vertex $v$, and consider a shortest path to it $(p_0=v, p_1, \ldots, p_k=a)$. Before the first phase, the shortest path to the vertex $p_0 = v$ was found correctly. During the first phase, the edge $(p_0,p_1)$ has been checked by the algorithm, and therefore, the distance to the vertex $p_1$ was correctly calculated after the first phase. Repeating this statement $k$ times, we see that after $k_{th}$ phase the distance to the vertex $p_k = a$ gets calculated correctly, which we wanted to prove. +**Proof**: +Consider an arbitrary vertex $a$ to which there is a path from the starting vertex $v$, and consider a shortest path to it $(p_0=v, p_1, \ldots, p_k=a)$. Before the first phase, the shortest path to the vertex $p_0 = v$ was found correctly. During the first phase, the edge $(p_0,p_1)$ has been checked by the algorithm, and therefore, the distance to the vertex $p_1$ was correctly calculated after the first phase. Repeating this statement $k$ times, we see that after $k_{th}$ phase the distance to the vertex $p_k = a$ gets calculated correctly, which we wanted to prove. The last thing to notice is that any shortest path cannot have more than $n - 1$ edges. Therefore, the algorithm sufficiently goes up to the $(n-1)_{th}$ phase. After that, it is guaranteed that no relaxation will improve the distance to some vertex. @@ -152,7 +149,7 @@ Everywhere above we considered that there is no negative cycle in the graph (pre It is easy to see that the Bellman-Ford algorithm can endlessly do the relaxation among all vertices of this cycle and the vertices reachable from it. Therefore, if you do not limit the number of phases to $n - 1$, the algorithm will run indefinitely, constantly improving the distance from these vertices. -Hence we obtain the criterion for presence of a cycle of negative weights reachable for source vertex $v$: after $(n-1)_{th}$ phase, if we run algorithm for one more phase, and it performs at least one more relaxation, then the graph contains a negative weight cycle that is reachable from $v$; otherwise, such a cycle does not exist. +Hence we obtain the **criterion for presence of a cycle of negative weights reachable for source vertex $v$**: after $(n-1)_{th}$ phase, if we run algorithm for one more phase, and it performs at least one more relaxation, then the graph contains a negative weight cycle that is reachable from $v$; otherwise, such a cycle does not exist. Moreover, if such a cycle is found, the Bellman-Ford algorithm can be modified so that it retrieves this cycle as a sequence of vertices contained in it. For this, it is sufficient to remember the last vertex $x$ for which there was a relaxation in $n_{th}$ phase. This vertex will either lie in a negative weight cycle, or is reachable from it. To get the vertices that are guaranteed to lie in a negative cycle, starting from the vertex $x$, pass through to the predecessors $n$ times. Hence we will get the vertex $y$, namely the vertex in the cycle earliest reachable from source. We have to go from this vertex, through the predecessors, until we get back to the same vertex $y$ (and it will happen, because relaxation in a negative weight cycle occur in a circular manner). @@ -161,43 +158,39 @@ Moreover, if such a cycle is found, the Bellman-Ford algorithm can be modified s ```cpp void solve() { - vector d (n, INF); + vector d(n, INF); d[v] = 0; - vector p (n, - 1); + vector p(n, -1); int x; - for (int i=0; i d[e[j].a] + e[j].cost) - { - d[e[j].b] = max (-INF, d[e[j].a] + e[j].cost); - p[e[j].b] = e[j].a; - x = e[j].b; + for (Edge e : edges) + if (d[e.a] < INF) + if (d[e.b] > d[e.a] + e.cost) { + d[e.b] = max(-INF, d[e.a] + e.cost); + p[e.b] = e.a; + x = e.b; } } if (x == -1) cout << "No negative cycle from " << v; - else - { + else { int y = x; - for (int i=0; i path; - for (int cur=y; ; cur=p[cur]) - { - path.push_back (cur); + for (int cur = y;; cur = p[cur]) { + path.push_back(cur); if (cur == y && path.size() > 1) break; } - reverse (path.begin(), path.end()); + reverse(path.begin(), path.end()); cout << "Negative cycle: "; - for (size_t i=0; i Date: Sat, 22 Apr 2023 21:16:07 +0200 Subject: [PATCH 058/590] fix failing test --- test/test_hashing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_hashing.cpp b/test/test_hashing.cpp index d3145c433..c9738edcf 100644 --- a/test/test_hashing.cpp +++ b/test/test_hashing.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include From e949b36d0c079da4d2914c37b9e3d12939930891 Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sat, 22 Apr 2023 21:16:29 +0200 Subject: [PATCH 059/590] info about fast distinct-substring computation with suffix arrays/trees --- src/string/string-hashing.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/string/string-hashing.md b/src/string/string-hashing.md index afa49bf2c..5ce399283 100644 --- a/src/string/string-hashing.md +++ b/src/string/string-hashing.md @@ -185,6 +185,9 @@ int count_unique_substrings(string const& s) { } ``` +Notice, that $O(n^2)$ is not the best possible time complexity for this problem. +A solution with $O(n \log n)$ is described in the article about [Suffix Arrays](suffix-array.md), and it's even possible to compute it in $O(n)$ using a [Suffix Tree](./suffix-tree-ukkonen.md) or a [Suffix Automaton](./suffix-automaton.md). + ## Improve no-collision probability Quite often the above mentioned polynomial hash is good enough, and no collisions will happen during tests. From 03f54f3779cbb670d3c493219477bce874c2e270 Mon Sep 17 00:00:00 2001 From: Michael Clock <85312805+MichaelStudies@users.noreply.github.com> Date: Mon, 24 Apr 2023 16:01:31 +0200 Subject: [PATCH 060/590] =?UTF-8?q?than=20=E2=80=94>=20then?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A minor spelling mistake in balanced bracket sequences --- src/combinatorics/bracket_sequences.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/combinatorics/bracket_sequences.md b/src/combinatorics/bracket_sequences.md index c737e1aa5..6d7de00a0 100644 --- a/src/combinatorics/bracket_sequences.md +++ b/src/combinatorics/bracket_sequences.md @@ -29,7 +29,7 @@ For this case there exists a very simple algorithm. Let $\text{depth}$ be the current number of open brackets. Initially $\text{depth} = 0$. We iterate over all character of the string, if the current bracket character is an opening bracket, then we increment $\text{depth}$, otherwise we decrement it. -If at any time the variable $\text{depth}$ gets negative, or at the end it is different from $0$, than the string is not a balances sequence. +If at any time the variable $\text{depth}$ gets negative, or at the end it is different from $0$, then the string is not a balances sequence. Otherwise it is. If there are several bracket types involved, then the algorithm needs to be changes. From bd20cdd38a1a2a3749e67d8189e9a9d298f7f8bd Mon Sep 17 00:00:00 2001 From: Michael Clock <85312805+MichaelStudies@users.noreply.github.com> Date: Mon, 24 Apr 2023 16:05:51 +0200 Subject: [PATCH 061/590] =?UTF-8?q?balances=20=E2=80=94>=20balanced?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/combinatorics/bracket_sequences.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/combinatorics/bracket_sequences.md b/src/combinatorics/bracket_sequences.md index 6d7de00a0..ce8aa9542 100644 --- a/src/combinatorics/bracket_sequences.md +++ b/src/combinatorics/bracket_sequences.md @@ -29,7 +29,7 @@ For this case there exists a very simple algorithm. Let $\text{depth}$ be the current number of open brackets. Initially $\text{depth} = 0$. We iterate over all character of the string, if the current bracket character is an opening bracket, then we increment $\text{depth}$, otherwise we decrement it. -If at any time the variable $\text{depth}$ gets negative, or at the end it is different from $0$, then the string is not a balances sequence. +If at any time the variable $\text{depth}$ gets negative, or at the end it is different from $0$, then the string is not a balanced sequence. Otherwise it is. If there are several bracket types involved, then the algorithm needs to be changes. From 31c757ff7f5d22f103126d5004b9d81d653309bf Mon Sep 17 00:00:00 2001 From: Michael Hayter Date: Wed, 26 Apr 2023 04:45:02 -0400 Subject: [PATCH 062/590] Display issue (spaces vs tabs) with z_function Both Brave and Edge show spacing issue. --- src/string/z-function.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/string/z-function.md b/src/string/z-function.md index 87027e2f0..632eddc43 100644 --- a/src/string/z-function.md +++ b/src/string/z-function.md @@ -93,9 +93,9 @@ vector z_function(string s) { vector z(n); int l = 0, r = 0; for(int i = 1; i < n; i++) { - if(i < r) { + if(i < r) { z[i] = min(r - i, z[i - l]); - } + } while(s[z[i]] == s[i + z[i]]) { z[i]++; } From 4a1113386930220be9066f3ac4e6e35bc3a07452 Mon Sep 17 00:00:00 2001 From: Michael Hayter Date: Sun, 30 Apr 2023 07:33:19 -0400 Subject: [PATCH 063/590] Quick edit + partially addressing Issue #924. Change minlength(v) to minlen(v) for consistency. Issue #924 improvement. Will complete after feedback! --- src/string/suffix-automaton.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/string/suffix-automaton.md b/src/string/suffix-automaton.md index 2ae0771c4..5037ab906 100644 --- a/src/string/suffix-automaton.md +++ b/src/string/suffix-automaton.md @@ -193,7 +193,7 @@ Before proceeding to the algorithm itself, we recap the accumulated knowledge, a - For each state $v$ one or multiple substrings match. We denote by $longest(v)$ the longest such string, and through $len(v)$ its length. We denote by $shortest(v)$ the shortest such substring, and its length with $minlen(v)$. - Then all the strings corresponding to this state are different suffixes of the string $longest(v)$ and have all possible lengths in the interval $[minlength(v); len(v)]$. + Then all the strings corresponding to this state are different suffixes of the string $longest(v)$ and have all possible lengths in the interval $[minlen(v); len(v)]$. - For each state $v \ne t_0$ a suffix link is defined as a link, that leads to a state that corresponds to the suffix of the string $longest(v)$ of length $minlen(v) - 1$. The suffix links form a tree with the root in $t_0$, and at the same time this tree forms an inclusion relationship between the sets $endpos$. - We can express $minlen(v)$ for $v \ne t_0$ using the suffix link $link(v)$ as: @@ -494,6 +494,21 @@ The number of different substrings is the value $d[t_0] - 1$ (since we don't cou Total time complexity: $O(length(S))$ + +Alternatively, we can take advantage of the fact that each state $v$ matches to substrings of length $[minlen(v),len(v)]$. +Therefore, given $minlen(v) = 1 + len(link(v))$, we have total distinct substrings at state $v$ being $len(v) - minlen(v) + 1 = len(v) - 1 + len(link(v)) + 1 = len(v) - len(link(v))$. + +This is demonstrated succinctly below: + +```cpp +long long tot{}; +for(int i=1;i Date: Sun, 30 Apr 2023 21:01:18 -0400 Subject: [PATCH 064/590] Forgot parenthesis around minlen(v) expansion --- src/string/suffix-automaton.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string/suffix-automaton.md b/src/string/suffix-automaton.md index 5037ab906..554a7d627 100644 --- a/src/string/suffix-automaton.md +++ b/src/string/suffix-automaton.md @@ -496,7 +496,7 @@ Total time complexity: $O(length(S))$ Alternatively, we can take advantage of the fact that each state $v$ matches to substrings of length $[minlen(v),len(v)]$. -Therefore, given $minlen(v) = 1 + len(link(v))$, we have total distinct substrings at state $v$ being $len(v) - minlen(v) + 1 = len(v) - 1 + len(link(v)) + 1 = len(v) - len(link(v))$. +Therefore, given $minlen(v) = 1 + len(link(v))$, we have total distinct substrings at state $v$ being $len(v) - minlen(v) + 1 = len(v) - (1 + len(link(v))) + 1 = len(v) - len(link(v))$. This is demonstrated succinctly below: From da025de7bda78c323c317cc9e74b71334b21233b Mon Sep 17 00:00:00 2001 From: Michael Hayter Date: Sun, 30 Apr 2023 22:08:28 -0400 Subject: [PATCH 065/590] Updated c++ code to work on current style of suffix automaton This is tested on current suffix automaton. Also, made more modular --- src/string/suffix-automaton.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/string/suffix-automaton.md b/src/string/suffix-automaton.md index 554a7d627..de4ae289a 100644 --- a/src/string/suffix-automaton.md +++ b/src/string/suffix-automaton.md @@ -501,9 +501,12 @@ Therefore, given $minlen(v) = 1 + len(link(v))$, we have total distinct substrin This is demonstrated succinctly below: ```cpp -long long tot{}; -for(int i=1;i Date: Tue, 2 May 2023 02:00:18 -0400 Subject: [PATCH 066/590] complete issue #924 I've now resolved issue #924. I added new techniques to calculating the total length of different strings. --- src/string/suffix-automaton.md | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/string/suffix-automaton.md b/src/string/suffix-automaton.md index de4ae289a..46ec5db19 100644 --- a/src/string/suffix-automaton.md +++ b/src/string/suffix-automaton.md @@ -510,7 +510,7 @@ long long get_diff_strings(){ } ``` -While this is also $O(length(S))$, it requires no extra space besides (what's used for the suffix automaton construction) and no recursive calls, consequently running faster in practice. +While this is also $O(length(S))$, it requires no extra space and no recursive calls, consequently running faster in practice. ### Total length of all different substrings @@ -529,6 +529,26 @@ We take the answer of each adjacent vertex $w$, and add to it $d[w]$ (since ever Again this task can be computed in $O(length(S))$ time. +Alternatively, we can, again, take advantage of the fact that each state $v$ matches to substrings of length $[minlen(v),len(v)]$. +Since $minlen(v) = 1 + len(link(v))$ and the arimetic series formula $S[n] = n * (a[1]+a[n]) / 2$ (where $S[n]$ denotes the sum of $n$ terms,$a[1]$ representing the first term, and $a[n]$ representing the last), we can compute the length of substrings at a state in constant time. We then sum up these totals for each state $v \neq t[0]$ in the automaton. This is shown by the code below: + +```cpp +long long get_tot_len_diff_substings() { + long long tot{}; + for(int i=1;i Date: Tue, 2 May 2023 02:15:45 -0400 Subject: [PATCH 067/590] notation rendering changes notation changes as preview wasn't working. --- src/string/suffix-automaton.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string/suffix-automaton.md b/src/string/suffix-automaton.md index 46ec5db19..ec7ace253 100644 --- a/src/string/suffix-automaton.md +++ b/src/string/suffix-automaton.md @@ -530,7 +530,7 @@ We take the answer of each adjacent vertex $w$, and add to it $d[w]$ (since ever Again this task can be computed in $O(length(S))$ time. Alternatively, we can, again, take advantage of the fact that each state $v$ matches to substrings of length $[minlen(v),len(v)]$. -Since $minlen(v) = 1 + len(link(v))$ and the arimetic series formula $S[n] = n * (a[1]+a[n]) / 2$ (where $S[n]$ denotes the sum of $n$ terms,$a[1]$ representing the first term, and $a[n]$ representing the last), we can compute the length of substrings at a state in constant time. We then sum up these totals for each state $v \neq t[0]$ in the automaton. This is shown by the code below: +Since $minlen(v) = 1 + len(link(v))$ and the arithmetic series formula $S_n = n * (a_1+a_n) / 2$ (where $S_n$ denotes the sum of $n$ terms, $a_1$ representing the first term, and $a_n$ representing the last), we can compute the length of substrings at a state in constant time. We then sum up these totals for each state $v \neq t_0$ in the automaton. This is shown by the code below: ```cpp long long get_tot_len_diff_substings() { From 5cd5460b57e8218eba1b9c1906ab87599e1fd982 Mon Sep 17 00:00:00 2001 From: Dao Le Bao Minh Date: Tue, 2 May 2023 22:42:50 +0700 Subject: [PATCH 068/590] Update suffix-array.md small typo needs to be fixed --- src/string/suffix-array.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string/suffix-array.md b/src/string/suffix-array.md index c7d7fc2cb..63170e9e4 100644 --- a/src/string/suffix-array.md +++ b/src/string/suffix-array.md @@ -376,7 +376,7 @@ Thus we will not overlook any by accident. Because the suffixes are sorted, it is clear that the current suffix $p[i]$ will give new substrings for all its prefixes, except for the prefixes that coincide with the suffix $p[i-1]$. Thus, all its prefixes except the first $\text{lcp}[i-1]$ one. -Since the length of the current suffix is $n - p[i]$, $n - p[i] - \text{lcp}[i-1]$ new suffixes start at $p[i]$. +Since the length of the current suffix is $n - p[i]$, $n - p[i] - \text{lcp}[i-1]$ new prefixes start at $p[i]$. Summing over all the suffixes, we get the final answer: $$\sum_{i=0}^{n-1} (n - p[i]) - \sum_{i=0}^{n-2} \text{lcp}[i] = \frac{n^2 + n}{2} - \sum_{i=0}^{n-2} \text{lcp}[i]$$ From 27b663b12a6302dd74e28b7bdf9c626683ba2489 Mon Sep 17 00:00:00 2001 From: Cameron Custer Date: Sat, 6 May 2023 15:32:54 -0400 Subject: [PATCH 069/590] fix disjoint set union article typo --- src/data_structures/disjoint_set_union.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data_structures/disjoint_set_union.md b/src/data_structures/disjoint_set_union.md index d25f76900..96c41ab0c 100644 --- a/src/data_structures/disjoint_set_union.md +++ b/src/data_structures/disjoint_set_union.md @@ -381,7 +381,7 @@ Therefore we receive the formula ($\oplus$ denotes the XOR operation): $$t = x \oplus y \oplus 1$$ -Thus regardless of how many joins we perform, the parity of the edges is carried from on leader to another. +Thus regardless of how many joins we perform, the parity of the edges is carried from one leader to another. We give the implementation of the DSU that supports parity. As in the previous section we use a pair to store the ancestor and the parity. In addition for each set we store in the array `bipartite[]` whether it is still bipartite or not. From af01de8daa0356a4d1b391362d0f4bbc203bb604 Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sun, 7 May 2023 11:55:15 +0200 Subject: [PATCH 070/590] fix some formatting --- src/string/suffix-automaton.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/string/suffix-automaton.md b/src/string/suffix-automaton.md index ec7ace253..07afdbe5d 100644 --- a/src/string/suffix-automaton.md +++ b/src/string/suffix-automaton.md @@ -502,9 +502,9 @@ This is demonstrated succinctly below: ```cpp long long get_diff_strings(){ - ll tot{}; - for(int i=1;i Date: Sun, 14 May 2023 15:41:48 -0700 Subject: [PATCH 071/590] fix z_function --- src/string/z-function.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/string/z-function.md b/src/string/z-function.md index 632eddc43..c83938cb4 100644 --- a/src/string/z-function.md +++ b/src/string/z-function.md @@ -33,7 +33,7 @@ vector z_function_trivial(string s) { int n = s.size(); vector z(n); for (int i = 1; i < n; i++) { - while (s[z[i]] == s[i + z[i]]) { + while (i + z[i] < n && s[z[i]] == s[i + z[i]]) { z[i]++; } } @@ -96,7 +96,7 @@ vector z_function(string s) { if(i < r) { z[i] = min(r - i, z[i - l]); } - while(s[z[i]] == s[i + z[i]]) { + while(i + z[i] < n && s[z[i]] == s[i + z[i]]) { z[i]++; } if(i + z[i] > r) { From 66d2ce2966f1014e513d03c27b2d3a1aa97390e2 Mon Sep 17 00:00:00 2001 From: Akash Nayar <33558235+Akash-Nayar@users.noreply.github.com> Date: Wed, 17 May 2023 10:22:40 -0400 Subject: [PATCH 072/590] Update bit-manipulation.md (Fix Typo) "enought" -> "enough" --- src/algebra/bit-manipulation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algebra/bit-manipulation.md b/src/algebra/bit-manipulation.md index b61cfbf85..f4047181d 100644 --- a/src/algebra/bit-manipulation.md +++ b/src/algebra/bit-manipulation.md @@ -37,7 +37,7 @@ assert(negative_signed_number == 0b1111'1111'1111'1111'1111'1111'1111'0011); CPUs are very fast manipulating those bits with specific operations. For some problems we can take these binary number representations to our advantage, and speed up the execution time. -And for some problems (typically in combinatorics or dynamic programming) where we want to track which objects we already picked from a given set of objects, we can just use an large enought integer where each digit represents an object and depending on if we pick or drop the object we set or clear the digit. +And for some problems (typically in combinatorics or dynamic programming) where we want to track which objects we already picked from a given set of objects, we can just use an large enough integer where each digit represents an object and depending on if we pick or drop the object we set or clear the digit. ## Bit operators From 4901d15a58f18cd1ddeb419cdfbe8a983bac06b1 Mon Sep 17 00:00:00 2001 From: Vedant Borkar Date: Fri, 2 Jun 2023 15:59:32 +0530 Subject: [PATCH 073/590] Update search-for-connected-components.md --- src/graph/search-for-connected-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graph/search-for-connected-components.md b/src/graph/search-for-connected-components.md index 2c61dfaa6..e96391d11 100644 --- a/src/graph/search-for-connected-components.md +++ b/src/graph/search-for-connected-components.md @@ -57,7 +57,7 @@ void find_comps() { ## Iterative implementation of the code Deeply recursive functions are in general bad. -Ever single recursive call will require a little bit of memory in the stack, and per default programs only have a limited amount of stack space. +Every single recursive call will require a little bit of memory in the stack, and per default programs only have a limited amount of stack space. So when you do a recursive DFS over a connected graph with millions of nodes, you might run into stack overflows. It is always possible to translate a recursive program into an iterative program, by manually maintaining a stack data structure. From a042eb6c13b08a96019de53b19ced3b1ed57b9df Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sat, 3 Jun 2023 14:19:53 +0200 Subject: [PATCH 074/590] new GA4 tag --- mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index 7fe24eeb9..f539e7249 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -74,4 +74,4 @@ plugins: extra: analytics: provider: google - property: UA-85220282-1 + property: G-7FLS2HCYHH From 7a24c816d12eeeb4f4938c6cdf9ce4172c9336c1 Mon Sep 17 00:00:00 2001 From: Jatin Grover <95739604+scion03@users.noreply.github.com> Date: Wed, 7 Jun 2023 08:31:46 +0530 Subject: [PATCH 075/590] Fixed Typo in segment_tree.md --- src/data_structures/segment_tree.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data_structures/segment_tree.md b/src/data_structures/segment_tree.md index cd1be608b..393983629 100644 --- a/src/data_structures/segment_tree.md +++ b/src/data_structures/segment_tree.md @@ -759,7 +759,7 @@ After that, we can assign the left child with the new value, without loosing any Summarizing we get: for any queries (a modification or reading query) during the descent along the tree we should always push information from the current vertex into both of its children. -We can understand this in such a way, that when we descent the tree we apply delayed modifications, but exactly as much as necessary (so not to degrade the complexity of $O(\log n)$. +We can understand this in such a way, that when we descent the tree we apply delayed modifications, but exactly as much as necessary (so not to degrade the complexity of $O(\log n)$). For the implementation we need to make a $\text{push}$ function, which will receive the current vertex, and it will push the information for its vertex to both its children. We will call this function at the beginning of the query functions (but we will not call it from the leaves, because there is no need to push information from them any further). From d1ca1cfdafbaab574db1972c644403a71e9d8b03 Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sat, 10 Jun 2023 19:15:07 +0200 Subject: [PATCH 076/590] fix example in lis --- src/sequences/longest_increasing_subsequence.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sequences/longest_increasing_subsequence.md b/src/sequences/longest_increasing_subsequence.md index 3d24bef61..b48b5ff1d 100644 --- a/src/sequences/longest_increasing_subsequence.md +++ b/src/sequences/longest_increasing_subsequence.md @@ -32,7 +32,7 @@ To accomplish this task, we define an array $d[0 \dots n-1]$, where $d[i]$ is th $$\begin{array}{ll} a &= \{8, 3, 4, 6, 5, 2, 0, 7, 9, 1\} \\ - d &= \{1, 1, 2, 2, 3, 1, 1, 4, 5, 2\} + d &= \{1, 1, 2, 3, 3, 1, 1, 4, 5, 2\} \end{array}$$ The longest increasing subsequence that ends at index 4 is $\{3, 4, 5\}$ with a length of 3, the longest ending at index 8 is either $\{3, 4, 5, 7, 9\}$ or $\{3, 4, 6, 7, 9\}$, both having length 5, and the longest ending at index 9 is $\{0, 1\}$ having length 2. From e1712a4e7069b224a2385999d09a5328d22fe1f5 Mon Sep 17 00:00:00 2001 From: NUHASHROXME <106915718+YashNuhash@users.noreply.github.com> Date: Mon, 12 Jun 2023 11:10:47 +0600 Subject: [PATCH 077/590] Updated Problem list binary_search.md Added a new Problem. --- src/num_methods/binary_search.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/num_methods/binary_search.md b/src/num_methods/binary_search.md index a95db3c32..31332a209 100644 --- a/src/num_methods/binary_search.md +++ b/src/num_methods/binary_search.md @@ -143,6 +143,7 @@ This paradigm is widely used in tasks around trees, such as finding lowest commo * [LeetCode - Valid Perfect Square](https://leetcode.com/problems/valid-perfect-square/) * [LeetCode - Guess Number Higher or Lower](https://leetcode.com/problems/guess-number-higher-or-lower/) * [LeetCode - Search a 2D Matrix II](https://leetcode.com/problems/search-a-2d-matrix-ii/) +* [LeetCode - Kth Ancestor of a Tree Node](https://leetcode.com/problems/kth-ancestor-of-a-tree-node) * [Codeforces - Interesting Drink](https://codeforces.com/problemset/problem/706/B/) * [Codeforces - Magic Powder - 1](https://codeforces.com/problemset/problem/670/D1) * [Codeforces - Another Problem on Strings](https://codeforces.com/problemset/problem/165/C) From 7b25bc1cb69343f4920954891a6a11aaef90774b Mon Sep 17 00:00:00 2001 From: Mirco Paul <63196848+Electron1997@users.noreply.github.com> Date: Wed, 21 Jun 2023 14:39:40 +0200 Subject: [PATCH 078/590] Added problems to binary-exp.md Added a few matrix exponentiation Codeforces problems, roughly sorted all the problems according to their difficulty --- src/algebra/binary-exp.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/algebra/binary-exp.md b/src/algebra/binary-exp.md index 595b44e63..c57a66db3 100644 --- a/src/algebra/binary-exp.md +++ b/src/algebra/binary-exp.md @@ -253,9 +253,15 @@ $$a \cdot b = \begin{cases} * [UVa 374 - Big Mod](http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=24&page=show_problem&problem=310) * [UVa 11029 - Leading and Trailing](https://uva.onlinejudge.org/index.php?option=onlinejudge&page=show_problem&problem=1970) * [Codeforces - Parking Lot](http://codeforces.com/problemset/problem/630/I) +* [leetcode - Count good numbers](https://leetcode.com/problems/count-good-numbers/) +* [Codechef - Chef and Riffles](https://www.codechef.com/JAN221B/problems/RIFFLES) +* [Codeforces - Decoding Genome](https://codeforces.com/contest/222/problem/E) +* [Codeforces - Neural Network Country](https://codeforces.com/contest/852/problem/B) +* [Codeforces - Magic Gems](https://codeforces.com/problemset/problem/1117/D) * [SPOJ - The last digit](http://www.spoj.com/problems/LASTDIG/) * [SPOJ - Locker](http://www.spoj.com/problems/LOCKER/) * [LA - 3722 Jewel-eating Monsters](https://vjudge.net/problem/UVALive-3722) * [SPOJ - Just add it](http://www.spoj.com/problems/ZSUM/) -* [Codechef - Chef and Riffles](https://www.codechef.com/JAN221B/problems/RIFFLES) -* [leetcode - Count good numbers](https://leetcode.com/problems/count-good-numbers/) +* [Codeforces - Stairs and Lines](https://codeforces.com/contest/498/problem/E) + + From be77729fc85dc76dbfdf68f7961d2cabb6508a80 Mon Sep 17 00:00:00 2001 From: SiddharthEEE <99067988+SiddharthEEE@users.noreply.github.com> Date: Fri, 23 Jun 2023 15:39:21 +0530 Subject: [PATCH 079/590] Added 2 practice problems --- src/data_structures/segment_tree.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/data_structures/segment_tree.md b/src/data_structures/segment_tree.md index 393983629..0c4f4fb0a 100644 --- a/src/data_structures/segment_tree.md +++ b/src/data_structures/segment_tree.md @@ -1202,6 +1202,8 @@ Obviously this idea can be extended in lots of different ways. E.g. by adding su * [Codeforces - Kefa and Watch](https://codeforces.com/problemset/problem/580/E) * [Codeforces - A Simple Task](https://codeforces.com/problemset/problem/558/E) * [Codeforces - SUM and REPLACE](https://codeforces.com/problemset/problem/920/F) +* [Codeforces - XOR on Segment](https://codeforces.com/problemset/problem/242/E) [Lazy propagation] +* [Codeforces - Please, another Queries on Array?](https://codeforces.com/problemset/problem/1114/F) [Lazy propagation] * [COCI - Deda](https://oj.uz/problem/view/COCI17_deda) [Last element smaller or equal to x / Binary search] * [Codeforces - The Untended Antiquity](https://codeforces.com/problemset/problem/869/E) [2D] * [CSES - Hotel Queries](https://cses.fi/problemset/task/1143) From 5b8f602cb5dcdc6e257d8f485f6cc2486e57d054 Mon Sep 17 00:00:00 2001 From: Noble Mittal <62551163+beingnoble03@users.noreply.github.com> Date: Mon, 26 Jun 2023 19:48:45 +0530 Subject: [PATCH 080/590] Add the missing space --- src/graph/euler_path.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graph/euler_path.md b/src/graph/euler_path.md index 1846e8c87..f13e943d2 100644 --- a/src/graph/euler_path.md +++ b/src/graph/euler_path.md @@ -65,7 +65,7 @@ Reformulate the problem. Let the numbers written on the bottoms be the vertices The program below searches for and outputs a Eulerian loop or path in a graph, or outputs $-1$ if it does not exist. First, the program checks the degree of vertices: if there are no vertices with an odd degree, then the graph has an Euler cycle, if there are $2$ vertices with an odd degree, then in the graph there is only an Euler path (but no Euler cycle), if there are more than $2$ such vertices, then in the graph there is no Euler cycle or Euler path. -To find the Euler path (not a cycle), let's do this: if $V1$ and $V2$ are two vertices of odd degree,then just add an edge $(V1, V2)$, in the resulting graph we find the Euler cycle (it will obviously exist), and then remove the "fictitious" edge $(V1, V2)$ from the answer. +To find the Euler path (not a cycle), let's do this: if $V1$ and $V2$ are two vertices of odd degree, then just add an edge $(V1, V2)$, in the resulting graph we find the Euler cycle (it will obviously exist), and then remove the "fictitious" edge $(V1, V2)$ from the answer. We will look for the Euler cycle exactly as described above (non-recursive version), and at the same time at the end of this algorithm we will check whether the graph was connected or not (if the graph was not connected, then at the end of the algorithm some edges will remain in the graph, and in this case we need to print $-1$). Finally, the program takes into account that there can be isolated vertices in the graph. From 2638b5b3dd259f65befde13a3fa3c93b554b4429 Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Mon, 26 Jun 2023 17:45:29 +0200 Subject: [PATCH 081/590] Update install-mkdocs.sh install mkdocs plugin --- scripts/install-mkdocs.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/install-mkdocs.sh b/scripts/install-mkdocs.sh index d7ccb735f..4202c9a97 100755 --- a/scripts/install-mkdocs.sh +++ b/scripts/install-mkdocs.sh @@ -7,4 +7,5 @@ pip install \ mkdocs-git-authors-plugin \ mkdocs-git-revision-date-localized-plugin \ mkdocs-simple-hooks \ + mkdocs-rss-plugin \ plugins/mkdocs-git-committers-plugin-2 From 5807accf74b4f942eba35c7876c67d9b45a276b1 Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Mon, 26 Jun 2023 17:49:17 +0200 Subject: [PATCH 082/590] adding rss plugin --- mkdocs.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mkdocs.yml b/mkdocs.yml index f539e7249..14b8b574a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,4 +1,6 @@ site_name: Algorithms for Competitive Programming +site_url: https://cp-algorithms.com +site_description: 'The goal of this project is to translate the wonderful resource http://e-maxx.ru/algo which provides descriptions of many algorithms and data structures especially popular in field of competitive programming. Moreover we want to improve the collected knowledge by extending the articles and adding new articles to the collection.' docs_dir: src site_dir: public use_directory_urls: false @@ -70,6 +72,7 @@ plugins: token: !ENV MKDOCS_GIT_COMMITTERS_APIKEY enabled: !ENV [MKDOCS_ENABLE_GIT_COMMITTERS, False] - macros + - rss extra: analytics: From 8f36c4a0477782e7b7313355bf9cf1109f8e7426 Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Mon, 26 Jun 2023 18:22:06 +0200 Subject: [PATCH 083/590] add RSS icon and link --- mkdocs.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mkdocs.yml b/mkdocs.yml index 14b8b574a..c88e2a671 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -78,3 +78,6 @@ extra: analytics: provider: google property: G-7FLS2HCYHH + social: + - icon: fontawesome/solid/rss + link: https://cp-algorithms.com/feed_rss_created.xml From 1f53d7973de5fa13c14abc404288155b7a1d8fa8 Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Mon, 26 Jun 2023 18:36:06 +0200 Subject: [PATCH 084/590] set repo name --- mkdocs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/mkdocs.yml b/mkdocs.yml index c88e2a671..1251e4d25 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -27,6 +27,7 @@ theme: - toc.integrate - search.suggest repo_url: https://github.com/cp-algorithms/cp-algorithms +repo_name: cp-algorithms/cp-algorithms edit_uri: edit/master/src/ copyright: Text is available under the Creative Commons Attribution Share Alike 4.0 International License
Copyright © 2014 - 2022 by https://github.com/cp-algorithms extra_javascript: From 1d95a7fb183bdefd4316792614a2b53c8a200dcc Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Mon, 26 Jun 2023 19:51:11 +0200 Subject: [PATCH 085/590] rss icon in the header --- src/overrides/partials/header.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/overrides/partials/header.html b/src/overrides/partials/header.html index c288bfafb..07a3e30aa 100644 --- a/src/overrides/partials/header.html +++ b/src/overrides/partials/header.html @@ -86,7 +86,11 @@ {% if config.repo_url %}
{% include "partials/source.html" %} + + {% include ".fontawesome/solid/rss.svg" %} +
+ {% endif %} {% if "navigation.tabs.sticky" in features %} From a8d3e835c3b105bca5ef2ac5a2b6a7c72f65e4ef Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Mon, 26 Jun 2023 19:54:23 +0200 Subject: [PATCH 086/590] fix --- src/overrides/partials/header.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/overrides/partials/header.html b/src/overrides/partials/header.html index 07a3e30aa..ff2a0dfcc 100644 --- a/src/overrides/partials/header.html +++ b/src/overrides/partials/header.html @@ -87,7 +87,9 @@ From 391041693138ee38d5abd0acd967a2e1963de07c Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Mon, 26 Jun 2023 19:59:24 +0200 Subject: [PATCH 087/590] fix.. --- src/overrides/partials/header.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/overrides/partials/header.html b/src/overrides/partials/header.html index ff2a0dfcc..7dd1275b6 100644 --- a/src/overrides/partials/header.html +++ b/src/overrides/partials/header.html @@ -86,10 +86,11 @@ {% if config.repo_url %}
{% include "partials/source.html" %} + - +
{% include ".icons/fontawesome/solid/rss.svg" %} - +
From fa3a07774b49024b98f0b0c65049ef003aa56c6c Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Mon, 26 Jun 2023 20:04:01 +0200 Subject: [PATCH 088/590] fixing divs and links --- src/overrides/partials/header.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overrides/partials/header.html b/src/overrides/partials/header.html index 7dd1275b6..967330642 100644 --- a/src/overrides/partials/header.html +++ b/src/overrides/partials/header.html @@ -86,12 +86,12 @@ {% if config.repo_url %}
{% include "partials/source.html" %} - - -
- {% include ".icons/fontawesome/solid/rss.svg" %} -
-
+
+ + {% endif %} From 32f97c4a5701146469b53266de0a45f8bb848c04 Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Mon, 26 Jun 2023 20:08:09 +0200 Subject: [PATCH 089/590] no need for RSS in social anymore --- mkdocs.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index 1251e4d25..8db24a408 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -79,6 +79,3 @@ extra: analytics: provider: google property: G-7FLS2HCYHH - social: - - icon: fontawesome/solid/rss - link: https://cp-algorithms.com/feed_rss_created.xml From 3c014e96431031c07a1cd246039651077a6c79be Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Mon, 26 Jun 2023 20:11:09 +0200 Subject: [PATCH 090/590] update in changelog --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index fb01878a9..ef2a16f6e 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Compiled pages are published at [https://cp-algorithms.com/](https://cp-algorith ## Changelog +- June 26, 2023: Added automatic RSS feeds for [new articles](https://cp-algorithms.com/feed_rss_created.xml) and [updates in articles](https://cp-algorithms.com/feed_rss_updated.xml). - December 20, 2022: The repository name and the owning organizations were renamed! Now the repo is located at [https://github.com/cp-algorithms/cp-algorithms](https://github.com/cp-algorithms/cp-algorithms). It is recommended to update the upstream link in your local repositories, if you have any. - October 31, 2022: It is now possible to select and copy $\LaTeX$ source code of formulas within the articles. - June 8, 2022: Tags are enabled. Each article is now marked whether it is translated or original, overall tag info is present in the [tag index](https://cp-algorithms.com/tags.html). For translated articles, clicking on `From: X` tag would lead to the original article. From 8e5edffa3147063824990a8b8e631b55c908ff73 Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Tue, 27 Jun 2023 12:29:25 +0200 Subject: [PATCH 091/590] update link to tex-mml-chtml.js --- mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index 8db24a408..4403365d6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -33,7 +33,7 @@ copyright: Text is available under the Date: Thu, 6 Jul 2023 12:31:25 +0200 Subject: [PATCH 095/590] wording --- src/algebra/bit-manipulation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algebra/bit-manipulation.md b/src/algebra/bit-manipulation.md index c831d842d..36c30d909 100644 --- a/src/algebra/bit-manipulation.md +++ b/src/algebra/bit-manipulation.md @@ -116,7 +116,7 @@ $1 \ll x$ is a number with only the $x$-th bit set, while $\sim(1 \ll x)$ is a n ### Check if a bit is set -The value of the $x$-th bit can be checked by shifting the number $x$-positions to the right until the $x$-th bit is at the unit place, then we can extract it by performing a bitwise & with 1. +The value of the $x$-th bit can be checked by shifting the number $x$ positions to the right, so that the $x$-th bit is at the unit place, after which we can extract it by performing a bitwise & with 1. ``` cpp bool is_set(unsigned int number, int x) { From 4913931e523abc0c4b23c743250ec77741c100c3 Mon Sep 17 00:00:00 2001 From: Mert Koksal <85784378+Mychecksdead@users.noreply.github.com> Date: Sun, 2 Jul 2023 22:05:41 +0300 Subject: [PATCH 096/590] updated the implementation for zero length edges --- src/geometry/minkowski.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/geometry/minkowski.md b/src/geometry/minkowski.md index fc32e63f2..a9c89d22e 100644 --- a/src/geometry/minkowski.md +++ b/src/geometry/minkowski.md @@ -95,12 +95,12 @@ vector minkowski(vector P, vector Q){ vector result; size_t i = 0, j = 0; while(i < P.size() - 2 || j < Q.size() - 2){ - result.push_back(P[i] + Q[j]); - auto cross = (P[i + 1] - P[i]).cross(Q[j + 1] - Q[j]); - if(cross >= 0) - ++i; - if(cross <= 0) - ++j; + result.push_back(P[i] + Q[j]); + auto cross = (P[i + 1] - P[i]).cross(Q[j + 1] - Q[j]); + if(cross >= 0 && i < P.size() - 2) + ++i; + if(cross <= 0 && j < Q.size() - 2) + ++j; } return result; } From 62984870ba44a1488b5c24683d619d4bae8d02c2 Mon Sep 17 00:00:00 2001 From: Mert Koksal <85784378+Mychecksdead@users.noreply.github.com> Date: Sun, 2 Jul 2023 22:09:30 +0300 Subject: [PATCH 097/590] update --- src/geometry/minkowski.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/geometry/minkowski.md b/src/geometry/minkowski.md index a9c89d22e..42abcfa86 100644 --- a/src/geometry/minkowski.md +++ b/src/geometry/minkowski.md @@ -95,12 +95,12 @@ vector minkowski(vector P, vector Q){ vector result; size_t i = 0, j = 0; while(i < P.size() - 2 || j < Q.size() - 2){ - result.push_back(P[i] + Q[j]); - auto cross = (P[i + 1] - P[i]).cross(Q[j + 1] - Q[j]); - if(cross >= 0 && i < P.size() - 2) - ++i; - if(cross <= 0 && j < Q.size() - 2) - ++j; + result.push_back(P[i] + Q[j]); + auto cross = (P[i + 1] - P[i]).cross(Q[j + 1] - Q[j]); + if(cross >= 0 && i < P.size() - 2) + ++i; + if(cross <= 0 && j < Q.size() - 2) + ++j; } return result; } From f67d122d308db17ba518076cfdb3007b6f6bc25c Mon Sep 17 00:00:00 2001 From: Ching Lam Lau Date: Mon, 10 Jul 2023 11:59:30 -0400 Subject: [PATCH 098/590] Fix typo in dinic.md --- src/graph/dinic.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graph/dinic.md b/src/graph/dinic.md index a0d985952..d1945d893 100644 --- a/src/graph/dinic.md +++ b/src/graph/dinic.md @@ -47,7 +47,7 @@ From these two lemmas we conclude that there are less than $V$ phases because $l In order to find the blocking flow on each iteration, we may simply try pushing flow with DFS from $s$ to $t$ in the layered network while it can be pushed. In order to do it more quickly, we must remove the edges which can't be used to push anymore. To do this we can keep a pointer in each vertex which points to the next edge which can be used. -A single DFS run takes $O(k+V)$ time, where $k$ is the number of pointer advances on this run. Sumed up over all runs, number of pointer advances can not exceed $E$. On the other hand, total number of runs won't exceed $E$, as every run saturates at least one edge. In this way, total running time of finding a blocking flow is $O(VE)$. +A single DFS run takes $O(k+V)$ time, where $k$ is the number of pointer advances on this run. Summed up over all runs, number of pointer advances can not exceed $E$. On the other hand, total number of runs won't exceed $E$, as every run saturates at least one edge. In this way, total running time of finding a blocking flow is $O(VE)$. ## Complexity From 99abc99816d86882da49c3127059801d41daa2eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Alves?= <71379045+andremralves@users.noreply.github.com> Date: Sat, 8 Jul 2023 23:27:59 -0300 Subject: [PATCH 099/590] Fix typo in module-inverse.md --- src/algebra/module-inverse.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algebra/module-inverse.md b/src/algebra/module-inverse.md index 875c0182e..a4062931f 100644 --- a/src/algebra/module-inverse.md +++ b/src/algebra/module-inverse.md @@ -16,7 +16,7 @@ $$a \cdot x \equiv 1 \mod m.$$ We will also denote $x$ simply with $a^{-1}$. We should note that the modular inverse does not always exist. For example, let $m = 4$, $a = 2$. -By checking all possible values modulo $m$ is should become clear that we cannot find $a^{-1}$ satisfying the above equation. +By checking all possible values modulo $m$ it should become clear that we cannot find $a^{-1}$ satisfying the above equation. It can be proven that the modular inverse exists if and only if $a$ and $m$ are relatively prime (i.e. $\gcd(a, m) = 1$). In this article, we present two methods for finding the modular inverse in case it exists, and one method for finding the modular inverse for all numbers in linear time. From e8d009b0072e9afa12c269685f175207dce222fd Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Mon, 10 Jul 2023 18:57:46 +0200 Subject: [PATCH 100/590] Update module-inverse.md --- src/algebra/module-inverse.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algebra/module-inverse.md b/src/algebra/module-inverse.md index a4062931f..dd68b9667 100644 --- a/src/algebra/module-inverse.md +++ b/src/algebra/module-inverse.md @@ -16,7 +16,7 @@ $$a \cdot x \equiv 1 \mod m.$$ We will also denote $x$ simply with $a^{-1}$. We should note that the modular inverse does not always exist. For example, let $m = 4$, $a = 2$. -By checking all possible values modulo $m$ it should become clear that we cannot find $a^{-1}$ satisfying the above equation. +By checking all possible values modulo $m$, it should become clear that we cannot find $a^{-1}$ satisfying the above equation. It can be proven that the modular inverse exists if and only if $a$ and $m$ are relatively prime (i.e. $\gcd(a, m) = 1$). In this article, we present two methods for finding the modular inverse in case it exists, and one method for finding the modular inverse for all numbers in linear time. From 5b9310af25b1b03164b688d8e05006a0ddb0655b Mon Sep 17 00:00:00 2001 From: Luke Videckis Date: Thu, 6 Jul 2023 15:16:28 -0700 Subject: [PATCH 101/590] fix typo --- src/string/suffix-automaton.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string/suffix-automaton.md b/src/string/suffix-automaton.md index 07afdbe5d..629be1eff 100644 --- a/src/string/suffix-automaton.md +++ b/src/string/suffix-automaton.md @@ -596,7 +596,7 @@ $$cnt[link(v)] \text{ += } cnt[v]$$ This gives the correct value for each state. Why is this correct? -The total stats obtained not obtained by cloning are exactly $length(T)$, and the first $i$ of them appeared when we added the first $i$ characters. +The total states obtained not obtained by cloning are exactly $length(T)$, and the first $i$ of them appeared when we added the first $i$ characters. Consequently for each of these states we count the corresponding position at which it was processed. Therefore initially we have $cnt = 1$ for each such state, and $cnt = 0$ for all other. From 6b59f759442ce2f2d30bad666a1917d16faea5c4 Mon Sep 17 00:00:00 2001 From: Luke Videckis Date: Sun, 9 Jul 2023 11:31:18 -0700 Subject: [PATCH 102/590] reword sentence --- src/string/suffix-automaton.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string/suffix-automaton.md b/src/string/suffix-automaton.md index 629be1eff..304546c44 100644 --- a/src/string/suffix-automaton.md +++ b/src/string/suffix-automaton.md @@ -596,7 +596,7 @@ $$cnt[link(v)] \text{ += } cnt[v]$$ This gives the correct value for each state. Why is this correct? -The total states obtained not obtained by cloning are exactly $length(T)$, and the first $i$ of them appeared when we added the first $i$ characters. +The total states obtained not via cloning are exactly $length(T)$, and the first $i$ of them appeared when we added the first $i$ characters. Consequently for each of these states we count the corresponding position at which it was processed. Therefore initially we have $cnt = 1$ for each such state, and $cnt = 0$ for all other. From c098d8286bc3e78ab5294e4dfbf2395c6c1b2135 Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Mon, 10 Jul 2023 19:00:55 +0200 Subject: [PATCH 103/590] Update suffix-automaton.md --- src/string/suffix-automaton.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string/suffix-automaton.md b/src/string/suffix-automaton.md index 304546c44..f7a46c81f 100644 --- a/src/string/suffix-automaton.md +++ b/src/string/suffix-automaton.md @@ -596,7 +596,7 @@ $$cnt[link(v)] \text{ += } cnt[v]$$ This gives the correct value for each state. Why is this correct? -The total states obtained not via cloning are exactly $length(T)$, and the first $i$ of them appeared when we added the first $i$ characters. +The total number of states obtained _not_ via cloning is exactly $length(T)$, and the first $i$ of them appeared when we added the first $i$ characters. Consequently for each of these states we count the corresponding position at which it was processed. Therefore initially we have $cnt = 1$ for each such state, and $cnt = 0$ for all other. From c469486cfa6907927ad31769634742d233e6cb37 Mon Sep 17 00:00:00 2001 From: Yury Semenov Date: Wed, 12 Jul 2023 18:52:18 +0300 Subject: [PATCH 104/590] Added an article on planar graph faces --- src/geometry/planar.md | 151 +++++++++++++++++++++++++++++++++++ src/geometry/planar_hole.png | Bin 0 -> 42198 bytes src/navigation.md | 2 + test/test_planar_faces.cpp | 100 +++++++++++++++++++++++ 4 files changed, 253 insertions(+) create mode 100644 src/geometry/planar.md create mode 100644 src/geometry/planar_hole.png create mode 100644 test/test_planar_faces.cpp diff --git a/src/geometry/planar.md b/src/geometry/planar.md new file mode 100644 index 000000000..d9b059eb9 --- /dev/null +++ b/src/geometry/planar.md @@ -0,0 +1,151 @@ +--- +title: Finding faces of a planar graph +tags: + - Translated +--- +# Finding faces of a planar graph + +Consider a graph $G$ with $n$ vertices and $m$ edges, which can be drawn on a plane in such a way that two edges intersect only at a common vertex (if it exists). +Such graphs are called **planar**. Now suppose that we are given a planar graph together with its straight-line drawing, which means that for each vertex $v$ we have a corresponding point $(x, y)$ and all edges are drawn as line segments between these points without intersection (such drawing always exists). These line segments split the plane into several regions, which are called faces. Exactly one of the faces is unbounded. This face is called **outer**, while the other faces are called **inner**. + +In this article we will deal with finding both inner and outer faces of a planar graph. We will assume that the graph is connected. + +## Some facts about planar graphs + +In this section we present several facts about planar graphs without proof. Readers who are interested in proofs should refer to [Graph Theory by R. Diestel](https://sites.math.washington.edu/~billey/classes/562.winter.2018/articles/GraphTheory.pdf) or some other book. + +### Euler's theorem +Euler's theorem states that any correct drawing of a connected planar graph with $n$ vertices, $m$ edges and $f$ faces satisfies: + +$$n - m + f = 2$$ + +And more generally, every planar graph with $k$ connected components satisfies: + +$$n - m + f = 1 + k$$ + +### Number of edges of a planar graph. +If $n \ge 3$ then the maximum number of edges of a planar graph with $n$ vertices is $3n - 6$. This number is achieved by any connected planar graph where each face is bounded by a triangle. In terms of complexity this fact means that $m = O(n)$ for any planar graph. + +### Number of faces of a planar graph. +As a direct consequence of the above fact, if $n \ge 3$ then the maximum number of faces of a planar graph with $n$ vertices is $2n - 4$. + +### Minimum vertex degree in a planar graph. +Every planar graph has a vertex of degree 5 or less. + +## The algorithm + +Firstly, sort the adjacent edges for each vertex by polar angle. +Now let's traverse the graph in the following way. Suppose that we entered vertex $u$ through the edge $(v, u)$ and $(u, w)$ is the next edge after $(v, u)$ in the sorted adjacency list of $u$. Then the next vertex will be $w$. It turns out that if we start this traversal at some edge $(v, u)$, we will traverse exactly one of the faces adjacent to $(v, u)$, the exact face depending on whether our first step is from $u$ to $v$ or from $v$ to $u$. + +Now the algorithm is quite obvious. We must iterate over all edges of the graph and start the traversal for each edge that wasn't visited by one of the previous traversals. This way we will find each face exactly once, and each edge will be traversed twice (once in each direction). + +### Finding the next edge +During the traversal we have to find the next edge in counter-clockwise order. The most obvious way to find the next edge is binary search by angle. However, given the counter-clockwise order of adjacent edges for each vertex, we can precompute the next edges and store them in a hash table. If the edges are already sorted by angle, the complexity of finding all faces in this case becomes linear. + +### Finding the outer face +It's not hard to see that the algorithm traverses each inner face in a clockwise order and the outer face in the counter-clockwise order, so the outer face can be found by checking the order of each face. + +### Complexity +It's quite clear that the complexity of the algorithm is $O(m \log m)$ because of sorting, and since $m = O(n)$, it's actually $O(n \log n)$. As mentioned before, without sorting the complexity becomes $O(n)$. + +## What if the graph isn't connected? + +At the first glance it may seem that finding faces of a disconnected graph is not much harder because we can run the same algorithm for each connected component. However, the components may be drawn in a nested way, forming **holes** (see the image below). In this case the inner face of some component becomes the outer face of some other components and has a complex disconnected border. Dealing with such cases is quite hard, one possible approach is to identify nested components with [point location](point-location.md) algorithms. + +
![Planar graph with holes](planar_hole.png)
+ +## Implementation +The following implementation returns a vector of vertices for each face, outer face goes first. +Inner faces are returned in counter-clockwise orders and the outer face is returned in clockwise order. + +For simplicity we find the next edge by doing binary search by angle. +```{.cpp file=planar} +struct Point { + int64_t x, y; + + Point(int64_t x_, int64_t y_): x(x_), y(y_) {} + + Point operator - (const Point & p) const { + return Point(x - p.x, y - p.y); + } + + int64_t cross (const Point & p) const { + return x * p.y - y * p.x; + } + + int64_t cross (const Point & p, const Point & q) const { + return (p - *this).cross(q - *this); + } + + int half () const { + return int(y < 0 || (y == 0 && x < 0)); + } +}; + +std::vector> find_faces(std::vector vertices, std::vector> adj) { + size_t n = vertices.size(); + std::vector> used(n); + for (size_t i = 0; i < n; i++) { + used[i].resize(adj[i].size()); + used[i].assign(adj[i].size(), 0); + auto compare = [&](size_t l, size_t r) { + Point pl = vertices[l] - vertices[i]; + Point pr = vertices[r] - vertices[i]; + if (pl.half() != pr.half()) + return pl.half() < pr.half(); + return pl.cross(pr) > 0; + }; + std::sort(adj[i].begin(), adj[i].end(), compare); + } + std::vector> faces; + for (size_t i = 0; i < n; i++) { + for (size_t edge_id = 0; edge_id < adj[i].size(); edge_id++) { + if (used[i][edge_id]) { + continue; + } + std::vector face; + size_t v = i; + size_t e = edge_id; + while (!used[v][e]) { + used[v][e] = true; + face.push_back(v); + size_t u = adj[v][e]; + size_t e1 = std::lower_bound(adj[u].begin(), adj[u].end(), v, [&](size_t l, size_t r) { + Point pl = vertices[l] - vertices[u]; + Point pr = vertices[r] - vertices[u]; + if (pl.half() != pr.half()) + return pl.half() < pr.half(); + return pl.cross(pr) > 0; + }) - adj[u].begin() + 1; + if (e1 == adj[u].size()) { + e1 = 0; + } + v = u; + e = e1; + } + std::reverse(face.begin(), face.end()); + int sign = 0; + for (size_t j = 0; j < face.size(); j++) { + size_t j1 = (j + 1) % face.size(); + size_t j2 = (j + 2) % face.size(); + int64_t val = vertices[face[j]].cross(vertices[face[j1]], vertices[face[j2]]); + if (val > 0) { + sign = 1; + break; + } else if (val < 0) { + sign = -1; + break; + } + } + if (sign <= 0) { + faces.insert(faces.begin(), face); + } else { + faces.emplace_back(face); + } + } + } + return faces; +} +``` +## Problems + * [TIMUS 1664 Pipeline Transportation](https://acm.timus.ru/problem.aspx?space=1&num=1664) diff --git a/src/geometry/planar_hole.png b/src/geometry/planar_hole.png new file mode 100644 index 0000000000000000000000000000000000000000..1059a2197b7e118f99bfab5c2ee55e1e103854c7 GIT binary patch literal 42198 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�yFY#Av23hlyODAJRqU)^O{? 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 z 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 literal 0 HcmV?d00001 diff --git a/src/navigation.md b/src/navigation.md index b37bab725..260c68a26 100644 --- a/src/navigation.md +++ b/src/navigation.md @@ -133,6 +133,8 @@ search: - [Convex hull trick and Li Chao tree](geometry/convex_hull_trick.md) - Sweep-line - [Search for a pair of intersecting segments](geometry/intersecting_segments.md) + - Planar graphs + - [Finding faces of a planar graph](geometry/planar.md) - [Point location in O(log N)](geometry/point-location.md) - Miscellaneous - [Finding the nearest pair of points](geometry/nearest_points.md) diff --git a/test/test_planar_faces.cpp b/test/test_planar_faces.cpp new file mode 100644 index 000000000..731bae4db --- /dev/null +++ b/test/test_planar_faces.cpp @@ -0,0 +1,100 @@ +#include +#include +#include + +#include "planar.h" + +bool equal_cycles(const std::vector & a, const std::vector & b) { + size_t n = a.size(); + if (n != b.size()) { + return false; + } + for (size_t begin = 0; begin < n; begin++) { + bool ok = true; + for (size_t i = 0; i < n; i++) { + if (a[(begin + i) % n] != b[i]) { + ok = false; + break; + } + } + if (ok) { + return true; + } + } + return false; +} + +void test_simple() { + std::vector p = { + Point(0, 0), + Point(1, 0), + Point(1, 1), + Point(0, 1) + }; + + std::vector> adj = { + {1, 2, 3}, + {0, 2}, + {0, 1, 3}, + {0, 2} + }; + + auto faces = find_faces(p, adj); + assert(faces.size() == 3u); + assert(equal_cycles(faces[0], {3, 2, 1, 0})); + bool eq11 = equal_cycles(faces[1], {0, 1, 2}); + bool eq12 = equal_cycles(faces[1], {0, 2, 3}); + bool eq21 = equal_cycles(faces[2], {0, 1, 2}); + bool eq22 = equal_cycles(faces[2], {0, 2, 3}); + assert(eq11^eq21); + assert(eq12^eq22); +} + +void test_degenerate() { + std::vector p = { + Point(0, 0), + Point(1, 1), + Point(2, 2) + }; + + std::vector> adj = { + {1}, + {0, 2}, + {1} + }; + + auto faces = find_faces(p, adj); + assert(faces.size() == 1u); + assert(equal_cycles(faces[0], {0, 1, 2, 1})); +} + +void test_cycle_with_chain() { + std::vector p = { + Point(0, 0), + Point(0, 3), + Point(3, 3), + Point(3, 0), + Point(1, 1), + Point(2, 2) + }; + + std::vector> adj = { + {1, 3}, + {0, 2}, + {1, 3, 5}, + {0, 2}, + {5}, + {2, 4} + }; + + auto faces = find_faces(p, adj); + assert(faces.size() == 2u); + assert(equal_cycles(faces[0], {0, 1, 2, 3})); + assert(equal_cycles(faces[1], {2, 5, 4, 5, 2, 1, 0, 3})); +} + +int main() { + test_simple(); + test_degenerate(); + test_cycle_with_chain(); +} From 60acd9b5b5106825a799c7f2b5b23c7767e44033 Mon Sep 17 00:00:00 2001 From: Yury Semenov Date: Thu, 13 Jul 2023 23:54:38 +0300 Subject: [PATCH 105/590] added building graph from segments --- src/geometry/planar.md | 195 +++++++++++++++++++++++++++++++ src/geometry/planar_implicit.png | Bin 0 -> 35023 bytes test/test_planar_implicit.cpp | 82 +++++++++++++ 3 files changed, 277 insertions(+) create mode 100644 src/geometry/planar_implicit.png create mode 100644 test/test_planar_implicit.cpp diff --git a/src/geometry/planar.md b/src/geometry/planar.md index d9b059eb9..9e3808313 100644 --- a/src/geometry/planar.md +++ b/src/geometry/planar.md @@ -147,5 +147,200 @@ std::vector> find_faces(std::vector vertices, std::ve return faces; } ``` + +## Building planar graph from line segments + +Sometimes you are not given a graph explicitly, but rather as a set of line segments on a plane, and the actual graph is formed by intersecting those segments, as shown in the picture below. In this case you have to build the graph manually. The easiest way to do so is as follows. Fix a segment and intersect it with all other segments. Then sort all intersection points together with the two endpoints of the segment lexicographically and add them to the graph as vertices. Also link each two adjacent vertices in lexicographical order by an edge. After doing this procedure for all edges we will obtain the graph. Of course, we should ensure that two equal intersection points will always correspond to the same vertex. The easiest way to do this is to store the points in a map by their coordinates, regarding points whose coordinates differ by a small number (say, less than $10^{-9}$) as equal. This algorithm works in $O(n^2 \log n)$. + +
![Implicitly defined graph](planar_implicit.png)
+ +## Implementation +```{.cpp file=planar_implicit} +using dbl = long double; + +const dbl eps = 1e-9; + +struct Point { + dbl x, y; + + Point(){} + Point(dbl x_, dbl y_): x(x_), y(y_) {} + + Point operator * (dbl d) const { + return Point(x * d, y * d); + } + + Point operator + (const Point & p) const { + return Point(x + p.x, y + p.y); + } + + Point operator - (const Point & p) const { + return Point(x - p.x, y - p.y); + } + + dbl cross (const Point & p) const { + return x * p.y - y * p.x; + } + + dbl cross (const Point & p, const Point & q) const { + return (p - *this).cross(q - *this); + } + + dbl dot (const Point & p) const { + return x * p.x + y * p.y; + } + + dbl dot (const Point & p, const Point & q) const { + return (p - *this).dot(q - *this); + } + + bool operator < (const Point & p) const { + if (fabs(x - p.x) < eps) { + if (fabs(y - p.y) < eps) { + return false; + } else { + return y < p.y; + } + } else { + return x < p.x; + } + } + + bool operator == (const Point & p) const { + return fabs(x - p.x) < eps && fabs(y - p.y) < eps; + } + + bool operator >= (const Point & p) const { + return !(*this < p); + } +}; + +struct Line{ + Point p[2]; + + Line(Point l, Point r){p[0] = l; p[1] = r;} + Point& operator [](const int & i){return p[i];} + const Point& operator[](const int & i)const{return p[i];} + Line(const Line & l){ + p[0] = l.p[0]; p[1] = l.p[1]; + } + Point getOrth()const{ + return Point(p[1].y - p[0].y, p[0].x - p[1].x); + } + bool hasPointLine(const Point & t)const{ + return std::fabs(p[0].cross(p[1], t)) < eps; + } + bool hasPointSeg(const Point & t)const{ + return hasPointLine(t) && t.dot(p[0], p[1]) < eps; + } +}; + +std::vector interLineLine(Line l1, Line l2){ + if(std::fabs(l1.getOrth().cross(l2.getOrth())) < eps){ + if(l1.hasPointLine(l2[0]))return {l1[0], l1[1]}; + else return {}; + } + Point u = l2[1] - l2[0]; + Point v = l1[1] - l1[0]; + dbl s = u.cross(l2[0] - l1[0])/u.cross(v); + return {Point(l1[0] + v * s)}; +} + +std::vector interSegSeg(Line l1, Line l2){ + if (l1[0] == l1[1]) { + if (l2[0] == l2[1]) { + if (l1[0] == l2[0]) + return {l1[0]}; + else + return {}; + } else { + if (l2.hasPointSeg(l1[0])) + return {l1[0]}; + else + return {}; + } + } + if (l2[0] == l2[1]) { + if (l1.hasPointSeg(l2[0])) + return {l2[0]}; + else + return {}; + } + auto li = interLineLine(l1, l2); + if (li.empty()) + return li; + if (li.size() == 2) { + if (l1[0] >= l1[1]) + std::swap(l1[0], l1[1]); + if (l2[0] >= l2[1]) + std::swap(l2[0], l2[1]); + std::vector res(2); + if (l1[0] < l2[0]) + res[0] = l2[0]; + else + res[0] = l1[0]; + if (l1[1] < l2[1]) + res[1] = l1[1]; + else + res[1] = l2[1]; + if (res[0] == res[1]) + res.pop_back(); + if (res.size() == 2u && res[1] < res[0]) + return {}; + else + return res; + } + Point cand = li[0]; + if (l1.hasPointSeg(cand) && l2.hasPointSeg(cand)) + return {cand}; + else + return {}; +} + +std::pair, std::vector>> build_graph(std::vector segments) { + std::vector p; + std::vector> adj; + std::map point_id; + auto get_point_id = [&](Point pt) { + if (!point_id.count(pt)) { + adj.emplace_back(); + size_t id = point_id.size(); + point_id[pt] = id; + p.push_back(pt); + return id; + } else { + return point_id[pt]; + } + }; + for (size_t i = 0; i < segments.size(); i++) { + std::vector curr = { + get_point_id(segments[i][0]), + get_point_id(segments[i][1]) + }; + for (size_t j = 0; j < segments.size(); j++) { + if (i == j) + continue; + auto inter = interSegSeg(segments[i], segments[j]); + for (auto pt: inter) { + curr.push_back(get_point_id(pt)); + } + } + std::sort(curr.begin(), curr.end(), [&](size_t l, size_t r) { return p[l] < p[r]; }); + curr.erase(std::unique(curr.begin(), curr.end()), curr.end()); + for (size_t j = 0; j + 1 < curr.size(); j++) { + adj[curr[j]].push_back(curr[j + 1]); + adj[curr[j + 1]].push_back(curr[j]); + } + } + for (size_t i = 0; i < adj.size(); i++) { + std::sort(adj[i].begin(), adj[i].end()); + // removing edges that were added multiple times + adj[i].erase(std::unique(adj[i].begin(), adj[i].end()), adj[i].end()); + } + return {p, adj}; +} +``` + ## Problems * [TIMUS 1664 Pipeline Transportation](https://acm.timus.ru/problem.aspx?space=1&num=1664) + * [TIMUS 1681 Brother Bear's Garden](https://acm.timus.ru/problem.aspx?space=1&num=1681) diff --git a/src/geometry/planar_implicit.png b/src/geometry/planar_implicit.png new file mode 100644 index 0000000000000000000000000000000000000000..37a0e72f8cab363269c8f3e7dd333189b7198f96 GIT binary patch literal 35023 zcmc$`hdbe<_sZVu zcfEDr_xJn#3w}NB&*O7HKArdbyk6Jq8qe!_JzpnGOGAm6fSv$_LJ_MdD`=xoI2ib6 z`y3wpm){R-x8Pr6w({~?F4{_RC=@Nm+{{es8|w5;5+b5XPmUYc|7sABN8chKQoblq zS@HCgsF{V?jyti!)hot*#Ju;WTGDAQjPl|boy(9#eNdKo{jC+}KKlAEii_@^D%bH} z7U14TpQn2E>)Lt26{?`q;}Fhq|B>&T1_wj zM~E-t+1L+fJiK9LJiIYNA|m5%vd2$P*$Z5Gr$U5=Z8`rE2~1~JDuK=7J1HBwpirD@ z$Umou25$u zgu%ImPi?YlAsqPI=<>|35mOx7`tQ+z!5YtMP8%T1ca2mV}Sg+Bz>vir`S{J#nF zY1+K z{?z}!j}!Lqp@-hN!F1f%RDeJ(AwVK7)~cxD#J>C>fGGI z!orU|GWdJ|qm&2P<(dr&nZu1AEOme9vQnCteYYjyql%fa~JZE$#DlK#B9O|Ng0G;3759SYcz1)0J>K3+$=`wii z`|=x-rM*!oE-rTq%R@oVo3Hr}2H(HO&Cb~sc>9(Fg);G+qOLwz`)bFC3B@x*&S7Y0 zG=Q|o_s|Pf-xwqr{i<{ryKHacH2OIVi$WRmpD!*c32;|rr8u$rU7H6F6y)S^P-au@ zstSr$5wrV}l6fnuE$c7i;-0;w7j0~8^nY}db?q5XP-v*~d6OrrH&EBCrt{cHUZKe7 z-UM}Y=-)Cm4VX#x)|i_h@4oUY2bS z1_w1#YipTGtY4&jVP~ECpaV|uHZMCHg;KaN6)vHLbIr!)bXuBowM=a2&j!Rr-mag% zW~wvHHnvLyp5%sjS@iT#Pfp_b6>CqKfYcb}yHC{F$jNQf^706&si~bRjm3QSgi!Fk zE2e76UFV1`M*@}APfYr}vs0tOxbWzr=ifh-M|CrX$3J@AL`G94cEhWytDnlg2t8;) zzVo_(ZYTrq)vFY!??ZQ)SGqQzG*^2*GtH!oK1RG-nVbzjI>1xTQosMr)2^}IaQO3o z9!{rF{`c_e>T1O!b6IYll$L5wS?1muT|Jqo3!+=*yK7Uh9PX1dsB?99-#XiRO`aWf z^YxWeZ{ECVZEd|~WySf&K{VNS&-Q2kF^_Hum^TZk{O)ik*}5es|gp)KfY^t1AW+Iic`$YuW|{>kZ$d^^}RA^Cl=1 zJG)fy?5y$U&mAopDx_)HWq$D5cV(MmMn<*Q?)>IL)u-Kf@$&WS*-dexIEDFp;K0S9 zk&%%{Gc21ltT!T=q@SNReL~LcyEFFEbbAx)$2f8@ExP)9F9czufYB8_HEN=ot=4?}xx%Mz)ADwu$VS1d&B3tB>gu--@)h(DkFp?Z zI2UbbXlTOYTS^igaJR}`T`%FPW&6t!LE|D`etxSWb^;tEQ6|mL&aN1VI0TW2zrLhP z(wnnkR>ZE&4Cy3VgNP^^{JX+wOzv8W^=DXsjRb}XG2Hk&67p!pSAP{EnPr*Qr@slh zhB7Q(7}*KtH8>hSUssy#6Wek6^E##FD*`ci=X2HsuFD*hh_-K<mv3uY^H8&vl$6xy9b8e^(+qQyYoc@T2x*9E^@HfLFeHlJo3c;(o^rH-zL_X? zt2;$lwA?`I&fAnbi3-3x(;i;w7gWGmzS8w*+`BnA!a(jEb zmWj!*X;f57xWE4s3oEPpU*q@;DxEFAcaGvCr=Fdgdp}et+DyZjG^ioQW@G0j2YJM= zDBlgX>b?0qld_DAC$5kE!XhK_uzRGwE4T+6S+ch$XRaz3wICmQg~53CCi@+E@|xBf zV^X@TdBYSV!N3Q7-@iY#{2I3zQc2BYa^2ba)O$_S$k0#&)HO9VX?ps|)Ix{z?O#Vu zqoh{qamCyhe}(!n$!EBQ_2D0`#n&l#d4008rsXzxpP6}Yp|1d(5f?TVZAwp1|MKly z0@Q0^d*QxD1|NGJ&9JNhi#fp>oS9HxSlu9bejn)7u> zn-31YjT{g|k%Mf}K&B!CyRsc1X0Y?fs;#Z{LtH68GD(${zNgk_f902X)G1W*lQs3p zNh#^vF7YQj=YN$id$Oa^<_-R5()Yq2O*FHh(IG57ld7t!EBhnf$77bgxwk$3R?Y}X zbo(qCP!LBTZ_~bgn;K;{EVZAF%YouGIgn=6#?irf77Q&}EiHXxOp=Hs{XZr`O17A_Nqe6O>66{LP-ph{F$$xK1smG zGqegwuPN+x4-P)>lG!IZ-oqY02P{BhxhyFvazAvU0ZA5zq`kPDta`bI5|Ci zRVya^l2-HQ&t{E*`1FZZHpync_O^1BNIr>g&_1Fy@E<>FVoGEDn?u zW5dG2u6uh+f=jY+Si0)`X41zFFMIJDQh4;ocBoJ_ZuDg`*i=Mj&d`0$$Y77qP|je2 z%@Eo?e0bx=jWd57%Dc$K4J<6!QSVa6JnChS_conTM3~706G%giW-6|bVxz+%I2A~y z@i7kDDK8WDsjNDUg>y@Eb*qEo;=Fhbi%;X@5hhzl->3UQW6pT%^Ci9o>>;{ zjM7pnFa!#fu!LRtOj#%Iv9rS>d)yd=>m*U<|M%|&6zXUpIJjqEAPioaSG?zU*zY&z zyyt!CUqZw;MP0M70AG|4xuVeb^XI$TTA6oU7gR#2cAJ=wo+4q1db+byX;9-OY1Luy z3{nUdYj0nLD&MbL84DRXi&9WhGCw{#O!u7;HI%=5m$7z#XxXdxzPb78bb_OuD`Z5l z3M7v?d?@SuOaPe*^Es+3SExelU7gwtfLyM}j&>Oss??Ds^wNyLbB^ZO-Eh z3HNUK9hP*-ycjuhx9Fd;P*3qY5`X^UMU5TQ+~T*<@M;Xa+P3u^OHaJ$$P>!_?d6sn z9ZRRm_Wgy4<_INMS1MLEG%FVuzGLk!=XA##%2$FfD_^~OHM(7QT%-SRbG~<{^Kor@ zH`Grv6+Nh-8EJ8GG`hOF?~03ioLHPM{Y(D!Rm-(6*4CV{b=w_+U1m^=b5p{?XEysy zTcBE0+i6N~Qq`_uur{u&Q?Mv%r%bY2WS(*skP>q9^3*9=&%Ou^t@l4e_d+vu#g`qasial(V-^Y zHm{H;xDERH`mP$pi~(job8U`H+^U0ia&ofXs$^5sdO=))gy#JD5P0YK!S4ED8N31F zjn}ADxhf#~ubaC&z1M1G-2r|aK$(dFI%0W_ZZcX{rNVdbP??#TCa}taZrj#N3i=~fp2^yQ z4KW>n8EsI(t@Tq=Q!Ko^M30w;m#|6VE_m_$cNe+Ws@&Ap*6tUYU9#9jj6Q0)RO ztG%6_mcIV^?=ul}f_Nec#DM8qJ315qFE=(7Y)2VhzkUip(BIoGRYMTnv2PHN5o1>A zI3n{Coc8^Dye!R><{X`@=(lhEch_gO>$vQHyjQ0`M6=w_W`A)nR9ETVz0@nZg@z@H z>6FpKh97k1#=2HIg9y(9inbWJbLY;B!9k;gIZZztl+?jW)2~_|Nz*XZx1)}-SIefS ztq_m+^yw{&_Kh=V&J@4>I@MU?y-h|>pW6_oyqv#vbIPpN-%?&4ci8XP=TFsRQgZSS z9xDyZW<41j$Ga)wvws~F%*}=0zO~abIpQQ?5PJ&WJPu&G9+I>$U^BhXqVq3vt|-j6 z^w%A^8EScK_UcC`B;<96DP#W+j9X7R4qu&Uv3Fu!B6_l}0r_9%_`n4P(Bu?UFj8gZ zR;IOmHPxfbx_U>VsL|b-looqz4b6rirRPdH8{J#Vv0;mWC&J1Lq$bp zw*7YqImmBXDp%9;mMbd6zMfI7uQIQ+@8?I=Kc~i;?XJZi?j5D2$+Dqmu&Xn&j*VS@ zM=nyEKXqEaekGia4%=HT=b%$9LPA_#Pme}E!yj?s)SfA4TUYuX!IC-^>x}oBDI};0 zml=}jPM^l*YjXmR|0?DiuG=pTA3m&JY1CUBsr zKm!2a3d*cI%}-AE=WNsF_?P3rTy8W8qeRBf?$F@RBZV0`@85G)3^_mv6I6Jsb^ZFY z#fK6QJgG6&MLKieC~;zAaJ*@*a#)^fj*R$x-t>xYjKt3GI9=*+vbi^%R-r#r{QYqd zglHmMTO5ryA&424N_8GAJ&U`S`2D+p^39GfQ(sL-zo*I@6kCK*w6Lv()%kE`;{~_A zeM=9JpA+&k1FN8*AUO@q`|q|Ywon|dLvJG?A+cv4f7!GdLjQ_&Cj+sjqE~ls@0W$; zQyR%qVOv}7?CA4m9k20E`I*?wvl`bPoFQSB>CjTS4xP;N`=J>P1Ox;tz<7A|0-+$! zaSByvQp25R=$1r=>Ub+mhypbAu64#!Cgiv}nx2-M>mpIKP-0`FoME(d&SW!!bEzLEQh>&o>RHT#4 zR-@Kr;8$;NP#7iJ&WW{$(!}R0pJ^?FQY1se)YlMP0*t6bMfac=lUh9g1pQ_0Gx8k7 zZIrCiJif08q9IuTpFLY+26ko|H*nyvC&LUYj+&R8iPx7*`#GF z080q^^T#+aC}<3z<6#-ZtMMmSe8^`%z)3kw7Xo8qV}->cYIzNcP?xJ$a7?_Hgb()m zZ9TRI(v?*VuPko60X``o_Bvhe;Ks_$O%TheF8An>0O03fl~~RkC+Fg;!K$(Lz!KfQ zefzlh5r$6N^0U(9P_RhTYg2M;H5-y83gbZ_d?lgxG!CL8KfHj zHAvXL59(tN{YZwOP)O6W{CwV<$x?J^&E&=w=DI-n5Z}nxuiu15B!vOqn4RCFfZo97 zq4e*%Sm!U#sewP(+T+Dj)5ew0Y#=6zhV%f)pLlj1F9Zt3&A{MbZdaq?V#FQ4L5{#; zNm*D}=o3Rrn^_n~WR7;s8GzYCy?pud>C{(d|KCfBj?3!Cb-wid*p#iky)a6)53Y0C zNYACLrq%>W`O)h54J`IvQHGg$wh(Qw^3_~m1lTz^Jl(S1zJ03&qzoJpgqYEo1j`4A zEwLmG?BLGo#OlTm%?WGSeL8+1Bih?lAyL3no6CE|q{m;e8wGdD_lV+tmpitcz&Vvi zL>P%Ihy-HdCDNBr^x*7s!TlD8YkucVJ6Fe70CJ#2Cm;WAH&WfBt#`>-TArW zjo=4|A&Ha}0RY)44M-=8ycA9t!XRsBx9t-xw_7kvOh8F{f5L!0ko9m(us7;4w=1%ywGVwszoyUnV6j^(HMYECfJ_gs90M zYEX8o?ZdyJpkU)f@8hvO^caX(&OEgks_)F7Xn9rmh%nci$y6o_-o3l#KD7iK12f;BQQpk-IlUbNm3tS&iefaryT+fhRmkJ4qYT~(kUzAP=xcSRe zR`y!*abYl;O?cI_y>4f*q-&*HiTT9dY;5u;3>_HGSgVuV=u40>=2jW3C*HEA0J)-L>#cT-d0V^9YVfHChj;a zRjVGzn+4mZ;l9g%Uc_-YABz3MC-2u};J8byyV~Kn?=AlNaDBhB>5N*JU>s4L5XC2a z46p_!$AXsaRFeR&*w}D^T6`_?@GbX@mV`oZV4w$a-xURlU0+Lcz*C$WiP?Zq)Q!=u zrnhfniqv*n*`mzmdNQvc??Q+QeUrBYc0AepulRu6WCOxW9{hb=*97RC>TowABI2-1 z9t@VlCL%(Eutt?GGkf+!LqovD8kE{ZBL;Iy`tCy#f(!Elld_76ig$OtUjP7(5hBJ& zx-ZrPVe*%mU5Y|LAP8t{qcj>WO%j2HN?D1GtB-|YD)>c#VOQl$!+S6*Q;&{ z3ZciD&J)ePy0?9p`wNrm=X>*3+j+2~Q}L!-3o{;all44H*T6Ph=>T0hI5?2{+fASE zyXkYd=LY9>?;cCC$2dN*#^kZCSO5p{jaaQpa344VTmgag4^CqwDffEVSjNcN*%_4X z4#}qH&Y$&|!sxF&_S=38tRTkcA+$JX#KpMKqN3;T-Md%ez3t#vP*_L;&{unj&aNl8 z7hRX6frft2(v9P>c4V_w13)AJgPtN?QjFx|zn=lG;h_v_jfeM`RlWAM$!SE$`TJ$Z zfg2T3RZ|O~XMHGg0k8`lYnXq=|B|&aKjhjH=d88XXtrM^)=~MjmS1UpJrIGdd`mH_ zeE3`B^XJbtu5vwsx8*JG+_`W<_}4EEbVbYyT7BCSsXcH$KkU2zP-?A}?e&#=a@VZy zhqCu*0JP!N{WRo|f452xP&0l0-p#2b$;Sv{-UNC$TOv^~am*iDbKuJ8Z}w{K9_=ru zr={U^cki}#9`$C+TL1kMzcLkH<+S)qAm8A_eT9*)WGWfVwR(h`o13dCYO!l&8kfYy z4Fi5;f1PtB82QAh67yHj7R+IjP0yW|n~OrlqOnA?F5}~Iteo#r40i>O7u`76)NYLQ|EJP9>qTlw+I6` zB3|XD7U$;^p~%jcvyXN?2bTo8+SSz+aJq_#pW~?ON2cUkEUY7tT0Q{w#lHQ$WR)$% zl~=3MGUhZ2Dchv1wN?2pIQfobb(5LO)ArQ0&ta6PSNND%PQIouFY4rh%+Sj>fa-6d z1+7A(mddonm$qe}{jD)Tbj6?8RbI>Ze8NN1ze)AC1O_93W0UaqddLs}Q4|>k#ZDA4 zK0Yq$;Be$v+IKBBWfXffkEOj7Ms!J5)>O}>(zp@BWAQ{U;lRPcfyTspW^&RD7)AO- z8&|0YZ7P51hT@u}_{}J8~R88HJQml9NAMTzr5vGBss3 z=8soIrPT^}#l1%dTTi#ti_WzNUatc+wJADDV2xF~IWrcZ4Y5g`H zCzlWHljTig*Yx${^&kGJcobZ>MMKAJ5EmaWXkZjRpGtw+`a493vauESzgv~&G}p5n za2C=i9t;$}OMwv?n-SlndsX+)P(g$3CEENeyFR1!r=IN1 zWg#8}5akCfbw;yjad!6ms6~c|x*Ug-pJnSw@_;GXal=?s6r`v93il<(Keais1K@FR00FV}RYjd)* zzjhY079)!5%S_OkQ!_DPV)7V0WtcRi%IY%C>gsZJJ;4>~)3YC0nqQ%k8*ZIpWElRy zITWIb`c-Nho8Rof5iP!oiI}$NYg-Nu#)Cvfck`qDf3*O>6&1NJ8G%ulftM{VzWQLK zmN6;m2usa=D5#KaQ6AGO@he9NU83PD$v{&2@uOF-oV+}r=Moy7( z5^0@*-@kdPw=~q$1P?XZyUmJ9@tXeg&e2*`7l8>07QiZddtQcjW7uJQZsWvyXkH{F zD<7ol&J&i;a{02R9xygAj{Z3+M0Kg8fHJqRkj9-$A8QhEmidWR043eokjEY0v{EU| zU_%4|Ak9h!s_g(xEb7s}8W_%)a1wJ`9+t)$J$S$y;&LFQTOow#OD{pTp*Sy3Eg<&RMWXZEr;x=wZIYP27uU9YLDb^ z03oi4H7p+d*R2BtEKbaN(DUO5IV0oJ?JDOf0y}$qVF~hxI70~xpd3+$KQDX5m!!Rj z;->GnYT*}wsm?$uIV&io;L~_nsogd{GN(u-%ukB*L}Pi##Tt2TcUOoCa|qj+=2*qFhpD|zYm!ra_-PtQuo z>(N)C8=qfT2)f%o^)-G1j$7~e8mA~2(QTe8AhVNBLKg>llrgJ5;@fQO2(m@T;f-AN zM6u}p;p>x{MUxMMWawm0OzrT*GW`Rc=bAULy*uMCE?c;%#9T3NCITBW{?~?#SD$2` z{#C$!wFJ1Oz>pB{UifyTm5R_%V7vEI!%|J{#meAstCH00Y~=t-L(+iE)z_^5UJob9 zpDv>_=PD5-ulPqL2aR;e6a1Se#QDF*_gEuIB4~TqTT^eO=w84IsTh^t`?iv5g1le zk<1_ygeaN4Y&>*Y19VbfzI-8yqrZCl-@*{Mb6tuZ2WQU{ao};mhn!QX)~6k(C8>A3Z@prpz1uf2Y+AZRWlI zgbAEUB%NiF7L0IK1|`|p0(b&l!yB~yZql9D0u5gu65WR{o}^)1;dC7wN9ChO%0^I= zF7S(u_aP` zec-!XvmIDR%B~`J|9%?0{Mvu9MnK2U)EG!s>timM=6Bm|%X#`(f)E!Zr{>=&*8l>X zf|j?;a{k|PUdC zvF=L#mh_6VX^e5x@Snf(r_FHhGC3Vqcx~q9zmIp5)5xNP$tUtsT3O#}*qa#`j!D)x zu|fM@+&K&ivVhh7l7TD0)?bDQB;1&gEJGjSwsGAtsU6yT=zjn{7Y$sS{$fUF97phP zy+EfwpPaP78UfX;ks?#j9o8!ExDd!da<=whP0cW=f4J|nHE%$R^S`qjwPQJ4Ez_`B zVMhIQ2F$-WSf-}ux7LP6sBGv%NkM%8S=zjaf#Yk?No^__<+-q_RH|`_i%UhM02}PR z{TClwlck=}ob+l^zo^=6Ar22M$gdWBa+=qF+B#Pn+t}Ilj0&BeUGP+e>XVzxeNugt zlps!e62|;3f$0jEI%jb8-*Gnlix!Jb7~c?U$UpU!n;IywhKv}(Q(xi4$*#k0| zNLA+Zt58^VCg#i=wu;g6;#$vXwSmj8W@crvadI~2A+va(ZX+}-9vWdOp`uWlcy}d; zMm32G@scc`ZtnS)i-^R|6q0%wpeLc^O|?@a#+}4M#_CR2qT>xQ+x_>_u;jc+>WaNm z6SV8zhAs4_@_MFqzS7fODcE+pRtA{slsk^}jauwk?f&xy*R) zYr8HbB_?**JJMtRYpjbz7^MEra;m=#EG-qn8fj{hf_6bjB3js1eD`qcw`R+@Di;f~&=r#Iz^KopS7yu44#d)TBUj>JZ@WyydAE(W+RNUZUmln4`m)NEt;xI26tG4;`bC*nW7eYDY=|3ZoH0xuo+*?VA+ zinX;h3t^IlZ26@bt|13e5CB+gwlH}Uy*PiFWUz|^hnCmpUN#kCyVu$}I+j10`S|z% zf0x4YNy^Z5H~NP`ECvqLd&Qt#K$qa;yAyHxgWo2#0|Fg~*6{?-LnGVX#ZGarXrozc z4i_=TXMGVn`2vlpGW-6(yX`R1GC$nge10sIHs<6pbD5Ug=j1ydh$Q4sL!0pDPkw`K zzC45xZ7Nv!+_7Jqy<<<0R>RuLSW_H+91%ty`Md{c$DTrAHcY}kAYv-(!)KImJqP_X zf|?quJ=duY4Hej?G>fXew+r#mI;8SbWJoRNtS!EE7b-+sTN^-P{YC3PpWM_umZa_b zc>iXw57F`)z`!v<0s@W%afykxuCDlAv3yD?J1I@5=8vX3=nxA7Sijz#a)as|&snwL z_Irpeq~_-4Lc_vVbA^S3-hKQCB*U9KMd&(vdwYma43GYJY6z3|;tUzrm)wS!)E-jA zk)mb^s?*Zs0%BjA7D)mqlNXr;O~SV^h8|%aJjfHWCohHr_VORd`BP#|8p$Be3d~U; zG#}h+f}#Fj?3yHrFuwP}AO;GQqx|uNFyn>T_yg*vSFaBo?CdC@v7VkDZ$qaL?W~9W zyaIU1b@pYBKZkr~3Sy8rhyxhGd-i&Hd+(mT9<;f!arz;WG05=rOuS>ecPM$6hpMs~ z+FpIp5=Q_Q9iiy}?Gs{R;^May3xPmoMUu+wT+zaPw@7?SGz3Nc_XY^Pnq`hUT4m6W3& zzpT8R5L*M>u2`b{dy$hSChp8vAiGDS{0`UhoHwqgsAIk^OfNCTgVBDDRkXl zBam_e_tbfRlde~SC8UXk;a&0XrE~cBbiKQwFr6{m1^HW7YiDNzjD}W!>S&J19!lt*Jp zt>KVXytft`e&+mG31B`zVKDrkzwkBY8;&SmZ@6=b_dqiv(}#3*m2{#V!+G$v?tl<^ zz38xq{N^zc5#|&UiM0PuM|tK>I8S!!`LPY6Yd4`>W&9 z1|Ju%JotDVk)v}=pOfPk>;%c9oSMl}^CjeTz4c}TAgF}NH>$ql&GA!eo_2WK>#k)G z8>M5%8p<}|lKwfiwudYR-5^oB_*wI8T_o-A#iyiP z&J)nZ2mJ?V5lzZgR-7QS;H-Q#J)$Tm_@=Bm63nIZT=C!#QOrvFTtJNigwx&g zkR!qnfH{?qp=Gng?%3Pd%+?vDMFRu@Jkf?-mi1VblL1emTPhV68Jr5}o&Z z$vvD=Qe+gYo-{L}Hqp{Wv{NFLlGGz zlZ|er4;F0{H#!w9T$2m$TUd-n`FqF&B&h~KiBcXJpO}b_i<`c^08AV6f#SW=B-LB* z5`}ERmBR1J!_x~%aiId$jZs4N1PUu*hLvdkY+2)7~`$b?o3rkBb4>^J0_KS$g>P~XT zAHOuMxrH~aK)M4TVBMM6HpY;~f=mEWPX`C}ofi69O-no$^w{j|O;4c?e#joi#we|a zrCwD=V(W6Z9Sh0Ajw3tLG|TVwu|hBWXk6h-m!bs?sq_XJ!rh`!B#d4bpGTH=nW}~g z2h9POUq=pFMm&mb<3y6b{K|n}Pe-yqwOnBXU|IjbxaNF!k0Xje9iv zon@dO;Gyl0_h*(KC|Iq5h+urQA>g%y8+Te-8VHBGf4bs4e29MHt9k!EtM7Wkh|OAv zC>+PSE6>@pUmuV7#Dm^nJ}t)_Bu}8f`uydKtrM#`Spg*hKK?2J=G(V#Py+$EJQ%JP zpS5Pc8ZbO;0xGVJV>b|p((oAte*dlo>e{sGY6eS7%UKvdf(*soT?7Qcpg9PKQLTDs zhgJ>_;>FegyIR}YqVIa9NVpN?=@sh8_huX&H26pw1wnKIGnV;HtP`uj)xWSD5; zHOB#Sd#!XG;)pKY+^1c76myiO17gm#?z&!yVvppu3{IgQ{HeILBf`cSlZVAB0k4{W z1jTS(L<@%qlRL&P7JU?27+QgKwrL`s3oWeC(b1`ljj=h6e9b~1AJz!=@$tbxT6fq% zlU5GJ$vQg|#X}<^HgoURcu|9YcF!v8iT;d)o`-93Lp6qdzfO=m%mRAKsPrO5X2$5biXlD>{Y@W^t0AL35H%~wBkq~PWWDM$)PNa)W-hl|i z4fRynZ>PN($)Bx&)2pg}=P{9!H$YsFlM&CLz8{vApM_B`;%w(l^MV|Pt8*G`H@@{t zq(T!m=9UDr4QREETG+0Z!sO*%{Mv^WrXQP5o!8*y=J0Y;s5{{s8?IO*N5{*cNy+IB z+fWnQl?Kva>~bSa@kwULBA(s~alyNv{qv+afZ``cf7CfmYvAY4z>^WUdlh49>H)R< zWR#}N?&%bttv4rI$71e!wfKz-BPpjA2BU3ufAqOTcjl{VY8Yp_QsRAv2FvV07leb+ zxMA@?k-3vDG*z1os@Yt~H>)O4&eqsLi~j{MCp0}W#3UG?D8E!Zny5ww-PK#1^v_~q zD8`&LZrzH;%fcs;&s0RL5Cv{GM!f?Z9;9qvVj@g`;az!{uK|x)U8@+w4u7(JgjnV2 z?ZjF_hkS!oi2=D~Fh8-JSdm%?giODmf@S!X1Jn#lU%p{_+dyb|HV8UT!k6x$nDxc~ zJ|U8zt~XKCX-Z^_{t4YAjQRo0WytCV2L(Msb9A43ZF%zH2;}voAQXu`d{GVbHpBvb zlCr5(QX4Q_AVtQh7|A5U$3NwCjBrKrB~T7wrb2qs*1$xliFk$x>X!iGeexT|FrEs+ zLwBbD6EhBBZekxK)ujW9@RO_pjvJIf8Sb^T)S#7vix^Vg*S9vmnP+9c@NQKw5ZbP8 zZkzp5sXY$mU*Fei56#l5|~YC90`o}3TJb6z`~SRo04 z1k4}`s6Bx5I(qfB+sTU=k?P@%$gMyXslNm@DLXIk$E?Djvlv5T|Ltj* z#|yoxlM6jSS{`u!)fQ&a191NXQUA`9@9F;SmJb1jj7>naHoLU6nXCEc>J71<3JUkF zm`;4s8u6=So3fX^h4stBHH29|@KGlEBXDu21xU;*F!nEqRJ6DR=&*h!#g9MFaiI8% z>oEfumJIO9Acfl)XrdP@iwcSQQl&BZi39E5Y=g-aW8*|y{d2_4TDGX# zPnhNE^+>!dmSUQ27mO7F<~+YKnL8H<37#WS(vLNbKa_@5wfP*Zw#bCITDp$- z88Ltp!Mo2SlQbX(J$nHKomGkX{`>a}`~E`D!y1^ieLe7JU(<&H!wDIW@8_35{hwze zAP*Q8Kx`Hi6hLemB94Ymd2-T0L+T#e%iz*^e-S##hzWAKV9dX5B8d0rc{;iDhEBS`)E=bm(l$l%pj9c)3V7E?pdYai82SX+zB?B(mxL|^_)6$A zgf1a3=YV;yb0vUIK4J|)35_hBj|5y07VcGdx5}Wm<>KNpMk|~qnb~R7vekkJ%;8~S zIR)&ANf|^Ey;a$FNCuII``gH<5gF&{oiCsqpA;oWbWHdmF3+Do=N)OY&K5#&{7(+Z zz9$q)cn74qp#EV{8^saNcsQ*kC>Q4CeVuXY1fLNWi>|$*OHYf~jG}<%YGbV`91t?> z12q{NE34d&^q*TQ?D{Y+__J)cY41oHtQvrnd1+uKV2Zz<3lx{e&OxdPC}jz&UO^dY z2KX_%z7LA?>PKSM9z+4lZlMTGqw+SXV z(O&Gu@!i=8DLD1t2SFfXs2;V??f9pHrFyHgtBcwFU48$gXg}P{dL-5Yx6L>kV0jXN zfH@b|%07OacOdu!G7zv$@h2NJNWR^5DGbSBEZL%EOMx7UlIxkmEZKTSX)mg($IEfO z(Aw}OnlXpVODJsjf=(S`UeC13oiD`YG%O+zR_}(?Gdr(JoVv%$$t#22gQd1jBybW+ z9Nj*kt}nh`4uZ`OYIC4^3`0Vj1ablVDb~Me*8mU=83vaBUJ8Bwd~HEcAvH!`!a^8a zQ5=z8md9M$VP#_r8d5FLC+zL-ha>nJf4K!jd5haKU|0d&7!2H_gdvNwi;H-o;OT!4 zDKmNjdG=%OGg1ZZDA5`l`-2x&YBWNV=!z*wX2MD2Gw}gtP(4ZGapK#){dc5}`Tyd; z=T2UonUUd?L}sW6vms!FVT?V-%sB_Fr8?l!v{57g$H&L3?Eo!N)|yNHf~*Km2r6DS z-`^oNNo44{HdV1iK`%IfFAf~HR_3NK5s<)X@eT)6#A)Gg+hq<`f5U2!&NU8&|=mh9` za+9u~(BeR_CO)gs2+hw090s{Irq^?6Nj6xO5*+(d1x#TPWi@sXY;(H`=Q1B3wMHUz z_TZJax+!gLauzojI&b00XSN~hF@_1z*YeVV_ z1`$Ha9M@a^V8H+LX9bwX8iQ;OaPX}a3u|k0P@J3RUnJivK;*E7x!i!ym8aaeEsm zBXhWCe9BJ-!VU8(E-np=?aHHJX71v*M1kxTf+KAdq*4;VtJl~)eE6`@P4*etUGJ8b zma|WmmRO9?pUXpE(mfJGi~aZ0BJ|rKP1Fy>Nq?s%i_bB0VM_L}o_6GL6d}l2$%GQw&b+@kfe)2?+9$;lbuL zeL|nrFL0&MG38`}@h#!}cWctm8XShFLR|b`{QEco$*rvP>gp#yQyxPF7%STbEe_R^ zHV!!MbU6rN{<(UH3l(JlTaakDG+oaywenm5atY+v7H(BTk#H>}YR}~cxNgUT?6E{( zWk8JKazDEiDKD?$qobd}G#d*|P`{R`sqA=HZcYw42r&wbf`I>x*bA@ymk|u%B*uZ* zE0)04V7_SC-aGlW4bDiNERBdAmqZQpe@BnE4hAovpatYw(2Zo2jFaSUqk<7TT+Smz zYJjI|KFwf_x9I;xzDMpos1*_tYPEZk9Mh2osZb9SM)zwmCvRKv8NzpgGM~C}Ce%F2%TM|Mbg1({>PLlynvt9M(&CkH%Rofxz z1@E$#kiFtfeYp_Q?M5fMkr88|2(AlP0g?XbO1FyxFN^};yh3@ z;KHQ|r1wzyzYCzpx5Y6hF|FITIgsUmz>UYZ8ObmmimppY=UYfd0AhR`q;ZXb5K<~N znuUvz(5lOmN(Vwe%I#Zw^6}s%@xgo98NSG>ls1@FojweV#@3csFAR3bHtZd* zRcnMooazFJ+Q@I|>kF_DAiK&T;*pWFm8#vf|7Mm**Nn_8zrCe?RYLr^&G9N_t+>)1 zxCH^#g4Ob7iVP$CaE1w#JQ1wfKwlpxqybUKWNt_UaL!V>xw(ONRY_*DLy$W!VA8~~ zB0z2^-Ysg+M6PEgEny3HX>50T}D#!H*#XBGzagJ@pLXb7hqP zaWs@ksuLI6l;{mqg`N*r_p zaQD~=na=yb$p5vJXE7ccHcn50ynu(7_cI7WYvhc9OF)?c5A@cR>lAE%V%#ZGMnJdc zB~reOVQ>NWv8zAD!f~VilFlGMQWEPDCdUEGItQ*9*d&fXrNm$8+6sVox z3N`LZ{E9owYsZSh=^=u`-07X{%PL-QCE#kG| z4!o@b7@I!1X{;XZRatCiC41!_6Z~mfa?f+)y$sNt2$P`%-#FzIc^!ExWSGf24<8l) z?s1+{{RP+{NuoDzxUcX1UVS8}l7LRiO%AXTLn<1-C0uI+@R8LJW^;)MBXl3mXm=VW zrbq`2KUbl9oJR{nHH#6K`JY_3JEsxLQ!#W3(14>*gIi8+Ee-@Ug^+$lIwoi^aZvzi z2S)U(bPy4IPM43RgBHa&7Jo< zUqKIdwAsMzS79UBu#t`P(1?f~j8|@L!Sx#&cf+5?e4pLqG9JTzzd-V|*yOwO@uG~3 z38-^q;R}Ak7kpZVS%Sy$;kMklNA)Vhv z5Ep`Q-i=FIL4VXvMjzIlVGWR|amM$>^XEch#1W_EInDqUD3*ZU1DR_gy$2_!;*K|OU!%gfmWy3OZdS6_|*ph6#Q`QW^6eMo$P@FLQc2_r0Aa-g9DQf!`}aA z=qc}u)yoUo>2&N71lbb!=^5Y+in#%6L2|$vDJTSX*)Kl>HJ^pBu*txsPkNJ+qH|EV z!y%7QL33dEO^MkjFyJidNz)2#6w}uJjeX?0&4Wjudcd6009|e%Sjfb{pmmG^7p}V^ z@JX)+?g7Iww70M2sliRN9>Bzf`b*#o*XwX*Bv^XVdwR6Tm_0m}9`b^N(Yo`raYHQd zo7VColU4W~qdHlr6qkPObKgjfi5;mehUztKcFltj(VJzI!?3V#N)?sVT77siCsqRW{lB}P} zFLhlUu;wrnq>v_YP7t#{2j-|_5k`sRwY$v@<>qUXZEQ!?0_M%{;GU5lX`c(`$&Bcn zioJc_zv&R*4GduZG3cOAJqG6kJw&q| zOR#EBfVB74C^8L0n#C)&J?tO=RE4tp4k}Vd{haGKjF5}rN<<65aOzz;=z-$DX0}?B z!q1|>rA9l*&j3oazrztL>Khv3!!SBec5gNvxygASP7GU|o2$A-WPK6(Qy8d61qPn} z;)~bqgkr}=4oO29LFn=gL~*hTspvE{gD%RyU>q?6M$>p z&>P8X`C1jFZ=p6@Zj-0riBBgVyBa@(EyH_C-!^m5p}AOg%zqGxZR%`1o+5tQ^7qbqTjO$*!Uz}c@rhQ|)V^*bCB zK6d(^u}RT0zd<19Lo)Mk*hC-#p#WCT(Es23Oi?k{c}ZI9%GPaXC61he%*-3VG81L} zWDu$z#B4zKXK=gos6>IT|Al-AN!v*l&eGK1wvopn-^nAL=nFgI{+dJp1qfPD)z`D0e3@Yslr`tI)-3Gs23{kcDYK{RGaDR?k4-}L4$wGk16^x zuoBI1$=1RRj10xw)*p1GY#9TT}y^Ks7nR zRuK`sqY8fT%TYH^Dq9~UGO1-JNTJ$lkmpuz5&q36C4pr@o0Wk!+uun=7O=wK)=q0G0y~ z#L)SH7S;sKLPi|?=mdxzt*qV`eu7^+qoibeQq`%f4}PkBMHnRV2uI^L`s^$sYCsf) z6ksL@9PJm-RKPtEMDzNzri6 z|4cF@T4r`#~A*Mp-`x>OYi`?K| z-X8Ff>VxDtkw*}2Az;b&S3$wxa~R5_wd{snt!uqb_eE zrfZj?Fm0lFz}GHKLeu;mt zyrHuPluf>DlK1Fu$ghWT>z@|BMy&*FNhs~d<#9dHo0aLR*7SWTz8V{ zmlC?neDUI|QD$0N6^b6kln#2{3SLXPG{D1$`~;kh9c-QvX_6^rmUJtYQPRZ=CiH160;+<{VGdN#MO6{VP)Wih19N8$l z)Gq|95!&3PZ4cWn&-2WgGX~?Q>-g3jS31Q-6^MmcbbD zidNqUyLw{iqujt$wtd{9L?P~%G(jW0O)B0dQ%CZ6@B3e)4XR}Ojn`^D64sJOBp6z% zoLMk5zf^g}A`Am^l+-wf9 zJpf-bFLK3JTomFYWl-M&2Rxw5NN-xh%mZ*#Fg<)pu**?i&eyhCf8Ia%@#q!0ml8^s zOK{5;#D+USPY7%P5OT=I#@SN(^)nt;$g46OIivKT#-tPmcU8xDNObwJ1Fx zSJK<|l(U_)7scr#sBYb*50^;QVC%P1U3slWxJ_WFC9m$9GZ9z5*?!?q{d84 z+zl??(;6Fe$z()FtJ2oGuf(-~=Exu3>DZ72Y}TS1CEd4ooQ~p_K4%J(`k%O|c#beT zPRC5`^;=OM5I2u8xCtEqtE#Gw0pHkeN0rErj8HiKdfvCB$(I*-H}BArG9Y=SZ#1fs z=wC{_x{&JXF4MW%l0paJ;3iue8{bdV4pE`4b?fr_!xv);lA3t@)^>=MakSJMg$n~gdfR;57) z40oAM5CsJPFAK8w*QZ;FkiDi~J!t2HLiTlQ4nLvJ^MR_NV^HMB^%l;Bw%*?#V!r_i zbZgtwZ)|1d(^+q2WfhTxlzMYoRoWh#s#7&acMvuG-r@<^;{0^k=}s)++btb`zqvY! z(s%McSBkj?`un3KtqRVXvG+}jS_sG&z7+sKDR+u4Q>s<@>LKGyvJw1SkCNFZD`RGv%RDC~PMv9GRJ`#Q< zhDdaWU}vD#8tl+jT2kIYPRV0`u3hXi^Q$w;6X^$pZlX#zCQ%Y7$)l&6=lx6mW@~OK zkTrT()S$%?232#Kf?UsGVa=t&_AWls*v0{P&uQe~*7N`1M)e@ZSFz)x&6 zQuP>0N*=!2hOUB{WKZhvS~CCfpL6V?66C7VN1}*INTK!ZqKS!#i71~tspZ&JnfO*w zXw8Zh<-1d$VlC*hg~yO^@r1XqdDP6><4<(y5R85Am0?qy0dQApffdpPr^g4|A7o~_ z4W6Wx0S^zI&EyX$g|2eMHr|}a=qK>>H;xC=WhD3to+LPfd&BaKd*Y^AfN-y~yWrBl zGj{l&n+LFqcwh^P_U5pfA<>xNlWFz99(W|1nvqu{=9!41DtGAW8<5``?Q0%#&RqEd(}Qkp%=po zj*^j8=TkSdAlBUBJw6yH@-S%XvqJ1m2IGx*P58k;Js#MG&c3ft_c<4iMkUX@;+H#x zd`dxl=Tm`_5)@E7RtEZinf-(3+ zicub1EJ$JQAB67p69(%K4x`%c>S~kR6O)G~N-DUKOOtesQ*{4f; z*1j!2426N-3UF15Z^fr>+PLw>@ag!6BgBis8=0*&S)0{mnqme|^z5ZJa2)GU7>pm! z-dbO*udhEa)d0>Ez67+u^4yYi0Gs-;{tL8~+4bYKuwd-GaS@CTR;myt7BPvXSL6F7 zG6>wbIEnP|W&$i0&N+WHa;bdx=ys&1l3 zoT|+>rAu=ak=tDr;_|9}D<J2d1`r#pI7#*Re=MNT%MgX4Ig&m`~|dnjf{?tHazXE^V5^*lxi-iRrHtB2jUzGm% zfCx{YDX>yL@U(L-wn^7Tr;ZXB8MrY=x-Gp@qwV7=(Uir+(6Dk~3_NmE(2$ebqi@_^qL5VGdaaCXk!p!~vBT)BgMh4JtqIp$y6nIfq01}ktDq%LjdWEB z#%?$~_bGLQH4G%WF$$CPtb@J%9U`(>Unv2LJmM~Exqh2kJj_OIguT% z>H{|3+kZ8^+C}u|`lGpQ574Z7pr)J+h^CUI0m6S&lMA-*GJ64+3za!Z-diNEw~LO? zL03cmJcdoa`;U8Yw+jklx7f~=B5wiM0zu;)!+gkIvmS3DTC=@%dmN&*rlYeH&ZUHM zpkCW*Oc$ckkyMcYgB?h1|Bf*%P2 ztal1Y+rz~eKMc&;c28l>!GnotTpnl+HxvHAsqNR$>HGH?0mdq;=5_+}s0G2nE)9eH9KWkEKzL5t8WS$= zMgKT;!0iqFcnkd$kw1X@aN+YcL-Zm&;oY;i;?Q64vj^cOZPnb}Yr0zX{HNTT=gn3?Y`_Nw)BSONDUVXRLW&G;4Rt!-1Dn-*@1( zJvHA@2&qk2EEBMMzE+MrJWz!6&uZ|_3TM7#eG;D+AulZBkpV?ps*K?4M9?Dd0K7^> zYd!;Xwym7BcQVWv+|LpDKBmEU55$|DGI#FWaYb~Pq#-=*HT+o-Au2onZ@$5`T2kRW z8g8=t1D<4Mg`aj_o^>M5umDZEHXqI^G3uP(-BY&4UX+l)Z-y*#hR~-SE)F1Z7Qb9UTgm0hXe+2H ztU}?$K$ZpiPk;)^QSO6FF%rpQSJ`zpE_H~#j>!Fa{xZ55tf=P;LuE;FMLLsdc=qgB zt#q`20qVWcXG>9CD^1W!Z(JZzNGHH1kAZAgJtDHBWH>8SkGxl_4yPjE-JD=`=#XvN z56k3TE#AZXckJA0-VFtI9SUszRAqVrYCS;LniyfzH(I^!$08c|(b`^=)gb)1i*2`Y z$dj`OXw>?YEJ9aO?xkk(3R=nbqXKAk6J{Rl0=xQEm#-D-WaH4e98#AES;ll35Z{hl zTFcKMt_<}`UxvPd_C#!ZUtpdmeU&)PgB z0<;`!mB*=tWaxAC_Kny;G*I zx|M`>-){&J)0}lVI*$SV<_>EwvqOj2=o)ptZBOnhcn=pYT!@5DdHCp&iLbA(R(f{! zAq2dS`|NmL!U8M}+q-#msjTTK4zjQ)e0QK;$$IN<)4gjKpXh{R;|5*vWyh~(S!wBa zx#pK(LtY=>W(CT3VpLq*=WInT?9DIl`J2nYnJ+}GZPWxZ&0*-uHq3fK-4M^7AA2k= z08!L#XzerqAi%Mg?nu(T*=3Y>ScPc1pfV5*8~v`?#AFo00F}>Q!!s9e6LW_nxJZor zmJCEHywtz|ow0x1G7)w-aO@zkP-INs|4ism#Hkcj0o=TsMh!P4fyT*8U+{PlG zVdMQH2-XyF5ewl_d&%XkhU}(;Uza}&nmYip=i8-P2oX+Uw}|9Ewpa#1$#ci+E z$C_Ns3*67{E%&cE=`f@kZ-4lmKqG%s5+V!)g_qhzd6q$x)}`h%0Gohv19iA2rs3eq zOwcJodDLg3i1A@|_KtLodVT0cu=0^*vGiJ3iOIRGT$}C+w1Z$TL@cu(iZA-qz)YycDI`ueuTSW7Rds7Y(eakgpj%V;e8@pjdJHk9kSA>T>O z_4y2Ozp2M45`tE!t8)O^;Q6dt(sg!sJ}SZ2Y2e?Qp@ENx=DC{F)!>2`mnxHP7u?cZ zO+mPU&iXu3D}f*!JwmT;N#?cn+-Ga^Xqn!Ut8X|Mu1KkJNj+Xa_~bpZH%3socbJ2q zs(a@;YVgL~_~7PyXX~Tk9lsS0KdS0M_1)YByi$~I@b-yLS)G-BW&i& zMj(QI!s}1i(XO6Sa7csUM^+!Lb}0Q=PWcV!!Bd^>hTJ;#-}f50qwpkdYxqHhJag(; zm^wPW=s2$u?c(XKV?2}{cF4H1}5%8QiN=$xY!RlUHbLq$rh8xfRQBD)wO2g(W z?d>;>SNCaf@AE;5y9e)L(7nA~4LSnNs{kpkzu&o4poa&H)D-l!Dh=5l%e?}wFYlMH zL{}l&c|;uToS2NFxGt57SY=~G-us!ZbUMIHiMqe zvDTcL()O$$4MHvLBk(kLTWvm>_cMOmiMdvAn4oReq@9-qiS?LhdCX2n5i31$nx~Gm z^`eA_CzW_tz{6+@H{s|4@C2U|1-~#c$(pp<}&nw|D+WA6qE+v>S4arE2 zh!iZnCNHgmO6D(HI*y`{5%izoOgqwZ!2bN*POAD)B)X6pa{RjOh>cAq2m|(zmxf}$ z;@|}9RjRBx1Y1z*na?PE`Q-8A zgP_8ggKhnzhtLN|z{p@Ur=g%Rp>@RjHGR~|+`PL)x5yNF25tQTxJ^@uwS;}BMm#90 z7UKh~8Jt2 zqcaSYIQu=w8dU#Qzgl_dT8qzEMNQq$Ai@tRp6MyB1LC#a!!jubX!RSMtdkX31}=6X z8dnL%y;nyF0k*0hlWZQriz@!5Agqm|y}w?B>7((})A@d5zQqAX5r2L5r25Tt?%Uz= zy}Fytu4AxPSx{Fuw;sfg(UP?_dq&2;`DwHb zOkdP+KQPuh>!^G0&fnXe3TNVhC!+6AoMFDla7riddEyV^K!OySQg4YpWdIgm(6cYQ z9_=bNZnl{*yRGOvSRAlxc1rG$(G#6JI~`eLC>d6WT}0iQE_}`b%EQ-UGn5Bnjg!Q` z4O_A86`3w{0unukCTP>&G-mFvr&`_(5ub6^^(%jHNFz#e8t1yyf%0cx&2C!)X}ouD z?LOGX;cBmvmF07K$+b^Tyc5(#HyC}uEzBehyY8BO3ddgc<;2~pODwT4s4$L-j8vit zJq5|+<7rJa1b4-9hEOBbfE8R?yv{wAM+fKvO=o~>__FZwq^Tp{-kIs=HBSfT#Kfo4 zjhUZ5f377Vxof6Xz(CWBo9&_{e-YUPUiIOo8Ge6r{jLp{smbEG?6}tH9|+t5?>>4I zx4u(S%-v!uj53ks7Cazpx{cASJkp7G*(BP#R+hOR6m`k_$|DRX)Md=0Rkx zkn2}_cCFF<84OJ+S@7l=^}S=Fk^F4_cU0IyV9`5mWk5c*xWg7s@7rn3RMP0Tuc^FE~3oa%4^p-rvj4uD8BPS6$Ik z@O4*L1**Q>9z2|UA<1^0`R)vu!melKjU(18SnNZG592Hq8U5z;<}%m>(QkfGf^1GNu3mxTFhM~s9yduz8&)a9_w?l~F0JedBshi!Ic zbFj;5-|=JcfyRZg=7$Hkz8j}@kKPww+B5#6Z)_@_n|CJDcjW$BT_f~8^qp*MO&JY+ zzd){+8QRGh^M42b4z;_9Kyi*1pGjRv;juzZ2m-lm&rt`QLbHE%Nbcik*L}a#Z6{LF zAn{9=e!fw2|L0F`SP1B~*2LgozZ;Ufa5PIpq3S66Z0^P7stl+KV^j>rnR|KVBbZ7- zK0wL+NhT!zq##jL=*>r}K__tHPqLYf&;C1#v&~2zqeTovE*^1uw%dR;TKNZ>)$xrY z3^M{QhD3iYB3IZS7iTD%{|^1nP`9tIsfv@k?K z@7tK%?mB=}NPj4OQuiYmJNNt$3)T_6u36wK2@@_bUG4DgU>D>7a(~WcA)0mn1lM|V zc8il#!N=3uDnFW@o0HgJ8qNy`JDBqlE|*%cQ?iCfw(-Unr?U-zBP4)ZA1&fy0hMxJ z)T}rAqXDiLa9VFqqFK*xaA-KP5F}n(kE>KP07EzT*q;f_t+aB`$GeQUR>B!l3&qR0 zdk}-U)E%xGj*x(2`U48!9nuEsa&Q6w!5tWLVPGD%pWle=%)wnFmD={xUnxQep{@f? z_wk+2&<>WIdCr1}W@KbMn>K)b7{hC*Ya(}2Pyh@CIm^A7C6lZE6+6Lyzsx6*f7q&2 z2(mK$9(?NTN+fVXRX5@_$Xt0}a7tE;!HeqYi7H**C7*4+0eLWz*o8h3*?HzxpT@$H zLX0B;u=ajmkN78M0Gm0O6D+-o?-X1};4dY}<@sMnre$?;P#GMWXEp)*2+%@BYZ9co z95uL0+HezbfY`fIdYm&is}IP=nYEE{7@-I!GjR00=zjJREa(| zcv;H}xEg!Md8?I=7g>({gomMTjzfG5m>u80pX(FIormi;BFADU!ul~$>y`;a1OQ69 z202qYjYLwu;)?mZr|R)*+=UPhxg&HTO9;ft1+>ke2b-*U0s>^UOO=yD1oEKI^uf- z_+!Pl_#%ACWHL_~a;rj_6CZ#JJ0^eJ2akUFXxSAGY>YflP-*+KSOI?@#2NmT>GbP& z=`zUynadiUJKo{oQ1ByQcs6gg<30)o!6FH|Y;!4W-t`I-y&P2rTK2ik;Cu3dACT#JQA;ob&ctkfVH(#=SSUrgp9<=_lx%5R?tOHyLkA4 zsW@~%*9aAbzEj`C^&`L+*nwm+JWwfvmvATDdE@jXjw0nEw*j@^KI82n6XLVqQdN-I z13jE^bGvDEsz$~>@oCl1@zeMAhRGa)Oq1IJ7r@bT2O>srR28(n`#irXZZ0U9rxz5G z(5%6GU-9@GIZ0jOlN~af<=r1&&@|-g=omIJQf(hKgW>t}YeLV$*+K1&jxghW z`$CGQ`<(5@UsJ$D;NiNWOY7u0HZ)02KNvYMJ90oo-8%`V|74mNJvpV>s(9kv0=hpSR*uFTEm?G^VR( zli&}PJ%2h!hpg98x@_Dr96Xn5_zOp%SV~hx>+k*P_u$GE=k=p2lasGzd;hXYOYeI| zx^8^&)}pYX#<@bBY`>4@P*0JRMcjK|P;nxh7Jg4cj|kIJ(0Bkbe{G5|m(Fr6DQxqV|BS7PYk4@`)U?(@T~2ZAXOGx{1a-%cot(G%{R65k zz;j9V)UW%`y<39#_X(>n_xFO1(z$05voVF5oUkmRv!f%epuos1?3d;V$6Qh(FuE(P^?bTGe=J#&-SlGJMxSy_leG70iW}nT+>1`Oo-uWN zBzt7m6DVol-_&T_xN7HAeWbcwXL*8Ngp4d7!+$wcN7HU3r!Hhsbs~Jx+2|BbU2t%0 zzNgqabsbC7-#lx)fB)ii^K3nh@s|sGcS-m^gJRLq%#rsoNMs$TFn&8(?>B9xi&NER zE%se2P-PD6@*dxegh_&agztE%c!Q4u#U9oz+~3J|f+ND{5XHuMH`$VG#bOVF@-6S~ z&ZAWfT-{ro);ja^r}&wo+3A6Y5P+zeRPe^pTD+#zxjik z(i*kdr=thFTcO-XaZZ*Yib&3PcTpl>agRQOlc&$@?K2hHbn^r@ZM~fgEWG+;?^9L3 zUFdbQboufg)SFelxw<^t?!ZNnRf=g390K}_{Q}ScIu-QvZk#E0Zm@VsExr0?)2K6As7#R>uzcL{ypHOkOP*vI9sw;Bw8kWbv0a>v@e&$F;KROO<^< z-wD|wwTOZZ<_2G7_3kc{x5u}MDIfP~bpxR*e9hE(?s2hM26wJ>9wTkoi`na})QLXe zl{f%IRB5rl0oi%~eih2m(%>7x%JIO;l|V%s#3Q4H95o{$VW9GIZ#EhUIKsszX8*Rl z?G>O)Z9H01{&SEJR?{ffMbtwnL=Vlm5bASN-lJk+dw~zN({3ReIyx@5y2KwzziT$y zq%~R90Ii&pm|aYfhCnTt-(2=`xaV5g;Y}$pHi5vSG-?0){6uO5ZtX+<7Qyd+STGCD z_uc0B!5|F(_Jd0V$dkj6k^6Nv&T!MRYSdagk;<6#1#GgpJmCMEH!Gbq|8>Oj-i{mz$csl<0g>*KOY$(eogLlK?CBe;$v5zxE zDytJ@wpi|?5*V`)jQ*#EW~~I^LvxwqWX${H)xIK}rpZE>EGpBV4Na&P!#~-&0xSLe zu7!QaDAiU$gm7vI;z~J;n|}#*vRw;LF|UzU9wDWV<)!3cd9wtNf3xl<`vNe5bPe2J znj*Q&J&RvEGK0yuC6T5pF{R5o_c+JlAk26~qPJiqK_S!k0eH*dP0aH*BhR=7R!x2+ zV2pj&S7+C}_&Jv*NA3k@=JOgc+$sqUl*Hx>E$Ji2Q&|cq4jwrL`tIDo|2}Q_dlcP@?;(L41T zspC{DEaQqL*nrRGAJ1XcB-49_Bk>X8sA)F*k#50exN2EEKU0N;Jj0pQ+X^2rtAq07 z5`Oa>7Jr2?{GJjgJaXmYB&X!%TEAy?P-ZXX10a$2mn2+en~UxbIh88II^HE4o|pVs zIMT_sm1=8h8ud_xf$0EcN1vcN5{Ee71_J))EHhYyf-$pj8X z^1eEmC!CBWbjT}*^;wlDprY}=`Ss&8`AP)IjXFD>k}cd!Fh+@Ha*OhcX1yG1zdOM$ zpyZd%UqgA0z?l|klh1JKH39GTMQeL3Xo85=NLq*@+Fnlv5`MG78eQ(~a?IUhBjAN9eZP$#0#fk8qhR4h@*|Nc}>I=wNR z>Q}0aGPfk||30c#Ek+FY2mu30M^QM&_1&*z3w9KhtY0kFuT7~KuH2Bp@5#-&DWs_a znaaHYW-k)$F@g-YRpmzrpkKiyaTw#aeA&}nHdDt3m;0{~Q8K-mHU~JfO#Gj3f4LIfJhT$rlOlhS@xki?Hha5a1 zpXtvuL5d>w=kLG2ra`TPnM%~mHS+1M9OOZJ0$HPE#=%1NmnEZ*N2)2tQhMa8UBb%z z$O9VF&weB695Ir75wtyn8~i%}}|Ex+H=xT!APU~E(oZ(RV@P(uFhZA=qY zp)=DH zOT6NsXbxSr+GCVVL?$L?P*M?pD<>fz{{Q@4o2KSHo<+>W49eyb>p8|}u3}Hlp3V!}L8Z&~SxdhrK-psW($3gGlXyi5^JCvduA2p9b%oAvlO~@=TqgQ}SajY(>W1Ib z&(9B%gR%NL%1LBb{WFpOv41xliOSka0_P*oc=F@J)pI1k*`at#H#e7=B%~r?;V+IY zHBQaTXQXXWxBKsJBNhB@=?Bt`EN{DWs>`mjftB-RBNGG5 zpoW09B!^X-u8=M)qQfLN24P^%xT#7WV;UcAJO0|LI1{ai(c9?IAuvuUHsq~$AQJna ze&7TCE+(_a`8%)->f%K75cYR1vM~uY%9IjEGU|$QCtG=K6-eSdV7Qdlr%x@Ezlbpa z)F}REK*vFS)|B{Cn=WdQN|ZfXApL#UcMByKnve52*|a;)94=0j#|xmUjI+fF^+IB6 zFMJ4k+#Z<i+gBQUI1tI%~o6&~7w z<2GVJ&b{?ocTR~a`N75*tbWfxQBNQeB_O&96{RqlmzHW#NETZnJc4c7;`n>S;9^Q- z&8U*a3Ptg1+YscA_h4_P6!#`QzA1vGzNpeND><p-bEI=g00Ne9Q}&wUB}4=7`_A)55n1DHZ^o{ZQU__IDLJL;GR@6-DlcAOZC zIPFZ?4Le5hX-@AIh(hd0!t}ZftJ6~xXhZlJnL9XtZVsUNs9|}ypq(kjIRxGP`s7cb z2r3|b#Z7co9THLfIY(EU-u?`hkYScVX~=SE@8;Tv?_7sY?g?2q>jo~EJrHb99Cf+FsYyxtngAsuytdkH`CJN5 zB{3O*2XrH3WM+2T+GYxLO{!0itWr7qw_60k>{K%ydHnAln^;AWoNgDN@zTA>9~trN zRMo8Up;|d9UB8iievwg6=WxP6o)(-Vlag7alJV+Q$Hn=Pg(>?dpT7+~lGHl&U2y_O zq}~n|=JKCBJ1rnliC5X-JLPU`cfBS;YT#iO&BG|cWnx4HG1)yyHmEIbE&PI%-MdqT zH1DEpMmIuFzc_||H!_J&*xJx{#wQ{PB-_SwJ1K)gSW(R$0mdJHd_=xs+X<%uCMlQr z_22GJ2h}ga#4t;tqoP|Ng^vBa7z=)Pw5VED(aoVOff4OC*{1?3j^6(+aYXN>h$Q~y z=ToPSbXNGS)qQ|dC;sK8?iSs;|Yf74#m{vAY`I z8nRs+&P?&^vJUtT2?Nw?^xR7sgvRhM@%lG4F*?#zS(kp%#=pp=^JzpIJ+pBj;CkKLyCw$|Jn4-2{Lv1tFA3?g$gY~1Iv=NAX!`E@thg=^IAxH>GuSRzyZ7mzS?|a{za<24^SVCT&8MXnGVHfjm~Aug58X z;0`$GrO1bu-llm!SnzWl_rguAS3$KT{Sfcjy%BlPa`t^Le_1Fa3ME`VrI_;{uBRYW zfv{0D%OLC&iVn&-@ZUx#V9?%dG4~Wo65v+~#Xk}{oLu|=;i7536$%r#J`Hc)j>l7U N|D^88&^mhI{{TK-go^+G literal 0 HcmV?d00001 diff --git a/test/test_planar_implicit.cpp b/test/test_planar_implicit.cpp new file mode 100644 index 000000000..5bd6c75d7 --- /dev/null +++ b/test/test_planar_implicit.cpp @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include + +#include "planar_implicit.h" + +void test_square() { + std::vector s = { + Line(Point(0, 0), Point(0, 1)), + Line(Point(0, 0), Point(1, 0)), + Line(Point(1, 1), Point(0, 1)), + Line(Point(1, 1), Point(1, 0)), + Line(Point(0, 0), Point(1, 1)), + Line(Point(1, 0), Point(0, 1)) + }; + auto [pts, adj] = build_graph(s); + std::vector pts1 = {Point(0, 0), Point(0, 1), Point(1, 0), Point(1, 1), Point(0.5, 0.5)}; + assert(pts == pts1); + std::sort(adj[4].begin(), adj[4].end()); + std::vector adj1 = {0, 1, 2, 3}; + assert(adj[4] == adj1); +} + +void test_grid() { + std::vector s = { + Line(Point(0, 0), Point(0, 3)), + Line(Point(0, 0), Point(3, 0)), + Line(Point(3, 3), Point(0, 3)), + Line(Point(3, 3), Point(3, 0)), + Line(Point(1, 0), Point(1, 3)), + Line(Point(2, 0), Point(2, 3)), + Line(Point(0, 1), Point(3, 1)), + Line(Point(0, 2), Point(3, 2)) + }; + auto [pts, adj] = build_graph(s); + auto pts_copy = pts; + std::sort(pts_copy.begin(), pts_copy.end()); + std::vector pts1 = { + Point(0, 0), Point(0, 1), Point(0, 2), Point(0, 3), + Point(1, 0), Point(1, 1), Point(1, 2), Point(1, 3), + Point(2, 0), Point(2, 1), Point(2, 2), Point(2, 3), + Point(3, 0), Point(3, 1), Point(3, 2), Point(3, 3), + }; + assert(pts_copy == pts1); + std::map m; + for (size_t i = 0; i < pts.size(); i++) { + m[pts[i]] = i; + } + for (int i = 0; i < 3; i++) { + for (int j = 0; j <= 3; j++) { + size_t v = m[Point(i, j)]; + size_t u = m[Point(i + 1, j)]; + assert(std::find(adj[v].begin(), adj[v].end(), u) != adj[v].end()); + assert(std::find(adj[u].begin(), adj[u].end(), v) != adj[u].end()); + } + } + for (int i = 0; i < 3; i++) { + for (int j = 0; j <= 3; j++) { + size_t v = m[Point(j, i)]; + size_t u = m[Point(j, i + 1)]; + assert(std::find(adj[v].begin(), adj[v].end(), u) != adj[v].end()); + assert(std::find(adj[u].begin(), adj[u].end(), v) != adj[u].end()); + } + } +} + +void test_multiedges() { + std::vector s = { + Line(Point(0, 0), Point(2, 2)), + Line(Point(1, 1), Point(3, 3)) + }; + auto [pts, adj] = build_graph(s); + assert(adj[0].size() == 1u && adj[1].size() == 2u && adj[2].size() == 2u && adj[3].size() == 1u); +} + +int main() { + test_square(); + test_grid(); + test_multiedges(); +} From 3641395acfbbef065cd966d38919cd2fdcfa6ed3 Mon Sep 17 00:00:00 2001 From: Yury Semenov Date: Fri, 14 Jul 2023 00:06:12 +0300 Subject: [PATCH 106/590] resized pictures --- src/geometry/planar_hole.png | Bin 42198 -> 25767 bytes src/geometry/planar_implicit.png | Bin 35023 -> 34990 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/src/geometry/planar_hole.png b/src/geometry/planar_hole.png index 1059a2197b7e118f99bfab5c2ee55e1e103854c7..4e94589371553effaedcced8743fc7f10a2091eb 100644 GIT binary patch literal 25767 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 literal 42198 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�yFY#Av23hlyODAJRqU)^O{? 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 z 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 diff --git a/src/geometry/planar_implicit.png b/src/geometry/planar_implicit.png index 37a0e72f8cab363269c8f3e7dd333189b7198f96..3b33aa5926a3612995390a10c5b68f80a889d4a2 100644 GIT binary patch literal 34990 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򧲮yh4P9#tKmh6i+v*+l71?<}0{_8_Y>~k=@q^2DS|m>rgu?tB zum!Wx?Rzxf3q??&Mc_dcVcO9ceLA>ozH;(!3&SM~f+Wb#$i~cO2gsBRNYInG_3cAZ zGxZNjDP~3v14xapi&wT87Wc)uH$Ch~gTr_V9c1UIVE=n>ae&AY6K_yn^l%uRS-EG8Q8K-C^vjcRB>A}Sl;BVcT^CNf z$RMbN@iYk~F>!`mf|%X~R=R*)z?Dzp$}t-Ji{c(bM8SBbq@-N=c^|x71SwdjKZyRM zd$da2#i_Z!WDf5iA)q9oNzEk)kbbgOsYGF=tvTh&{Xd=MP$+OnS@xe}I% z&_QA+gkP8wE(SrVAL$YoGoA{Sx9+{RGek{#UwunrAw+ASQp`l+GBO(Xk9u9E2dMsJ0&UFx zTVL|)ohC;Kw&3Em9hGv2vns{CkoZ)6uK0y>)at++3&UP0cqsg_$Vi|6^uxP%qSD_s_8vkWddJ0HPX{x% z0!+(@O$V~|_V}#es6g3D4HO`grZ$DOv{+`kH7hKNSN1trwPp6(%A9t+i9hy%y6uYi z;;4*52tCu1bIT%TJbFP)rJ%+diip7%9)y3NTyy)Ekfn90;gur!j?{cQSz^b|hq@iQ zx3;(5ExBrAniY;mw~q@CPY#Rt9GB$QKO!#QmEv#GX*0Q2`WBVs%0HVd}p^=WE@--VK%JWiMKIXZ@atm_BHG_!7 zGCy%y!3KDe9LBiT01ixnl}CoR+}(Iw)M1{N(9|=5{h*-#%8A!sj5zy02hE;$dh)`V z=)Z9F_S2B(T{NQ>;Wr{z7MPflGKvri(M*bYnsPN!%9wO~+=8k? zUH%3x>C9En7d!P)n6Jv%fO}`sm@4E`QHAg2+#RrNH!pYq`4eJhIgnS0)SakBxk#6p z_~>P*@CVcx0tG)+E-pbW(3aw<*ijju+s?fFewor>^&ReWOBXRlAGr%z0uInzW;Xc+04wQ zGarJSW`g2CNpzvhwtVP24o6oCyOk5==`IAQtbY8%@7;g11Cs+~MsG3$>kR^z*;Y+i zw*3OSGz5QhFPwB-^G~~~^w;((Z@ZL1FRy;Bf1Z9W0PZj)Dz608o2_;+OwoEwRq>iB z|6k`76qIZ&QtKIj9uU1QVx^;iOmp54QTA8))$(WZw2zGAj3KT%WDem`etdvCwh z-BUe!Uil^WGm_WZY?~^KR8Kx3#_ItbC3FBV*s0%a^y_tF$teMKvIz)m~MX z=`ls$%j(sAfIXN`L1A&%Iel~O(*(H}vSD#O%l3+h1FA~Xg@7#f^y#YfN|-y? zGLd5e)v(Y7%1d{CWFrvpL!vas(%rkgzP&$K==U={0Bl%OXD$S^dIq2kxvyNGQY?F6-?8zxEMk;G~6dG{S_mdE@#3<5Y7W+_ptg z*e<+k0f1;wUhFEi#W(?`P+%=k1n@^#sIB_O zn5jQlgMYnt7ayMw5Y2KWZ}1pkCG4A?=&|0;of8QYgfSt(pB7uoyy42gBQ9HlR!xm& zOplG#A45>2HSm!(b!HI z#`A@092fu$_UefTDb7r=%NRHmlzF$VJLh}Q^_w`HFJVg-HT2)nFAcP^M zJS=GDkRkdTAZx%?yHK69O?3PBdxzk#niIX~Vu0kEzs0n-u|o~8*I^N zS~%DhC?lV~MU0BVF!owFneF3A^ErERPSfiN z!z>1HVzl}!38`FA6%H%TEC?e;GQhSSpor3iEjc8?;Jj`ap6n<-nZtk}N>0K7X)6kO z$GK%Th|92Kf-4?M5yceC^NTC@2X0N5A9G#WA)#a&PGvl0t_vA);n=Fyj7iN#uy(=l zK}-{|z_oY(l+A4qZaP7+A(Y>*Z*}vL5`lt+U{sK&VIY~>-THx{BIpO788~PV+SH{Z z@4CHa&D92}tgJY;NLK%rbNZ#VPew7a7hgGZ_YXuNEsd$(02MTzH+l3Q;!5Nf7Naqd zb}&>Eb^>g)F066RaM8YZ!FI6psm#6Q8JRu7LrB!^ETqo8|OZ0um&)I>yc! z)RxybWB8sQ%=Fx(X%u=b%a@5}A*Xoo=c&rU6WE(**0}{9)$R`)cEy84l*}y0!Nnp- z4bxuG^P6TiHn;mf2Y`9}7#WkksVrGMGxp3u6&99#{zd`FWMr6HS{?v?L3ErLzG{@R z55&{?x6cY5Jg_Wro8PH8rsxB{jmyp!H^(5H5P1-^puU7rn9ZEb14mqJ8x*9?Ws!jw z{`>C~Aa1$^cYw&H6F!B4HUntmQwz>?LD9l>$`CN9%~`t^EgolL@?}Nu?k500g%Kly zJg0z_K}sX-^M}(~(!891c7Tec(7L}LNG>7;*7nPnFD+hJ%jgoH8D@R0)8f~z5dCRN za&o(Gw_a`C22=!3v1kFd8s;Z;oZE=_ZW}&_@=z9Pu zvS;7qrYqknE|(8|mON|0+L~!C6|Y(^DxZ0+8nvI7vkX|2?p=6mvzi1=j5Z0#J;;hm;4K#|`Y$b3X)7a9iKpQPRC*O9JACq%SOH zMj+%nC(q3QzXUk{&!)h1TMi1Tb5E!U4a*mNzrqnMoW7~x?q08`d~J%{>VUM#eVpC5 zwEn4DBko`)7uh*(A`Tm)p8oUCKLg8rV`5_P4?a`kYL&5rqk6tY=I$zd`qbNL&z=*W z+D*|x`JUPb^1cP+1#@CaL*x@{jR*^yNR`<~ZmTzs04$)n2_p;>R?$Ydj<&w`?PudU z#E6`I;0rNI{q^Rrql>qCw5!iIXz!Zpaok!X@Rd%{J4cB1_JvLL6W+Yo*sijEM5%n5 z`{IVV(%W*_luW0dBAYAD_R?Fu`fXz7tMP-Bd}dbRke8_Ww|+$h?M5EwyUdc2 zse8O8NzF(qea1tNSD&g^v>a;pCvKJfap}IeNHrifgxNwNpfP@YaYaQT8dz%bMUBOk zhGa#kGV38(H*5=KE~;FElm!YuR$FU?;Fh@t=p`hH0#;$$700X$QZBmo?hNJ5Ni$(Y zqgA_p!-gd<&X?9TCZ;%&dM{)yQR;3SGpCvvZ8``cGDmspwCg-f`LtA0_49y07 z@0#L)TX{)=*J$L1pCqWemxZsERD$$OjJ&ku+*^t=N>QW7;pbUA8i$aJ(Lf(!TzI^?DG6&M|tNeeS7Y&Ev@_3ObfnH-MGxhU_VnQlrj}V zaRH3sjE5e3(SwSyfHBuXJd}N{8uC@*m#Um7`1~q2W~y92T#t!ATiu5$b=TC?{BM4U zCS*DTfXtn6qxE{k!%$jO$V=o=nA6 z9r9h-dsv7uF+hx)5Ra%O=;q@J-7@bwuFSDFW@gdM$4cTBJ!ckYn~zbi}?qAtXLoG&tYa!7++J(8n~OMgc6bw6RPA&v~`KYR|58M2cy94c*-x8Dm^ z&7TwZ#b}NKGJ9~Fr`IYe+``^_`AS{i)hyiwFKN&~v&weTGHHspFCZ8u-zS%c?~>(l z#Vo#^<%Y!orLbrt7aL)nM0qUW( z9C*k{f7&w+4>M%Mje8(A0Z12EY@QwJI9&WDqqSBi3qYF0fivh-N=_6oH4CWTg7HVduY~Gh8ESc(fkDMY@E6<-x+@zsIL2Mr`DIlVPYFxNEsiC1P#Szv6 zwuo))$CKjWvUqvk%^Kq8hw7UOq756A^`$vT@7uBQmv4jRQ`7!kZKM zwb@qH7^*kJV#W)r=nLqWV8?*1M{T$=Yi*v4E<;BgNJ38D6ES!PNn-2PFw}}nI#R*o z58!m~MX>5R8M1O5P5BR7{4gj-jW_nW_nB`j{)Do=01> z{a)dAm34!}N0DLBJ)xiDBu)s(k5pxa9FO60$RS23N6&>9T9esVM!8L{_{~MMR%C5}JQM-*UIj$Ga zY%4Jv4GAJdAi%3$jfrEAsQbUFw>ncpTV*^}^;`2UyQ`b#elnTGM6U>03a%k?`n+lj z;U-NpGxtJC!;i141*O>{59f{^a<8%LCNOG50B9-}K^wCj;14m%qU;DDx~7dq+DzRX zza#<0XK{elbhtnk{Ka>7vh8@a3@eXBSJpXqGtba4KOn_axhv1e;!UZHe^+=^z?JWo z8l~z!4jVRf8ati2deze=6{AmvFRg;^DhwI&uCJD1u}EK9{PN7B(=kd%6&&Hcdwg%J z$x1knL1z5>I90Agd_()nYQcbLOYPG!Yn#;!hp-hd80qWx01ki-#QHq(c!2kK_^*up z8ft3R5$@KEHc`Ig?FiX1WAhuI6Q@TRj_vpufPippV?Z9&h=<3O(jt&Pk^ZHDrxJc!=uEr$QzK z&MlalZ-vv;=Zr8{Zk{cERhXf%oq!#Dq|`&|wq@BtG;N((VQ{61Zd)KWC{}4Pcywv7 zw}eH*nS5>xx=@Z_8-?R8W&@yG?V)GvmAdmPxjz0<;Fae~a{zGI_0)CrQ=&c)C-oE$ zQ3qFnmoB~L8S2el zikcV32UVelzEzqlSu{?_BeA3lq`jwO;zS3HS*6(QqB*}A^5w=xvH2(y1bGh-10)6z zQ}na%f4712!2!+)BK$B%hIx;sj!tgUcM2XV6m~Twdi@D$r4F@TZd+q2t*sc@MgRUZ zYm;=otJsHI;7&zy<(rUSp|-i4RGM9}VcSio&6~f@D!4@m1Q>hx=n>G2@UcitG$Myz zI84-fKr3=KBSRcP4j+oa1O1ox)|Aq!P2`DJ>kcF5-oYRy=cdhQbJ9l2mm z54KboS&F_E+CDL>vU+-CA#>J2^FeJ8<>xed6Xu5v8^-U7K0Zp*MQo}EY%0S(vieoL zv9R!PrbDm7@EPdmP@ItCU=1g8^qBDIvsX$<3IzIArp>3C1A<>9^5- zA~v4O)`H9;Tk8C{#<-x>Dajvx1K(gg}O2yH$0aUnT${Up>Z^+JL`4ryxUn1 z@y+N!qdAlycUmo=FImDNKm6nOlvO~)^qb^Y|IT3+%%v#m!U#JdQ+WW)WUN`c)>M5c zB9OL6cJ-;t^BodK{V28XqbmWuCdhq`l%NvCA8DLEFNQT%EQ#_H({fSOp&RLK z-50!T-XwxVD!|++COj){7hE|8aNfV?)TEIjUa@uUoxU*H{a*Eq%?Lin}c58yA4g>mQ}wrw2B+J&gg zx&i_Uqj06H6z|toEXW8kWr#YG6DHBXym;}e*N3!C)05tNgM%PPN5Ft&ji04)Ml;D& z^^cuF?kXWAlmRO1$BY{%nq$7AB9z{k^p19#o)WNw-)q6xsaH;a1nsUCZp2~$%r-ptr2LbS8Zen_gws)@vj9=|HV-vA zD@{ZA3$mnXHXC{B?_=MNtw@i31VLs^8hoeOw%F4@Q?ZzXt znm%VvyouVy^mGDqf7+LsCZQ(omAQIx85#w#v_FiTOr1K_+SXP%x-jkX<%fp`MRQgC z`t?K5&Wf%3W3jIBEc>;6hy#w32RAkK^K9`v`RjZ8yXJ5GXK1$^Ty^PI=;$J{=c2`n zvEwbN-K<|}C_cb>VZHkAiM7@)3Ri!1WP#mi>6-3+4GikS3Un}&nBaM;wANI=a^Wod z-m_QtrM^Y~-fPf=J-Ct$e>;7-b%d`|+1Bm$ZyKso_ZsIr*PndpCDmKq*Gf0lJ~gzU zHK5-3$b!DBZ8qMR=xj6au=^>;hCU6=xi)roZja-X+k5z@oe#U|GV4Vvfn=4 zmh!7>=5Bws&FihoF6X`&{i7AV*giK!#{ceKj|$6+7n9@xD9%6DYa7IGaP%6BeqP4U zzN=fzOPkvU6gvCgxN)P)Ihh%=_}@j_mZvON_@7yG)Z4cW%Sz?nre{Zw4xfy=sE79H zzsl6EOM7LmcdvWq^788A{GUIsT=&X2P+vOnzC)mK&W)miNFB3;T}3BnrBkBUc9ZO_ zRq#(`(B-bH`(C(k;bqRRVZn;SiYr=se|U6u?Ub<}KeZmN8&A~v@bJ-|ghBZ#|H|60 zRk$zT^!~fC3#~y2P)I$aD`tj11lBt*FR`wi7Z zTnwkZd1&kP5$oqw$qndztY4{~-f!_=0uFXx)bZ!r>dMj+eXaCV93)c@F1RUcKj7%z mG1rxqyPA9I|NsBt^W2vbUdys}Bwy>oe}?)?^ip&k_WeHri77h( literal 35023 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 N|D^88&^mhI{{TK-go^+G From 61d8edb8a7e1a6c4e9478754625cc082d70888f4 Mon Sep 17 00:00:00 2001 From: "Stanislav (Stanley) Modrak" <44023416+smith558@users.noreply.github.com> Date: Wed, 12 Jul 2023 23:15:01 +0100 Subject: [PATCH 107/590] Update link to use HTTPS --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ef2a16f6e..a491c8a94 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [![Translation Progress](https://img.shields.io/badge/translation_progress-85.2%25-yellowgreen.svg)](https://github.com/cp-algorithms/cp-algorithms/wiki/Translation-Progress) The goal of this project is to translate the wonderful resource -[http://e-maxx.ru/algo](http://e-maxx.ru/algo) which provides descriptions of many algorithms +[https://e-maxx.ru/algo](https://e-maxx.ru/algo) which provides descriptions of many algorithms and data structures especially popular in field of competitive programming. Moreover we want to improve the collected knowledge by extending the articles and adding new articles to the collection. From d7a84e8c57c871358d3d1c1a340eabb07a147ab3 Mon Sep 17 00:00:00 2001 From: simonyanli <21114999+simonyanli@users.noreply.github.com> Date: Tue, 11 Jul 2023 10:34:53 +1200 Subject: [PATCH 108/590] Update divide-and-conquer-dp.md typo, quadrangle was spelled "qudrangle" --- src/dynamic_programming/divide-and-conquer-dp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dynamic_programming/divide-and-conquer-dp.md b/src/dynamic_programming/divide-and-conquer-dp.md index ac5358da1..67de88070 100644 --- a/src/dynamic_programming/divide-and-conquer-dp.md +++ b/src/dynamic_programming/divide-and-conquer-dp.md @@ -21,7 +21,7 @@ time. Then the straightforward evaluation of the above recurrence is $O(m n^2)$. are $m \times n$ states, and $n$ transitions for each state. Let $opt(i, j)$ be the value of $k$ that minimizes the above expression. Assuming that the -cost function satisfies the qudrangle inequality, we can show that +cost function satisfies the quadrangle inequality, we can show that $opt(i, j) \leq opt(i, j + 1)$ for all $i, j$. This is known as the _monotonicity condition_. Then, we can apply divide and conquer DP. The optimal "splitting point" for a fixed $i$ increases as $j$ increases. From e27e8dff4acc5bc10c228fa6adffc9ea8eb7b3d2 Mon Sep 17 00:00:00 2001 From: Toufiq Shishir Date: Fri, 14 Jul 2023 23:49:25 +0600 Subject: [PATCH 109/590] modified newton's method for finding roots --- src/num_methods/roots_newton.md | 14 +++++++++++++- src/num_methods/roots_newton.png | Bin 0 -> 6531 bytes 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 src/num_methods/roots_newton.png diff --git a/src/num_methods/roots_newton.md b/src/num_methods/roots_newton.md index 47b3b9dd1..820e539c0 100644 --- a/src/num_methods/roots_newton.md +++ b/src/num_methods/roots_newton.md @@ -18,12 +18,24 @@ We want to solve the equation. More precisely, we want to find one of its roots The input parameters of the algorithm consist of not only the function $f(x)$ but also the initial approximation - some $x_0$, with which the algorithm starts. +![](roots_newton.png) + Suppose we have already calculated $x_i$, calculate $x_{i+1}$ as follows. Draw the tangent to the graph of the function $f(x)$ at the point $x = x_i$, and find the point of intersection of this tangent with the $x$-axis. $x_{i+1}$ is set equal to the $x$-coordinate of the point found, and we repeat the whole process from the beginning. -It is not difficult to obtain the following formula: +It is not difficult to obtain the following formula, $$ x_{i+1} = x_i - \frac{f(x_i)}{f^\prime(x_i)} $$ +First, we calculate the slope $f'(x)$, derivative of $f(x)$, and then determine the equation of the tangent which is, + +$$ y - f(x_i) = f'(x_i)(x - x_i) $$ + +The tangent intersects with the x-axis at cordinate, $y = 0$ and $x = x_{i+1}$, + +$$ - f(x_i) = f'(x_i)(x_{i+1} - x_i) $$ + +Now, solving the equation we get the value of $x_{i+1}$. + It is intuitively clear that if the function $f(x)$ is "good" (smooth), and $x_i$ is close enough to the root, then $x_{i+1}$ will be even closer to the desired root. The rate of convergence is quadratic, which, conditionally speaking, means that the number of exact digits in the approximate value $x_i$ doubles with each iteration. diff --git a/src/num_methods/roots_newton.png b/src/num_methods/roots_newton.png new file mode 100644 index 0000000000000000000000000000000000000000..67140d340b2e89919bf944ef2f4769b98f5d2f9a GIT binary patch literal 6531 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 Date: Fri, 14 Jul 2023 23:55:15 +0600 Subject: [PATCH 110/590] modified newton's method for finding roots --- src/num_methods/roots_newton.png | Bin 6531 -> 6503 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/num_methods/roots_newton.png b/src/num_methods/roots_newton.png index 67140d340b2e89919bf944ef2f4769b98f5d2f9a..3edc7cf3fde5ae558a0884be8f3da4b3f3626f59 100644 GIT binary patch delta 6492 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 literal 6531 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 Date: Sat, 15 Jul 2023 00:07:34 +0600 Subject: [PATCH 111/590] modified newton's method for finding roots --- src/num_methods/roots_newton.md | 4 +++- src/num_methods/roots_newton.png | Bin 6503 -> 6875 bytes 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/num_methods/roots_newton.md b/src/num_methods/roots_newton.md index 820e539c0..785c4a971 100644 --- a/src/num_methods/roots_newton.md +++ b/src/num_methods/roots_newton.md @@ -18,7 +18,9 @@ We want to solve the equation. More precisely, we want to find one of its roots The input parameters of the algorithm consist of not only the function $f(x)$ but also the initial approximation - some $x_0$, with which the algorithm starts. -![](roots_newton.png) +
+ ![Image](roots_newton.png) +
Suppose we have already calculated $x_i$, calculate $x_{i+1}$ as follows. Draw the tangent to the graph of the function $f(x)$ at the point $x = x_i$, and find the point of intersection of this tangent with the $x$-axis. $x_{i+1}$ is set equal to the $x$-coordinate of the point found, and we repeat the whole process from the beginning. diff --git a/src/num_methods/roots_newton.png b/src/num_methods/roots_newton.png index 3edc7cf3fde5ae558a0884be8f3da4b3f3626f59..0a1e006362f3919f87f95983945fa93cd558b0de 100644 GIT binary patch literal 6875 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 j{wfxiZhD5z+XjskfOV;e?zYd=@j)pym;hL delta 6489 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%0DlGiJjlUk7D<9D@-KcShg)bj5g!EOK37_AC0 zIsc$)Xa!x%nF_E02$zerSt6DW6`Y&KzdIoIMp1!h|InTyN{-p29+Pavu(UMx;nFY^ zOLU?7-*TF>&*7@~Sp7{V#pE?w<0u2}|A_-4ZjN)tTw!rUyipzw0y;H>@P>Ta4&UT$ zgZ1u8LQM0{0#>KW+?HODg|4XZYsl=jCh3c~emensX5IXka~!r3pmzxT{Y9SR;cJh7 zs3AvGhk{n^bgUe{m;PVg5HEjdzd&LjYwstC-i5nnq#?VkF~qmV*(_xo1kj(jPphGW zWMDP;kIX?oSUDkpFO{>5 z-zTyCWkA=m!Z+rJp>NWX{?#vGrQTw6X#N8@3_Xyl%zqDU`nw7Yw z2cixX+F_;LZKFDVF<=%NT>^dk6jP-_Cy0Kn;zy0Me zidg&6G;XrR4aFG#jgNl1Wf1r$J}BEPr{qr~SefnGFM95J++T0?_0P~d-?N_Tc_E?( z3+=dbH_Zw+E=V94yq{RJng@uPcpo)ubC19kFM4`-S>{IBhkx`k7!JrYN_0A3Z|ozm zrbezxBXxD%8*34}@#xb@j_;iM*tpTlhMFT}^)lPs3OAauysq%Dq4~>CUIU!vDuAqL z0HbiKp`Y3b;*uiPz{9~mM3sy-M9&KkPPjtU$}~8BNd;x80yh(UboIMfKWxu=dmE1+}2Dek%9Y9%B{VF z3M=*!)Nbv{)vzYo)4Fz{Pv$aI^ODX`vJTu!SfN!663{MACC;m=xl=tc_xZ5!72Z!1 zZ>)@PW_E{cjOAZOmwH06A3Vd^yDlGDWa{;6JP8yzP6k&ct!X|meJUUUiOI1<7C+Tu zW=TGCg1E9WFl+Wpo6ol0c6T$Dt7HG-qXKag>~Sngw5MGk@V})U*Z)L)RwBYFT#`K) zzFp!+8CRm$B^AAsxN|gw_cPBPO*dk3{xu4VGEha22v1m~#9a>%bhCS4(E%A{|L<1Q m{r`qS|36IsCak`9W}z(^SD4WBm-Y+goT1*$Yvm}HsQ&{KU`o6I From 68b3a6317f49994c81c4e43a5c420dc6e52f0614 Mon Sep 17 00:00:00 2001 From: Toufiq Shishir Date: Sat, 15 Jul 2023 00:09:33 +0600 Subject: [PATCH 112/590] modified newton's method for finding roots --- src/num_methods/roots_newton.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/num_methods/roots_newton.md b/src/num_methods/roots_newton.md index 785c4a971..5c6d2bd45 100644 --- a/src/num_methods/roots_newton.md +++ b/src/num_methods/roots_newton.md @@ -18,9 +18,7 @@ We want to solve the equation. More precisely, we want to find one of its roots The input parameters of the algorithm consist of not only the function $f(x)$ but also the initial approximation - some $x_0$, with which the algorithm starts. -
- ![Image](roots_newton.png) -
+![Image](roots_newton.png) Suppose we have already calculated $x_i$, calculate $x_{i+1}$ as follows. Draw the tangent to the graph of the function $f(x)$ at the point $x = x_i$, and find the point of intersection of this tangent with the $x$-axis. $x_{i+1}$ is set equal to the $x$-coordinate of the point found, and we repeat the whole process from the beginning. From 59a86609e3c885aa3c56f51a0e770e24eb78bcb6 Mon Sep 17 00:00:00 2001 From: Toufiq Shishir Date: Sat, 15 Jul 2023 00:12:11 +0600 Subject: [PATCH 113/590] modified newton's method for finding roots --- src/num_methods/roots_newton.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/num_methods/roots_newton.md b/src/num_methods/roots_newton.md index 5c6d2bd45..fab99b85a 100644 --- a/src/num_methods/roots_newton.md +++ b/src/num_methods/roots_newton.md @@ -18,7 +18,9 @@ We want to solve the equation. More precisely, we want to find one of its roots The input parameters of the algorithm consist of not only the function $f(x)$ but also the initial approximation - some $x_0$, with which the algorithm starts. -![Image](roots_newton.png) +

+ plot_f(x) +

Suppose we have already calculated $x_i$, calculate $x_{i+1}$ as follows. Draw the tangent to the graph of the function $f(x)$ at the point $x = x_i$, and find the point of intersection of this tangent with the $x$-axis. $x_{i+1}$ is set equal to the $x$-coordinate of the point found, and we repeat the whole process from the beginning. From ca07bb0b5e7872289ec7750efa004a2bd9203625 Mon Sep 17 00:00:00 2001 From: Toufiq Shishir Date: Sat, 15 Jul 2023 00:40:54 +0600 Subject: [PATCH 114/590] modified newton's method for finding roots --- src/num_methods/roots_newton.png | Bin 6875 -> 6720 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/num_methods/roots_newton.png b/src/num_methods/roots_newton.png index 0a1e006362f3919f87f95983945fa93cd558b0de..735fb983527a62e08c322724a03ac28be920c883 100644 GIT binary patch literal 6720 zcmaKRWk6I>^EZg}0!uF;xU`asf(uA3AYBFuk_#&+APUkcxrBsBD4hmf(y??&JSecj zlESXAut+!m%k#dUpAYxkJ9Flo`OTb|x#vWi7-=)manq5Jkum7%Xx=9yBbNof=V_>b z($m>S5_r+R(lPfSBco@%e8|Z@WkLWZxyOBN1X=kA?_Yqp>Zoq0PDWOhK!0jSNk+!? zOIK6j(BhSeBgdB?x}tqyQ$?%tON>xcxvq z={hJqu@KDyiZ0TfO~^riv4f$^3W~kn(Y|0)mwAMd9YB5&i|)Kf5uNX{nK4tpYGmwf z>^-`BU^v=h{Ojw-%{H8plFfk;4!g$Alg|5tH_8LJ3< z#S-#ux`m!0&}QRW-_g3m;o!2|SR`|DIxSS>lhkp~noYrhap8AiKq9&zHYllS9{XZ9 z_LDkNBs|@u3Bp#jven5>&vhNfiZHltka1ei)SYFh;4hkTtOkRTCQ zW=J{3fCUB?y* z35a3NiO`2yM5rS~uC~ggR?&@OxY1^IiHXtJhyh%1$lR?;O1;CE!c?>$(+%N{@L|E? zJ6^P!&M=++ZXyQqWHzPLg66F?PlOx&?ySMpOR;O9))194Cq8$MtUsBeV>SXo!rl4E z%N}#XvdR9{>3!0oKDz>0dcHfz_8@}{#3BpBIZ*DF{qeN|`Pob<`a`=lF9H1RS)h-J z^lvdxQ`PU-jB2Tf?!69WozVRi(xxzj#%wNgqoex(P5~@!x=^hmno@0uYFDX0K3KQI zA{?;iUf52Is8+usVU$71UuWh?$8>hSBe<*!XtI}w&LR^19H;DFPk;x3RuHyI=e)zm zC4gC)fvfpbVVSr^qU4h&pp`4f*K|6HIl{sXJ~&F@1E;N*h`1*WYs`N`g3K&SC}^jD z+5=b@3n?Y^yO+*_L!V8l8dC4xL7Jp1I@O0%WwhlZ{JnM#`rAa;cd4?3Bx@Y?4#nA34zh6p(b;xn0Az<`eCr?O zT60&0Pgo2ALM7@?t@vg2Ed%R9i@om*WSdktLs}v#jaV-b1sp#Yma8-E{DJ1=5j>Qq zur>(3kKm6?hStq^rIR0-@+X+sVX;zeFSYit@w=6#lx2h_E#75f^GNEm%mdaD6((t~ zuJeujQIF=D0+oBQvV$45rzr!|BfrFyhff%(`DC+N~x9@3U*a3fkZ27RD zJTc|@&iaT-n2Yqm8^?N%%%O{A>v8$^gCedCYZB24LeZ>--tUMam^daV`roVz)~@|w zx+n#dzMH~^TR%=Yx$)+XD5++; z4_g60F-4MeRVLa-R5pm+p&mQ^EZ?quoocX}_HL-z$;_g>$T~}{N$B#o&HF(+q7sE6 zWzDQ-o_(&-$lO>X24@BiVb?Qp3&gjC`IGz_dce#-Nk0@ZJPl-R&dHk=M=8>66aKNJ9>St@EEVVgMBW9e-Zxgqss$A*1e#?zp$GlL0r~86uSX@hJho~ zL6cbA$YwOr{s#RCY2--47xy#R-AkofxhQL&2`CsC5pK&FY^C(d(Gqm;Z zdYMZ<*XSKXmvw%#fK)=j%%V!>7DbXT=I`Hm|5(H_2#2*BsKRAtW$+d>oW|9th97t_qRXF(5QYbE zulFW>2FJysOHVUZX-RdwEE|q@_BtOnS4YO}n7k^36l-}9n>b`iBLMBQ+|D+~DgeD#^I-cJ)WX>%MVMLO?;m4d@oXdG4_oSj zs5;qbsN|s+g}(;cnRVPfb=Y8Q zZTl<#ma|I8b?uTXF@wcD0sr&WjGw= zs}Yp#O(!(EhrjZT-$<#=+lX`_&(OCzpmDSrJo2W!kf*jwtQ%<8HI5Iiuh7C%W29z{?8`@x5%ul5F>i{4%B^!6yW=7MB*K?CNm-Plf}81|Xk5d|cG%*b=UzF#V}e_USWc7@h{nAN>uP}r|087!4sSop6f zOklii8}0c;ReA2&Y@$8tqT)H+Z*VtSgT7onVZ;8b{cg}vmj`2jOEMqUbE^QOnzM6M zjv%=yvjTHY*di``if^S7!DdYG>h@Hg z!t^zN-`cagj`Lxh^|ICvae**>R{O`t^K>Khr^*4@Pak1G8%Kh>=7+pZA2HXV8S>RH zgL>N!_1h$Vd&8^wpB3u`z@Fz!6@3%1{R=uX)fOn}2o8&GSgfgT8FRBe#Fx(m4*%}M zFfoR{3O~paE>~Y{rRu>w{lm+Iw@Kgv;zWkXHlInc*=&Tm9bLuW9nd*>!1Hg0;|k^w zKVk2sQ<<*L4mjV0Hbg%k-u=s2`(M+4`eH_A)`;)6kl+2I_iNV|@Rh|0cKs^WIV;Jj zd9(A5FJyH3iz8a7<4@Av)knkmFk1Z_wYv(#H)e=L?=jW(3JGA*yb6|MrWOyqNC;b` zSZQW_o+c{uR~~i#15*5@@@eCPh~SI|ZE)sxy&L?Dy(VAQhn-!Osc6k-2G&EnXNa9J zH)4X!>03ja6N5ujJ+FbuRCv^d8SfYqPRBIs+jGli`+Go?`)%;MW{_1@q>7K;M&+4# zuiSP^^&y1+eXFSf^_i6}-6wT)8-y{goszSH>Z#zYqHJ>D_?@749- zcR+Bjd)tI-FWpIZ+%3xdj?$Ix6OlGx>&%FqV1e7jiI)@kH<)CMSEu97P=FqhtQO{h zoA{!7bHg{NZ?5KwV%G77X!0jB(H=8!&``Btd+d2ee0!)wySwnV{WUFMo+ax|q8*L{ zr=QJ@le&yCx;e?h4ic$83g5hiV^i%}1vsDmjm(HE(m^!NRVHu^l}5d}x%Tch7tpZZ z5_3{pB_O^YTxL`^(7Y*)@!x8XIwn8MxUNYlrDJWLoY6Bqm#H`s!P$^Vj_>QaBkb5a z5jMlxbE)=T5}uvs)~~j^<Z#T)#OR^i0IF&N|qO0d_ z`t*zOs=6)xSo2h;&Gj-TJ2vd>9G+c>*CSTn9nKD@;N=&QwC@+*)o!?np1dYG19?RSW2?atu`Tr z0m5(Zeamg{6Jr2OiJL#B!MRZi)fAl}sBar{H45SNu=d9$RJq3JoioagaFH}a<0;$& zu~SRCGwE^vq>&7xDnjz@ss{6M3ZN|CrHGAQ3wlm@!kJ`OkfepL@>1eFdh&KHG)1e0 zm&edb7v}XuKRSCVHraKq_RWPtjIaLB_$t;(Y2>PW+L~fRcO3&ub&rUoQ*%Dts5j+{ zboBR~?uxjEqLTU-5AWZmQkLK_SYDGW-Sy3?QN1S}ECGILnJPCI?hXuMEXHz8uA>3p zv$a&M|1Hp(C?V;9QobF@fKbcny$cHiGgJxrqKwjoD@b8B^-@{!7@KJ~B_;Yc*_CpQ za@WK}IYaX#yHjxqx}o-YJILm1R8P-fA~0oX%kxd)qubVweR6^rF$WUl$c3QxKg!fT`)XA_znEcN3t#G%?DAhXq>GjKRr7T4q~L}R zL{GZhjsJCF$W)UZ8ol_|Ye@2cj)869fdlR1B<)^Q2O;9MFsbtQ?e$82>qTy@LW<*n z3ZL{R;JI~TfDd`WtJits3Aw>PnhuMfDH$m*A_|A}Ea$I7dG4T^Ld6%I7d(2_r-V)j zz8+E=QJ0&#clkP63PkF+hsL6LE7`eYE(L$uDXt8jvRC(t3oa`1^?8iK^ zc!Qlj{Nhi!2F3l6FVaXLRsLd;cPayW1bBBjx3ohh(wF+QaAPc6aLm%{UBQQ(DCs_p zCwWVnKRK&*-CgL`V!!qPNKzVEPL6`uTi`e{RdGRHe8}*=Lk4a6?r=l#BJ9h2iUIYm z9L~T%4$vuVhBRj!uA9^)+Txz^$U>E#l(LcIGSxF?)A~p-8A$MT`oFP+$JB_x{X;QF zLo(BKryjepGq|mPFvQz}O4v(Jk?IF>gNf{8Q*Q)e9snFve@tM6>qygd>Wd*QwYK;m zbqgjN-dn^O0`cC@p)q6WJ`R6}o9%+n7{kI{AimfmOuGC(c1KYy{3}KY@zm0|krnhx zRK7fK*{R4WF*eXtMPyPvcyChD#4jTKHHf8J*5RE_Z(q99YvWqO%`lQ)r0Yn74{EI? zID{0+7vWx*WOPgJF{5#3ZfyrEkq>K$HFA`?&~jwFy& z-1EITSzyp}eqevU$@|ubq_tfdU>|&Y{Ihstd1*v!L^)+0bZyh+%e}MnVd^zG!G{3j>lsW*Rgrc|A~5$X(W3|@(wqlkViDrARZg z<_iIKT@#ayi>(S>k8!Y3Tn>f+@f)7YU;h7VvGA|5SS9gXV<9BsVfS_DQyox`hoCSL z@v{RU#Fkd3mqLQn1Vl6qfpIF^{N@j^U_=}xFsO_~y;KGQb(0C|F_arft4j2! z&l>GecT3>x8gly)kXx5y`R(d1g`-BvHQI48faC)Gx^hh3JB$Ds0;XL4lXUf4#Fv30 ztvMe8j4*)VE8{a7Q}zfD(=hIqN6`GY9mll~8N{pzE&Lo4RC5`SdcFqq``7(0N*NCA zrU4k_8h}4#hc%KrBA&bgP73bd$>pDj0PNMm$jl(jYI&csH;v2P4!)13?3HOoOsb!S z1Q}%3wKF2nlzlQ8|4+h9!~6sxp%{r}k?kUopB-B0`LH9e$PC9PGCYkhql?T&yM}_1 zrZ9u{#1!-RvYUhKtjJIqgZji2E1+7PE#(=sJKQ$i8p`unO|_U_5+X3jO808}{DFm0 z7^K*^AM~rFJ{8JwFXbx-3hg}p{9Pm!%pfh%(kW@$AS$bwHRip7r1@>AJII3Oz)YuelLniGJMUK8VfF-zxy zjpR(_Wn!tr3Gh$u`Q35tZv3i>(z2h{oEfvY2~O~q)1F|}E1hl*G7V*@zu>X*SNg?f zC-HpwW|4}j{+1r>Gd6F2n@FTx0ho{4=4c7(=%2^^G`ITh+pTN2gkH7P)GPWws5Uh6 z@G7bq8lOKiOAYoFLehuiWhWN7{h3*$6j*;Utvz$6N=X^IFEFk z`ordU2d>0%w4&G9RV9eh*{JBc=L4IG$;OL?xOF9{um;ti^0ahdnX+(c#9;2Wk|T$o zQd^~k8xvsPS8MZvPB&sM2p z)~H3F!zd^?^eF3R8%gQJeLG0IwjG4~<2RG(8iMw{31ew{>NlAeZrY+M;sPAetV4@a zpL57k?WwL26}Ae@EA)uhws3dm4y|@y?o%gE%}3^ZIJX&)pK0yJZjRUaj%+)q=6l`6 ztAPBR%t`i&1W(~94OaIkOpBV|a9jeVw7Aa;-}%?$Fet~>nBKbRcTLA*yxYl7x%!r* z@9z9CQ<(X@pqN2leyvMtY`LFlpNEaJgwEa$#5y(<)9%(g6m;`9;0!A23o}s!I`x5& z^=lp#nuJcKD{o-aS#hJdxJ5zx**>4ArjDMI2NC26}|{dk$Lga8;9>=k{|A3l9?qEvk1ygh4d@2DR1pU zNf`V-?E63f%xgIz{9;7Gsi(14I$^}_oUb`&clCzfXLa-q5W+Zi$DV7!(Q-HwcSRLm!x2=K_E_*FDneB!AulZz8jgmb*d&b9T4?h@+Fc2J zeH0Jl?A^Jiv$;0Hz66p7g+xh&fsroV;$gAwANJnZSET2K^23$rf`T?8fPfXTNASGC zkWc5KK&tsY4nID1*v>u*rBHSzzNmd2y_+rzN9>mUs%wrzrXPd2tO8} z)}q-DFQDO0!ceL2%m4?`WRiBDW*iCnwtq9+Nnvn~6H)s~>O-q^xD$*DMWTmV#8)3g zfXj;MJ#R#SC3|zFiop3RU-WN;JIPu7_XVR8ZleRlR__Dl4?m|%fgXt8T>9V+pjr3J z;kQdpN@)})jKkpeP+ga0KS1+oKJ_e?@;XvW^8w?QGV6@V)Q34{dQ4%^7k%lo+KuK|=5*y;^ZUzQ?C8R`BsnIZ` zr4?itX;1oISB4QdKoF-UxuiXN>whOdgq#aKW;)e-PRnR86zLlZxeTG!YB|^ zX(2DuA0xiDm@abNydr)Q{{0VbWUt`t=fYXI{OGUn5nOvwL;H_e_oBh0*7c2((BG$< zON;AHtYP}p>2*;bBH|7l9LaU~zR76L1A6J(lZ;)5L4Ma~efG);OO zZwxijw=x({M1=Mw^WYI~^mhKIoX{^$Dy&UpFiiExiCpxFaKh3Tc~V;s4dswN9z;pcp_Vobz35Am zK@63wHkVN&MVhJ*w|kU$3d>*A2}n(Q@IK>Q=t6E8CK~gS-X5Ice#}!3X_f@VHVZfk zDRO(mhidJdtL$}ZxTOaz4y)w#hSBKLg-vP)pi8!E4SAP&GpeI_cU|7-?v+lwvp!8< z5#6x`{hXD*CR8n?!4g-AKIj402kAygrV}iEBr|EuWsPUK)z$akQa0Uf=P(}L4ET~T zfih4J%ZyXDR;^!IkZxaT=xz(i$3l-tCr1x`Y{UE9O)>)RVo5U&9CMYO$z1-AL{RQe zc#IgZ2baj1Tu^z4@_T)-j;`XBE*dnb>45vVL>D8i@4NT4U_7``so^!;vpd#&@y7)( zN|)V8jD#(vISt^_)9b#l+aG@wAU=+Qd^XQ&JK!o7bOE}ujrt>oe?XOWUa43aIQ?vm zbz;byB1y90ocu2NJ}n(ut1zB1eR=0L$&qzIabHQ~lwBZTjq+e*yhKx| zc{f5T2JuNv6(W9{r;ktic@j%Q0`b^`dX%?%E4_x>CLmx^jU_yov{_-=WMBHwfqCg* z%xu>=P>|fvdbh!AYPVYerB-ky5rlv8_Pq26(+(>xIytfJmSpv8Nmz{1)-1`jtjALJ zo@5oY8JPytJKf5$ak##O$O46H?hli~@<+Z*mR=DlJ%7%Bwgz{Ls$sSZK2F$cdz?6{ ze6hQlxm=WGx4~@fD2XD6v~UnOS`vwB+}?Pt^Xz6!6^Ha*%kn1(Ly%myLt+TI=7) zW8xfugXUy%r^4yi-IMgoeEBP$7wA%oh$EiyQGo_qSpN{ zkYQPoOy)a(tM0PfU%WN$c=l|7&&c>O3oa3f8djXHMjLK1q z@Y|^E`$4)M9La_~%Qmu)yMo2FNK?N&E_6K}UAu`=o;=Y02|GNZ7$Q~tFONipy}x%L z`g4%N(gjAg^Egr3CoZw?bbyz5<%K$%h}F@1?U2urL&=dO5Z+qixcSr|&QVhL+?gp; zZ*K9nd7P`B7PwhhPbfdU2xv~aL-iD`OZpoHBo~8-=QAXGEqu+o&$s=R*>;p2S6B~? z45i)?x#MKOu{eF{_4fODsTf^3{owNSW7W8TI-Mhm4=VT1`2hkes(z&2K6>v=eZLBg zvumGvN?WY#(Pi1fQ_N5}a$y4>u6J6ow zEmOnEB&$G`pQ%6aaJ`=eJ}Q*(!)S3_oLzqod)JwG*B!1K7TtaacFPXJ6fIbmBlOV9 zXm#&Y#Uk(9(H)WI%XUdT0+lL-0_zK6fnSnOd6E|gh?pbz%V#VW@>UAWV|~9`8QdUE&gLzx=b5fqW986Zd8( zk{R)QAbH0GrQx`gWXW#e{^eaP;+p?CiQmgBA_+0*H%8Gc{3St8(h@N3!1q(c2Pl%`#PJ{SB(>XttKux@h z%&%zxR%3$Y(^aHvWR^UhC6~V2-nX?xU0=)KTkCsJel+gU#f(a#*@r$RIbgfk`|WO> zC(4m=o zTHzQd@VYaT6t$9&l_HfSl~moa)L+Bxu@Dh2Kf<=M+RgE-F4Hm8{3vqZtUObqUctm8 z&&brq?jFy@8s2dtC7D+Tz8JL8tgeO&>k+9J)|YFC5oY*$2! ze#tIgED`3UZ(ynyRE~+8IGGXeeinAyXd#Mk)xBY?;pRkD2h~W`0xIBGXxPYJ)FVof zo?k7|@5MwT90sCZb!IgltbLw7S-&m#{Q}`C0FMLTWF9m7c7f4tE6Tg{2%*BGLZP4W z;pQj$rOJeRGVQ9eHT+~+ah-l6wTd;qchqdKL5%|2lKf-FK15=~<3Qwh9}je42a-$_3ohrXXmCkMj@Y37-$z+`alpiZLc*WYS zBYEBSDkBFZ29+u`nVj^klvugV)R)+K&uHjEaYKjQsYI-zY;8w(E&)G4(0&e|aoP|M zdFc8=ejIWRua&bP8JL(jJZGv^YMZ)u_yO+H>o(`bJj@ZD;#30OJM^@M&)xX45<=0d zKX*IJTLp^xhCV| zfAu&lzq9IpHQKK@PuNN{DHGp(c@1Yj{hv8LxP?{GKSHB>*BR%==S3f(5i>@|!i0}9 z=SswKOt%`};(r)&zsQc1F>)_DoZh&my)?hTzL%Xwz)86lqbP<-DU1{lt-rhX!#XoR zSpSVbXXW|jCwnH{GHVE!tiV!3MYFnwg>LzV@t=;GR@>-ba&g1`DH$)uAkKQ!sO42l zuPE-89YX$ySI2+X=@+)|lV6RF|5bUkmyXuOxRorn%@AxMb1y0t_iFQgvaV$H ziD6)lR}BwvkvD=nWEggvx&O)x#ZXvXA#y9c07r%gL5FBbUU?_=zoUd3pdfXvSP!>QMD1>m?%) z-Glay9Ot5VN z#;Jl(6`wDo!DfhWvnCfY_*ey`!6O#aN6_U?_*#dLc`E6OZ_m#*d0LVI*dV;csuD8B zw}|`Jn#3?%oU0cy+MM zq(<1fTxwG$b8`;`@2LZ+tL|}0iQ%| zMhM58ohOtoijE*!%Nl)l_?7>WQTGoR^<~9gA&K4=v2Kz+67Xl})!81<6!l{+>2mD2 zs*PiGi)i7Nqg#aDihe&vaF(%(7rv^b!uh$+tj==2(+UV>kiNF^2LfmS)F)An$C2LS zxlV$~26{{bpVvNE+{d>)owv_ae2W}Fm60oG>-maHsgC#1H0oy)qxG0-kt&%=G%sL|=IrErWjeiDZy zsR0EP{F^~U-2)rsi#Ft^LaY#Ztc1nXb*QZ5OQhP>z$I|m=LnIQ$Y|wWjL!CLss@C$ zv(_(4I*KR?XOEZ5U?(bav{fS(sk9Qy)@tw*!=Hductn2z3^WBLYm=;KqJ#amBI@%CUQC zCrs`Va$KOMhol*nYhooTbvxTiO13=!EaEgM zA#XBcY5U9xE83atpg>ra$L-ad4l5w=v9!`^4r$hEHINs#5MSGZ!D1e=@e_MKSmn=M za?h}T{Wgp2%yiHYvv$nR&svu@<0Q+b@XWc!p+sGmEXtoCf3JocN(1Wt%^(sv%90uX z_^5Iwo|q6j>*)=Dd%-?O@ohDdg|eQ^NkU{`HaDHf2XoQOVdFK814h)+duYi9Gzo zNvW=umc{r&TjBO4w?G;b0~&_U0v$NynPa1CU?^u9MKz>K>-QsXgJ&S}=hbP>sm>M? zxIC>HIA@%IuYf<@K+kNv^#NFsGyD?2vq2Jw49Al#U21DSyvGbtYdWaz9yFJk1R}%w zeuEwn%Ag9_ME4KQ#FMxk+02P#@CEFU34mq%2j6V2G|6p^^S4A#IfFOPi5Bhzm}%f%hW}k!+|pRBJlr zL7a7xtqWX4*DAPF$W^X?SKZuo*E4qVL8()l)rolg2Nv7m>5SrP{(|YCKr6&?K$l=`P|64XyNymQV)Ab_0A$jaG!SsFM&-UMEg2>b#*NMgOFzW;{e zx{kANhipzG4rUY!8ue`>gyJu*t>kopff6~B+37WpT|s0eRB*nJ0Bl|>FoN1c@*?+r&%?^knO>keldQOtAyL3X}NxP!PT#L|X+8|1s4Ljj?L*uxbAOTkCl zuz`GVvvFLWguezVVmR65-P8-zGYBto&=mp&Ik|La2SwNPX@4N%=T-J+XQ$$e8SsYC|iP7#66DCmtwHT;&s z=mv+#7Nhxl-$^iepP9s%GKSoQ<}g1*DGox2wZ)oZ`yJx5He(!GARAHpR?KP6n94z` zGgDW<93>0Y2n6XzuxkAg*t(2AwI+GRR0(Qa+1~~SJcM@#Glfe}xGE3rlxdN!Ls_lJ zPE63KM!bWWL9yngflc{lputyTl0FcB!b50siwpJ7nYHX1L^=W&#JaCVdQw?Qp#+^# z47G0l?k@ZIb0R~Gvpo__Anxbdh?zh67wRT+n{=S7qRn#igZxP2lKByU*!uK` z2c)yH!ZSc&P}5f_@?ikUWcV##SID2_tp}&iCwGo#Gt2#=57sSb@4Q<7f(rIZt#gw( zCH|o)QF)7Cx6XB~@63Z~0|@QNaCgn1WL}UZ)nJTq z-dH-qc3$o(a3NC5PfbbD?YkZPEFU&l5C7{rU84XD*NAySN1SIx`iCegB3l7wN;aZb zn4jk1|NhF_7CpOjIcd~idG$Gkc6rRx<=3h&uyEDj?Yo;vv}=gfqfbFe!-;QR%MtI! zlpP;C7YWb~-cE9@-yxj4-&ilaw_J}IVQRa&p8`hHK?^VAQJpDIF-`WIxJI^f3^w&I zl)~7Zk$+!UXwSp&p}lp>S}75sMjk>FTQv!Nf}Pb@GGHkVJS<5p=t^O8@VDIMgsgLA z<^dr{oS6;e;%C)Y680Rw#YVZl;X{vd!HDzo)5kEJThyjRY$4xa8v0>2-?*_n+FGUW zy(P61oM@ceIxAvPnAFiXmpuOA_arj#y6=3(k>?A^#m;J#iY`hyvEwNzDVECSb^}x+ zn!cq_sTX!v^ZgkM2RnA?7P@R8US=D+j4J-{OHQoJoYUNam+{9qN`Ymi9=jU5X&P}m zr@ZR~Bbgr>>K4~G-^#;e@TU>EtAFmC18h{O`@_b)tXbk?yK28=Xa2tjC!(8J#@(T&Qrtp%!)umANs}XMbH~KPtRPOq$qL#>nZq6b)%n~pL38EViW0i$IqX`@4we~Qe7)I^Q zxBpxSWwYnz4Pk7kGU6^gCKtNfcM?|1j( zlD7>B&7H>yv(}n1_lQt>dk!Ll0oGsXLIUE4Sg^h(>m+3SDFK~;i0-rJz!E(#zkl2} zmQT*M+@)>z^ofXqN6tA2H!#kkn+BUoY{k>w99GOZutUQ0+z2wzz@B5276*QA5+!Hr zu2#jps^rINjG4ske^ta1%S(E~zQxasc@jMtE{GVuYN09Jphh{#9&1_9oFz8F|IY&< zl4gT5Wx_t8y|QFmZcvqJ;=~)hb`Y#aP3bs93365AA3=_SLOVAaMFpyt;VZ;TuIdt3 zA~Z&zfSld&2r>y#VrrBpBBF5tOxP97KmQJpUYad?DIXS)V#`aWRg@NH>%I%Z5UrVr j{wfxiZhD5z+XjskfOV;e?zYd=@j)pym;hL From bed765f0a5c03ee870b38f9d482b27cea47bdfe5 Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Fri, 14 Jul 2023 21:54:12 +0200 Subject: [PATCH 115/590] e_maxx_link: facets --- src/geometry/planar.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/geometry/planar.md b/src/geometry/planar.md index 9e3808313..0917381b8 100644 --- a/src/geometry/planar.md +++ b/src/geometry/planar.md @@ -2,6 +2,7 @@ title: Finding faces of a planar graph tags: - Translated +e_maxx_link: facets --- # Finding faces of a planar graph From 5ba4d6fcfbdb18fe977cb6f314443d6f7c9ae25e Mon Sep 17 00:00:00 2001 From: Yury Semenov Date: Sat, 15 Jul 2023 10:07:51 +0300 Subject: [PATCH 116/590] fix --- README.md | 1 + src/geometry/planar.md | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ef2a16f6e..f21f5d57e 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ Compiled pages are published at [https://cp-algorithms.com/](https://cp-algorith ### New articles +- (12 July 2023) [Finding faces of a planar graph](https://cp-algorithms.com/geometry/planar.html) - (18 April 2023) [Bit manipulation](https://cp-algorithms.com/algebra/bit-manipulation.html) - (17 October 2022) [Binary Search](https://cp-algorithms.com/num_methods/binary_search.html) - (17 October 2022) [MEX (Minimum Excluded element in an array)](https://cp-algorithms.com/sequences/mex.html) diff --git a/src/geometry/planar.md b/src/geometry/planar.md index 0917381b8..cb632b5ba 100644 --- a/src/geometry/planar.md +++ b/src/geometry/planar.md @@ -7,7 +7,7 @@ e_maxx_link: facets # Finding faces of a planar graph Consider a graph $G$ with $n$ vertices and $m$ edges, which can be drawn on a plane in such a way that two edges intersect only at a common vertex (if it exists). -Such graphs are called **planar**. Now suppose that we are given a planar graph together with its straight-line drawing, which means that for each vertex $v$ we have a corresponding point $(x, y)$ and all edges are drawn as line segments between these points without intersection (such drawing always exists). These line segments split the plane into several regions, which are called faces. Exactly one of the faces is unbounded. This face is called **outer**, while the other faces are called **inner**. +Such graphs are called **planar**. Now suppose that we are given a planar graph together with its straight-line embedding, which means that for each vertex $v$ we have a corresponding point $(x, y)$ and all edges are drawn as line segments between these points without intersection (such embedding always exists). These line segments split the plane into several regions, which are called faces. Exactly one of the faces is unbounded. This face is called **outer**, while the other faces are called **inner**. In this article we will deal with finding both inner and outer faces of a planar graph. We will assume that the graph is connected. @@ -16,7 +16,7 @@ In this article we will deal with finding both inner and outer faces of a planar In this section we present several facts about planar graphs without proof. Readers who are interested in proofs should refer to [Graph Theory by R. Diestel](https://sites.math.washington.edu/~billey/classes/562.winter.2018/articles/GraphTheory.pdf) or some other book. ### Euler's theorem -Euler's theorem states that any correct drawing of a connected planar graph with $n$ vertices, $m$ edges and $f$ faces satisfies: +Euler's theorem states that any correct embedding of a connected planar graph with $n$ vertices, $m$ edges and $f$ faces satisfies: $$n - m + f = 2$$ From 66c5eeda2a7aa2bbb19db44a2566245e96033c5e Mon Sep 17 00:00:00 2001 From: Yury Semenov Date: Sat, 15 Jul 2023 15:45:57 +0300 Subject: [PATCH 117/590] fixed map bug --- src/geometry/planar.md | 12 ++++++++---- test/test_planar_implicit.cpp | 2 ++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/geometry/planar.md b/src/geometry/planar.md index cb632b5ba..1c613f585 100644 --- a/src/geometry/planar.md +++ b/src/geometry/planar.md @@ -301,16 +301,20 @@ std::vector interSegSeg(Line l1, Line l2){ std::pair, std::vector>> build_graph(std::vector segments) { std::vector p; std::vector> adj; - std::map point_id; + std::map, size_t> point_id; auto get_point_id = [&](Point pt) { - if (!point_id.count(pt)) { + auto repr = std::make_pair( + int64_t(std::round(pt.x * 1000000000) + 1e-6), + int64_t(std::round(pt.y * 1000000000) + 1e-6) + ); + if (!point_id.count(repr)) { adj.emplace_back(); size_t id = point_id.size(); - point_id[pt] = id; + point_id[repr] = id; p.push_back(pt); return id; } else { - return point_id[pt]; + return point_id[repr]; } }; for (size_t i = 0; i < segments.size(); i++) { diff --git a/test/test_planar_implicit.cpp b/test/test_planar_implicit.cpp index 5bd6c75d7..86c3c7388 100644 --- a/test/test_planar_implicit.cpp +++ b/test/test_planar_implicit.cpp @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include #include "planar_implicit.h" From 2c9e1c01c9de585d0c7283f93eae767d1431db60 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Sun, 16 Jul 2023 23:51:05 +0530 Subject: [PATCH 118/590] Update lca_binary_lifting.md The question I added, can also be solved using LCA concept, so I wanted to share, --- src/graph/lca_binary_lifting.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/graph/lca_binary_lifting.md b/src/graph/lca_binary_lifting.md index e8f51dc94..af862e1a4 100644 --- a/src/graph/lca_binary_lifting.md +++ b/src/graph/lca_binary_lifting.md @@ -96,3 +96,4 @@ void preprocess(int root) { ## Practice Problems * [Codechef - Longest Good Segment](https://www.codechef.com/problems/LGSEG) +* [HackerEarth - Optimal Connectivity](https://www.hackerearth.com/practice/algorithms/graphs/graph-representation/practice-problems/algorithm/optimal-connectivity-c6ae79ca/) From 36de2cc200db292eebeecf7ffd066d845eae6fb0 Mon Sep 17 00:00:00 2001 From: Roman Steinberg Date: Sun, 18 Jun 2023 12:56:02 +0200 Subject: [PATCH 119/590] Update kuhn_maximum_bipartite_matching.md Two important terms are defined: maximal and maximum matching. The formulation of the Beurge's lemma requires maximum matching term definition. And it is important to show difference between maximal and maximum matching. It is also possible to state perfect and near perfect matching definition, but this particular article doesn't require them. --- src/graph/kuhn_maximum_bipartite_matching.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/graph/kuhn_maximum_bipartite_matching.md b/src/graph/kuhn_maximum_bipartite_matching.md index 64647cb5f..7b1bbd595 100644 --- a/src/graph/kuhn_maximum_bipartite_matching.md +++ b/src/graph/kuhn_maximum_bipartite_matching.md @@ -26,6 +26,10 @@ by this matching. * An **augmenting path** (in a bipartite graph, with respect to some matching) is an alternating path whose initial and final vertices are unsaturated, i.e., they do not belong in the matching. +* A **maximal matching** is a matching M of a graph G that is not a subset of any other matching. + +* A **maximum matching** (also known as maximum-cardinality matching) is a matching that contains the largest possible number of edges. Every maximum matching is a maximal matching. + * The **symmetric difference** (also known as the **disjunctive union**) of sets $A$ and $B$, represented by $A \oplus B$, is the set of all elements that belong to exactly one of $A$ or $B$, but not to both. That is, $A \oplus B = (A - B) \cup (B - A) = (A \cup B) - (A \cap B)$. From c3aeb45fd21d0f3bdf244fd30a5fb1953e92c1fb Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Mon, 17 Jul 2023 21:50:56 +0200 Subject: [PATCH 120/590] style changes --- src/graph/kuhn_maximum_bipartite_matching.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/graph/kuhn_maximum_bipartite_matching.md b/src/graph/kuhn_maximum_bipartite_matching.md index 7b1bbd595..25b835ca1 100644 --- a/src/graph/kuhn_maximum_bipartite_matching.md +++ b/src/graph/kuhn_maximum_bipartite_matching.md @@ -15,10 +15,14 @@ that no selected edge shares a vertex with any other selected edge. ### Required Definitions * A **matching** $M$ is a set of pairwise non-adjacent edges of a graph (in other words, no more than one edge from the set should be incident to any vertex of the graph $M$). -The **cardinality** of a matching is the number of edges in it. The maximum (or largest) matching is a matching whose cardinality is maximum among all possible matchings -in a given graph. All those vertices that have an adjacent edge from the matching (i.e., which have degree exactly one in the subgraph formed by $M$) are called **saturated** +The **cardinality** of a matching is the number of edges in it. +All those vertices that have an adjacent edge from the matching (i.e., which have degree exactly one in the subgraph formed by $M$) are called **saturated** by this matching. +* A **maximal matching** is a matching $M$ of a graph $G$ that is not a subset of any other matching. + +* A **maximum matching** (also known as maximum-cardinality matching) is a matching that contains the largest possible number of edges. Every maximum matching is a maximal matching. + * A **path** of length $k$ here means a *simple* path (i.e. not containing repeated vertices or edges) containing $k$ edges, unless specified otherwise. * An **alternating path** (in a bipartite graph, with respect to some matching) is a path in which the edges alternately belong / do not belong to the matching. @@ -26,10 +30,6 @@ by this matching. * An **augmenting path** (in a bipartite graph, with respect to some matching) is an alternating path whose initial and final vertices are unsaturated, i.e., they do not belong in the matching. -* A **maximal matching** is a matching M of a graph G that is not a subset of any other matching. - -* A **maximum matching** (also known as maximum-cardinality matching) is a matching that contains the largest possible number of edges. Every maximum matching is a maximal matching. - * The **symmetric difference** (also known as the **disjunctive union**) of sets $A$ and $B$, represented by $A \oplus B$, is the set of all elements that belong to exactly one of $A$ or $B$, but not to both. That is, $A \oplus B = (A - B) \cup (B - A) = (A \cup B) - (A \cap B)$. From b8c085161973011ede4b3b09da5483036b121a29 Mon Sep 17 00:00:00 2001 From: Egor Gorbachev Date: Sun, 16 Jul 2023 21:48:51 +0200 Subject: [PATCH 121/590] Update polynomial.md typo in indices --- src/algebra/polynomial.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/algebra/polynomial.md b/src/algebra/polynomial.md index c5f01ce9f..52ecb997f 100644 --- a/src/algebra/polynomial.md +++ b/src/algebra/polynomial.md @@ -263,7 +263,7 @@ Note that the matrix above is a so-called triangular [Toeplitz matrix](https://e Let's generalize the Sieveking–Kung algorithm. Consider equation $F(P) = 0$ where $P(x)$ should be a polynomial and $F(x)$ is some polynomial-valued function defined as -$$F(x) = \sum\limits_{i=0}^\infty \alpha_i (x-\beta)^k,$$ +$$F(x) = \sum\limits_{i=0}^\infty \alpha_i (x-\beta)^i,$$ where $\beta$ is some constant. It can be proven that if we introduce a new formal variable $y$, we can express $F(x)$ as @@ -271,7 +271,7 @@ $$F(x) = F(y) + (x-y)F'(y) + (x-y)^2 G(x,y),$$ where $F'(x)$ is the derivative formal power series defined as -$$F'(x) = \sum\limits_{i=0}^\infty (k+1)\alpha_{i+1}(x-\beta)^k,$$ +$$F'(x) = \sum\limits_{i=0}^\infty (i+1)\alpha_{i+1}(x-\beta)^i,$$ and $G(x, y)$ is some formal power series of $x$ and $y$. With this result we can find the solution iteratively. From ac5eef2e744913b9c9481d195a92da658dca599b Mon Sep 17 00:00:00 2001 From: Egor Gorbachev Date: Mon, 17 Jul 2023 20:08:07 +0200 Subject: [PATCH 122/590] Update polynomial.md --- src/algebra/polynomial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algebra/polynomial.md b/src/algebra/polynomial.md index 52ecb997f..6676f9fed 100644 --- a/src/algebra/polynomial.md +++ b/src/algebra/polynomial.md @@ -384,7 +384,7 @@ The coefficient of $x^{n+r}$ of the product of the polynomials $A_0(x) = \sum\li Assume you need to calculate $A(x_1), \dots, A(x_n)$. As mentioned earlier, $A(x) \equiv A(x_i) \pmod{x-x_i}$. Thus you may do the following: 1. Compute a segment tree such that in the segment $[l,r)$ stands the product $P_{l, r}(x) = (x-x_l)(x-x_{l+1})\dots(x-x_{r-1})$. -2. Starting with $l=1$ and $r=n$ at the root node. Let $m=\lfloor(l+r)/2\rfloor$. Let's move down to $[l,m)$ with the polynomial $A(x) \pmod{P_{l,m}(x)}$. +2. Starting with $l=0$ and $r=n$ at the root node. Let $m=\lfloor(l+r)/2\rfloor$. Let's move down to $[l,m)$ with the polynomial $A(x) \pmod{P_{l,m}(x)}$. 3. This will recursively compute $A(x_l), \dots, A(x_{m-1})$, now do the same for $[m,r)$ with $A(x) \pmod{P_{m,r}(x)}$. 4. Concatenate the results from the first and second recursive call and return them. From 77ef08ad68f42b9fcf998b426c13d67d7092b83a Mon Sep 17 00:00:00 2001 From: Egor Gorbachev Date: Mon, 17 Jul 2023 23:00:23 +0200 Subject: [PATCH 123/590] Update polynomial.md --- src/algebra/polynomial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algebra/polynomial.md b/src/algebra/polynomial.md index 6676f9fed..fe81cfa8e 100644 --- a/src/algebra/polynomial.md +++ b/src/algebra/polynomial.md @@ -384,7 +384,7 @@ The coefficient of $x^{n+r}$ of the product of the polynomials $A_0(x) = \sum\li Assume you need to calculate $A(x_1), \dots, A(x_n)$. As mentioned earlier, $A(x) \equiv A(x_i) \pmod{x-x_i}$. Thus you may do the following: 1. Compute a segment tree such that in the segment $[l,r)$ stands the product $P_{l, r}(x) = (x-x_l)(x-x_{l+1})\dots(x-x_{r-1})$. -2. Starting with $l=0$ and $r=n$ at the root node. Let $m=\lfloor(l+r)/2\rfloor$. Let's move down to $[l,m)$ with the polynomial $A(x) \pmod{P_{l,m}(x)}$. +2. Starting with $l=1$ and $r=n+1$ at the root node. Let $m=\lfloor(l+r)/2\rfloor$. Let's move down to $[l,m)$ with the polynomial $A(x) \pmod{P_{l,m}(x)}$. 3. This will recursively compute $A(x_l), \dots, A(x_{m-1})$, now do the same for $[m,r)$ with $A(x) \pmod{P_{m,r}(x)}$. 4. Concatenate the results from the first and second recursive call and return them. From 43d93af0f35201fad545d45bb28e33f7e2f3ab8d Mon Sep 17 00:00:00 2001 From: Nikita Voitik <69681605+NikitaVoitik@users.noreply.github.com> Date: Thu, 20 Jul 2023 20:39:02 +0300 Subject: [PATCH 124/590] Fix typo in catalan-numbers.md --- src/combinatorics/catalan-numbers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/combinatorics/catalan-numbers.md b/src/combinatorics/catalan-numbers.md index d3fa1ce64..40de84b53 100644 --- a/src/combinatorics/catalan-numbers.md +++ b/src/combinatorics/catalan-numbers.md @@ -9,7 +9,7 @@ Catalan numbers is a number sequence, which is found useful in a number of combi This sequence was named after the Belgian mathematician [Catalan](https://en.wikipedia.org/wiki/Eug%C3%A8ne_Charles_Catalan), who lived in the 19th century. (In fact it was known before to Euler, who lived a century before Catalan). -The first few numbers Catalan numbers, $C_n$ (starting from zero): +The first few numbers of Catalan numbers, $C_n$ (starting from zero): $1, 1, 2, 5, 14, 42, 132, 429, 1430, \ldots$ From 133f1e86367559732213d9f92b09f951735eca13 Mon Sep 17 00:00:00 2001 From: Md Shamim Ahmmed <56692841+Md-Shamim-Ahmmed@users.noreply.github.com> Date: Sat, 22 Jul 2023 07:45:17 +0600 Subject: [PATCH 125/590] Update divisors.md --- src/algebra/divisors.md | 48 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/src/algebra/divisors.md b/src/algebra/divisors.md index eabc485d0..53ae7d4a0 100644 --- a/src/algebra/divisors.md +++ b/src/algebra/divisors.md @@ -29,8 +29,7 @@ A way of thinking about it is the following: * If there are two distinct prime divisors $n = p_1^{e_1} \cdot p_2^{e_2}$, then you can arrange all divisors in form of a tabular. $$\begin{array}{c|ccccc} -& 1 & p_2 & p_2^2 & \dots & p_2^{e_2} \\\\ -\hline +& 1 & p_2 & p_2^2 & \dots & p_2^{e_2} \\\\\hline 1 & 1 & p_2 & p_2^2 & \dots & p_2^{e_2} \\\\ p_1 & p_1 & p_1 \cdot p_2 & p_1 \cdot p_2^2 & \dots & p_1 \cdot p_2^{e_2} \\\\ p_1^2 & p_1^2 & p_1^2 \cdot p_2 & p_1^2 \cdot p_2^2 & \dots & p_1^2 \cdot p_2^{e_2} \\\\ @@ -42,18 +41,39 @@ So the number of divisors is trivially $(e_1 + 1) \cdot (e_2 + 1)$. * A similar argument can be made if there are more then two distinct prime factors. + +```cpp +vector primes; + +long long NumberOfDivisors(long long num) { + long long total = 1; + + for (long long p: primes) { + if (num % p == 0) { + int e = 0; + while (num % p == 0) { + e++; + num /= p; + } + total *= (e + 1); + } + } + return total; +} +``` + ## Sum of divisors We can use the same argument of the previous section. * If there is only one distinct prime divisor $n = p_1^{e_1}$, then the sum is: - + $$1 + p_1 + p_1^2 + \dots + p_1^{e_1} = \frac{p_1^{e_1 + 1} - 1}{p_1 - 1}$$ * If there are two distinct prime divisors $n = p_1^{e_1} \cdot p_2^{e_2}$, then we can make the same table as before. The only difference is that now we now want to compute the sum instead of counting the elements. It is easy to see, that the sum of each combination can be expressed as: - + $$\left(1 + p_1 + p_1^2 + \dots + p_1^{e_1}\right) \cdot \left(1 + p_2 + p_2^2 + \dots + p_2^{e_2}\right)$$ $$ = \frac{p_1^{e_1 + 1} - 1}{p_1 - 1} \cdot \frac{p_2^{e_2 + 1} - 1}{p_2 - 1}$$ @@ -62,6 +82,26 @@ $$ = \frac{p_1^{e_1 + 1} - 1}{p_1 - 1} \cdot \frac{p_2^{e_2 + 1} - 1}{p_2 - 1}$$ $$\sigma(n) = \frac{p_1^{e_1 + 1} - 1}{p_1 - 1} \cdot \frac{p_2^{e_2 + 1} - 1}{p_2 - 1} \cdots \frac{p_k^{e_k + 1} - 1}{p_k - 1}$$ +```cpp +vector primes; + +long long SumOfDivisors(long long num) { + long long total = 1; + + for (long long p: primes) { + if (num % p == 0) { + int e = 0; + while (num % p == 0) { + e++; + num /= p; + } + total *= (pow(p, (e + 1)) - 1) / (p - 1); + } + } + return total; +} +``` + ## Multiplicative functions A multiplicative function is a function $f(x)$ which satisfies From d9aba33a6b52006222088784ef2683a4c952afe8 Mon Sep 17 00:00:00 2001 From: Le Bao Hiep Date: Wed, 26 Jul 2023 15:23:19 +0700 Subject: [PATCH 126/590] Fix typos --- src/algebra/bit-manipulation.md | 2 +- src/algebra/discrete-log.md | 4 ++-- src/algebra/garners-algorithm.md | 2 +- src/algebra/polynomial.md | 8 ++++---- src/graph/bridge-searching-online.md | 4 ++-- src/graph/lca_farachcoltonbender.md | 2 +- src/graph/min_cost_flow.md | 2 +- src/string/rabin-karp.md | 10 +++++----- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/algebra/bit-manipulation.md b/src/algebra/bit-manipulation.md index 36c30d909..76d117668 100644 --- a/src/algebra/bit-manipulation.md +++ b/src/algebra/bit-manipulation.md @@ -170,7 +170,7 @@ int countSetBits(int n) } ``` -### Addtional tricks +### Additional tricks - $n ~\&~ (n + 1)$ clears all trailing ones: $0011~0111_2 \rightarrow 0011~0000_2$. - $n ~|~ (n + 1)$ sets the last cleared bit: $0011~0101_2 \rightarrow 0011~0111_2$. diff --git a/src/algebra/discrete-log.md b/src/algebra/discrete-log.md index 1c16dccb0..dd899fb25 100644 --- a/src/algebra/discrete-log.md +++ b/src/algebra/discrete-log.md @@ -47,7 +47,7 @@ This problem can be solved using the meet-in-the-middle method as follows: ## Complexity -We can calculate $f_1(p)$ in $O(\log m)$ using the [binary exponentation algorithm](binary-exp.md). Similarly for $f_2(q)$. +We can calculate $f_1(p)$ in $O(\log m)$ using the [binary exponentiation algorithm](binary-exp.md). Similarly for $f_2(q)$. In the first step of the algorithm, we need to calculate $f_1$ for every possible argument $p$ and then sort the values. Thus, this step has complexity: @@ -107,7 +107,7 @@ Internally, `map` uses a red-black tree to store values. Thus this code is a little bit slower than if we had used an array and binary searched, but is much easier to write. Notice that our code assumes $0^0 = 1$, i.e. the code will compute $0$ as solution for the equation $0^x \equiv 1 \pmod m$ and also as solution for $0^x \equiv 0 \pmod 1$. -This is an often used convention in algebra, but it's also not univerally accepted in all areas. +This is an often used convention in algebra, but it's also not universally accepted in all areas. Sometimes $0^0$ is simply undefined. If you don't like our convention, then you need to handle the case $a=0$ separately: diff --git a/src/algebra/garners-algorithm.md b/src/algebra/garners-algorithm.md index 1a34f8ba6..fada69fd1 100644 --- a/src/algebra/garners-algorithm.md +++ b/src/algebra/garners-algorithm.md @@ -19,7 +19,7 @@ A mixed radix representation is a positional numeral system, that's a generaliza For instance the decimal numeral system is a positional numeral system with the radix (or base) 10. Every a number is represented as a string of digits $d_1 d_2 d_3 \dots d_n$ between $0$ and $9$, and E.g. the string $415$ represents the number $4 \cdot 10^2 + 1 \cdot 10^1 + 5 \cdot 10^0$. -In general the string of digits $d_1 d_2 d_3 \dots d_n$ represents the number $d_1 b^{n-1} + d_2 b^{n-2} + \cdots + d_n b^0$ in the positional numberal system with radix $b$. +In general the string of digits $d_1 d_2 d_3 \dots d_n$ represents the number $d_1 b^{n-1} + d_2 b^{n-2} + \cdots + d_n b^0$ in the positional numeral system with radix $b$. In a mixed radix system, we don't have one radix any more. The base varies from position to position. diff --git a/src/algebra/polynomial.md b/src/algebra/polynomial.md index fe81cfa8e..0aadba26c 100644 --- a/src/algebra/polynomial.md +++ b/src/algebra/polynomial.md @@ -16,7 +16,7 @@ In this section, we focus more on the definitions and "intuitive" properties of ### Polynomial multiplication !!! info "Definition" - **Univariate polynomial** is an expresion of form $A(x) = a_0 + a_1 x + \dots + a_n x^n$. + **Univariate polynomial** is an expression of form $A(x) = a_0 + a_1 x + \dots + a_n x^n$. The values $a_0, \dots, a_n$ are polynomial coefficients, typically taken from some set of numbers or number-like structures. In this article, we assume that the coefficients are taken from some [field](https://en.wikipedia.org/wiki/Field_(mathematics)), meaning that operations of addition, subtraction, multiplication and division are well-defined for them (except for division by $0$) and they generally behave in a similar way to real numbers. @@ -25,7 +25,7 @@ Typical example of such field is the field of remainders modulo prime number $p$ For simplicity we will drop the term _univariate_, as this is the only kind of polynomials we consider in this article. We will also write $A$ instead of $A(x)$ wherever possible, which will be understandable from the context. It is assumed that either $a_n \neq 0$ or $A(x)=0$. !!! info "Definition" - The **product** of two polynomials is defined by expanding it as an arythmetic expression: + The **product** of two polynomials is defined by expanding it as an arithmetic expression: $$ A(x) B(x) = \left(\sum\limits_{i=0}^n a_i x^i \right)\left(\sum\limits_{j=0}^m b_j x^j\right) = \sum\limits_{i,j} a_i b_j x^{i+j} = \sum\limits_{k=0}^{n+m} c_k x^k = C(x). @@ -69,12 +69,12 @@ The coefficient near $x^k$ in the polynomial $A(x)$ is denoted shortly as $[x^k] ### Formal power series !!! info "Definition" - A **formal power series** is an infite sum $A(x) = a_0 + a_1 x + a_2 x^2 + \dots$, considered regardless of its convergence properties. + A **formal power series** is an infinite sum $A(x) = a_0 + a_1 x + a_2 x^2 + \dots$, considered regardless of its convergence properties. In other words, when we consider e.g. a sum $1+\frac{1}{2}+\frac{1}{4}+\frac{1}{8}+\dots=2$, we imply that it _converges_ to $2$ when the number of summands approach infinity. However, formal series are only considered in terms of sequences that make them. !!! info "Definition" - The **product** of formal power series $A(x)$ and $B(x)$, is also defined by expanding it as an arythmetic expression: + The **product** of formal power series $A(x)$ and $B(x)$, is also defined by expanding it as an arithmetic expression: $$ diff --git a/src/graph/bridge-searching-online.md b/src/graph/bridge-searching-online.md index 0c5da3a4c..da3af4402 100644 --- a/src/graph/bridge-searching-online.md +++ b/src/graph/bridge-searching-online.md @@ -259,13 +259,13 @@ This function is used many times in the rest of the code, since after the compre The DSU for the connected components is stored in the vector `dsu_cc`, and there is also an additional vector `dsu_cc_size` to store the component sizes. The function `find_cc(v)` returns the leader of the connectivity component (which is actually the root of the tree). -The re-rooting of a tree `make_root(v)` works as descibed above: +The re-rooting of a tree `make_root(v)` works as described above: if traverses from the vertex $v$ via the ancestors to the root vertex, each time redirecting the ancestor `par` in the opposite direction. The link to the representative of the connected component `dsu_cc` is also updated, so that it points to the new root vertex. After re-rooting we have to assign the new root the correct size of the connected component. Also we have to be careful that we call `find_2ecc()` to get the representatives of the 2-edge-connected component, rather than some other vertex that have already been compressed. -The cycle finding and compression function `merge_path(a, b)` is also implemented as descibed above. +The cycle finding and compression function `merge_path(a, b)` is also implemented as described above. It searches for the LCA of $a$ and $b$ be rising these nodes in parallel, until we meet a vertex for the second time. For efficiency purposes we choose a unique identifier for each LCA finding call, and mark the traversed vertices with it. This works in $O(1)$, while other approaches like using $set$ perform worse. diff --git a/src/graph/lca_farachcoltonbender.md b/src/graph/lca_farachcoltonbender.md index 9c9b9e6ac..f67365511 100644 --- a/src/graph/lca_farachcoltonbender.md +++ b/src/graph/lca_farachcoltonbender.md @@ -118,7 +118,7 @@ int min_by_h(int i, int j) { } void precompute_lca(int root) { - // get euler tour & indices of first occurences + // get euler tour & indices of first occurrences first_visit.assign(n, -1); height.assign(n, 0); euler_tour.reserve(2 * n); diff --git a/src/graph/min_cost_flow.md b/src/graph/min_cost_flow.md index cdc2a6a22..9f96e575b 100644 --- a/src/graph/min_cost_flow.md +++ b/src/graph/min_cost_flow.md @@ -17,7 +17,7 @@ Sometimes the task is given a little differently: you want to find the maximum flow, and among all maximal flows we want to find the one with the least cost. This is called the **minimum-cost maximum-flow problem**. -Both these problems can be solved effectively with the algorithm of sucessive shortest paths. +Both these problems can be solved effectively with the algorithm of successive shortest paths. ## Algorithm diff --git a/src/string/rabin-karp.md b/src/string/rabin-karp.md index 38625b285..e9dcc74da 100644 --- a/src/string/rabin-karp.md +++ b/src/string/rabin-karp.md @@ -37,13 +37,13 @@ vector rabin_karp(string const& s, string const& t) { for (int i = 0; i < S; i++) h_s = (h_s + (s[i] - 'a' + 1) * p_pow[i]) % m; - vector occurences; - for (int i = 0; i + S - 1 < T; i++) { - long long cur_h = (h[i+S] + m - h[i]) % m; + vector occurrences; + for (int i = 0; i + S - 1 < T; i++) { + long long cur_h = (h[i+S] + m - h[i]) % m; if (cur_h == h_s * p_pow[i] % m) - occurences.push_back(i); + occurrences.push_back(i); } - return occurences; + return occurrences; } ``` From 8a78e7dcbefd51b69ea4827afe305cd466521077 Mon Sep 17 00:00:00 2001 From: Matthias Langer Date: Fri, 28 Jul 2023 09:53:19 +0200 Subject: [PATCH 127/590] Clarify preconditions when calculating multiplicative inverses --- src/algebra/module-inverse.md | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/algebra/module-inverse.md b/src/algebra/module-inverse.md index dd68b9667..677d1f68d 100644 --- a/src/algebra/module-inverse.md +++ b/src/algebra/module-inverse.md @@ -77,24 +77,28 @@ From these results, we can easily find the modular inverse using the [binary exp Even though this method is easier to understand than the method described in previous paragraph, in the case when $m$ is not a prime number, we need to calculate Euler phi function, which involves factorization of $m$, which might be very hard. If the prime factorization of $m$ is known, then the complexity of this method is $O(\log m)$. -## Finding the modular inverse using Euclidean Division +## Finding the modular inverse for prime mods using Euclidean Division -Given that $m > i$ (or we can modulo to make it smaller in 1 step), according to [Euclidean Division](https://en.wikipedia.org/wiki/Euclidean_division) +Given that $p > i$ (or we can modulo to make it smaller in 1 step), according to [Euclidean Division](https://en.wikipedia.org/wiki/Euclidean_division) -$$m = k \cdot i + r$$ +$$p = k \cdot i + r$$ -where $k = \left\lfloor \frac{m}{i} \right\rfloor$ and $r = m \bmod i$, then +where $k = \left\lfloor \frac{p}{i} \right\rfloor$ and $r = p \bmod i$, then $$ \begin{align*} -& \implies & 0 & \equiv k \cdot i + r & \mod m \\ -& \iff & r & \equiv -k \cdot i & \mod m \\ -& \iff & r \cdot i^{-1} & \equiv -k & \mod m \\ -& \iff & i^{-1} & \equiv -k \cdot r^{-1} & \mod m +& \implies & 0 & \equiv k \cdot i + r & \mod p \\ +& \iff & r & \equiv -k \cdot i & \mod p \\ +& \iff & r \cdot i^{-1} & \equiv -k & \mod p \\ +& \iff & i^{-1} & \equiv -k \cdot r^{-1} & \mod p \end{align*} $$ -From there we can have the following recursive function (in C++) for computing the modular inverse for number $i$ with respect to module $m$ +Note that this reasoning does not hold if $p$ is not prime, since the existence of $i^{-1}$ does not imply the existence of $r^{-1}$ +in the general case. To see this, lets try to calculate $5^{-1}$ modulo $12$ with the above formula. We would like to arrive at $5$, +since $5 \cdot 5 \equiv 1 \bmod 12$. However, $12 = 2 \cdot 5 + 2$, and we have $k=2$ and $r=2$, with $2$ being not invertible modulo $12$. + +If the modulus is prime however, all $i$ with $0 < i < p$ are invertible modulo $p$, and we can have the following recursive function (in C++) for computing the modular inverse for number $i$ with respect to $p$ ```{.cpp file=modular_inverse_euclidean_division} int inv(int i) { From 08cc8a624ee78ba98301c6a842796db87223d684 Mon Sep 17 00:00:00 2001 From: PirateOfAndaman <82709887+PirateOfAndaman@users.noreply.github.com> Date: Sat, 5 Aug 2023 12:12:51 +0530 Subject: [PATCH 128/590] Update dijkstra.md added a comma to improve readability --- src/graph/dijkstra.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graph/dijkstra.md b/src/graph/dijkstra.md index 3771fd294..6c98705bc 100644 --- a/src/graph/dijkstra.md +++ b/src/graph/dijkstra.md @@ -38,7 +38,7 @@ Note that if some vertices are unreachable from the starting vertex $s$, the val ### Restoring Shortest Paths -Usually one needs to know not only the lengths of shortest paths but also the shortest paths themselves. Let's see how to maintain sufficient information to restore the shortest path from $s$ to any vertex. We'll maintain an array of predecessors $p[]$ in which for each vertex $v \ne s$ $p[v]$ is the penultimate vertex in the shortest path from $s$ to $v$. Here we use the fact that if we take the shortest path to some vertex $v$ and remove $v$ from this path, we'll get a path ending in at vertex $p[v]$, and this path will be the shortest for the vertex $p[v]$. This array of predecessors can be used to restore the shortest path to any vertex: starting with $v$, repeatedly take the predecessor of the current vertex until we reach the starting vertex $s$ to get the required shortest path with vertices listed in reverse order. So, the shortest path $P$ to the vertex $v$ is equal to: +Usually one needs to know not only the lengths of shortest paths but also the shortest paths themselves. Let's see how to maintain sufficient information to restore the shortest path from $s$ to any vertex. We'll maintain an array of predecessors $p[]$ in which for each vertex $v \ne s$, $p[v]$ is the penultimate vertex in the shortest path from $s$ to $v$. Here we use the fact that if we take the shortest path to some vertex $v$ and remove $v$ from this path, we'll get a path ending in at vertex $p[v]$, and this path will be the shortest for the vertex $p[v]$. This array of predecessors can be used to restore the shortest path to any vertex: starting with $v$, repeatedly take the predecessor of the current vertex until we reach the starting vertex $s$ to get the required shortest path with vertices listed in reverse order. So, the shortest path $P$ to the vertex $v$ is equal to: $$P = (s, \ldots, p[p[p[v]]], p[p[v]], p[v], v)$$ From 059a101a75450e2bca72ba160845575dff983c2f Mon Sep 17 00:00:00 2001 From: iagorrr <85769349+iagorrr@users.noreply.github.com> Date: Thu, 10 Aug 2023 12:44:19 -0300 Subject: [PATCH 129/590] Adds practice problems to Sprague-Grundy theorem. Nim Adds 3 exercises in this topic in ascending order of their difficulty. --- src/game_theory/sprague-grundy-nim.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/game_theory/sprague-grundy-nim.md b/src/game_theory/sprague-grundy-nim.md index 99156bae2..9ffe95272 100644 --- a/src/game_theory/sprague-grundy-nim.md +++ b/src/game_theory/sprague-grundy-nim.md @@ -199,3 +199,10 @@ $$g(n) = \text{mex} \Bigl( \{ g(n-2) \} \cup \{g(i-2) \oplus g(n-i-1) \mid 2 \le So we've got a $O(n^2)$ solution. In fact, $g(n)$ has a period of length 34 starting with $n=52$. + + +## Practice Problems + +- [KATTIS S-Nim](https://open.kattis.com/problems/snim) +- [CodeForces - Marbles (2018-2019 ACM-ICPC Brazil Subregional)](https://codeforces.com/gym/101908/problem/B) +- [KATTIS - Cuboid Slicing Game](https://open.kattis.com/problems/cuboidslicinggame) From 60fa701e5951ef4477b198d7b1e7bb59abf9638f Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sun, 20 Aug 2023 19:42:00 +0200 Subject: [PATCH 130/590] more sprague-grundy practice problems --- src/game_theory/sprague-grundy-nim.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/game_theory/sprague-grundy-nim.md b/src/game_theory/sprague-grundy-nim.md index 9ffe95272..0d03983f9 100644 --- a/src/game_theory/sprague-grundy-nim.md +++ b/src/game_theory/sprague-grundy-nim.md @@ -206,3 +206,6 @@ In fact, $g(n)$ has a period of length 34 starting with $n=52$. - [KATTIS S-Nim](https://open.kattis.com/problems/snim) - [CodeForces - Marbles (2018-2019 ACM-ICPC Brazil Subregional)](https://codeforces.com/gym/101908/problem/B) - [KATTIS - Cuboid Slicing Game](https://open.kattis.com/problems/cuboidslicinggame) +- [HackerRank - Tower Breakers, Revisited!](https://www.hackerrank.com/contests/5-days-of-game-theory/challenges/tower-breakers-2) +- [HackerRank - Tower Breakers, Again!](https://www.hackerrank.com/contests/5-days-of-game-theory/challenges/tower-breakers-3/problem) +- [HackerRank - Chessboard Game, Again!](https://www.hackerrank.com/contests/5-days-of-game-theory/challenges/a-chessboard-game) From 4cb485b78d04bab46c1c2458af792d616430d783 Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sun, 20 Aug 2023 20:07:23 +0200 Subject: [PATCH 131/590] fix old link and rename variables --- src/algebra/module-inverse.md | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/algebra/module-inverse.md b/src/algebra/module-inverse.md index 677d1f68d..71e4aa6e9 100644 --- a/src/algebra/module-inverse.md +++ b/src/algebra/module-inverse.md @@ -77,36 +77,37 @@ From these results, we can easily find the modular inverse using the [binary exp Even though this method is easier to understand than the method described in previous paragraph, in the case when $m$ is not a prime number, we need to calculate Euler phi function, which involves factorization of $m$, which might be very hard. If the prime factorization of $m$ is known, then the complexity of this method is $O(\log m)$. -## Finding the modular inverse for prime mods using Euclidean Division +
+## Finding the modular inverse for prime moduli using Euclidean Division -Given that $p > i$ (or we can modulo to make it smaller in 1 step), according to [Euclidean Division](https://en.wikipedia.org/wiki/Euclidean_division) +Given a prime modulus $m > a$ (or we can apply modulo to make it smaller in 1 step), according to [Euclidean Division](https://en.wikipedia.org/wiki/Euclidean_division) -$$p = k \cdot i + r$$ +$$m = k \cdot a + r$$ -where $k = \left\lfloor \frac{p}{i} \right\rfloor$ and $r = p \bmod i$, then +where $k = \left\lfloor \frac{m}{a} \right\rfloor$ and $r = m \bmod a$, then $$ \begin{align*} -& \implies & 0 & \equiv k \cdot i + r & \mod p \\ -& \iff & r & \equiv -k \cdot i & \mod p \\ -& \iff & r \cdot i^{-1} & \equiv -k & \mod p \\ -& \iff & i^{-1} & \equiv -k \cdot r^{-1} & \mod p +& \implies & 0 & \equiv k \cdot a + r & \mod m \\ +& \iff & r & \equiv -k \cdot a & \mod m \\ +& \iff & r \cdot a^{-1} & \equiv -k & \mod m \\ +& \iff & a^{-1} & \equiv -k \cdot r^{-1} & \mod m \end{align*} $$ -Note that this reasoning does not hold if $p$ is not prime, since the existence of $i^{-1}$ does not imply the existence of $r^{-1}$ +Note that this reasoning does not hold if $m$ is not prime, since the existence of $a^{-1}$ does not imply the existence of $r^{-1}$ in the general case. To see this, lets try to calculate $5^{-1}$ modulo $12$ with the above formula. We would like to arrive at $5$, since $5 \cdot 5 \equiv 1 \bmod 12$. However, $12 = 2 \cdot 5 + 2$, and we have $k=2$ and $r=2$, with $2$ being not invertible modulo $12$. -If the modulus is prime however, all $i$ with $0 < i < p$ are invertible modulo $p$, and we can have the following recursive function (in C++) for computing the modular inverse for number $i$ with respect to $p$ +If the modulus is prime however, all $a$ with $0 < a < m$ are invertible modulo $m$, and we can have the following recursive function (in C++) for computing the modular inverse for number $a$ with respect to $m$ ```{.cpp file=modular_inverse_euclidean_division} -int inv(int i) { - return i <= 1 ? i : m - (long long)(m/i) * inv(m % i) % m; +int inv(int a) { + return a <= 1 ? a : m - (long long)(m/a) * inv(m % a) % m; } ``` -The exact time complexity of the this recursion is not known. It's is somewhere between $O(\frac{\log m}{\log\log m})$ and $O(n^{\frac{1}{3} - \frac{2}{177} + \epsilon})$. +The exact time complexity of the this recursion is not known. It's is somewhere between $O(\frac{\log m}{\log\log m})$ and $O(m^{\frac{1}{3} - \frac{2}{177} + \epsilon})$. See [On the length of Pierce expansions](https://arxiv.org/abs/2211.08374). In practice this implementation is fast, e.g. for the modulus $10^9 + 7$ it will always finish in less than 50 iterations. @@ -115,8 +116,8 @@ Applying this formula, we can also precompute the modular inverse for every numb ```{.cpp file=modular_inverse_euclidean_division_all} inv[1] = 1; -for(int i = 2; i < m; ++i) - inv[i] = m - (long long)(m/i) * inv[m%i] % m; +for(int a = 2; a < m; ++a) + inv[a] = m - (long long)(m/a) * inv[m%a] % m; ``` ## Finding the modular inverse for array of numbers modulo $m$ From 0e950f842e74be1d9e0ba2ef9bc656a3dc8d0dd7 Mon Sep 17 00:00:00 2001 From: Harshit Jain <117633610+harshit-jain52@users.noreply.github.com> Date: Sun, 20 Aug 2023 23:50:34 +0530 Subject: [PATCH 132/590] Update prefix-function.md --- src/string/prefix-function.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/string/prefix-function.md b/src/string/prefix-function.md index 1fab80255..94d3efc3e 100644 --- a/src/string/prefix-function.md +++ b/src/string/prefix-function.md @@ -381,6 +381,7 @@ The problem can be solved in the same way by constructing the automaton of the p * [UVA 12467 - Secret Word](https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3911) * [UVA 11019 - Matrix Matcher](https://uva.onlinejudge.org/index.php?option=onlinejudge&page=show_problem&problem=1960) * [SPOJ - Pattern Find](http://www.spoj.com/problems/NAJPF/) +* [SPOJ - A Needle in the Haystack](https://www.spoj.com/problems/NHAY/) * [Codeforces - Anthem of Berland](http://codeforces.com/contest/808/problem/G) * [Codeforces - MUH and Cube Walls](http://codeforces.com/problemset/problem/471/D) * [Codeforces - Prefixes and Suffixes](https://codeforces.com/contest/432/problem/D) From e169a6f647f6b73f0605d535f9350b3792d3bd5c Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sun, 20 Aug 2023 20:50:35 +0200 Subject: [PATCH 133/590] Update catalan-numbers.md --- src/combinatorics/catalan-numbers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/combinatorics/catalan-numbers.md b/src/combinatorics/catalan-numbers.md index 40de84b53..94d559a78 100644 --- a/src/combinatorics/catalan-numbers.md +++ b/src/combinatorics/catalan-numbers.md @@ -9,7 +9,7 @@ Catalan numbers is a number sequence, which is found useful in a number of combi This sequence was named after the Belgian mathematician [Catalan](https://en.wikipedia.org/wiki/Eug%C3%A8ne_Charles_Catalan), who lived in the 19th century. (In fact it was known before to Euler, who lived a century before Catalan). -The first few numbers of Catalan numbers, $C_n$ (starting from zero): +The first few Catalan numbers $C_n$ (starting from zero): $1, 1, 2, 5, 14, 42, 132, 429, 1430, \ldots$ From 890ea70e4af68f8efb7f69818c270b0397abf2f3 Mon Sep 17 00:00:00 2001 From: Arnar Bjarni Arnarson Date: Sun, 20 Aug 2023 23:06:41 +0000 Subject: [PATCH 134/590] Add String Hashing on Kattis as a Practice Problem --- src/string/string-hashing.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/string/string-hashing.md b/src/string/string-hashing.md index 5ce399283..7e62380bb 100644 --- a/src/string/string-hashing.md +++ b/src/string/string-hashing.md @@ -207,6 +207,7 @@ When comparing $10^6$ strings with each other, the probability that at least one ## Practice Problems * [Good Substrings - Codeforces](https://codeforces.com/contest/271/problem/D) * [A Needle in the Haystack - SPOJ](http://www.spoj.com/problems/NHAY/) +* [String Hashing - Kattis](https://open.kattis.com/problems/hashing) * [Double Profiles - Codeforces](http://codeforces.com/problemset/problem/154/C) * [Password - Codeforces](http://codeforces.com/problemset/problem/126/B) * [SUB_PROB - SPOJ](http://www.spoj.com/problems/SUB_PROB/) From db1381b7c40b66620a6a9b98408742cda2cf2297 Mon Sep 17 00:00:00 2001 From: TrietMinh Date: Wed, 23 Aug 2023 21:59:19 +0700 Subject: [PATCH 135/590] Add more problems to sieve of eratosthenes article --- src/algebra/primality_tests.md | 2 +- src/algebra/sieve-of-eratosthenes.md | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/algebra/primality_tests.md b/src/algebra/primality_tests.md index dcebf116a..2acc0cffa 100644 --- a/src/algebra/primality_tests.md +++ b/src/algebra/primality_tests.md @@ -217,4 +217,4 @@ However, since these numbers (except 2) are not prime, you need to check additio ## Practice Problems -- [SPOJ - Prime or Not](https://www.spoj.com/problems/PON/) +- [SPOJ - Prime or Not](https://www.spoj.com/problems/PON/) \ No newline at end of file diff --git a/src/algebra/sieve-of-eratosthenes.md b/src/algebra/sieve-of-eratosthenes.md index 1fd2e9cb3..f537ff46a 100644 --- a/src/algebra/sieve-of-eratosthenes.md +++ b/src/algebra/sieve-of-eratosthenes.md @@ -254,6 +254,8 @@ However, this algorithm also has its own weaknesses. ## Practice Problems +* [Leetcode - Four Divisors](https://leetcode.com/problems/four-divisors/) +* [Leetcode - Count Primes](https://leetcode.com/problems/count-primes/) * [SPOJ - Printing Some Primes](http://www.spoj.com/problems/TDPRIMES/) * [SPOJ - A Conjecture of Paul Erdos](http://www.spoj.com/problems/HS08PAUL/) * [SPOJ - Primal Fear](http://www.spoj.com/problems/VECTAR8/) From 8645e70baed217d189276c96a6066edbe8534c93 Mon Sep 17 00:00:00 2001 From: MInhTriet <57322084+TrietMinh799@users.noreply.github.com> Date: Wed, 23 Aug 2023 22:03:28 +0700 Subject: [PATCH 136/590] Update sieve-of-eratosthenes.md I add 2 problems from leetcode to this article. --- src/algebra/sieve-of-eratosthenes.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/algebra/sieve-of-eratosthenes.md b/src/algebra/sieve-of-eratosthenes.md index 1fd2e9cb3..f537ff46a 100644 --- a/src/algebra/sieve-of-eratosthenes.md +++ b/src/algebra/sieve-of-eratosthenes.md @@ -254,6 +254,8 @@ However, this algorithm also has its own weaknesses. ## Practice Problems +* [Leetcode - Four Divisors](https://leetcode.com/problems/four-divisors/) +* [Leetcode - Count Primes](https://leetcode.com/problems/count-primes/) * [SPOJ - Printing Some Primes](http://www.spoj.com/problems/TDPRIMES/) * [SPOJ - A Conjecture of Paul Erdos](http://www.spoj.com/problems/HS08PAUL/) * [SPOJ - Primal Fear](http://www.spoj.com/problems/VECTAR8/) From f774c39e8841d73fec7b6fcd80a44447c08985e2 Mon Sep 17 00:00:00 2001 From: Md Shamim Ahmad <56692841+md-shamim-ahmad@users.noreply.github.com> Date: Thu, 24 Aug 2023 20:17:22 +0600 Subject: [PATCH 137/590] Update divisors.md --- src/algebra/divisors.md | 43 ++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/src/algebra/divisors.md b/src/algebra/divisors.md index 53ae7d4a0..2356b0a9c 100644 --- a/src/algebra/divisors.md +++ b/src/algebra/divisors.md @@ -43,21 +43,21 @@ So the number of divisors is trivially $(e_1 + 1) \cdot (e_2 + 1)$. ```cpp -vector primes; - -long long NumberOfDivisors(long long num) { +long long numberOfDivisors(long long num) { long long total = 1; - - for (long long p: primes) { - if (num % p == 0) { + for (int i = 2; (long long)i * i <= num; i++) { + if (num % i == 0) { int e = 0; - while (num % p == 0) { + do { e++; - num /= p; - } - total *= (e + 1); + num /= i; + } while (num % i == 0); + total *= e + 1; } } + if (num > 1) { + total *= 2; + } return total; } ``` @@ -83,21 +83,28 @@ $$ = \frac{p_1^{e_1 + 1} - 1}{p_1 - 1} \cdot \frac{p_2^{e_2 + 1} - 1}{p_2 - 1}$$ $$\sigma(n) = \frac{p_1^{e_1 + 1} - 1}{p_1 - 1} \cdot \frac{p_2^{e_2 + 1} - 1}{p_2 - 1} \cdots \frac{p_k^{e_k + 1} - 1}{p_k - 1}$$ ```cpp -vector primes; - long long SumOfDivisors(long long num) { long long total = 1; - for (long long p: primes) { - if (num % p == 0) { + for (int i = 2; (long long)i * i <= num; i++) { + if (num % i == 0) { int e = 0; - while (num % p == 0) { + do { e++; - num /= p; - } - total *= (pow(p, (e + 1)) - 1) / (p - 1); + num /= i; + } while (num % i == 0); + + long long sum = 0, pow = 1; + do { + sum += pow; + pow *= i; + } while (e-- > 0); + total *= sum; } } + if (num > 1) { + total *= (1 + num); + } return total; } ``` From b021708cad4194f3c7a6248ff22721b2982df1a8 Mon Sep 17 00:00:00 2001 From: dallasyan Date: Sun, 27 Aug 2023 17:21:38 +1000 Subject: [PATCH 138/590] Update point-in-convex-polygon.md, fix cross product 0 check and `prepair` typo --- src/geometry/point-in-convex-polygon.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/geometry/point-in-convex-polygon.md b/src/geometry/point-in-convex-polygon.md index f04012748..7d6e630b7 100644 --- a/src/geometry/point-in-convex-polygon.md +++ b/src/geometry/point-in-convex-polygon.md @@ -42,7 +42,7 @@ If it is inside, then it will be equal. ## Implementation -The function `prepair` will make sure that the lexicographical smallest point (smallest x value, and in ties smallest y value) will be $p_0$, and computes the vectors $p_i - p_0$. +The function `prepare` will make sure that the lexicographical smallest point (smallest x value, and in ties smallest y value) will be $p_0$, and computes the vectors $p_i - p_0$. Afterwards the function `pointInConvexPolygon` computes the result of a query. We additionally remember the point $p_0$ and translate all queried points with it in order compute the correct distance, as vectors don't have an initial point. By translating the query points we can assume that all vectors start at the origin $(0, 0)$, and simplify the computations for distances and lengths. @@ -95,7 +95,7 @@ void prepare(vector &points) { bool pointInConvexPolygon(pt point) { point = point - translation; - if (seq[0].cross(point) != 1 && + if (seq[0].cross(point) != 0 && sgn(seq[0].cross(point)) != sgn(seq[0].cross(seq[n - 1]))) return false; if (seq[n - 1].cross(point) != 0 && From 3fe9c7053c59f119369646f99f0c59e05d1a183e Mon Sep 17 00:00:00 2001 From: Mehrdad <70322560+mehrdad3301@users.noreply.github.com> Date: Sun, 27 Aug 2023 22:56:44 +0330 Subject: [PATCH 139/590] fix: fix small grammar --- src/data_structures/segment_tree.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data_structures/segment_tree.md b/src/data_structures/segment_tree.md index 0c4f4fb0a..67090a82e 100644 --- a/src/data_structures/segment_tree.md +++ b/src/data_structures/segment_tree.md @@ -121,7 +121,7 @@ We can show that this proposition (at most four vertices each level) is true by At the first level, we only visit one vertex, the root vertex, so here we visit less than four vertices. Now let's look at an arbitrary level. By induction hypothesis, we visit at most four vertices. -If we only visit at most two vertices, the next level has at most four vertices. That trivial, because each vertex can only cause at most two recursive calls. +If we only visit at most two vertices, the next level has at most four vertices. That is trivial, because each vertex can only cause at most two recursive calls. So let's assume that we visit three or four vertices in the current level. From those vertices, we will analyze the vertices in the middle more carefully. Since the sum query asks for the sum of a continuous subarray, we know that segments corresponding to the visited vertices in the middle will be completely covered by the segment of the sum query. From 181fce0efeb863312845ef158da5f06fc6144c45 Mon Sep 17 00:00:00 2001 From: iagorrr <85769349+iagorrr@users.noreply.github.com> Date: Sun, 27 Aug 2023 18:34:43 -0300 Subject: [PATCH 140/590] Update suffix-automaton.md, adds practice problems --- src/string/suffix-automaton.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/string/suffix-automaton.md b/src/string/suffix-automaton.md index f7a46c81f..47c60c169 100644 --- a/src/string/suffix-automaton.md +++ b/src/string/suffix-automaton.md @@ -775,6 +775,13 @@ After that, the answer to the problem will be the string $longest(v)$ for the st ## Practice Problems + - [CSES - Finding Patterns](https://cses.fi/problemset/task/2102) + - [CSES - Counting Patterns](https://cses.fi/problemset/task/2103) + - [CSES - String Matching](https://cses.fi/problemset/task/1753) + - [CSES - Patterns Positions](https://cses.fi/problemset/task/2104) + - [CSES - Distinct Substrings](https://cses.fi/problemset/task/2105) + - [CSES - Word Combinations](https://cses.fi/problemset/task/1731) + - [CSES - String Distribution](https://cses.fi/problemset/task/2110) - [AtCoder - K-th Substring](https://atcoder.jp/contests/abc097/tasks/arc097_a) - [SPOJ - SUBLEX](https://www.spoj.com/problems/SUBLEX/) - [Codeforces - Cyclical Quest](https://codeforces.com/problemset/problem/235/C) From 35eb407d9c2ada7abab257bc2d1f6ad83a27a67f Mon Sep 17 00:00:00 2001 From: Akash Nayar <33558235+Akash-Nayar@users.noreply.github.com> Date: Wed, 17 May 2023 10:22:40 -0400 Subject: [PATCH 141/590] Update bit-manipulation.md (Fix Typo) "enought" -> "enough" --- src/algebra/bit-manipulation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algebra/bit-manipulation.md b/src/algebra/bit-manipulation.md index b61cfbf85..f4047181d 100644 --- a/src/algebra/bit-manipulation.md +++ b/src/algebra/bit-manipulation.md @@ -37,7 +37,7 @@ assert(negative_signed_number == 0b1111'1111'1111'1111'1111'1111'1111'0011); CPUs are very fast manipulating those bits with specific operations. For some problems we can take these binary number representations to our advantage, and speed up the execution time. -And for some problems (typically in combinatorics or dynamic programming) where we want to track which objects we already picked from a given set of objects, we can just use an large enought integer where each digit represents an object and depending on if we pick or drop the object we set or clear the digit. +And for some problems (typically in combinatorics or dynamic programming) where we want to track which objects we already picked from a given set of objects, we can just use an large enough integer where each digit represents an object and depending on if we pick or drop the object we set or clear the digit. ## Bit operators From 918fb74fa0056feed71e09dbecc0bea0c13eb6c9 Mon Sep 17 00:00:00 2001 From: huggin Date: Sun, 14 May 2023 15:41:48 -0700 Subject: [PATCH 142/590] fix z_function --- src/string/z-function.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/string/z-function.md b/src/string/z-function.md index 632eddc43..c83938cb4 100644 --- a/src/string/z-function.md +++ b/src/string/z-function.md @@ -33,7 +33,7 @@ vector z_function_trivial(string s) { int n = s.size(); vector z(n); for (int i = 1; i < n; i++) { - while (s[z[i]] == s[i + z[i]]) { + while (i + z[i] < n && s[z[i]] == s[i + z[i]]) { z[i]++; } } @@ -96,7 +96,7 @@ vector z_function(string s) { if(i < r) { z[i] = min(r - i, z[i - l]); } - while(s[z[i]] == s[i + z[i]]) { + while(i + z[i] < n && s[z[i]] == s[i + z[i]]) { z[i]++; } if(i + z[i] > r) { From d4e1bf399c70372b39b9225036497190e961230a Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sat, 3 Jun 2023 14:19:53 +0200 Subject: [PATCH 143/590] new GA4 tag --- mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index 7fe24eeb9..f539e7249 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -74,4 +74,4 @@ plugins: extra: analytics: provider: google - property: UA-85220282-1 + property: G-7FLS2HCYHH From 271a56bf9117476923dae354cf7e93661f5b2121 Mon Sep 17 00:00:00 2001 From: Sourav Date: Fri, 1 Sep 2023 00:46:49 -0300 Subject: [PATCH 144/590] Added Hare n Tortoise algorithm under data structures --- .../hare_tortoise_algorithm.md | 105 ++++++++++++++++++ src/data_structures/tortoise_hare_algo.png | Bin 0 -> 17291 bytes .../tortoise_hare_algo_proof.png | Bin 0 -> 26102 bytes src/data_structures/tortoise_hare_proof.png | Bin 0 -> 27733 bytes .../tortouse_hare_cycle_found.png | Bin 0 -> 21399 bytes 5 files changed, 105 insertions(+) create mode 100644 src/data_structures/hare_tortoise_algorithm.md create mode 100644 src/data_structures/tortoise_hare_algo.png create mode 100644 src/data_structures/tortoise_hare_algo_proof.png create mode 100644 src/data_structures/tortoise_hare_proof.png create mode 100644 src/data_structures/tortouse_hare_cycle_found.png diff --git a/src/data_structures/hare_tortoise_algorithm.md b/src/data_structures/hare_tortoise_algorithm.md new file mode 100644 index 000000000..ae1844d31 --- /dev/null +++ b/src/data_structures/hare_tortoise_algorithm.md @@ -0,0 +1,105 @@ + +--- +tags: + - Translated +e_maxx_link: hare_tortoise_algorithm +--- + +# Floyd's Linked List Cycle Finding Algorithm + +Given a linked list where the starting point of that linked list is denoted by `head`, and there may or may not be a cycle present. For instance: + +![[tortoise_hare_algo.png]] + +Here we need to find out the point `C`, i.e the starting point of the cycle. + +## Proposed algorithm +The algorithm is called `Floyd’s Cycle Algorithm or Tortoise n Hare algorithm`. +In order to figure out the starting point of the cycle, we need to figure out of the the cycle even exists or not. +So, it involved two steps: +1. Figure out the presence of the cycle. +2. Find out the starting point of the cycle. + +### Step 1: Presence of the cycle +1. Take two pointers $slow$ and $fast$. +2. Both of them will point to head of the linked list initially. +3. $slow$ will move one step at a time. +4. $fast$ will move two steps at a time. (twice as speed as $slow$ pointer). +5. check if at any point they point to the same node before any one(or both) reach null. +6. if they point to any same node at any point of their journey, it would indicate that the cycle indeed exists in the linked list. +7. if we get null, it would indicate that the linked list has no cycle. + +![[tortouse_hare_cycle_found.png]] + +Now, that we have figured out that there is a cycle present in the linked list, for the next step we need to find out the starting point of cycle, i.e., `C. +### Step 2: Starting point of the cycle +1. Reset the $slow$ pointer to the `head` of the linked list. +2. Move both pointers one step at a time. +3. The point they will meet at will be the starting point of the cycle. + +```java +// Presence of cycle +public boolean hasCycle(ListNode head) { + ListNode slow = head; + ListNode fast = head; + + while(slow !=null && fast != null && fast.next != null){ + slow = slow.next; + fast = fast.next.next; + if(slow==fast){ + return true; + } + } + + return false; +} +``` + +```java +// Assuming there is a cycle present and slow and fast are point to their meeting point +slow = head; +while(slow!=fast){ + slow = slow.next; + fast = fast.next; +} + +return slow; // the starting point of the cycle. +``` + +## Why does it work + +### Step 1: Presence of the cycle +Since the pointer $fast$ is moving with twice as speed as $slow$, we can say that at any point of time, $fast$ would have covered twice as much distance as $slow$. +We can also deduce that the difference between the distance covered by both of these pointers is increasing by $1$. +``` +slow: 0 --> 1 --> 2 --> 3 --> 4 (distance covered) +fast: 0 --> 2 --> 4 --> 6 --> 8 (distance covered) +diff: 0 --> 1 --> 2 --> 3 --> 4 (difference between distance covered by both pointers) +``` + +So, if we assume that Length of cycle is: $L$, we can also say that there will be a point when the difference between $slow$ and $fast$ pointer will grow and reach $NXL$ where $N>0$ . + +When both $slow$ and $fast$ are within cycle, and the difference between their covered lengths is $NXL$, then they are bound to point at same node, indicating the presence of cycle. + +### Step 2: Starting point of the cycle + +Lets try to calculate the distance covered by both of the pointers till they point they met within the cycle. + +distance covered by slow = $slowDist$ +distance covered by fast = $fastDist$ + +$slowDist = a + xL + b$ $x\ge0$ +$fastDist = a + yL + b$ $y\ge0$ + +![[tortoise_hare_proof.png]] + +$a + yL + b = 2(a + xL + b)$ + +$a=(y-2x)L-b$ where $y-2x$ is an integer. + +We know that $fast$ has already covered $b$, so, we can say that the distance $a$ is same as some multiple of length of the cycle. + +# Problems: +- [Linked List Cycle (EASY)](https://leetcode.com/problems/linked-list-cycle/) +- [Find the Duplicate Number (Medium)](https://leetcode.com/problems/find-the-duplicate-number/) + diff --git a/src/data_structures/tortoise_hare_algo.png b/src/data_structures/tortoise_hare_algo.png new file mode 100644 index 0000000000000000000000000000000000000000..24d2f688261cf59f3ed1471338b072f7c790d6c6 GIT binary patch literal 17291 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 literal 0 HcmV?d00001 From 9713dace5ff724ec0b49ef7c108bf9a5b1e21981 Mon Sep 17 00:00:00 2001 From: Sourav Date: Fri, 1 Sep 2023 00:47:32 -0300 Subject: [PATCH 145/590] Update navigation.md --- src/navigation.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/navigation.md b/src/navigation.md index 260c68a26..ab6db7722 100644 --- a/src/navigation.md +++ b/src/navigation.md @@ -50,6 +50,7 @@ search: - Fundamentals - [Minimum Stack / Minimum Queue](data_structures/stack_queue_modification.md) - [Sparse Table](data_structures/sparse-table.md) + - [Hare Tortoise Algorithm (Linked List cycle detection)](hare_tortoise_algorithm.md) - Trees - [Disjoint Set Union](data_structures/disjoint_set_union.md) - [Fenwick Tree](data_structures/fenwick.md) From fa35cc41baa9034b3cc0de2cce7b88d11a4a44a1 Mon Sep 17 00:00:00 2001 From: Sourav Date: Fri, 1 Sep 2023 00:51:39 -0300 Subject: [PATCH 146/590] Update navigation.md --- src/navigation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/navigation.md b/src/navigation.md index ab6db7722..e11a9e06b 100644 --- a/src/navigation.md +++ b/src/navigation.md @@ -50,7 +50,7 @@ search: - Fundamentals - [Minimum Stack / Minimum Queue](data_structures/stack_queue_modification.md) - [Sparse Table](data_structures/sparse-table.md) - - [Hare Tortoise Algorithm (Linked List cycle detection)](hare_tortoise_algorithm.md) + - [Hare Tortoise Algorithm (Linked List cycle detection)](data_structures/hare_tortoise_algorithm.md) - Trees - [Disjoint Set Union](data_structures/disjoint_set_union.md) - [Fenwick Tree](data_structures/fenwick.md) From f60fb44f9b618dc4068fddac9f89034ad00312cb Mon Sep 17 00:00:00 2001 From: Harshit Jain <117633610+harshit-jain52@users.noreply.github.com> Date: Fri, 1 Sep 2023 11:23:19 +0530 Subject: [PATCH 147/590] Update fenwick.md --- src/data_structures/fenwick.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/data_structures/fenwick.md b/src/data_structures/fenwick.md index 01a49040b..81142bdbd 100644 --- a/src/data_structures/fenwick.md +++ b/src/data_structures/fenwick.md @@ -486,6 +486,7 @@ def range_sum(l, r): * [Codeforces - Goodbye Souvenir](http://codeforces.com/contest/849/problem/E) * [SPOJ - Ada and Species](http://www.spoj.com/problems/ADACABAA/) * [Codeforces - Thor](https://codeforces.com/problemset/problem/704/A) +* [CSES - Forest Queries II](https://cses.fi/problemset/task/1739/) * [Latin American Regionals 2017 - Fundraising](http://matcomgrader.com/problem/9346/fundraising/) ## Other sources From 2f48179b8aea09df8aef31c8524571927a8d2d51 Mon Sep 17 00:00:00 2001 From: Sourav Date: Sat, 9 Sep 2023 22:43:20 -0300 Subject: [PATCH 148/590] Update hare_tortoise_algorithm.md Modified the article. --- .../hare_tortoise_algorithm.md | 42 ++++++++++--------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/src/data_structures/hare_tortoise_algorithm.md b/src/data_structures/hare_tortoise_algorithm.md index ae1844d31..c7e93f440 100644 --- a/src/data_structures/hare_tortoise_algorithm.md +++ b/src/data_structures/hare_tortoise_algorithm.md @@ -1,20 +1,19 @@ --- tags: - - Translated -e_maxx_link: hare_tortoise_algorithm + - Original --- # Floyd's Linked List Cycle Finding Algorithm -Given a linked list where the starting point of that linked list is denoted by `head`, and there may or may not be a cycle present. For instance: +Given a linked list where the starting point of that linked list is denoted by **head**, and there may or may not be a cycle present. For instance: ![[tortoise_hare_algo.png]] -Here we need to find out the point `C`, i.e the starting point of the cycle. +Here we need to find out the point **C**, i.e the starting point of the cycle. ## Proposed algorithm -The algorithm is called `Floyd’s Cycle Algorithm or Tortoise n Hare algorithm`. +The algorithm is called **Floyd’s Cycle Algorithm or Tortoise And Hare algorithm**. In order to figure out the starting point of the cycle, we need to figure out of the the cycle even exists or not. So, it involved two steps: 1. Figure out the presence of the cycle. @@ -25,15 +24,15 @@ So, it involved two steps: 2. Both of them will point to head of the linked list initially. 3. $slow$ will move one step at a time. 4. $fast$ will move two steps at a time. (twice as speed as $slow$ pointer). -5. check if at any point they point to the same node before any one(or both) reach null. -6. if they point to any same node at any point of their journey, it would indicate that the cycle indeed exists in the linked list. -7. if we get null, it would indicate that the linked list has no cycle. +5. Check if at any point they point to the same node before any one(or both) reach null. +6. If they point to any same node at any point of their journey, it would indicate that the cycle indeed exists in the linked list. +7. If we get null, it would indicate that the linked list has no cycle. ![[tortouse_hare_cycle_found.png]] -Now, that we have figured out that there is a cycle present in the linked list, for the next step we need to find out the starting point of cycle, i.e., `C. +Now, that we have figured out that there is a cycle present in the linked list, for the next step we need to find out the starting point of cycle, i.e., **C**. ### Step 2: Starting point of the cycle -1. Reset the $slow$ pointer to the `head` of the linked list. +1. Reset the $slow$ pointer to the **head** of the linked list. 2. Move both pointers one step at a time. 3. The point they will meet at will be the starting point of the cycle. @@ -76,28 +75,33 @@ slow: 0 --> 1 --> 2 --> 3 --> 4 (distance covered) fast: 0 --> 2 --> 4 --> 6 --> 8 (distance covered) diff: 0 --> 1 --> 2 --> 3 --> 4 (difference between distance covered by both pointers) ``` - -So, if we assume that Length of cycle is: $L$, we can also say that there will be a point when the difference between $slow$ and $fast$ pointer will grow and reach $NXL$ where $N>0$ . - -When both $slow$ and $fast$ are within cycle, and the difference between their covered lengths is $NXL$, then they are bound to point at same node, indicating the presence of cycle. +Let $\lambda$ denote the length of the cycle, and $\mu$ represent the number of steps required for the slow pointer to reach the cycle. It's important to emphasize that there exists a positive integer $k$ ($k > 0$) such that $k\lambda \geq \mu$. +When the slow pointer has moved $k\lambda$ steps, and the fast pointer has covered $2k\lambda$ steps, both pointers find themselves within the cycle. At this point, there is a separation of $k\lambda$ between them. Given that the cycle's length remains $\lambda$, this signifies that they meet at the same point within the cycle, resulting in their encounter. ### Step 2: Starting point of the cycle Lets try to calculate the distance covered by both of the pointers till they point they met within the cycle. -distance covered by slow = $slowDist$ -distance covered by fast = $fastDist$ +![[tortoise_hare_proof.png]] $slowDist = a + xL + b$ $x\ge0$ -$fastDist = a + yL + b$ $y\ge0$ +$fastDist = a + yL + b$ $y\ge0 -![[tortoise_hare_proof.png]] +- $slowDist$ is the total distance covered by slow pointer. +- $fastDist$ is the total distance covered by fast pointer. +- $a$ is the number of steps both pointers need to take to enter the cycle. +- $b$ is the distance between **C** and **G**, i.e., distance between the starting point of cycle and meeting point of both pointers. +- $x$ is the number of times the slow pointer has circulated inside the cycle, starting from and ending at **C**. +- $y$ is the number of times the fast pointer has circulated inside the cycle, starting from and ending at **C**. +Knowing that $slowDist = 2 \cdot (fastDist)$. $a + yL + b = 2(a + xL + b)$ $a=(y-2x)L-b$ where $y-2x$ is an integer. -We know that $fast$ has already covered $b$, so, we can say that the distance $a$ is same as some multiple of length of the cycle. +This formula can translated as that basically $a$ steps is same as doing some number of full loops in cycle and go $b$ steps backwards. +Since the fast pointer already is $b$ steps ahead of the entry of cycle, if fast pointer does another $a$ steps it will end up at the entry of the cycle. +And since we let the slow pointer start at the start of the linked list, after $a$ steps it will also end up at the cycle entry. So, if they both move $a$ step they both will meet the entry of cycle. # Problems: - [Linked List Cycle (EASY)](https://leetcode.com/problems/linked-list-cycle/) From 92fe69ba517783fb58c3faa6a60c83300f0bf7f5 Mon Sep 17 00:00:00 2001 From: Sourav Date: Sat, 9 Sep 2023 22:46:12 -0300 Subject: [PATCH 149/590] Update hare_tortoise_algorithm.md --- src/data_structures/hare_tortoise_algorithm.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/data_structures/hare_tortoise_algorithm.md b/src/data_structures/hare_tortoise_algorithm.md index c7e93f440..30b90cf98 100644 --- a/src/data_structures/hare_tortoise_algorithm.md +++ b/src/data_structures/hare_tortoise_algorithm.md @@ -91,10 +91,10 @@ $fastDist = a + yL + b$ $y\ge0 - $fastDist$ is the total distance covered by fast pointer. - $a$ is the number of steps both pointers need to take to enter the cycle. - $b$ is the distance between **C** and **G**, i.e., distance between the starting point of cycle and meeting point of both pointers. -- $x$ is the number of times the slow pointer has circulated inside the cycle, starting from and ending at **C**. -- $y$ is the number of times the fast pointer has circulated inside the cycle, starting from and ending at **C**. +- $x$ is the number of times the slow pointer has looped inside the cycle, starting from and ending at **C**. +- $y$ is the number of times the fast pointer has looped inside the cycle, starting from and ending at **C**. -Knowing that $slowDist = 2 \cdot (fastDist)$. +Knowing that $slowDist = 2 \cdot (fastDist)$ $a + yL + b = 2(a + xL + b)$ $a=(y-2x)L-b$ where $y-2x$ is an integer. From 428fb2614f105dc858ddd297cf4ba908a0d98fb9 Mon Sep 17 00:00:00 2001 From: Sourav Date: Sat, 9 Sep 2023 22:47:35 -0300 Subject: [PATCH 150/590] Update hare_tortoise_algorithm.md --- src/data_structures/hare_tortoise_algorithm.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/data_structures/hare_tortoise_algorithm.md b/src/data_structures/hare_tortoise_algorithm.md index 30b90cf98..de69d3a62 100644 --- a/src/data_structures/hare_tortoise_algorithm.md +++ b/src/data_structures/hare_tortoise_algorithm.md @@ -95,6 +95,7 @@ $fastDist = a + yL + b$ $y\ge0 - $y$ is the number of times the fast pointer has looped inside the cycle, starting from and ending at **C**. Knowing that $slowDist = 2 \cdot (fastDist)$ + $a + yL + b = 2(a + xL + b)$ $a=(y-2x)L-b$ where $y-2x$ is an integer. From 3ee02152f8a1fe613af4d6cd5066c785e22fa82e Mon Sep 17 00:00:00 2001 From: Sourav Date: Sat, 9 Sep 2023 23:03:09 -0300 Subject: [PATCH 151/590] Update hare_tortoise_algorithm.md --- src/data_structures/hare_tortoise_algorithm.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/data_structures/hare_tortoise_algorithm.md b/src/data_structures/hare_tortoise_algorithm.md index de69d3a62..7ebdfb2db 100644 --- a/src/data_structures/hare_tortoise_algorithm.md +++ b/src/data_structures/hare_tortoise_algorithm.md @@ -75,7 +75,7 @@ slow: 0 --> 1 --> 2 --> 3 --> 4 (distance covered) fast: 0 --> 2 --> 4 --> 6 --> 8 (distance covered) diff: 0 --> 1 --> 2 --> 3 --> 4 (difference between distance covered by both pointers) ``` -Let $\lambda$ denote the length of the cycle, and $\mu$ represent the number of steps required for the slow pointer to reach the cycle. It's important to emphasize that there exists a positive integer $k$ ($k > 0$) such that $k\lambda \geq \mu$. +Let $\lambda$ denote the length of the cycle, and $\mu$ represent the number of steps required for the slow pointer to reach the entry of cycle. There exists a positive integer $k$ ($k > 0$) such that $k\lambda \geq \mu$. When the slow pointer has moved $k\lambda$ steps, and the fast pointer has covered $2k\lambda$ steps, both pointers find themselves within the cycle. At this point, there is a separation of $k\lambda$ between them. Given that the cycle's length remains $\lambda$, this signifies that they meet at the same point within the cycle, resulting in their encounter. ### Step 2: Starting point of the cycle @@ -94,14 +94,18 @@ $fastDist = a + yL + b$ $y\ge0 - $x$ is the number of times the slow pointer has looped inside the cycle, starting from and ending at **C**. - $y$ is the number of times the fast pointer has looped inside the cycle, starting from and ending at **C**. -Knowing that $slowDist = 2 \cdot (fastDist)$ +$slowDist = 2 \cdot (fastDist)$ $a + yL + b = 2(a + xL + b)$ -$a=(y-2x)L-b$ where $y-2x$ is an integer. +Resolving the formula we get: -This formula can translated as that basically $a$ steps is same as doing some number of full loops in cycle and go $b$ steps backwards. -Since the fast pointer already is $b$ steps ahead of the entry of cycle, if fast pointer does another $a$ steps it will end up at the entry of the cycle. +$a=(y-2x)L-b$ + +where $y-2x$ is an integer + +This basically means that $a$ steps is same as doing some number of full loops in cycle and go $b$ steps backwards. +Since the fast pointer already is $b$ steps ahead of the entry of cycle, if fast pointer moves another $a$ steps it will end up at the entry of the cycle. And since we let the slow pointer start at the start of the linked list, after $a$ steps it will also end up at the cycle entry. So, if they both move $a$ step they both will meet the entry of cycle. # Problems: From 662c6e1b5029306f6fc6e5190512c49334d995c6 Mon Sep 17 00:00:00 2001 From: Sourav Date: Sat, 9 Sep 2023 23:04:48 -0300 Subject: [PATCH 152/590] Update hare_tortoise_algorithm.md --- src/data_structures/hare_tortoise_algorithm.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/data_structures/hare_tortoise_algorithm.md b/src/data_structures/hare_tortoise_algorithm.md index 7ebdfb2db..8b22297ef 100644 --- a/src/data_structures/hare_tortoise_algorithm.md +++ b/src/data_structures/hare_tortoise_algorithm.md @@ -85,7 +85,8 @@ Lets try to calculate the distance covered by both of the pointers till they poi ![[tortoise_hare_proof.png]] $slowDist = a + xL + b$ $x\ge0$ -$fastDist = a + yL + b$ $y\ge0 + +$fastDist = a + yL + b$ $y\ge0$ - $slowDist$ is the total distance covered by slow pointer. - $fastDist$ is the total distance covered by fast pointer. From 43fa0890efcb61862ec775deecdaed578644bd7e Mon Sep 17 00:00:00 2001 From: Sourav Date: Sat, 9 Sep 2023 23:10:52 -0300 Subject: [PATCH 153/590] deleted unused image --- .../tortoise_hare_algo_proof.png | Bin 26102 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/data_structures/tortoise_hare_algo_proof.png diff --git a/src/data_structures/tortoise_hare_algo_proof.png b/src/data_structures/tortoise_hare_algo_proof.png deleted file mode 100644 index 46f7c254bb2371da5d710cddfd293957944302dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26102 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 Date: Sat, 9 Sep 2023 23:17:50 -0300 Subject: [PATCH 154/590] Update hare_tortoise_algorithm.md --- src/data_structures/hare_tortoise_algorithm.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data_structures/hare_tortoise_algorithm.md b/src/data_structures/hare_tortoise_algorithm.md index 8b22297ef..83fad231a 100644 --- a/src/data_structures/hare_tortoise_algorithm.md +++ b/src/data_structures/hare_tortoise_algorithm.md @@ -75,8 +75,8 @@ slow: 0 --> 1 --> 2 --> 3 --> 4 (distance covered) fast: 0 --> 2 --> 4 --> 6 --> 8 (distance covered) diff: 0 --> 1 --> 2 --> 3 --> 4 (difference between distance covered by both pointers) ``` -Let $\lambda$ denote the length of the cycle, and $\mu$ represent the number of steps required for the slow pointer to reach the entry of cycle. There exists a positive integer $k$ ($k > 0$) such that $k\lambda \geq \mu$. -When the slow pointer has moved $k\lambda$ steps, and the fast pointer has covered $2k\lambda$ steps, both pointers find themselves within the cycle. At this point, there is a separation of $k\lambda$ between them. Given that the cycle's length remains $\lambda$, this signifies that they meet at the same point within the cycle, resulting in their encounter. +Let $L$ denote the length of the cycle, and $a$ represent the number of steps required for the slow pointer to reach the entry of cycle. There exists a positive integer $k$ ($k > 0$) such that $k \cdot L \geq a$. +When the slow pointer has moved $k \cdot L$ steps, and the fast pointer has covered $2 \cdot k \cdot L$ steps, both pointers find themselves within the cycle. At this point, there is a separation of $k \cdot L$ between them. Given that the cycle's length remains $L$, this signifies that they meet at the same point within the cycle, resulting in their encounter. ### Step 2: Starting point of the cycle From 91bbeb2914471c8e6f6b4d1ec57d372d31f4e198 Mon Sep 17 00:00:00 2001 From: Sourav Date: Sat, 9 Sep 2023 23:28:20 -0300 Subject: [PATCH 155/590] Update factorization.md Linked tortoise and the hare algorithm. --- src/algebra/factorization.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algebra/factorization.md b/src/algebra/factorization.md index d6b102e87..4a7625e3c 100644 --- a/src/algebra/factorization.md +++ b/src/algebra/factorization.md @@ -271,7 +271,7 @@ In each iteration the first pointer advances to the next element, but the second It's not hard to see, that if there exists a cycle, the second pointer will make at least one full cycle and then meet the first pointer during the next few cycle loops. If the cycle length is $\lambda$ and the $\mu$ is the first index at which the cycle starts, then the algorithm will run in $O(\lambda + \mu)$ time. -This algorithm is also known as **tortoise and the hare algorithm**, based on the tale in which a tortoise (here a slow pointer) and a hare (here a faster pointer) make a race. +This algorithm is also known as **[tortoise and the hare algorithm]**, based on the tale in which a tortoise (here a slow pointer) and a hare (here a faster pointer) make a race. It is actually possible to determine the parameter $\lambda$ and $\mu$ using this algorithm (also in $O(\lambda + \mu)$ time and $O(1)$ space), but here is just the simplified version for finding the cycle at all. The algorithm and returns true as soon as it detects a cycle. From c94db367605921cd74f1cdc6c00a1a931b5cefd5 Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sun, 10 Sep 2023 10:06:32 +0200 Subject: [PATCH 156/590] Fix link --- src/algebra/factorization.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/algebra/factorization.md b/src/algebra/factorization.md index 4a7625e3c..fbd05ff12 100644 --- a/src/algebra/factorization.md +++ b/src/algebra/factorization.md @@ -271,7 +271,9 @@ In each iteration the first pointer advances to the next element, but the second It's not hard to see, that if there exists a cycle, the second pointer will make at least one full cycle and then meet the first pointer during the next few cycle loops. If the cycle length is $\lambda$ and the $\mu$ is the first index at which the cycle starts, then the algorithm will run in $O(\lambda + \mu)$ time. -This algorithm is also known as **[tortoise and the hare algorithm]**, based on the tale in which a tortoise (here a slow pointer) and a hare (here a faster pointer) make a race. +This algorithm is also known as the [Tortoise and Hare algorithm](data_structures/hare_tortoise_algorithm.md), based on the tale in which a tortoise (here a slow pointer) and a hare (here a faster pointer) make a race. + +src/data_structures/hare_tortoise_algorithm.md It is actually possible to determine the parameter $\lambda$ and $\mu$ using this algorithm (also in $O(\lambda + \mu)$ time and $O(1)$ space), but here is just the simplified version for finding the cycle at all. The algorithm and returns true as soon as it detects a cycle. From e788fd61e9e7f14b724a9fc11165cf4652939d57 Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sun, 10 Sep 2023 10:20:59 +0200 Subject: [PATCH 157/590] move tortoise and hare to others section --- src/algebra/factorization.md | 4 +--- src/navigation.md | 2 +- .../tortoise_and_hare.md} | 0 .../tortoise_hare_algo.png | Bin .../tortoise_hare_proof.png | Bin .../tortouse_hare_cycle_found.png | Bin 6 files changed, 2 insertions(+), 4 deletions(-) rename src/{data_structures/hare_tortoise_algorithm.md => others/tortoise_and_hare.md} (100%) rename src/{data_structures => others}/tortoise_hare_algo.png (100%) rename src/{data_structures => others}/tortoise_hare_proof.png (100%) rename src/{data_structures => others}/tortouse_hare_cycle_found.png (100%) diff --git a/src/algebra/factorization.md b/src/algebra/factorization.md index fbd05ff12..c7527feae 100644 --- a/src/algebra/factorization.md +++ b/src/algebra/factorization.md @@ -271,9 +271,7 @@ In each iteration the first pointer advances to the next element, but the second It's not hard to see, that if there exists a cycle, the second pointer will make at least one full cycle and then meet the first pointer during the next few cycle loops. If the cycle length is $\lambda$ and the $\mu$ is the first index at which the cycle starts, then the algorithm will run in $O(\lambda + \mu)$ time. -This algorithm is also known as the [Tortoise and Hare algorithm](data_structures/hare_tortoise_algorithm.md), based on the tale in which a tortoise (here a slow pointer) and a hare (here a faster pointer) make a race. - -src/data_structures/hare_tortoise_algorithm.md +This algorithm is also known as the [Tortoise and Hare algorithm](../others/tortoise_and_hare.md), based on the tale in which a tortoise (here a slow pointer) and a hare (here a faster pointer) make a race. It is actually possible to determine the parameter $\lambda$ and $\mu$ using this algorithm (also in $O(\lambda + \mu)$ time and $O(1)$ space), but here is just the simplified version for finding the cycle at all. The algorithm and returns true as soon as it detects a cycle. diff --git a/src/navigation.md b/src/navigation.md index e11a9e06b..7a1c1961f 100644 --- a/src/navigation.md +++ b/src/navigation.md @@ -50,7 +50,6 @@ search: - Fundamentals - [Minimum Stack / Minimum Queue](data_structures/stack_queue_modification.md) - [Sparse Table](data_structures/sparse-table.md) - - [Hare Tortoise Algorithm (Linked List cycle detection)](data_structures/hare_tortoise_algorithm.md) - Trees - [Disjoint Set Union](data_structures/disjoint_set_union.md) - [Fenwick Tree](data_structures/fenwick.md) @@ -212,6 +211,7 @@ search: - [Scheduling jobs on two machines](schedules/schedule_two_machines.md) - [Optimal schedule of jobs given their deadlines and durations](schedules/schedule-with-completion-duration.md) - Miscellaneous + - [Tortoise and Hare Algorithm (Linked List cycle detection)](others/tortoise_and_hare.md) - [Josephus problem](others/josephus_problem.md) - [15 Puzzle Game: Existence Of The Solution](others/15-puzzle.md) - [The Stern-Brocot Tree and Farey Sequences](others/stern_brocot_tree_farey_sequences.md) diff --git a/src/data_structures/hare_tortoise_algorithm.md b/src/others/tortoise_and_hare.md similarity index 100% rename from src/data_structures/hare_tortoise_algorithm.md rename to src/others/tortoise_and_hare.md diff --git a/src/data_structures/tortoise_hare_algo.png b/src/others/tortoise_hare_algo.png similarity index 100% rename from src/data_structures/tortoise_hare_algo.png rename to src/others/tortoise_hare_algo.png diff --git a/src/data_structures/tortoise_hare_proof.png b/src/others/tortoise_hare_proof.png similarity index 100% rename from src/data_structures/tortoise_hare_proof.png rename to src/others/tortoise_hare_proof.png diff --git a/src/data_structures/tortouse_hare_cycle_found.png b/src/others/tortouse_hare_cycle_found.png similarity index 100% rename from src/data_structures/tortouse_hare_cycle_found.png rename to src/others/tortouse_hare_cycle_found.png From 4cb750d759a69d199464efa5725f9511fcd59a93 Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sun, 10 Sep 2023 10:22:44 +0200 Subject: [PATCH 158/590] add tortoise and hare to new article section --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f3c76cabb..2bb00d5d4 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ Compiled pages are published at [https://cp-algorithms.com/](https://cp-algorith ### New articles +- (10 September 2023) [Tortoise and Hare Algorithm](https://cp-algorithms.com/others/tortoise_and_hare.html) - (12 July 2023) [Finding faces of a planar graph](https://cp-algorithms.com/geometry/planar.html) - (18 April 2023) [Bit manipulation](https://cp-algorithms.com/algebra/bit-manipulation.html) - (17 October 2022) [Binary Search](https://cp-algorithms.com/num_methods/binary_search.html) From b296cc4dbb58e88339e887d9db06194b6a4de93e Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sun, 10 Sep 2023 10:31:19 +0200 Subject: [PATCH 159/590] fix showing images --- src/others/tortoise_and_hare.md | 7 +++---- ...ycle_found.png => tortoise_hare_cycle_found.png} | Bin 2 files changed, 3 insertions(+), 4 deletions(-) rename src/others/{tortouse_hare_cycle_found.png => tortoise_hare_cycle_found.png} (100%) diff --git a/src/others/tortoise_and_hare.md b/src/others/tortoise_and_hare.md index 83fad231a..ba0240579 100644 --- a/src/others/tortoise_and_hare.md +++ b/src/others/tortoise_and_hare.md @@ -1,4 +1,3 @@ - --- tags: - Original @@ -8,7 +7,7 @@ tags: Given a linked list where the starting point of that linked list is denoted by **head**, and there may or may not be a cycle present. For instance: -![[tortoise_hare_algo.png]] +
!["Linked list with cycle"](tortoise_hare_algo.png)
Here we need to find out the point **C**, i.e the starting point of the cycle. @@ -28,7 +27,7 @@ So, it involved two steps: 6. If they point to any same node at any point of their journey, it would indicate that the cycle indeed exists in the linked list. 7. If we get null, it would indicate that the linked list has no cycle. -![[tortouse_hare_cycle_found.png]] +
!["Found cycle"](tortoise_hare_cycle_found.png)
Now, that we have figured out that there is a cycle present in the linked list, for the next step we need to find out the starting point of cycle, i.e., **C**. ### Step 2: Starting point of the cycle @@ -82,7 +81,7 @@ When the slow pointer has moved $k \cdot L$ steps, and the fast pointer has cove Lets try to calculate the distance covered by both of the pointers till they point they met within the cycle. -![[tortoise_hare_proof.png]] +
!["Proof"](tortoise_hare_proof.png)
$slowDist = a + xL + b$ $x\ge0$ diff --git a/src/others/tortouse_hare_cycle_found.png b/src/others/tortoise_hare_cycle_found.png similarity index 100% rename from src/others/tortouse_hare_cycle_found.png rename to src/others/tortoise_hare_cycle_found.png From eb09530f563e39c51c9c181fe9791f8166270083 Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sun, 10 Sep 2023 10:47:13 +0200 Subject: [PATCH 160/590] better proof image --- src/others/tortoise_hare_proof.png | Bin 27733 -> 32308 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/others/tortoise_hare_proof.png b/src/others/tortoise_hare_proof.png index 69e4fae343b09f38782bed2312c973a4f1d85bb6..bd62b57a26d44d9300904509df0bb231d877289c 100644 GIT binary patch literal 32308 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 Klq!=n4ER6cDhG}L literal 27733 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 Date: Tue, 12 Sep 2023 21:50:59 +0600 Subject: [PATCH 161/590] Refactor variable name Refactor variable name to align with written description --- src/algebra/binary-exp.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/algebra/binary-exp.md b/src/algebra/binary-exp.md index c57a66db3..52dfd27a5 100644 --- a/src/algebra/binary-exp.md +++ b/src/algebra/binary-exp.md @@ -144,13 +144,13 @@ vector applyPermutation(vector sequence, vector permutation) { return newSequence; } -vector permute(vector sequence, vector permutation, long long b) { - while (b > 0) { - if (b & 1) { +vector permute(vector sequence, vector permutation, long long k) { + while (k > 0) { + if (k & 1) { sequence = applyPermutation(sequence, permutation); } permutation = applyPermutation(permutation, permutation); - b >>= 1; + k >>= 1; } return sequence; } From 1348bc7abd4645d26addb15a3704e4c586879a32 Mon Sep 17 00:00:00 2001 From: Kanwae Kan <44528106+kanwaekan@users.noreply.github.com> Date: Wed, 13 Sep 2023 14:04:23 +0530 Subject: [PATCH 162/590] Added a comma for clarity --- src/others/tortoise_and_hare.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/others/tortoise_and_hare.md b/src/others/tortoise_and_hare.md index ba0240579..efe444273 100644 --- a/src/others/tortoise_and_hare.md +++ b/src/others/tortoise_and_hare.md @@ -83,9 +83,9 @@ Lets try to calculate the distance covered by both of the pointers till they poi
!["Proof"](tortoise_hare_proof.png)
-$slowDist = a + xL + b$ $x\ge0$ +$slowDist = a + xL + b$ , $x\ge0$ -$fastDist = a + yL + b$ $y\ge0$ +$fastDist = a + yL + b$ , $y\ge0$ - $slowDist$ is the total distance covered by slow pointer. - $fastDist$ is the total distance covered by fast pointer. From 64e7f287c10b411a25d0ec516537b68424075c23 Mon Sep 17 00:00:00 2001 From: Kanwae Kan <44528106+kanwaekan@users.noreply.github.com> Date: Wed, 13 Sep 2023 14:11:02 +0530 Subject: [PATCH 163/590] Minor error in Equation --- src/others/tortoise_and_hare.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/others/tortoise_and_hare.md b/src/others/tortoise_and_hare.md index efe444273..71405975e 100644 --- a/src/others/tortoise_and_hare.md +++ b/src/others/tortoise_and_hare.md @@ -94,7 +94,7 @@ $fastDist = a + yL + b$ , $y\ge0$ - $x$ is the number of times the slow pointer has looped inside the cycle, starting from and ending at **C**. - $y$ is the number of times the fast pointer has looped inside the cycle, starting from and ending at **C**. -$slowDist = 2 \cdot (fastDist)$ +$fastDist = 2 \cdot (slowDist)$ $a + yL + b = 2(a + xL + b)$ From d71651b14f3dc57c451ff7f467459a38770ecc7e Mon Sep 17 00:00:00 2001 From: fffelix-huang Date: Sat, 16 Sep 2023 22:08:10 +0800 Subject: [PATCH 164/590] Fix typos --- src/graph/bridge-searching-online.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/graph/bridge-searching-online.md b/src/graph/bridge-searching-online.md index da3af4402..702dc5a88 100644 --- a/src/graph/bridge-searching-online.md +++ b/src/graph/bridge-searching-online.md @@ -79,7 +79,7 @@ We will now consistently disassemble every operation that we need to learn to im For example you can re-root the tree of vertex $a$, and then attach it to another tree by setting the ancestor of $a$ to $b$. However the question about the effectiveness of the re-rooting operation arises: - in order to re-root the tree with the root $r$ to the vertex $v$, it is necessary to necessary to visit all vertices on the path between $v$ and $r$ and redirect the pointers `par[]` in the opposite direction, and also change the references to the ancestors in the DSU that is responsible for the connected components. + in order to re-root the tree with the root $r$ to the vertex $v$, it is necessary to visit all vertices on the path between $v$ and $r$ and redirect the pointers `par[]` in the opposite direction, and also change the references to the ancestors in the DSU that is responsible for the connected components. Thus, the cost of re-rooting is $O(h)$, where $h$ is the height of the tree. You can make an even worse estimate by saying that the cost is $O(\text{size})$ where $\text{size}$ is the number of vertices in the tree. @@ -103,7 +103,7 @@ We will now consistently disassemble every operation that we need to learn to im * Searching for the cycle formed by adding a new edge $(a, b)$. Since $a$ and $b$ are already connected in the tree we need to find the [Lowest Common Ancestor](lca.md) of the vertices $a$ and $b$. - The cycle will consist of the paths from $b$ to the LCA, from the LCA to $b$ and the edge $a$ to $b$. + The cycle will consist of the paths from $b$ to the LCA, from the LCA to $a$ and the edge $a$ to $b$. After finding the cycle we compress all vertices of the detected cycle into one vertex. This means that we already have a complexity proportional to the cycle length, which means that we also can use any LCA algorithm proportional to the length, and don't have to use any fast one. From 0b231a6f40847151deeb3d1f9fc24ba18e9ac49e Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sun, 17 Sep 2023 18:48:17 +0200 Subject: [PATCH 165/590] add problem to max flow --- src/graph/edmonds_karp.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/graph/edmonds_karp.md b/src/graph/edmonds_karp.md index 1b74cd3bb..29753eba1 100644 --- a/src/graph/edmonds_karp.md +++ b/src/graph/edmonds_karp.md @@ -213,3 +213,4 @@ This partition can be easily found using [DFS](depth-first-search.md) starting a - [CSES - Download Speed](https://cses.fi/problemset/task/1694) - [CSES - Police Chase](https://cses.fi/problemset/task/1695) - [CSES - School Dance](https://cses.fi/problemset/task/1696) +- [CSES - Distinct Routes](https://cses.fi/problemset/task/1711) From 9e76b3bb6709383fcb2b6ce4073a4a8e54f6853c Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sun, 17 Sep 2023 18:58:19 +0200 Subject: [PATCH 166/590] spelling --- src/data_structures/segment_tree.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data_structures/segment_tree.md b/src/data_structures/segment_tree.md index 67090a82e..1b212868b 100644 --- a/src/data_structures/segment_tree.md +++ b/src/data_structures/segment_tree.md @@ -602,7 +602,7 @@ This leads to a construction time of $O(n \log^2 n)$ (in general merging two red The $\text{query}$ function is also almost equivalent, only now the $\text{lower_bound}$ function of the $\text{multiset}$ function should be called instead ($\text{std::lower_bound}$ only works in $O(\log n)$ time if used with random-access iterators). Finally the modification request. -To process it, we must go down the tree, and modify all $\text{multiset}$ from the corresponding segments that contain the effected element. +To process it, we must go down the tree, and modify all $\text{multiset}$ from the corresponding segments that contain the affected element. We simply delete the old value of this element (but only one occurrence), and insert the new value. ```cpp @@ -682,7 +682,7 @@ other Segment Trees (somewhat discussed in [Generalization to higher dimensions] ### Range updates (Lazy Propagation) -All problems in the above sections discussed modification queries that only effected a single element of the array each. +All problems in the above sections discussed modification queries that only affected a single element of the array each. However the Segment Tree allows applying modification queries to an entire segment of contiguous elements, and perform the query in the same time $O(\log n)$. #### Addition on segments From 3a91b300823acc6e31f061c43a8f06fc0039e7cb Mon Sep 17 00:00:00 2001 From: 100GODMOON <86097037+100godmoon@users.noreply.github.com> Date: Mon, 18 Sep 2023 00:08:26 +0530 Subject: [PATCH 167/590] Update binary_search.md Added more problems on binary search article #1147 --- src/num_methods/binary_search.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/num_methods/binary_search.md b/src/num_methods/binary_search.md index a95db3c32..f44809c2e 100644 --- a/src/num_methods/binary_search.md +++ b/src/num_methods/binary_search.md @@ -138,6 +138,10 @@ This paradigm is widely used in tasks around trees, such as finding lowest commo * [LeetCode - Find First and Last Position of Element in Sorted Array](https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/) * [LeetCode - Search Insert Position](https://leetcode.com/problems/search-insert-position/) +* [LeetCode - Find Peak Element](https://leetcode.com/problems/find-peak-element/) +* [LeetCode - Search in Rotated Sorted Array](https://leetcode.com/problems/search-in-rotated-sorted-array/) +* [LeetCode - Find the Duplicate Number](https://leetcode.com/problems/find-the-duplicate-number/) +* [LeetCode - Find Right Interval](https://leetcode.com/problems/find-right-interval/) * [LeetCode - Sqrt(x)](https://leetcode.com/problems/sqrtx/) * [LeetCode - First Bad Version](https://leetcode.com/problems/first-bad-version/) * [LeetCode - Valid Perfect Square](https://leetcode.com/problems/valid-perfect-square/) From afe32e8a6766be3d0eddcf97c2cdf3e71ae5655a Mon Sep 17 00:00:00 2001 From: JustAnAverageGuy <68919330+JustAnAverageGuy@users.noreply.github.com> Date: Fri, 22 Sep 2023 16:47:11 +0530 Subject: [PATCH 168/590] Update point-location.md Changed an incorrect double negative typo to the intended meaning. --- src/geometry/point-location.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/geometry/point-location.md b/src/geometry/point-location.md index 4c9ca883d..10c0d3f51 100644 --- a/src/geometry/point-location.md +++ b/src/geometry/point-location.md @@ -5,7 +5,7 @@ tags: --- # Point location in $O(log n)$ -Consider the following problem: you are given a [planar subdivision](https://en.wikipedia.org/wiki/Planar_straight-line_graph) without no vertices of degree one and zero, and a lot of queries. +Consider the following problem: you are given a [planar subdivision](https://en.wikipedia.org/wiki/Planar_straight-line_graph) without any vertices of degree one and zero, and a lot of queries. Each query is a point, for which we should determine the face of the subdivision it belongs to. We will answer each query in $O(\log n)$ offline.
This problem may arise when you need to locate some points in a Voronoi diagram or in some simple polygon. From 44c507ea63e13543f7dcf34192c6daa32cdac829 Mon Sep 17 00:00:00 2001 From: sumitrawat10 <47861908+sumitrawat10@users.noreply.github.com> Date: Sat, 23 Sep 2023 22:18:18 +0530 Subject: [PATCH 169/590] Update 2SAT.md Just a typo --- src/graph/2SAT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graph/2SAT.md b/src/graph/2SAT.md index f22da73f6..ac8b83446 100644 --- a/src/graph/2SAT.md +++ b/src/graph/2SAT.md @@ -14,7 +14,7 @@ Find an assignment of $a, b, c$ such that the following formula is true: $$(a \lor \lnot b) \land (\lnot a \lor b) \land (\lnot a \lor \lnot b) \land (a \lor \lnot c)$$ -SAT is NP-complete, there is no known efficient solution known for it. +SAT is NP-complete, there is no known efficient solution for it. However 2SAT can be solved efficiently in $O(n + m)$ where $n$ is the number of variables and $m$ is the number of clauses. ## Algorithm: From 79b311ae29026b2ab2e6ec323b28d1d0d027ceb6 Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sun, 24 Sep 2023 19:24:14 +0200 Subject: [PATCH 170/590] remove navigation tracking fixes #1153 --- mkdocs.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index 4403365d6..8a049c265 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -22,7 +22,6 @@ theme: icon: repo: fontawesome/brands/github features: - - navigation.tracking - navigation.tabs - toc.integrate - search.suggest From 6337369b623699506735fd6a547af519f325fb11 Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sun, 24 Sep 2023 19:32:19 +0200 Subject: [PATCH 171/590] enable permalink next to sections --- mkdocs.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mkdocs.yml b/mkdocs.yml index 8a049c265..c6b402e5e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -52,6 +52,8 @@ markdown_extensions: emoji_index: !!python/name:materialx.emoji.twemoji emoji_generator: !!python/name:materialx.emoji.to_svg - meta + - toc: + permalink: true plugins: - mkdocs-simple-hooks: From 3af207a4c444520870e2b3ef3003bdc5201ac782 Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sun, 24 Sep 2023 19:37:38 +0200 Subject: [PATCH 172/590] move practice problem to the binary lifting article --- src/graph/lca_binary_lifting.md | 1 + src/num_methods/binary_search.md | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graph/lca_binary_lifting.md b/src/graph/lca_binary_lifting.md index e8f51dc94..72b47291a 100644 --- a/src/graph/lca_binary_lifting.md +++ b/src/graph/lca_binary_lifting.md @@ -95,4 +95,5 @@ void preprocess(int root) { ``` ## Practice Problems +* [LeetCode - Kth Ancestor of a Tree Node](https://leetcode.com/problems/kth-ancestor-of-a-tree-node) * [Codechef - Longest Good Segment](https://www.codechef.com/problems/LGSEG) diff --git a/src/num_methods/binary_search.md b/src/num_methods/binary_search.md index 31332a209..a95db3c32 100644 --- a/src/num_methods/binary_search.md +++ b/src/num_methods/binary_search.md @@ -143,7 +143,6 @@ This paradigm is widely used in tasks around trees, such as finding lowest commo * [LeetCode - Valid Perfect Square](https://leetcode.com/problems/valid-perfect-square/) * [LeetCode - Guess Number Higher or Lower](https://leetcode.com/problems/guess-number-higher-or-lower/) * [LeetCode - Search a 2D Matrix II](https://leetcode.com/problems/search-a-2d-matrix-ii/) -* [LeetCode - Kth Ancestor of a Tree Node](https://leetcode.com/problems/kth-ancestor-of-a-tree-node) * [Codeforces - Interesting Drink](https://codeforces.com/problemset/problem/706/B/) * [Codeforces - Magic Powder - 1](https://codeforces.com/problemset/problem/670/D1) * [Codeforces - Another Problem on Strings](https://codeforces.com/problemset/problem/165/C) From 7935df482fb2c8fe7e239851bdb6c4ddad5d116f Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sun, 24 Sep 2023 19:42:01 +0200 Subject: [PATCH 173/590] fix some absolute links --- src/data_structures/sqrt-tree.md | 2 +- src/others/josephus_problem.md | 2 +- src/string/manacher.md | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/data_structures/sqrt-tree.md b/src/data_structures/sqrt-tree.md index 0bfefe772..19e8bc6e4 100644 --- a/src/data_structures/sqrt-tree.md +++ b/src/data_structures/sqrt-tree.md @@ -17,7 +17,7 @@ Sqrt Tree can process such queries in $O(1)$ time with $O(n \cdot \log \log n)$ ### Building sqrt decomposition -Let's make a [sqrt decomposition](/data_structures/sqrt_decomposition.html). We divide our array in $\sqrt{n}$ blocks, each block has size $\sqrt{n}$. For each block, we compute: +Let's make a [sqrt decomposition](sqrt_decomposition.md). We divide our array in $\sqrt{n}$ blocks, each block has size $\sqrt{n}$. For each block, we compute: 1. Answers to the queries that lie in the block and begin at the beginning of the block ($\text{prefixOp}$) 2. Answers to the queries that lie in the block and end at the end of the block ($\text{suffixOp}$) diff --git a/src/others/josephus_problem.md b/src/others/josephus_problem.md index 3599034eb..5200d0ad4 100644 --- a/src/others/josephus_problem.md +++ b/src/others/josephus_problem.md @@ -18,7 +18,7 @@ It is required to find the last number. This task was set by **Flavius Josephus** in the 1st century (though in a somewhat narrower formulation: for $k = 2$). This problem can be solved by modeling the procedure. -Brute force modeling will work $O(n^{2})$. Using a [Segment Tree](/data_structures/segment_tree.html), we can improve it to $O(n \log n)$. +Brute force modeling will work $O(n^{2})$. Using a [Segment Tree](../data_structures/segment_tree.md), we can improve it to $O(n \log n)$. We want something better though. ## Modeling a $O(n)$ solution diff --git a/src/string/manacher.md b/src/string/manacher.md index 78e0c677d..2c7cb35b6 100644 --- a/src/string/manacher.md +++ b/src/string/manacher.md @@ -32,7 +32,7 @@ It's a surprising fact that there is an algorithm, which is simple enough, that ## Solution -In general, this problem has many solutions: with [String Hashing](/string/string-hashing.html) it can be solved in $O(n\cdot \log n)$, and with [Suffix Trees](/string/suffix-tree-ukkonen.html) and fast LCA this problem can be solved in $O(n)$. +In general, this problem has many solutions: with [String Hashing](string-hashing.md) it can be solved in $O(n\cdot \log n)$, and with [Suffix Trees](suffix-tree-ukkonen.md) and fast LCA this problem can be solved in $O(n)$. But the method described here is **sufficiently** simpler and has less hidden constant in time and memory complexity. This algorithm was discovered by **Glenn K. Manacher** in 1975. @@ -124,7 +124,7 @@ Again, we should not forget to update the values $(l, r)$ after calculating each At the first glance it's not obvious that this algorithm has linear time complexity, because we often run the naive algorithm while searching the answer for a particular position. -However, a more careful analysis shows that the algorithm is linear. In fact, [Z-function building algorithm](/string/z-function.html), which looks similar to this algorithm, also works in linear time. +However, a more careful analysis shows that the algorithm is linear. In fact, [Z-function building algorithm](z-function.md), which looks similar to this algorithm, also works in linear time. We can notice that every iteration of trivial algorithm increases $r$ by one. Also $r$ cannot be decreased during the algorithm. So, trivial algorithm will make $O(n)$ iterations in total. From db087ac079f24c2b1eca58ac4dc0e7c88b0642fc Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sun, 24 Sep 2023 20:22:52 +0200 Subject: [PATCH 174/590] remove some problems --- src/num_methods/binary_search.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/num_methods/binary_search.md b/src/num_methods/binary_search.md index f44809c2e..6aa488729 100644 --- a/src/num_methods/binary_search.md +++ b/src/num_methods/binary_search.md @@ -138,15 +138,11 @@ This paradigm is widely used in tasks around trees, such as finding lowest commo * [LeetCode - Find First and Last Position of Element in Sorted Array](https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/) * [LeetCode - Search Insert Position](https://leetcode.com/problems/search-insert-position/) +* [LeetCode - First Bad Version](https://leetcode.com/problems/first-bad-version/) +* [LeetCode - Valid Perfect Square](https://leetcode.com/problems/valid-perfect-square/) * [LeetCode - Find Peak Element](https://leetcode.com/problems/find-peak-element/) * [LeetCode - Search in Rotated Sorted Array](https://leetcode.com/problems/search-in-rotated-sorted-array/) -* [LeetCode - Find the Duplicate Number](https://leetcode.com/problems/find-the-duplicate-number/) * [LeetCode - Find Right Interval](https://leetcode.com/problems/find-right-interval/) -* [LeetCode - Sqrt(x)](https://leetcode.com/problems/sqrtx/) -* [LeetCode - First Bad Version](https://leetcode.com/problems/first-bad-version/) -* [LeetCode - Valid Perfect Square](https://leetcode.com/problems/valid-perfect-square/) -* [LeetCode - Guess Number Higher or Lower](https://leetcode.com/problems/guess-number-higher-or-lower/) -* [LeetCode - Search a 2D Matrix II](https://leetcode.com/problems/search-a-2d-matrix-ii/) * [Codeforces - Interesting Drink](https://codeforces.com/problemset/problem/706/B/) * [Codeforces - Magic Powder - 1](https://codeforces.com/problemset/problem/670/D1) * [Codeforces - Another Problem on Strings](https://codeforces.com/problemset/problem/165/C) From 1810d127f6f075ad47db88b3fc49d477dc2cb2e9 Mon Sep 17 00:00:00 2001 From: Jakob Kogler Date: Sun, 24 Sep 2023 20:27:05 +0200 Subject: [PATCH 175/590] fix broken link --- src/preview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/preview.md b/src/preview.md index 775d4fe87..e0ffe3866 100644 --- a/src/preview.md +++ b/src/preview.md @@ -29,7 +29,7 @@ # Article Preview -
Information for contributors +Information for contributors