├── codes ├── uncategorized │ ├── queue.cpp │ ├── coordinate_compression.cpp │ ├── merge_inversion_count.cpp │ ├── lis.cpp │ ├── MosQueryDecomposition.cpp │ ├── lis2d.cpp │ └── TwoStackQueue.cpp ├── math_nt │ ├── binomial_fac.cpp │ ├── sum_of_divisors.cpp │ ├── binomial_dp.cpp │ ├── count_prime_factors.cpp │ ├── count_divisors.cpp │ ├── KthPermutation.cpp │ ├── totient.cpp │ ├── discrete_log.cpp │ ├── xor_basis.cpp │ ├── matrix_exponentiation.cpp │ ├── miller_rabin.cpp │ ├── lagrange_modular.cpp │ ├── sieve.cpp │ ├── ntt.cpp │ ├── crt_diophantine.cpp │ ├── simplex.cpp │ ├── fft.cpp │ └── fast_multipoint.cpp ├── data_structures │ ├── Trie.cpp │ ├── ordered_set.cpp │ ├── bit2d.cpp │ ├── bipartite_dsu.cpp │ ├── bit.cpp │ ├── sparse_table.cpp │ ├── PersistentSegmentTree.cpp │ ├── min_lichao_cht.cpp │ ├── min_lichao_dbl_cht.cpp │ ├── max_cht.cpp │ ├── segment_tree.cpp │ ├── RangeUpdateDynamicSegmentTree.cpp │ ├── DynamicSegmentTree.cpp │ ├── splay_tree.cpp │ └── ImplicitTreap.cpp ├── strings │ ├── z_function.cpp │ ├── kmp.cpp │ ├── rolling_hash.cpp │ ├── manacher.cpp │ ├── aho_corasick.cpp │ ├── suffix_array.cpp │ └── SuffixAutomata.cpp ├── graphs │ ├── bellman_ford.cpp │ ├── floyd_warshall.cpp │ ├── MinPathCover.cpp │ ├── tarjan.cpp │ ├── StoerWagner.cpp │ ├── 2-sat.cpp │ ├── BlockCutTree.cpp │ ├── lca.cpp │ ├── centroid_decomp.cpp │ ├── scc.cpp │ ├── dominator_tree.cpp │ ├── euler.cpp │ ├── hld.cpp │ ├── Dynacon.cpp │ └── dinic.cpp └── geometry │ ├── vector3d.cpp │ ├── vector2d.cpp │ ├── geo2d_structures.cpp │ ├── convex_hull.cpp │ └── geo2d_functions.cpp └── README.md /codes/uncategorized/queue.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct Queue { 3 | vector queue; 4 | int top = 0; 5 | int size() { return (int)queue.size() - top; } 6 | bool empty() { return size() == 0; } 7 | void push(T item) { queue.push_back(item); } 8 | T get() { 9 | assert(!empty()); 10 | return queue[top++]; 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /codes/math_nt/binomial_fac.cpp: -------------------------------------------------------------------------------- 1 | namespace NT { 2 | vector fat; 3 | vector ifat; 4 | 5 | void precalculate(int n) { 6 | fat.resize(n + 1, 1); 7 | ifat.resize(n + 1, 1); 8 | for (int i = 1; i <= n; i++) { 9 | fat[i] = mod(fat[i - 1] * i); 10 | ifat[i] = exp(fat[i], M - 2); 11 | } 12 | } 13 | 14 | int C(int n, int k) { 15 | if (n < k) return 0; 16 | return mod(mod(fat[n] * ifat[n - k]) * ifat[k]); 17 | } 18 | } // namespace Combinatorics 19 | -------------------------------------------------------------------------------- /codes/math_nt/sum_of_divisors.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Sum of Divisors 3 | */ 4 | 5 | namespace NT { 6 | 7 | int SumOfDivisors(int a, int b) { 8 | int m = sqrt(b); 9 | int s = 0; 10 | for (int f = 1; f <= m; f++) { 11 | int x = (b / f) * (b / f) - max(m, (a - 1) / f) * max(m, (a - 1) / f) + 12 | (b / f) - max(m, (a - 1) / f); 13 | s += f * (b / f - (a - 1) / f); 14 | s += x / 2; 15 | } 16 | return s; 17 | } 18 | 19 | } // namespace NT 20 | -------------------------------------------------------------------------------- /codes/math_nt/binomial_dp.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Binomial Coefficient 3 | */ 4 | 5 | /* Dynammic Programming for Binomial Coefficient Calculation */ 6 | /* Using Stiefel Rule C(n, k) = C(n-1, k) + C(n-1, k-1) */ 7 | 8 | int binomial(int n, int k) { 9 | int c[n + 10][k + 10]; 10 | memset(c, 0, sizeof c); 11 | c[0][0] = 1; 12 | for (int i = 1; i <= n; i++) { 13 | for (int j = min(i, k); j > 0; j--) { 14 | c[i][j] = c[i - 1][j] + c[i - 1][j - 1]; 15 | } 16 | } 17 | return c[n][k]; 18 | } 19 | -------------------------------------------------------------------------------- /codes/math_nt/count_prime_factors.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Count Prime Factors 3 | */ 4 | 5 | namespace NT { 6 | 7 | int CountPrimeFactors(int x) { 8 | int ans = 0; 9 | for (int i = 2; i * i * i <= x; i++) { 10 | while (x % i == 0) { 11 | ans++; 12 | x /= i; 13 | } 14 | } 15 | 16 | if (PrimalityTest(x, 10)) 17 | ans++; 18 | else if ((int)sqrt(x) * (int)sqrt(x) == x && PrimalityTest((int)sqrt(x), 10)) 19 | ans += 2; 20 | else if (x != 1) 21 | ans += 2; 22 | 23 | return ans; 24 | } 25 | 26 | } // namespace NT 27 | -------------------------------------------------------------------------------- /codes/math_nt/count_divisors.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Count Divisors 3 | */ 4 | 5 | namespace NT { 6 | 7 | int CountDivisors(int x) { 8 | int ans = 1; 9 | for (int i = 2; i * i * i <= x; i++) { 10 | int cnt = 1; 11 | while (x % i == 0) { 12 | cnt++; 13 | x /= i; 14 | } 15 | ans *= cnt; 16 | } 17 | 18 | if (PrimalityTest(x, 15)) 19 | ans *= 2; 20 | else if ((int)sqrt(x) * (int)sqrt(x) == x && PrimalityTest((int)sqrt(x), 15)) 21 | ans *= 3; 22 | else if (x != 1) 23 | ans *= 4; 24 | 25 | return ans; 26 | } 27 | 28 | } // namespace NT 29 | -------------------------------------------------------------------------------- /codes/data_structures/Trie.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Neto 2 | * Trie structure example 3 | */ 4 | namespace Trie { 5 | const int SIZE_NODE = 26; 6 | struct node { 7 | node *adj[SIZE_NODE]; 8 | node() { 9 | for (int i = 0; i < SIZE_NODE; i++) adj[i] = nullptr; 10 | } 11 | }; 12 | 13 | struct Tree { 14 | node *t; 15 | 16 | Tree() { t = new node(); } 17 | 18 | void add() { 19 | node *cur = t; 20 | // add logic here 21 | } 22 | 23 | int query() { 24 | node *cur = t; 25 | // add logic here 26 | } 27 | 28 | void remove() { 29 | node *cur = t; 30 | // add logic here 31 | } 32 | }; 33 | 34 | } // namespace Trie 35 | -------------------------------------------------------------------------------- /codes/math_nt/KthPermutation.cpp: -------------------------------------------------------------------------------- 1 | /* Find the k-th permutation of numbers from [1..n] */ 2 | /* Be careful: n <= 19 */ 3 | vi find_permutation(int n, int k) { 4 | int fat[n]; 5 | fat[0] = 1; 6 | for (int i = 1; i < n; i++) fat[i] = fat[i - 1] * i; 7 | vi arr(n); 8 | iota(all(arr), 1); 9 | vi fatoriadic; 10 | for (int cur = k, i = 1; i <= n; i++) { 11 | fatoriadic.pb(cur % i); 12 | cur /= i; 13 | } 14 | reverse(all(fatoriadic)); 15 | vi ans; 16 | for (int x : fatoriadic) { 17 | ans.pb(arr[x]); 18 | vi new_arr; 19 | for (int y : arr) 20 | if (y != arr[x]) new_arr.pb(y); 21 | swap(arr, new_arr); 22 | } 23 | return ans; 24 | } 25 | -------------------------------------------------------------------------------- /codes/strings/z_function.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Z Function 3 | */ 4 | 5 | /* Calculate the size K of the largest substring which is a prefix */ 6 | 7 | struct ZFunction { 8 | vector z; 9 | 10 | ZFunction() {} 11 | 12 | void calculate(string t) { 13 | int n = t.size(); 14 | z.resize(n); 15 | z[0] = 0; 16 | int l = 0, r = 0; 17 | for (int i = 1; i < n; i++) { 18 | if (i > r) { 19 | l = i; 20 | r = i; 21 | } 22 | z[i] = min(z[i - l], r - i + 1); 23 | while (i + z[i] < n && t[i + z[i]] == t[z[i]]) z[i]++; 24 | if (i + z[i] > r) { 25 | l = i; 26 | r = i + z[i] - 1; 27 | } 28 | } 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /codes/uncategorized/coordinate_compression.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Coordinate Compression 3 | */ 4 | 5 | struct Compresser { 6 | vector original; 7 | map comp; 8 | Compresser() {} 9 | 10 | Compresser(int n) { original.resize(n, -1); } 11 | 12 | void compress(vector& v) { 13 | vector tmp; 14 | set s; 15 | for (int i = 0; i < v.size(); i++) s.insert(v[i]); 16 | for (int x : s) tmp.pb(x); 17 | for (int i = 0; i < v.size(); i++) { 18 | int idx = lower_bound(tmp.begin(), tmp.end(), v[i]) - tmp.begin(); 19 | original[idx] = v[i]; 20 | v[i] = idx; 21 | comp[v[i]] = idx; 22 | } 23 | } 24 | 25 | } compresser; 26 | -------------------------------------------------------------------------------- /codes/math_nt/totient.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Euler's Totient 3 | */ 4 | 5 | namespace NT { 6 | 7 | const int MAX_TOT = 1123456; 8 | 9 | int totient[MAX_TOT]; 10 | 11 | void EulerTotient(int n) { 12 | for (int i = 0; i <= n; i++) totient[i] = i; 13 | for (int p = 2; p <= n; p++) { 14 | if (totient[p] == p) { 15 | totient[p] = p - 1; 16 | for (int i = p + p; i <= n; i += p) { 17 | totient[i] = (totient[i] / p) * (p - 1); 18 | } 19 | } 20 | } 21 | } 22 | 23 | int SingleTotient(int x) { 24 | int ans = x; 25 | for (int i = 2; i * i <= x; i++) { 26 | if (x % i == 0) { 27 | while (x % i == 0) x /= i; 28 | ans -= ans / i; 29 | } 30 | } 31 | if (x > 1) ans -= ans / x; 32 | return ans; 33 | } 34 | 35 | }; // namespace NT 36 | -------------------------------------------------------------------------------- /codes/strings/kmp.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Knuth - Morris - Pratt Algorithm 3 | */ 4 | 5 | struct KMP { 6 | vector pi; 7 | 8 | vector matches; 9 | 10 | KMP() {} 11 | 12 | void calculate(string t) { 13 | int n = t.size(); 14 | pi.resize(n); 15 | pi[0] = 0; 16 | for (int i = 1; i < n; i++) { 17 | pi[i] = pi[i - 1]; 18 | while (pi[i] > 0 && t[i] != t[pi[i]]) pi[i] = pi[pi[i] - 1]; 19 | if (t[i] == t[pi[i]]) pi[i]++; 20 | } 21 | } 22 | 23 | void matching(string s) { 24 | int j = 0; 25 | int n = s.size(); 26 | for (int i = 0; i < n; i++) { 27 | while (j > 0 && s[i] != t[j]) j = pi[j - 1]; 28 | if (s[i] == t[j]) j++; 29 | if (j == t.size()) { 30 | matches.push_back(i - t.size() + 1); 31 | j = pi[j - 1]; 32 | } 33 | } 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /codes/uncategorized/merge_inversion_count.cpp: -------------------------------------------------------------------------------- 1 | namespace Sorting { 2 | 3 | /* Merge Sort + Inversion Count */ 4 | int merge(vector &a, vector &b, int l, int mid, int r) { 5 | int ans = 0; 6 | int k = mid + 1; 7 | for (int i = l; i <= r; i++) { 8 | if (l <= mid && (k > r || a[l] <= a[k])) { 9 | b[i] = a[l++]; 10 | } else { 11 | ans += mid - l + 1; 12 | b[i] = a[k++]; 13 | } 14 | } 15 | return ans; 16 | } 17 | int merge_sort(vector &a, vector &b, int l, int r) { 18 | if (l == r) return 0; 19 | int mid = l + r >> 1; 20 | return merge_sort(b, a, l, mid) + merge_sort(b, a, mid + 1, r) + 21 | merge(a, b, l, mid, r); 22 | } 23 | int MergeSort(vector &a) { 24 | vector b = a; 25 | return merge_sort(b, a, 0, a.size() - 1); 26 | } 27 | /* Merge Sort + Inversion Count */ 28 | 29 | } // namespace Sorting 30 | -------------------------------------------------------------------------------- /codes/data_structures/ordered_set.cpp: -------------------------------------------------------------------------------- 1 | // INCLUDES 2 | #include 3 | #include 4 | 5 | // NAMESPACE 6 | using namespace __gnu_pbds; 7 | 8 | typedef tree to use like multiset 9 | null_type, 10 | less, // change for pair to use like multiset 11 | rb_tree_tag, tree_order_statistics_node_update> 12 | ordered_set; 13 | 14 | // int differ = 0; for multiset 15 | 16 | // ordered_set myset; //declares a stl ordered set 17 | // myset.insert(1); //inserts 18 | // myset.insert(make_pair(1, differ++)); //insertion for multiset 19 | // myset.find_by_order(k)//returns an iterator to the k-th element (or returns 20 | // the end) myset.order_of_key(x)//returns the number of elements strictly less 21 | // than x myset.order_of_key(myset.lower_bound(make_pair(x, 0))) //for multisets 22 | -------------------------------------------------------------------------------- /codes/data_structures/bit2d.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Neto 2 | * 3 | */ 4 | 5 | struct BIT2D { 6 | vector > bit; 7 | 8 | int n, m; 9 | 10 | BIT2D() {} 11 | 12 | BIT2D(int n, int m) { 13 | bit.resize(n + 1, vector(m + 1)); 14 | this->n = n; 15 | this->m = m; 16 | } 17 | 18 | void update(int x, int y, int val) { 19 | for (int i = x; i <= n; i += i & -i) { 20 | for (int j = y; j <= m; j += j & -j) { 21 | bit[i][j] += val; 22 | } 23 | } 24 | } 25 | 26 | int prefix_query(int x, int y) { 27 | int ans = 0; 28 | for (int i = x; i > 0; i -= i & -i) { 29 | for (int j = y; j > 0; j -= j & -j) { 30 | ans += bit[i][j]; 31 | } 32 | } 33 | return ans; 34 | } 35 | 36 | int query(int x1, int y1, int x2, int y2) { 37 | return prefix_query(x2, y2) + prefix_query(x1 - 1, y1 - 1) - 38 | prefix_query(x2, y1 - 1) - prefix_query(x1 - 1, y2); 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /codes/graphs/bellman_ford.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Bellman Ford 3 | */ 4 | 5 | struct BellmanFord { 6 | struct edges { 7 | int u, v, weight; 8 | edges(int u, int v, int weight) : u(u), v(v), weight(weight) {} 9 | }; 10 | 11 | vector dist; 12 | 13 | bool cycle = false; 14 | 15 | BellmanFord() {} 16 | 17 | BellmanFord(int n) { dist.resize(n + 1); } 18 | 19 | void calculate(int source) { 20 | for (int i = 0; i < dist.size(); i++) { 21 | dist[i] = INF; 22 | } 23 | dist[source] = 0; 24 | for (int k = 0; k < dist.size() - 1; k++) { 25 | for (int i = 0; i < e.size(); i++) { 26 | if (dist[e[i].v] > dist[e[i].u] + e[i].weight) { 27 | dist[e[i].v] = dist[e[i].u] + e[i].weight; 28 | } 29 | } 30 | } 31 | for (int i = 0; i < e.size(); i++) { 32 | if (dist[e[i].v] > dist[e[i].u] + e[i].weight) { 33 | cycle = true; 34 | } 35 | } 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /codes/data_structures/bipartite_dsu.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Neto */ 2 | /* DSU to check bipartite properties on graphs */ 3 | /* d[] means depth of node relative to the root of group */ 4 | 5 | struct BipartiteDSU { 6 | vector uf, d, sz; 7 | 8 | BipartiteDSU(int n) { 9 | uf.resize(n + 1); 10 | sz.resize(n + 1); 11 | d.resize(n + 1); 12 | for (int i = 0; i <= n; i++) { 13 | uf[i] = i; 14 | sz[i] = 1; 15 | d[i] = 0; 16 | } 17 | } 18 | 19 | ii get(int x) { 20 | if (uf[x] == x) { 21 | return ii(x, 0); 22 | } 23 | ii ans = get(uf[x]); 24 | d[x] = d[x] + ans.ss; 25 | uf[x] = ans.ff; 26 | return ii(uf[x], d[x]); 27 | } 28 | 29 | bool merge(int a, int b) { 30 | auto x = get(a), y = get(b); 31 | if (x.ff == y.ff) return false; 32 | if (sz[x.ff] < sz[y.ff]) swap(x, y); 33 | uf[y.ff] = x.ff; 34 | sz[x.ff] += sz[y.ff]; 35 | d[y.ff] = y.ss + x.ss + 1; 36 | return true; 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /codes/math_nt/discrete_log.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Baby-Step Giant-Step Shank's Algorithm 3 | */ 4 | 5 | namespace NT { 6 | 7 | int discrete_log(int a, int b, int p) { 8 | a %= p, b %= p; 9 | 10 | if (b == 1) return 0; 11 | 12 | int cnt = 0, t = 1; 13 | for (int g = gcd(a, p); g != 1; g = gcd(a, p)) { 14 | if (b % g) return -1; 15 | 16 | p /= g, b /= g, t = t * a / g % p; 17 | cnt++; 18 | 19 | if (b == t) return cnt; 20 | } 21 | 22 | map hash; 23 | int m = (sqrt(p) + 1); 24 | int base = b; 25 | 26 | for (int i = 0; i != m; ++i) { 27 | hash[base] = i; 28 | base = base * a % p; 29 | } 30 | 31 | base = 1; 32 | for (int i = 0; i < m; i++) { 33 | base = (base * a) % p; 34 | } 35 | 36 | int cur = t; 37 | for (int i = 1; i <= m + 1; ++i) { 38 | cur = cur * base % p; 39 | if (hash.count(cur)) return i * m - hash[cur] + cnt; 40 | } 41 | return -1; 42 | } 43 | 44 | } // namespace NT 45 | -------------------------------------------------------------------------------- /codes/data_structures/bit.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Neto 2 | * 3 | */ 4 | 5 | struct BIT { 6 | vector bit; 7 | 8 | BIT() {} 9 | 10 | int n; 11 | 12 | BIT(int n) { 13 | this->n = n; 14 | bit.resize(n + 1); 15 | } 16 | 17 | void update(int idx, int val) { 18 | for (int i = idx; i <= n; i += i & -i) { 19 | bit[i] += val; 20 | } 21 | } 22 | 23 | int prefix_query(int idx) { 24 | int ans = 0; 25 | for (int i = idx; i > 0; i -= i & -i) { 26 | ans += bit[i]; 27 | } 28 | return ans; 29 | } 30 | 31 | int query(int l, int r) { return prefix_query(r) - prefix_query(l - 1); } 32 | 33 | // int bit 0-1 it finds the index of k-th element active 34 | int kth(int k) { 35 | int cur = 0; 36 | int acc = 0; 37 | for (int i = 19; i >= 0; i--) { 38 | if (cur + (1 << i) > n) continue; 39 | if (acc + bit[cur + (1 << i)] < k) { 40 | cur += (1 << i); 41 | acc += bit[cur]; 42 | } 43 | } 44 | return ++cur; 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /codes/graphs/floyd_warshall.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Floyd Warshall 3 | */ 4 | 5 | struct FloydWarshall { 6 | vector > > dist; 7 | 8 | FloydWarshall() {} 9 | 10 | FloydWarshall(int n) { 11 | dist.resize(n + 1, vector >(n + 1, vector(n + 1))); 12 | } 13 | 14 | void relax(int i, int j, int k) { 15 | dist[k][i][j] = 16 | min(dist[k - 1][i][j], dist[k - 1][i][k] + dist[k - 1][k][j]); 17 | } 18 | 19 | void calculate() { 20 | for (int k = 0; k < dist.size(); k++) { 21 | for (int i = 1; i < dist.size(); i++) { 22 | for (int j = 1; j < dist.size(); j++) { 23 | if (i == j) 24 | dist[k][i][j] = 0; 25 | else 26 | dist[k][i][j] = INF; 27 | } 28 | } 29 | } 30 | for (int k = 1; k < dist.size(); k++) { 31 | for (int i = 1; i < dist.size(); i++) { 32 | for (int j = 1; j < dist.size(); j++) { 33 | relax(i, j, k); 34 | } 35 | } 36 | } 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /codes/math_nt/xor_basis.cpp: -------------------------------------------------------------------------------- 1 | struct XorBasis { 2 | #define BASIS_SIZE 60 3 | using BitArray = bitset; 4 | 5 | vector basis; 6 | 7 | XorBasis() { basis.resize(BASIS_SIZE, BitArray(0)); } 8 | 9 | int get_msb(BitArray x) { 10 | for (int i = BASIS_SIZE - 1; i >= 0; i--) { 11 | if (x[i]) return i; 12 | } 13 | return -1; 14 | } 15 | 16 | bool add(BitArray x) { 17 | for (int i = BASIS_SIZE - 1; i >= 0; i--) { 18 | if (basis[i].none()) continue; 19 | if (get_msb(x) == i) { 20 | x ^= basis[i]; 21 | } 22 | } 23 | if (x != 0) { 24 | basis[get_msb(x)] = x; 25 | return true; 26 | } 27 | return false; 28 | } 29 | 30 | bool has(BitArray x) { 31 | for (int i = BASIS_SIZE - 1; i >= 0; i--) { 32 | if (basis[i].none()) continue; 33 | if (get_msb(x) == i) { 34 | x ^= basis[i]; 35 | } 36 | } 37 | return x.none(); 38 | } 39 | 40 | BitArray to_bitarray(int x) { return BitArray(x); } 41 | 42 | #undef BASIS_SIZE 43 | }; 44 | -------------------------------------------------------------------------------- /codes/graphs/MinPathCover.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Min Path Cover Implementation using Dinic 3 | */ 4 | 5 | int32_t main() { 6 | DESYNC; 7 | int n, m; 8 | cin >> n >> m; 9 | Dinic dinic(n + n); 10 | for (int i = 1; i <= n; i++) { 11 | dinic.add_to_src(i, 1); 12 | dinic.add_to_snk(i + n, 1); 13 | } 14 | 15 | for (int i = 0; i < m; i++) { 16 | int u, v; 17 | cin >> u >> v; 18 | dinic.add_edge(u, v + n, 1); 19 | } 20 | 21 | dinic.calculate(); 22 | for (int i = 1; i <= n; i++) { 23 | for (Dinic::FlowEdge e : dinic.adj[i]) { 24 | if (e.cap == 1 && e.c == 0 && 1 <= e.v && e.v - n <= n) { 25 | adj[i].pb(e.v - n); 26 | dg[e.v - n]++; 27 | } 28 | } 29 | } 30 | 31 | for (int i = 1; i <= n; i++) { 32 | if (dg[i] == 0) { 33 | paths.pb(vector()); 34 | go(i, paths.size() - 1); 35 | } 36 | } 37 | 38 | cout << paths.size() << endl; 39 | for (int i = 0; i < paths.size(); i++) { 40 | for (int v : paths[i]) cout << v << " "; 41 | cout << endl; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /codes/geometry/vector3d.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * 3D Rotation 3 | */ 4 | 5 | struct Vec3d { 6 | double x, y, z; 7 | Vec3d operator+(const Vec3d& rhs) const { 8 | return {x + rhs.x, y + rhs.y, z + rhs.z}; 9 | } 10 | Vec3d operator*(const double k) const { return {k * x, k * y, k * z}; } 11 | Vec3d operator-(const Vec3d& rhs) const { return *this + rhs * -1; } 12 | Vec3d operator/(const double k) const { return {x / k, y / k, z / k}; } 13 | double operator*(const Vec3d& rhs) const { 14 | return x * rhs.x + y * rhs.y + z * rhs.z; 15 | } 16 | double norm_sq() { return (*this) * (*this); } 17 | double norm() { return sqrt(norm_sq()); } 18 | }; 19 | 20 | Vec3d rotate(Vec3d p, Vec3d u /*unit vector*/, double ang) { 21 | double dot = p * u; 22 | double co = cos(ang); 23 | double si = sin(ang); 24 | double x = u.x * dot * (1 - co) + p.x * co + (u.y * p.z - u.z * p.y) * si; 25 | double y = u.y * dot * (1 - co) + p.y * co + (u.z * p.x - u.x * p.z) * si; 26 | double z = u.z * dot * (1 - co) + p.z * co + (u.x * p.y - u.y * p.x) * si; 27 | return {x, y, z}; 28 | } 29 | -------------------------------------------------------------------------------- /codes/math_nt/matrix_exponentiation.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Matrix Exponentiation Implementation 3 | */ 4 | 5 | struct Matrix { 6 | vector > m; 7 | Matrix() {} 8 | Matrix(int l, int c) { m.resize(l, vector(c)); } 9 | 10 | Matrix operator*(Matrix b) const { 11 | Matrix c(m.size(), b.m[0].size()); 12 | for (int i = 0; i < m.size(); i++) { 13 | for (int j = 0; j < b.m[0].size(); j++) { 14 | for (int k = 0; k < b.m.size(); k++) { 15 | c.m[i][j] += (m[i][k] * b.m[k][j]); 16 | // c.m[i][j] = mod(c.m[i][j], M); 17 | } 18 | } 19 | } 20 | return c; 21 | } 22 | 23 | Matrix exp(int k) { 24 | if (k == 1) return *this; 25 | Matrix c = (*this).exp(k / 2); 26 | c = c * c; 27 | if (k % 2) c = c * (*this); 28 | return c; 29 | } 30 | 31 | vector &operator[](int idx) { 32 | return m[idx]; 33 | } 34 | 35 | void show() { 36 | for (int i = 0; i < m.size(); i++) { 37 | for (int x : m[i]) 38 | cout << x << " "; 39 | cout << endl; 40 | } 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /codes/uncategorized/lis.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Longest Increasing Subsequence 3 | */ 4 | /* Use upper_bound to swap to longest non decreasing subsequence */ 5 | 6 | struct LIS { 7 | vector seq; 8 | vector pointer; 9 | int sz; 10 | LIS() {} 11 | 12 | LIS(int n) { 13 | seq.resize(n + 1); 14 | pointer.resize(n); 15 | } 16 | 17 | void calculate(vector& v) { 18 | int n = v.size(); 19 | vector aux(n + 1); 20 | for (int i = 1; i <= n; i++) { 21 | seq[i] = INT_MAX; 22 | aux[i] = -1; 23 | } 24 | seq[0] = INT_MIN; 25 | aux[0] = -1; 26 | for (int i = 0; i < n; i++) { 27 | int index = lower_bound(seq.begin(), seq.end(), v[i]) - seq.begin(); 28 | index--; 29 | if (seq[index + 1] > v[i]) { 30 | seq[index + 1] = min(seq[index + 1], v[i]); 31 | aux[index + 1] = i; 32 | } 33 | pointer[i] = ii(index + 1, aux[index]); 34 | } 35 | for (int i = n; i >= 0; i--) { 36 | if (seq[i] != INT_MAX) { 37 | sz = i; 38 | break; 39 | } 40 | } 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /codes/strings/rolling_hash.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Rolling Hash 3 | */ 4 | 5 | namespace Hash { 6 | 7 | int B1, B2, M1, M2; 8 | 9 | void init() { 10 | B1 = rand() % 65536; 11 | B2 = rand() % 65536; 12 | M1 = 1000000007; 13 | M2 = 1000000009; 14 | } 15 | 16 | struct RollingHash { 17 | vector hash; 18 | vector base; 19 | 20 | RollingHash() {} 21 | 22 | void calculate(string s) { 23 | int n = s.size(); 24 | hash.resize(n + 1); 25 | base.resize(n + 1); 26 | base[0] = ii(1, 1); 27 | hash[0] = ii(0, 0); 28 | for (int i = 1; i <= n; i++) { 29 | int val = (int)(s[i - 1]); 30 | base[i] = ii(mod(base[i - 1].ff * B1, M1), mod(base[i - 1].ss * B2, M2)); 31 | hash[i] = ii(mod(hash[i - 1].ff * B1 + val, M1), 32 | mod(hash[i - 1].ss * B2 + val, M2)); 33 | } 34 | } 35 | 36 | ii query(int l, int r) { 37 | l++, r++; 38 | ii ret; 39 | ret.ff = mod(hash[r].ff - hash[l - 1].ff * base[r - l + 1].ff, M1); 40 | ret.ss = mod(hash[r].ss - hash[l - 1].ss * base[r - l + 1].ss, M2); 41 | return ret; 42 | } 43 | }; 44 | 45 | } // namespace Hash 46 | -------------------------------------------------------------------------------- /codes/geometry/vector2d.cpp: -------------------------------------------------------------------------------- 1 | struct Vector2D { 2 | int x, y; 3 | Vector2D() {} 4 | Vector2D(int x, int y) : x(x), y(y) {} 5 | 6 | bool operator<(Vector2D v) const { return tie(x, y) < tie(v.x, v.y); } 7 | bool operator==(Vector2D v) const { return tie(x, y) == tie(v.x, v.y); } 8 | bool operator>(Vector2D v) const { return tie(x, y) > tie(v.x, v.y); } 9 | bool operator<=(Vector2D v) const { return tie(x, y) <= tie(v.x, v.y); } 10 | bool operator>=(Vector2D v) const { return tie(x, y) >= tie(v.x, v.y); } 11 | 12 | Vector2D normalize() { 13 | if (x == 0) { 14 | return Vector2D(0, 1); 15 | } 16 | if (y == 0) { 17 | return Vector2D(1, 0); 18 | } 19 | int g = gcd(x, y); 20 | Vector2D norm(x / g, y / g); 21 | if (norm.y < 0) norm.x = -norm.x, norm.y = -norm.y; 22 | return norm; 23 | } 24 | Vector2D normalized_orthogonal() { 25 | if (x == 0) { 26 | return Vector2D(1, 0); 27 | } 28 | if (y == 0) { 29 | return Vector2D(0, 1); 30 | } 31 | int g = gcd(x, y); 32 | Vector2D ort = Vector2D(-y / g, x / g); 33 | if (ort.y < 0) ort.x = -ort.x, ort.y = -ort.y; 34 | return ort; 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /codes/strings/manacher.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Manacher's Algorithm 3 | */ 4 | 5 | // Finds all Palindromes with odd and even length 6 | struct Manacher { 7 | vector d_e, d_o; 8 | Manacher() {} 9 | 10 | Manacher(string& s) { 11 | int n = s.size(); 12 | d_e.resize(n); 13 | d_o.resize(n); 14 | _calculate(s); 15 | } 16 | 17 | void _calculate(string& s) { 18 | int n = d_e.size(); 19 | // calculate for odd 20 | for (int i = 0, l = 0, r = -1; i < n; i++) { 21 | d_o[i] = (i > r) ? 1 : min(d_o[l + r - i], r - i + 1); 22 | while (i - d_o[i] >= 0 and i + d_o[i] < n and 23 | s[i - d_o[i]] == s[i + d_o[i]]) 24 | d_o[i]++; 25 | if (i + d_o[i] - 1 > r) { 26 | l = i - d_o[i] + 1; 27 | r = i + d_o[i] - 1; 28 | } 29 | } 30 | 31 | // calculate for even 32 | for (int i = 0, l = 0, r = -1; i < n; i++) { 33 | d_e[i] = (i > r) ? 0 : min(d_e[l + r - i + 1], r - i + 1); 34 | while (i - d_e[i] - 1 >= 0 and i + d_e[i] < n and 35 | s[i - d_e[i] - 1] == s[i + d_e[i]]) 36 | d_e[i]++; 37 | if (i + d_e[i] - 1 > r) { 38 | l = i - d_e[i]; 39 | r = i + d_e[i] - 1; 40 | } 41 | } 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /codes/data_structures/sparse_table.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Neto 2 | * Generic Sparse Table 3 | */ 4 | 5 | struct SparseTable { 6 | int MAXN, LOGN; 7 | vector> spt; 8 | vector e; 9 | function merge_fn; 10 | 11 | SparseTable(vector& v, function fn) { 12 | int n = v.size(); 13 | MAXN = n; 14 | LOGN = 0; 15 | merge_fn = fn; 16 | while (n > 0) { 17 | LOGN++; 18 | n /= 2LL; 19 | } 20 | spt.resize(MAXN + 1, vector(LOGN, 0)); 21 | e.resize(MAXN + 1); 22 | _build(v); 23 | } 24 | 25 | void _build(vector& a) { 26 | for (int i = 0; i < MAXN; i++) { 27 | spt[i][0] = a[i]; 28 | } 29 | 30 | for (int i = 1; (1 << i) <= MAXN; i++) { 31 | for (int j = 0; j + (1 << i) <= MAXN; j++) { 32 | spt[j][i] = merge_fn(spt[j][i - 1], spt[j + (1 << (i - 1))][i - 1]); 33 | } 34 | } 35 | 36 | int k = 0; 37 | for (int j = 0; (1 << j) <= 2 * MAXN; j++) { 38 | for (; k <= MAXN && k < (1 << j); k++) { 39 | e[k] = j - 1; 40 | } 41 | } 42 | } 43 | 44 | int query(int l, int r) { 45 | assert(r < MAXN && l >= 0 && l <= r); 46 | int sz = r - l + 1; 47 | return merge_fn(spt[l][e[sz]], spt[r - (1 << e[sz]) + 1][e[sz]]); 48 | } 49 | }; -------------------------------------------------------------------------------- /codes/uncategorized/MosQueryDecomposition.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Mos Algorithm Structure 3 | */ 4 | 5 | namespace Mos { 6 | 7 | int sqr; 8 | 9 | struct query { 10 | int id, l, r, ans; 11 | bool operator<(const query& b) const { 12 | if (l / sqr != b.l / sqr) return l / sqr < b.l / sqr; 13 | return (l / sqr) % 2 ? r > b.r : r < b.r; 14 | } 15 | }; 16 | 17 | struct QueryDecomposition { 18 | vector q; 19 | 20 | QueryDecomposition(int n, int nq) { 21 | q.resize(nq); 22 | sqr = (int)sqrt(n); 23 | } 24 | 25 | void read() {} 26 | 27 | void add(int idx) {} 28 | 29 | void remove(int idx) {} 30 | 31 | int answer_query() {} 32 | 33 | void calculate() { 34 | sort(q.begin(), q.end()); 35 | int l = 0, r = -1; 36 | for (int i = 0; i < q.size(); i++) { 37 | while (q[i].l < l) add(--l); 38 | while (r < q[i].r) add(++r); 39 | while (q[i].l > l) remove(l++); 40 | while (r > q[i].r) remove(r--); 41 | q[i].ans = answer_query(); 42 | } 43 | } 44 | 45 | void print() { 46 | sort(q.begin(), q.end(), 47 | [](const query& a, const query& b) { return a.id < b.id; }); 48 | 49 | for (query x : q) { 50 | cout << x.ans << endl; 51 | } 52 | } 53 | }; 54 | 55 | } // namespace Mos 56 | -------------------------------------------------------------------------------- /codes/graphs/tarjan.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Tarjan Bridges + Articulations 3 | */ 4 | 5 | struct Tarjan { 6 | int cont = 0; 7 | vector st; 8 | vector low; 9 | vector bridges; 10 | vector isArticulation; 11 | 12 | Tarjan() {} 13 | 14 | Tarjan(int n) { 15 | st.resize(n + 1); 16 | low.resize(n + 1); 17 | isArticulation.resize(n + 1); 18 | cont = 0; 19 | bridges.clear(); 20 | } 21 | 22 | void calculate(int u, int p = -1) { 23 | st[u] = low[u] = ++cont; 24 | int son = 0; 25 | for (int i = 0; i < adj[u].size(); i++) { 26 | if (adj[u][i] == p) { 27 | p = 0; 28 | continue; 29 | } 30 | if (!st[adj[u][i]]) { 31 | calculate(adj[u][i], u); 32 | low[u] = min(low[u], low[adj[u][i]]); 33 | if (low[adj[u][i]] >= st[u]) 34 | isArticulation[u] = true; // check articulation 35 | 36 | if (low[adj[u][i]] > st[u]) { // check if its a bridge 37 | bridges.push_back(ii(u, adj[u][i])); 38 | } 39 | 40 | son++; 41 | } else 42 | low[u] = min(low[u], st[adj[u][i]]); 43 | } 44 | 45 | if (p == -1) { 46 | if (son > 1) 47 | isArticulation[u] = true; 48 | else 49 | isArticulation[u] = false; 50 | } 51 | } 52 | }; 53 | -------------------------------------------------------------------------------- /codes/math_nt/miller_rabin.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Miller Rabin 3 | */ 4 | 5 | namespace NT { 6 | 7 | int mulmod(int a, int b, int c) { 8 | int x = 0, y = a % c; 9 | 10 | while (b > 0) { 11 | if (b % 2 == 1) { 12 | x = (x + y) % c; 13 | } 14 | 15 | y = (y * 2) % c; 16 | b /= 2; 17 | } 18 | 19 | return x % c; 20 | } 21 | 22 | int expmod(int a, int k, int p) { 23 | if (k == 0) return 1; 24 | if (k == 1) return a; 25 | 26 | int aux = expmod(a, k / 2, p); 27 | aux = mulmod(aux, aux, p); 28 | 29 | if (k % 2) aux = mulmod(aux, a, p); 30 | return aux; 31 | } 32 | 33 | bool PrimalityTest(int p, int iterations) { 34 | // Miller Rabin Primality Test 35 | mt19937 mt_rand(time(0)); 36 | 37 | if (p < 2) return false; 38 | if (p == 2) return true; 39 | if (p % 2 == 0) return false; 40 | 41 | int fixed_s = p - 1; 42 | while (fixed_s % 2 == 0) fixed_s /= 2; 43 | 44 | for (int iter = 0; iter < iterations; iter++) { 45 | int s = fixed_s; 46 | 47 | int a = mt_rand() % (p - 1) + 1; 48 | int b = expmod(a, s, p); 49 | 50 | while (s != p - 1 && b != 1 && b != p - 1) { 51 | b = mulmod(b, b, p); 52 | s *= 2; 53 | } 54 | 55 | if (b != p - 1 && s % 2 == 0) return false; 56 | } 57 | 58 | return true; 59 | } 60 | 61 | } // namespace NT 62 | -------------------------------------------------------------------------------- /codes/data_structures/PersistentSegmentTree.cpp: -------------------------------------------------------------------------------- 1 | namespace PersistentSegmentTree { 2 | 3 | struct Node { 4 | Node *left, *right; 5 | int x; 6 | Node() { 7 | left = nullptr; 8 | right = nullptr; 9 | x = 0; 10 | } 11 | 12 | Node(Node* n) { 13 | left = n->left; 14 | right = n->right; 15 | x = n->x; 16 | } 17 | }; 18 | 19 | Node* update(Node* cur, int l, int r, int x, int val) { 20 | assert(cur != nullptr); 21 | Node* new_cur = new Node(cur); 22 | if (l == r) { 23 | new_cur->x = val; 24 | return new_cur; 25 | } 26 | 27 | int m = (l + r) >> 1; 28 | if (x <= m) { 29 | if (!new_cur->left) new_cur->left = new Node(); 30 | new_cur->left = update(new_cur->left, l, m, x, val); 31 | } else { 32 | if (!new_cur->right) new_cur->right = new Node(); 33 | new_cur->right = update(new_cur->right, m + 1, r, x, val); 34 | } 35 | new_cur->x = max((new_cur->left ? new_cur->left->x : 0), 36 | (new_cur->right ? new_cur->right->x : 0)); 37 | return new_cur; 38 | } 39 | 40 | int query(Node* cur, int l, int r, int a, int b) { 41 | assert(cur != nullptr); 42 | if (r < a || b < l) return 0; 43 | if (a <= l and r <= b) return cur->x; 44 | int m = (l + r) >> 1; 45 | int ansl = 0, ansr = 0; 46 | if (cur->left) ansl = query(cur->left, l, m, a, b); 47 | if (cur->right) ansr = query(cur->right, m + 1, r, a, b); 48 | return max(ansl, ansr); 49 | } 50 | 51 | }; // namespace PersistentSegmentTree 52 | -------------------------------------------------------------------------------- /codes/data_structures/min_lichao_cht.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Neto 2 | * Min LiChao Tree 3 | */ 4 | namespace Lichao { 5 | 6 | struct Line { 7 | int a, b; 8 | Line() { 9 | a = 0; 10 | b = INF; 11 | } 12 | Line(int a, int b) : a(a), b(b) {} 13 | int eval(int x) { return a * x + b; } 14 | }; 15 | 16 | struct node { 17 | node *left, *right; 18 | Line ln; 19 | node() { 20 | left = NULL; 21 | right = NULL; 22 | } 23 | }; 24 | 25 | struct Tree { 26 | node* root; 27 | 28 | Tree() { root = new node(); } 29 | 30 | void add(node* root, int l, int r, Line ln) { 31 | if (!root->left) root->left = new node(); 32 | if (!root->right) root->right = new node(); 33 | int m = (l + r) >> 1; 34 | bool left = ln.eval(l) < (root->ln).eval(l); 35 | bool mid = ln.eval(m) < (root->ln).eval(m); 36 | 37 | if (mid) { 38 | swap(root->ln, ln); 39 | } 40 | 41 | if (l == r) 42 | return; 43 | else if (left != mid) 44 | add(root->left, l, m, ln); 45 | else 46 | add(root->right, m + 1, r, ln); 47 | } 48 | 49 | int query(node* root, int l, int r, int x) { 50 | if (!root->left) root->left = new node(); 51 | if (!root->right) root->right = new node(); 52 | int m = (l + r) >> 1; 53 | if (l == r) 54 | return (root->ln).eval(x); 55 | else if (x < m) 56 | return min((root->ln).eval(x), query(root->left, l, m, x)); 57 | else 58 | return min((root->ln).eval(x), query(root->right, m + 1, r, x)); 59 | } 60 | }; 61 | 62 | } // namespace Lichao 63 | -------------------------------------------------------------------------------- /codes/graphs/StoerWagner.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Stoer Wagner 3 | */ 4 | 5 | /* Initialization */ 6 | int cost[n + 1][n + 1]; 7 | memset(cost, 0, sizeof cost); 8 | while (m--) { 9 | int u, v, c; 10 | u = input.next(); 11 | v = input.next(); 12 | c = input.next(); 13 | cost[u][v] = c; 14 | cost[v][u] = c; 15 | } 16 | /* Stoer-Wagner: global minimum cut in undirected graphs */ 17 | int min_cut = 1000000000; 18 | bool added[n + 1]; 19 | int vertex_cost[n + 1]; 20 | for (int vertices_count = n; vertices_count > 1; --vertices_count) { 21 | memset(added, 0, sizeof(added[0]) * (vertices_count + 1)); 22 | memset(vertex_cost, 0, sizeof(vertex_cost[0]) * (vertices_count + 1)); 23 | int s = -1, t = -1; 24 | for (int i = 1; i <= vertices_count; ++i) { 25 | int vert = 1; 26 | while (added[vert]) ++vert; 27 | for (int j = 1; j <= vertices_count; ++j) 28 | if (!added[j] && vertex_cost[j] > vertex_cost[vert]) vert = j; 29 | if (i == vertices_count - 1) 30 | s = vert; 31 | else if (i == vertices_count) { 32 | t = vert; 33 | min_cut = min(min_cut, vertex_cost[vert]); 34 | } 35 | added[vert] = 1; 36 | for (int j = 1; j <= vertices_count; ++j) vertex_cost[j] += cost[vert][j]; 37 | } 38 | for (int i = 1; i <= vertices_count; ++i) { 39 | cost[s][i] += cost[t][i]; 40 | cost[i][s] += cost[i][t]; 41 | } 42 | for (int i = 1; i <= vertices_count; ++i) { 43 | cost[t][i] = cost[vertices_count][i]; 44 | cost[i][t] = cost[i][vertices_count]; 45 | } 46 | } 47 | printf("%d\n", min_cut); 48 | -------------------------------------------------------------------------------- /codes/graphs/2-sat.cpp: -------------------------------------------------------------------------------- 1 | // I'm not the author 2 | // Author: Vinicius Hirschle (viniciusth) 3 | struct _2SAT { // 1 based 4 | vector> g, gt; 5 | int n, n2; 6 | _2SAT() {} 7 | _2SAT(int n) : n(n) { // literals range from [1 ... n] 8 | n2 = 2 * n; 9 | g = gt = vector>(n2 + 1, vector()); 10 | } 11 | int neg(int a) { return a + n * (a > n ? -1 : 1); } 12 | void add(int a, int b) { 13 | // -x is negation of x 14 | if (a < 0) a = -a + n; 15 | if (b < 0) b = -b + n; 16 | // adding clause a v b is equal to adding -a -> b and -b -> a 17 | g[neg(a)].pb(b); 18 | gt[b].pb(neg(a)); 19 | g[neg(b)].pb(a); 20 | gt[a].pb(neg(b)); 21 | } 22 | vector solve() { 23 | vector used(n2 + 1), comp(n2 + 1, -1), res(n), order; 24 | function dfs1 = [&](int u) { 25 | used[u] = 1; 26 | for (int v : g[u]) 27 | if (!used[v]) dfs1(v); 28 | order.push_back(u); 29 | }; 30 | function dfs2 = [&](int u, int group) { 31 | comp[u] = group; 32 | for (int v : gt[u]) 33 | if (comp[v] == -1) dfs2(v, group); 34 | }; 35 | for (int i = 1; i <= n2; i++) 36 | if (!used[i]) dfs1(i); 37 | for (int i = n2 - 1, j = 0; i >= 0; i--) 38 | if (comp[order[i]] == -1) dfs2(order[i], j++); 39 | for (int i = 1; i <= n; i++) { 40 | if (comp[i] == comp[neg(i)]) { 41 | res.clear(); 42 | return res; // impossible 43 | } 44 | res[i - 1] = comp[i] > comp[neg(i)]; 45 | } 46 | return res; 47 | } 48 | }; 49 | -------------------------------------------------------------------------------- /codes/data_structures/min_lichao_dbl_cht.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Neto 2 | * LiChao with Doubles 3 | */ 4 | 5 | namespace Lichao { 6 | 7 | struct Line { 8 | double a, b; 9 | Line() { 10 | a = 0; 11 | b = INF; 12 | } 13 | Line(double a, double b) : a(a), b(b) {} 14 | double eval(double x) { return a * x + b; } 15 | }; 16 | 17 | struct node { 18 | node *left, *right; 19 | Line ln; 20 | node() { 21 | left = NULL; 22 | right = NULL; 23 | } 24 | }; 25 | 26 | struct Tree { 27 | node* root; 28 | 29 | Tree() { root = new node(); } 30 | 31 | void add(node* root, double l, double r, Line ln) { 32 | if (!root->left) root->left = new node(); 33 | if (!root->right) root->right = new node(); 34 | double m = (l + r) / 2.; 35 | bool left = ln.eval(l) < (root->ln).eval(l); 36 | bool mid = ln.eval(m) < (root->ln).eval(m); 37 | 38 | if (mid) { 39 | swap(root->ln, ln); 40 | } 41 | 42 | if (abs(r - l) <= 1e-9) 43 | return; 44 | else if (left != mid) 45 | add(root->left, l, m, ln); 46 | else 47 | add(root->right, m, r, ln); 48 | } 49 | 50 | double query(node* root, double l, double r, double x) { 51 | if (!root->left) root->left = new node(); 52 | if (!root->right) root->right = new node(); 53 | double m = (l + r) / 2.; 54 | if (abs(r - l) <= 1e-9) 55 | return (root->ln).eval(x); 56 | else if (x < m) 57 | return min((root->ln).eval(x), query(root->left, l, m, x)); 58 | else 59 | return min((root->ln).eval(x), query(root->right, m, r, x)); 60 | } 61 | }; 62 | 63 | } // namespace Lichao 64 | -------------------------------------------------------------------------------- /codes/math_nt/lagrange_modular.cpp: -------------------------------------------------------------------------------- 1 | namespace ModularLagrange { 2 | /* Interpolates a polynomial of degree N-1 given N point-value pairs (x,y) and 3 | * returns f(k) */ 4 | /* Uses modular arithmetic */ 5 | int Interpolate(const vector& v, int k) { 6 | int ans = 0; 7 | int n = v.size(); 8 | for (int i = 0; i < n; i++) { 9 | int num = v[i].ss; 10 | int den = 1; 11 | for (int j = 0; j < n; j++) { 12 | if (i == j) continue; 13 | num = mod(num * (k - v[j].ff)); 14 | den = mod(den * (v[i].ff - v[j].ff)); 15 | } 16 | ans = mod(ans + divp(num, den)); 17 | } 18 | return ans; 19 | } 20 | 21 | /* Fast version of Lagrange interpolation in linear time 22 | * Works when the set of given N points is a contiguous sequence from x = 1..n 23 | * Uses modular arithmetic 24 | */ 25 | int FastInterpolate(const vector& v, int k) { 26 | int ans = 0; 27 | int n = v.size(); 28 | int fat[n + 1]; 29 | int ifat[n + 1]; 30 | fat[0] = 1; 31 | ifat[0] = 1; 32 | for (int i = 1; i <= n; i++) { 33 | fat[i] = mod(fat[i - 1] * i); 34 | ifat[i] = exp(fat[i], M - 2); 35 | } 36 | 37 | int pref[n + 1]; 38 | int suf[n + 2]; 39 | pref[0] = 1; 40 | suf[n + 1] = 1; 41 | for (int i = 1; i <= n; i++) { 42 | pref[i] = mod(pref[i - 1] * (k - i)); 43 | } 44 | for (int i = n; i >= 1; i--) { 45 | suf[i] = mod(suf[i + 1] * (k - i)); 46 | } 47 | 48 | for (int i = 1; i <= n; i++) { 49 | int num = mod(pref[i - 1] * suf[i + 1]); 50 | num = mod(num * v[i - 1]); 51 | int den = mod(ifat[n - i] * ifat[i - 1]); 52 | if ((n - i) % 2) den = -den; 53 | ans = mod(ans + mod(num * den)); 54 | } 55 | return ans; 56 | } 57 | } // namespace ModularLagrange 58 | -------------------------------------------------------------------------------- /codes/data_structures/max_cht.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Neto 2 | * Max CHT Example (Suppose that lines are added in crescent order of a) 3 | */ 4 | struct ConvexHullTrick { 5 | ConvexHullTrick() {} 6 | struct Line { 7 | int id, a, b; 8 | Line() {} 9 | Line(int id, int a, int b) : id(id), a(a), b(b) {} 10 | }; 11 | bool remove(Line& a, Line& b, Line& c) { 12 | if ((a.a - c.a) * (c.b - b.b) <= (b.a - c.a) * (c.b - a.b)) 13 | return true; 14 | else 15 | return false; 16 | } 17 | vector cht; 18 | void add(Line& v) { 19 | if (cht.empty()) { 20 | cht.push_back(v); 21 | } else { 22 | if (cht.back().a == v.a) return; 23 | while (cht.size() > 1 && remove(cht[cht.size() - 2], cht.back(), v)) { 24 | cht.pop_back(); 25 | } 26 | cht.push_back(v); 27 | } 28 | } 29 | 30 | void preprocess_cht(vector& v) { 31 | sort(v.begin(), v.end(), [](const Line& a, const Line& b) { 32 | return (a.a < b.a || (a.a == b.a && a.b > b.b)); 33 | }); 34 | cht.clear(); 35 | for (int i = 0; i < v.size(); i++) { 36 | add(v[i]); 37 | } 38 | } 39 | 40 | int f(int i, int x) { return cht[i].a * x + cht[i].b; } 41 | 42 | // return Line index 43 | ii query(int x) { 44 | if (cht.size() == 0) return ii(-INF, -INF); 45 | if (cht.size() == 1) return ii(f(0, x), cht[0].id); 46 | int l = 0, r = cht.size() - 2; 47 | int ans = cht.size() - 1; 48 | while (l <= r) { 49 | int m = (l + r) / 2; 50 | int y1 = f(m, x); 51 | int y2 = f(m + 1, x); 52 | if (y1 >= y2) { 53 | ans = m; 54 | r = m - 1; 55 | } else 56 | l = m + 1; 57 | } 58 | return ii(f(ans, x), cht[ans].id); 59 | } 60 | }; 61 | -------------------------------------------------------------------------------- /codes/graphs/BlockCutTree.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Block Cut Tree Example 3 | */ 4 | 5 | vector adj[N]; 6 | int vis[N]; 7 | int ini[N]; 8 | int bef[N]; 9 | bool art[N] int num_bridges = 0; 10 | int T = 0; 11 | 12 | void dfs_tarjan(int v, int p) { 13 | vis[v] = 1; 14 | bef[v] = ini[v] = ++T; 15 | art[v] = false; 16 | int num_sub = 0; 17 | for (int i = 0; i < adj[v].size(); i++) { 18 | int ad = adj[v][i]; 19 | if (ad == p) continue; 20 | if (!vis[ad]) { 21 | dfs_tarjan(ad, v); 22 | if (bef[ad] > ini[v]) { 23 | // Bridge 24 | num_bridges++; 25 | } 26 | if (bef[ad] >= ini[v] && p != -1) { 27 | // v is an articulation 28 | art[v] = true; 29 | } 30 | num_sub++; 31 | } 32 | bef[v] = min(bef[v], ini[ad]); 33 | } 34 | if (p == -1 && num_sub > 1) { 35 | // Root is an articulation 36 | art[v] = true; 37 | } 38 | } 39 | 40 | int curId; 41 | vector adjbct[2 * 112345]; 42 | 43 | void dfs_block_cut(int v, int id) { 44 | vis[v] = 1; 45 | if (id != -1) { 46 | adjbct[v].pb(id); 47 | adjbct[id].pb(v); 48 | } 49 | for (int i = 0; i < adj[v].size(); i++) { 50 | int ad = adj[v][i]; 51 | if (!vis[ad]) { 52 | if (bef[ad] >= ini[v]) { 53 | curId++; 54 | adjbct[v].pb(curId); 55 | adjbct[curId].pb(v); 56 | dfs_block_cut(ad, curId); 57 | } else { 58 | dfs_block_cut(ad, id); 59 | } 60 | } 61 | } 62 | } 63 | 64 | int32_t main() { 65 | num_bridges = 0; 66 | T = 0; 67 | memset(vis, 0, sizeof vis); 68 | for (int i = 1; i <= n; i++) dfs_tarjan(i, -1); 69 | 70 | curId = n; 71 | memset(vis, 0, sizeof vis); 72 | for (int i = 1; i <= n; i++) dfs_block_cut(i, -1); 73 | } 74 | -------------------------------------------------------------------------------- /codes/graphs/lca.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Lowest Common Ancestor 3 | */ 4 | 5 | struct LCA { 6 | int tempo; 7 | vector st, ed, dad, anc[20], L; 8 | vector> adj; 9 | vector vis; 10 | 11 | LCA() {} 12 | 13 | LCA(int n) { 14 | tempo = 0; 15 | st.resize(n + 1); 16 | ed.resize(n + 1); 17 | dad.resize(n + 1); 18 | adj.resize(n+1, vector()); 19 | L.resize(n + 1); 20 | for (int i = 0; i < 20; i++) anc[i].resize(n + 1); 21 | vis.resize(n + 1); 22 | for (int i = 0; i <= n; i++) vis[i] = false; 23 | } 24 | 25 | void dfs(int u) { 26 | vis[u] = true; 27 | st[u] = tempo++; 28 | for (int i = 0; i < adj[u].size(); i++) { 29 | int v = adj[u][i]; 30 | if (!vis[v]) { 31 | dad[v] = u; 32 | L[v] = L[u] + 1; 33 | dfs(v); 34 | } 35 | } 36 | ed[u] = tempo++; 37 | } 38 | 39 | bool is_ancestor(int u, int v) { return st[u] <= st[v] && st[v] <= ed[u]; } 40 | 41 | int query(int u, int v) { 42 | if (is_ancestor(u, v)) return u; 43 | for (int i = 19; i >= 0; i--) { 44 | if (anc[i][u] == -1) continue; 45 | if (!is_ancestor(anc[i][u], v)) u = anc[i][u]; 46 | } 47 | return dad[u]; 48 | } 49 | 50 | int distance(int u, int v) { return L[u] + L[v] - 2 * L[query(u, v)]; } 51 | 52 | void precalculate() { 53 | for (int i = 1; i < st.size(); i++) { 54 | if (vis[i]) continue; 55 | dad[i] = -1; 56 | L[i] = 0; 57 | dfs(i); 58 | } 59 | for (int i = 1; i < st.size(); i++) { 60 | anc[0][i] = dad[i]; 61 | } 62 | for (int i = 1; i < 20; i++) { 63 | for (int j = 1; j < st.size(); j++) { 64 | if (anc[i - 1][j] != -1) { 65 | anc[i][j] = anc[i - 1][anc[i - 1][j]]; 66 | } else { 67 | anc[i][j] = -1; 68 | } 69 | } 70 | } 71 | } 72 | }; 73 | -------------------------------------------------------------------------------- /codes/math_nt/sieve.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Erasthostenes Sieve Implementation + Euler's Totient 3 | */ 4 | 5 | /* Calculate primes from 2 to N */ 6 | /* lf[i] stores the lowest prime factor of i(logn factorization) */ 7 | 8 | namespace NT { 9 | 10 | const int MAX_SIEVE = 1123456; 11 | 12 | bitset prime; 13 | vector primes; 14 | vector seg_primes; 15 | int lf[MAX_SIEVE]; 16 | int totient[MAX_SIEVE]; 17 | 18 | void Sieve(int n) { 19 | for (int i = 0; i <= n; i++) lf[i] = i; 20 | prime.set(); 21 | prime[0] = false; 22 | prime[1] = false; 23 | for (int p = 2; p * p <= n; p++) { 24 | if (prime[p]) { 25 | for (int i = p * p; i <= n; i += p) { 26 | prime[i] = false; 27 | lf[i] = min(lf[i], p); 28 | } 29 | } 30 | } 31 | for (int i = 2; i <= n; i++) 32 | if (prime[i]) primes.pb(i); 33 | } 34 | 35 | void SegmentedSieve(int l, int r) { 36 | prime.set(); 37 | seg_primes.clear(); 38 | for (int p : primes) { 39 | int start = l - l % p - p; 40 | while (start < l) start += p; 41 | if (p == start) start += p; 42 | for (int i = start; i <= r; i += p) { 43 | prime[i - l] = false; 44 | } 45 | } 46 | for (int i = 0; i < r - l + 1; i++) { 47 | if (prime[i] && l + i > 1) { 48 | seg_primes.pb(l + i); 49 | } 50 | } 51 | } 52 | 53 | void EulerTotient(int n) { 54 | for (int i = 0; i <= n; i++) totient[i] = i; 55 | for (int p = 2; p <= n; p++) { 56 | if (totient[p] == p) { 57 | totient[p] = p - 1; 58 | for (int i = p + p; i <= n; i += p) { 59 | totient[i] = (totient[i] / p) * (p - 1); 60 | } 61 | } 62 | } 63 | } 64 | 65 | int SingleTotient(int x) { 66 | int ans = x; 67 | for (int i = 2; i * i <= x; i++) { 68 | if (x % i == 0) { 69 | while (x % i == 0) x /= i; 70 | ans -= ans / i; 71 | } 72 | } 73 | if (x > 1) ans -= ans / x; 74 | return ans; 75 | } 76 | 77 | }; // namespace NT 78 | -------------------------------------------------------------------------------- /codes/graphs/centroid_decomp.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | */ 3 | 4 | /* Centroid Decomposition Implementation */ 5 | /* c_p[] contains the centroid predecessor on centroid tree */ 6 | /* removed[] says if the node was already selected as a centroid (limit the 7 | * subtree search) */ 8 | /* L[] contains the height of the vertex (from root) on centroid tree (Max is 9 | * logN) */ 10 | /* N is equal to the maximum size of tree (given by statement) */ 11 | 12 | struct CentroidDecomposition { 13 | vector removed; 14 | vector L, subsz; 15 | vector c_p; 16 | vector> adj; 17 | 18 | CentroidDecomposition() {} 19 | 20 | CentroidDecomposition(int n) { 21 | removed.resize(n + 1); 22 | L.resize(n + 1); 23 | c_p.resize(n + 1); 24 | subsz.resize(n + 1); 25 | adj.resize(n + 1, vector()); 26 | for (int i = 0; i < n + 1; i++) { 27 | c_p[i] = -1; 28 | } 29 | } 30 | 31 | void centroid_subsz(int u, int p) { 32 | subsz[u] = 1; 33 | for (int i = 0; i < adj[u].size(); i++) { 34 | int v = adj[u][i]; 35 | if (v == p || removed[v]) continue; 36 | centroid_subsz(v, u); 37 | subsz[u] += subsz[v]; 38 | } 39 | } 40 | 41 | int find_centroid(int u, int p, int sub) { 42 | for (int i = 0; i < adj[u].size(); i++) { 43 | int v = adj[u][i]; 44 | if (v == p || removed[v]) continue; 45 | if (subsz[v] > subsz[sub] / 2) { 46 | return find_centroid(v, u, sub); 47 | } 48 | } 49 | return u; 50 | } 51 | 52 | void decompose(int u = 1, int p = -1, int r = 0) { 53 | centroid_subsz(u, -1); 54 | int centroid = find_centroid(u, -1, u); 55 | L[centroid] = r; 56 | c_p[centroid] = p; 57 | removed[centroid] = true; 58 | 59 | process(centroid, p); 60 | 61 | for (int i = 0; i < adj[centroid].size(); i++) { 62 | int v = adj[centroid][i]; 63 | if (removed[v]) continue; 64 | decompose(v, centroid, r + 1); 65 | } 66 | } 67 | 68 | void process(int u, int p) { 69 | // do something here to process subtree 70 | } 71 | }; 72 | -------------------------------------------------------------------------------- /codes/graphs/scc.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Kosaraju Strongly Connected Components 3 | */ 4 | 5 | struct SCC { 6 | vector > adj_t; 7 | vector > scc_adj; 8 | int comp; 9 | vector vis; 10 | vector scc; 11 | stack vertex; 12 | 13 | SCC() {} 14 | 15 | SCC(int n) { 16 | adj_t.resize(n + 1, vector()); 17 | scc_adj.resize(n + 1, vector()); 18 | comp = 0; 19 | vis.resize(n + 1); 20 | scc.resize(n + 1); 21 | } 22 | 23 | void dfs(int u) { 24 | vis[u] = true; 25 | for (int i = 0; i < adj[u].size(); i++) { 26 | int v = adj[u][i]; 27 | if (!vis[v]) dfs(v); 28 | } 29 | vertex.push(u); 30 | } 31 | 32 | void dfst(int u, int comp) { 33 | scc[u] = comp; 34 | vis[u] = true; 35 | for (int i = 0; i < adj_t[u].size(); i++) { 36 | int v = adj_t[u][i]; 37 | if (!vis[v]) dfst(v, comp); 38 | } 39 | } 40 | 41 | void calculate() { 42 | int n = vis.size() - 1; 43 | 44 | for (int i = 0; i <= n; i++) { 45 | vis[i] = false; 46 | } 47 | 48 | for (int i = 1; i <= n; i++) { 49 | if (!vis[i]) { 50 | dfs(i); 51 | } 52 | } 53 | 54 | for (int i = 1; i <= n; i++) { 55 | for (int v : adj[i]) { 56 | adj_t[v].pb(i); 57 | } 58 | } 59 | 60 | for (int i = 1; i <= n; i++) { 61 | vis[i] = false; 62 | } 63 | 64 | while (!vertex.empty()) { 65 | if (!vis[vertex.top()]) { 66 | comp++; 67 | dfst(vertex.top(), comp); 68 | } 69 | vertex.pop(); 70 | } 71 | 72 | // set< ii > edge_check; //eliminates duplicate edges (additional O(logn)) 73 | 74 | for (int i = 1; i <= n; i++) { 75 | for (int j = 0; j < adj[i].size(); j++) { 76 | int v = adj[i][j]; 77 | if (scc[i] == scc[v]) continue; 78 | // if(edge_check.count(ii(scc[i], scc[v]))) continue; //eliminates 79 | // duplicate edges (additional O(logn)) 80 | scc_adj[scc[i]].push_back(scc[v]); 81 | // edge_check.insert(ii(scc[i], scc[v])); //eliminates duplicate edges 82 | // (additional O(logn)) 83 | } 84 | } 85 | } 86 | }; 87 | -------------------------------------------------------------------------------- /codes/data_structures/segment_tree.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Neto 2 | * SegmentTree Range Sum Example 3 | */ 4 | namespace SegmentTree { 5 | 6 | // val type example 7 | struct val_type { 8 | int val; 9 | val_type() {} 10 | val_type(int val) : val(val) {} 11 | }; 12 | 13 | // node type example 14 | struct node { 15 | int val = 0; 16 | int lazy = 0; 17 | node() {} 18 | node(int val, int lazy) : val(val), lazy(lazy) {} 19 | node neutral() { return node(0, 0); }; 20 | bool empty_lazy() { return lazy == 0; } 21 | void update_lazy(val_type val) { lazy += val.val; } 22 | void apply_lazy(int l, int r) { val += (r - l + 1) * lazy; } 23 | void reset_lazy() { lazy = 0; } 24 | node propagate(node b) { 25 | b.lazy += lazy; 26 | return b; 27 | } 28 | node combine(node b) { 29 | node ans; 30 | ans.val = b.val + val; 31 | return ans; 32 | } 33 | }; 34 | 35 | template 36 | class Tree { 37 | public: 38 | vector st; 39 | Tree() {} 40 | Tree(int n) { st.resize(4 * n); } 41 | void propagate(int cur, int l, int r) { 42 | if (st[cur].empty_lazy()) return; 43 | st[cur].apply_lazy(l, r); 44 | if (l != r) { 45 | st[2 * cur] = st[cur].propagate(st[2 * cur]); 46 | st[2 * cur + 1] = st[cur].propagate(st[2 * cur + 1]); 47 | } 48 | st[cur].reset_lazy(); 49 | } 50 | void update(int cur, int l, int r, int a, int b, val_t val) { 51 | propagate(cur, l, r); 52 | if (b < l || r < a) return; 53 | if (a <= l && r <= b) { 54 | st[cur].update_lazy(val); 55 | propagate(cur, l, r); 56 | return; 57 | } 58 | int m = (l + r) / 2; 59 | update(2 * cur, l, m, a, b, val); 60 | update(2 * cur + 1, m + 1, r, a, b, val); 61 | st[cur] = st[2 * cur].combine(st[2 * cur + 1]); 62 | } 63 | node_t query(int cur, int l, int r, int a, int b) { 64 | propagate(cur, l, r); 65 | if (b < l || r < a) return st[cur].neutral(); 66 | if (a <= l && r <= b) return st[cur]; 67 | int m = (l + r) / 2; 68 | node_t left = query(2 * cur, l, m, a, b); 69 | node_t right = query(2 * cur + 1, m + 1, r, a, b); 70 | node_t ans = left.combine(right); 71 | return ans; 72 | } 73 | }; 74 | } // namespace SegmentTree 75 | -------------------------------------------------------------------------------- /codes/strings/aho_corasick.cpp: -------------------------------------------------------------------------------- 1 | class AhoCorasick { 2 | public: 3 | const static int ALPHABET_SIZE = 26; 4 | 5 | struct Vertex { 6 | std::array next; 7 | int p = -1; 8 | char pch; 9 | int depth = 0; 10 | int link = 0; 11 | int next_terminal = 0; 12 | std::array go; 13 | bool terminal = false; 14 | 15 | // extra values 16 | int value = 0; 17 | int value_acc = 0; 18 | // vector< pair > occ; 19 | 20 | Vertex(int p, char ch, int depth) : p(p), pch(ch), depth(depth) { 21 | std::fill(next.begin(), next.end(), 0); 22 | std::fill(go.begin(), go.end(), 0); 23 | } 24 | }; 25 | 26 | std::vector t; 27 | 28 | AhoCorasick() : t(1, {-1, '$', 0}) {} 29 | 30 | void add(std::string const& s, int value, int x = -1) { 31 | int v = 0; 32 | for (char ch : s) { 33 | int c = ch - 'a'; 34 | if (!t[v].next[c]) { 35 | t[v].next[c] = t.size(); 36 | t.emplace_back(v, ch, t[v].depth + 1); 37 | } 38 | v = t[v].next[c]; 39 | } 40 | t[v].terminal = true; 41 | t[v].value += value; 42 | // t[v].occ.pb(ii(value, x)); 43 | } 44 | 45 | void push_links() { 46 | std::queue q; 47 | q.push(0); 48 | while (!q.empty()) { 49 | int v = q.front(); 50 | auto& cur = t[v]; 51 | auto& link = t[cur.link]; 52 | q.pop(); 53 | cur.next_terminal = link.terminal ? cur.link : link.next_terminal; 54 | cur.value_acc = link.value_acc + (cur.terminal ? cur.value : 0); 55 | // for(ii x : t[cur.next_terminal].occ) cur.occ.pb(x); 56 | for (int c = 0; c < ALPHABET_SIZE; c++) { 57 | if (cur.next[c]) { 58 | t[cur.next[c]].link = v ? link.next[c] : 0; 59 | q.push(cur.next[c]); 60 | } else { 61 | cur.next[c] = link.next[c]; 62 | } 63 | } 64 | } 65 | } 66 | 67 | int go(int idx, char c) { 68 | return t[idx].next[c - 'a']; 69 | } 70 | 71 | pair get_val(int idx){ 72 | return mp(t[idx].terminal, t[idx].value); 73 | } 74 | 75 | int get_acc(int idx){ 76 | return t[idx].value_acc; 77 | } 78 | 79 | int get_next_terminal(int idx){ 80 | return t[idx].next_terminal; 81 | } 82 | }; 83 | -------------------------------------------------------------------------------- /codes/graphs/dominator_tree.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Dominator Trees 3 | */ 4 | 5 | template 6 | struct LinkDsu { 7 | vector r; 8 | vector best; 9 | LinkDsu(int n = 0) { 10 | r = vector(n); 11 | iota(r.begin(), r.end(), 0); 12 | best = vector(n); 13 | } 14 | 15 | int find(int u) { 16 | if (r[u] == u) 17 | return u; 18 | else { 19 | int v = find(r[u]); 20 | if (best[r[u]] < best[u]) best[u] = best[r[u]]; 21 | return r[u] = v; 22 | } 23 | } 24 | 25 | T eval(int u) { 26 | find(u); 27 | return best[u]; 28 | } 29 | void link(int p, int u) { r[u] = p; } 30 | void set(int u, T x) { best[u] = x; } 31 | }; 32 | 33 | struct DominatorTree { 34 | typedef vector> Graph; 35 | vector semi, dom, parent, st, from; 36 | Graph succ, pred, bucket; 37 | int r, n, tempo; 38 | 39 | void dfs(int u, int p) { 40 | semi[u] = u; 41 | from[st[u] = tempo++] = u; 42 | parent[u] = p; 43 | for (int v : succ[u]) { 44 | pred[v].push_back(u); 45 | if (semi[v] == -1) { 46 | dfs(v, u); 47 | } 48 | } 49 | } 50 | 51 | void build() { 52 | n = succ.size(); 53 | dom.assign(n, -1); 54 | semi.assign(n, -1); 55 | parent.assign(n, -1); 56 | st.assign(n, 0); 57 | from.assign(n, -1); 58 | pred = Graph(n, vector()); 59 | bucket = Graph(n, vector()); 60 | LinkDsu> dsu(n); 61 | tempo = 0; 62 | 63 | dfs(r, r); 64 | for (int i = 0; i < n; i++) dsu.set(i, make_pair(st[i], i)); 65 | 66 | for (int i = tempo - 1; i; i--) { 67 | int u = from[i]; 68 | for (int v : pred[u]) { 69 | int w = dsu.eval(v).second; 70 | if (st[semi[w]] < st[semi[u]]) { 71 | semi[u] = semi[w]; 72 | } 73 | } 74 | dsu.set(u, make_pair(st[semi[u]], u)); 75 | bucket[semi[u]].push_back(u); 76 | dsu.link(parent[u], u); 77 | for (int v : bucket[parent[u]]) { 78 | int w = dsu.eval(v).second; 79 | dom[v] = semi[w] == parent[u] ? parent[u] : w; 80 | } 81 | bucket[parent[u]].clear(); 82 | } 83 | for (int i = 1; i < tempo; i++) { 84 | int u = from[i]; 85 | if (dom[u] != semi[u]) dom[u] = dom[dom[u]]; 86 | } 87 | } 88 | 89 | DominatorTree(const Graph& g, int s) : succ(g), r(s) { build(); } 90 | }; 91 | -------------------------------------------------------------------------------- /codes/math_nt/ntt.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Obs: this is a fork from kactl 3 | * Author: chilli 4 | * Date: 2019-04-16 5 | * License: CC0 6 | * Source: based on KACTL's FFT 7 | * Description: ntt(a) computes $\hat f(k) = \sum_x a[x] g^{xk}$ for all $k$, where $g=\text{root}^{(mod-1)/N}$. 8 | * N must be a power of 2. 9 | * Useful for convolution modulo specific nice primes of the form $2^a b+1$, 10 | * where the convolution result has size at most $2^a$. For arbitrary modulo, see FFTMod. 11 | \texttt{conv(a, b) = c}, where $c[x] = \sum a[i]b[x-i]$. 12 | For manual convolution: NTT the inputs, multiply 13 | pointwise, divide by n, reverse(start+1, end), NTT back. 14 | * Inputs must be in [0, mod). 15 | * Time: O(N \log N) 16 | * Status: stress-tested 17 | * Source: https://github.com/kth-competitive-programming/kactl/blob/master/content/numerical/NumberTheoreticTransform.h 18 | */ 19 | 20 | namespace NTT { 21 | const ll mod = (119 << 23) + 1, root = 62; // = 998244353 22 | // For p < 2^30 there is also e.g. 5 << 25, 7 << 26, 479 << 21 23 | // and 483 << 21 (same root). The last two are > 10^9. 24 | typedef vector poly; 25 | int sz(const poly& x) { return x.size(); } 26 | void ntt(poly& a) { 27 | int n = sz(a), L = 31 - __builtin_clz(n); 28 | static poly rt(2, 1); 29 | for (static int k = 2, s = 2; k < n; k *= 2, s++) { 30 | rt.resize(n); 31 | ll z[] = {1, exp(root, mod >> s)}; 32 | for (int i = k; i < 2 * k; i++) rt[i] = rt[i / 2] * z[i & 1] % mod; 33 | } 34 | vi rev(n); 35 | for (int i = 0; i < n; i++) rev[i] = (rev[i / 2] | (i & 1) << L) / 2; 36 | for (int i = 0; i < n; i++) 37 | if (i < rev[i]) swap(a[i], a[rev[i]]); 38 | for (int k = 1; k < n; k *= 2) 39 | for (int i = 0; i < n; i += 2 * k) 40 | for (int j = 0; j < k; j++) { 41 | ll z = rt[j + k] * a[i + j + k] % mod, &ai = a[i + j]; 42 | a[i + j + k] = ai - z + (z > ai ? mod : 0); 43 | ai += (ai + z >= mod ? z - mod : z); 44 | } 45 | } 46 | poly Multiply(const poly& a, const poly& b) { 47 | if (a.empty() || b.empty()) return {}; 48 | int s = sz(a) + sz(b) - 1, B = 32 - __builtin_clz(s), n = 1 << B; 49 | int inv = exp(n, mod - 2); 50 | poly L(a), R(b), out(n); 51 | L.resize(n), R.resize(n); 52 | ntt(L), ntt(R); 53 | for (int i = 0; i < n; i++) 54 | out[-i & (n - 1)] = (ll)L[i] * R[i] % mod * inv % mod; 55 | ntt(out); 56 | return {out.begin(), out.begin() + s}; 57 | } 58 | } // namespace NTT 59 | -------------------------------------------------------------------------------- /codes/data_structures/RangeUpdateDynamicSegmentTree.cpp: -------------------------------------------------------------------------------- 1 | namespace RangeDynamicSegmentTree { 2 | 3 | struct Node { 4 | Node *left, *right; 5 | int x = 0; 6 | int lazy = 0; 7 | Node() { 8 | left = nullptr; 9 | right = nullptr; 10 | x = 0; 11 | lazy = 0; 12 | } 13 | 14 | Node(Node* n) { 15 | left = n ? n->left : nullptr; 16 | right = n ? n->right : nullptr; 17 | x = n ? n->x : 0; 18 | lazy = n ? n->lazy : 0; 19 | } 20 | }; 21 | 22 | void push(Node* cur, int l, int r) { 23 | if (!cur) return; 24 | if (!cur->lazy) return; 25 | cur->x += cur->lazy; 26 | if (l != r) { 27 | cur->left = new Node(cur->left); 28 | cur->left->lazy += cur->lazy; 29 | 30 | cur->right = new Node(cur->right); 31 | cur->right->lazy += cur->lazy; 32 | } 33 | cur->lazy = 0; 34 | } 35 | 36 | void merge(Node* cur) { 37 | cur->x = 38 | max((cur->left ? cur->left->x : 0), (cur->right ? cur->right->x : 0)); 39 | } 40 | 41 | Node* update(Node* cur, int l, int r, int a, int b, int val) { 42 | assert(cur != nullptr); 43 | Node* new_cur = new Node(cur); 44 | push(new_cur, l, r); 45 | if (l == a && b == r) { 46 | new_cur->lazy += val; 47 | push(new_cur, l, r); 48 | return new_cur; 49 | } 50 | 51 | int m = (l + r) >> 1; 52 | if (b <= m) { 53 | if (!new_cur->left) new_cur->left = new Node(); 54 | new_cur->left = update(new_cur->left, l, m, a, b, val); 55 | push(new_cur->right, m + 1, r); 56 | } else if (m < a) { 57 | if (!new_cur->right) new_cur->right = new Node(); 58 | new_cur->right = update(new_cur->right, m + 1, r, a, b, val); 59 | push(new_cur->left, l, m); 60 | } else { 61 | if (!new_cur->left) new_cur->left = new Node(); 62 | if (!new_cur->right) new_cur->right = new Node(); 63 | new_cur->left = update(new_cur->left, l, m, a, m, val); 64 | new_cur->right = update(new_cur->right, m + 1, r, m + 1, b, val); 65 | } 66 | 67 | merge(new_cur); 68 | return new_cur; 69 | } 70 | 71 | int query(Node* cur, int l, int r, int a, int b) { 72 | assert(cur != nullptr); 73 | if (r < a || b < l) return 0; 74 | push(cur, l, r); 75 | if (a <= l and r <= b) { 76 | return cur->x; 77 | } 78 | int m = (l + r) >> 1; 79 | int ansl = 0, ansr = 0; 80 | if (cur->left) ansl = query(cur->left, l, m, a, b); 81 | if (cur->right) ansr = query(cur->right, m + 1, r, a, b); 82 | return max(ansl, ansr); 83 | } 84 | 85 | }; // namespace RangeDynamicSegmentTree 86 | -------------------------------------------------------------------------------- /codes/data_structures/DynamicSegmentTree.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Neto 2 | * Dynammic SegmentTree Structure 3 | */ 4 | namespace DynamicSegmentTree { 5 | 6 | struct node { 7 | node *left, *right; 8 | // attributes of node 9 | node() { 10 | // initialize attributes 11 | left = NULL; 12 | right = NULL; 13 | } 14 | }; 15 | 16 | void combine(node *ans, node *left, node *right) { 17 | // combine operation 18 | } 19 | 20 | void propagate(node *root, int l, int r) { 21 | // check if exists lazy 22 | 23 | // apply lazy on node 24 | 25 | // propagate 26 | if (!root->left) root->left = new node(); 27 | if (!root->right) root->right = new node(); 28 | 29 | if (l != r) { 30 | // propagate operation 31 | } 32 | 33 | // reset lazy 34 | } 35 | 36 | void build(node *root, int l, int r) { 37 | if (l == r) { 38 | // leaf operation 39 | return; 40 | } 41 | int m = (l + r) >> 1; 42 | if (!root->left) root->left = new node(); 43 | if (!root->right) root->right = new node(); 44 | build(root->left, l, m); 45 | build(root->right, m + 1, r); 46 | combine(root, root->left, root->right); 47 | } 48 | 49 | void update(node *root, int l, int r, int a, int b, int val) { 50 | propagate(root, l, r); 51 | if (l == a && r == b) { 52 | // do lazy operation 53 | return; 54 | } 55 | int m = (l + r) >> 1; 56 | if (!root->left) root->left = new node(); 57 | if (!root->right) root->right = new node(); 58 | if (b <= m) 59 | update(root->left, l, m, a, b, val); 60 | else if (m < a) 61 | update(root->right, m + 1, r, a, b, val); 62 | else { 63 | update(root->left, l, m, a, m, val); 64 | update(root->right, m + 1, r, m + 1, b, val); 65 | } 66 | propagate(root, l, r); 67 | propagate(root->left, l, m); 68 | propagate(root->right, m + 1, r); 69 | combine(root, root->left, root->right); 70 | } 71 | 72 | node *query(node *root, int l, int r, int a, int b) { 73 | propagate(root, l, r); 74 | if (l == a && r == b) { 75 | return root; 76 | } 77 | int m = (l + r) >> 1; 78 | if (!root->left) root->left = new node(); 79 | if (!root->right) root->right = new node(); 80 | if (b <= m) 81 | return query(root->left, l, m, a, b); 82 | else if (m < a) 83 | return query(root->right, m + 1, r, a, b); 84 | node *left = query(root->left, l, m, a, m); 85 | node *right = query(root->right, m + 1, r, m + 1, b); 86 | node *ans = new node(); 87 | combine(ans, left, right); 88 | return ans; 89 | } 90 | 91 | } // namespace DynamicSegmentTree 92 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ubiratan Correia Barbosa Neto - Competitive Programming Library 2 | 3 | This repository contains algorithms that I learned through my journey on competitive programming: 4 | 5 | * Data Structures 6 | * Segment Tree 7 | * Binary Indexed Tree 8 | * Dynamic/Persistent Segment Tree 9 | * Trie 10 | * Lichao Segment Tree (Online Convex Hull Trick)/ Integer and Float Version 11 | * Offline Convex Hull Trick 12 | * Ordered Set 13 | * Implicit Treap 14 | * Splay Tree 15 | 16 | * Uncategorized 17 | * Longest Increase Subsequence 18 | * 2D Longest Increase Subsequence 19 | * Inversion Count Offline (Merge-Sort) 20 | * Mos Query Decomposition 21 | * Find kth permutation 22 | 23 | * Basic 2D Geometry 24 | * Point/Vector Structure 25 | * Vector Structure 26 | * Line/Segment Structure 27 | * Distance from Point to Line 28 | * Distance from Point to Segment 29 | * Distance from Line to Segment 30 | * Distance from Point to Ray 31 | * Distance from Segment to Ray 32 | * Distance from Line to Ray 33 | * Distance between Segments 34 | * Distance between Rays 35 | * Distance between Lines 36 | * Line-Line Intersection 37 | * Segment-Segment Intersection 38 | * Line-Segment Intersection 39 | * Circle-Circle Intersection Area 40 | * Circle-Circle Intersection Points (NOT TESTED) 41 | * Tangent Line to a Circle Given a Point 42 | * Circle of Radius R Passing Through 2 Given Points 43 | * Barycenter, Circumcenter, Incenter, Excenter, Orthocenter, Centroid... 44 | 45 | * 2D Geometry Algorithms 46 | * Closest Pair of Points 47 | * Convex Hull(Monotone Chain) + Perimeter/Area Calculation 48 | * Smallest Enclosing Circle Randomized Algorithm 49 | * Check if a Point Lies in Convex Hull 50 | * Largest quadrilater given a set of distinct points 51 | * Check if line intersects polygon 52 | * Maximum dot product queries 53 | 54 | * Math and Number Theory 55 | * Binomial Coefficient 56 | * Euler Totient 57 | * Sieve of Erathostenes 58 | * Miller Rabin Primality Test 59 | * Count Primes/Divisors for Large Numbers + Sum Of Divisors of a Number 60 | * Matrix Exponentiation 61 | * Fast Fourier Transform (Iterative + Recursive) 62 | * Chinese Remainder Theorem 63 | * Diophantine Equations 64 | * Shank's Baby-Step Giant-Steps 65 | 66 | * Strings 67 | * Knuth - Morris - Pratt (KMP) 68 | * Z-Function 69 | * Rolling Hash 70 | * Aho-Corasick 71 | * Suffix Array + Linear Sorting (O(nlogn) S.Array) 72 | 73 | * Graphs 74 | * LCA 75 | * Max-Flow (Dinic's Algorithm) 76 | * Minimum Path Cover in Directed Acyclic Graphs 77 | * Minimum Edge Cover in Bipartite Graph 78 | * Minimum Cut in Flow Network 79 | * Minimum Vertex Cover in Bipartite Graph 80 | * Bellman Ford Shortest Path Algorithm 81 | * Dynammic Connectivity for connected(u,v) - query 82 | * Eulerian Circuit Directed/Undirected Graphs 83 | * Tarjan Algorithm for Bridges/Articulation Points 84 | * Heavy-Light Decomposition 85 | * Centroid Decomposition 86 | * Kosaraju's Strong Connected Components Algorithm 87 | 88 | -------------------------------------------------------------------------------- /codes/uncategorized/lis2d.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Longest Increasing Subsequence 2D 3 | */ 4 | 5 | struct LIS2D { 6 | struct node { 7 | node *left, *right; 8 | int mx = (int)1e18 + 1; 9 | node() { 10 | mx = (int)1e18 + 1; 11 | left = NULL; 12 | right = NULL; 13 | } 14 | }; 15 | 16 | LIS2D() {} 17 | 18 | vector lis; 19 | int L, R, size; 20 | 21 | void combine(node *ans, node *left, node *right) { 22 | if (left && right) 23 | ans->mx = min(left->mx, right->mx); 24 | else if (left) 25 | ans->mx = left->mx; 26 | else if (right) 27 | ans->mx = right->mx; 28 | else 29 | ans->mx = (int)1e18 + 1; 30 | } 31 | 32 | void update(node *root, int l, int r, int idx, int val) { 33 | if (l == r) { 34 | root->mx = min(root->mx, val); 35 | return; 36 | } 37 | int m = (l + r) >> 1; 38 | if (idx <= m) { 39 | if (!root->left) root->left = new node(); 40 | update(root->left, l, m, idx, val); 41 | } else { 42 | if (!root->right) root->right = new node(); 43 | update(root->right, m + 1, r, idx, val); 44 | } 45 | combine(root, root->left, root->right); 46 | } 47 | 48 | int query(node *root, int l, int r, int a, int b) { 49 | if (l == a && r == b) { 50 | return root->mx; 51 | } 52 | int m = (l + r) >> 1; 53 | if (b <= m) { 54 | if (!root->left) 55 | return (int)1e18 + 1; 56 | else 57 | return query(root->left, l, m, a, b); 58 | } else if (m < a) { 59 | if (!root->right) 60 | return (int)1e18 + 1; 61 | else 62 | return query(root->right, m + 1, r, a, b); 63 | } 64 | int left = (int)1e18 + 1; 65 | int right = (int)1e18 + 1; 66 | if (root->left) left = query(root->left, l, m, a, m); 67 | if (root->right) right = query(root->right, m + 1, r, m + 1, b); 68 | return min(left, right); 69 | } 70 | 71 | bool check(int id, int x, int y) { 72 | int val = query(lis[id], L, R, L, x - 1); 73 | return val < y; 74 | } 75 | 76 | void calculate(vector &v) { 77 | int n = v.size(); 78 | lis.resize(n + 1); 79 | set sx; 80 | vector aux; 81 | for (int i = 0; i < n; i++) { 82 | sx.insert(v[i].ff); 83 | } 84 | for (int x : sx) aux.pb(x); 85 | L = -1, R = sx.size(); 86 | for (int i = 0; i < n; i++) { 87 | v[i].ff = lower_bound(aux.begin(), aux.end(), v[i].ff) - aux.begin(); 88 | } 89 | for (int i = 0; i <= n; i++) { 90 | lis[i] = new node(); 91 | } 92 | update(lis[0], L, R, L, -(int)1e18 - 1); 93 | size = 0; 94 | for (ii par : v) { 95 | int x = par.ff, y = par.ss; 96 | int l = 0, r = n - 1; 97 | int ans = 0; 98 | while (l <= r) { 99 | int m = (l + r) >> 1; 100 | if (check(m, x, y)) { 101 | ans = m; 102 | l = m + 1; 103 | } else 104 | r = m - 1; 105 | } 106 | size = max(size, ans + 1); 107 | update(lis[ans + 1], L, R, x, y); 108 | } 109 | } 110 | }; 111 | 112 | int32_t main() { 113 | int n; 114 | scanf("%d", &n); 115 | vector v(n); 116 | set sx; 117 | vector aux; 118 | for (int i = 0; i < n; i++) { 119 | scanf("%d%d", &v[i].ff, &v[i].ss); 120 | } 121 | LIS2D lis2d; 122 | lis2d.calculate(v); 123 | printf("%d\n", lis2d.size); 124 | } 125 | -------------------------------------------------------------------------------- /codes/math_nt/crt_diophantine.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Diophantine and CRT 3 | */ 4 | 5 | namespace NT { 6 | 7 | int GCD(int a, int b) { 8 | if (a == 0) 9 | return b; 10 | else 11 | return GCD(b % a, a); 12 | } 13 | 14 | tuple shift_solution(int a, int b, int g, int s1, int s2) { 15 | // shifts solution 16 | int l = 0, r = 1e9; 17 | int ans = -1; 18 | while (l <= r) { 19 | int m = (l + r) >> 1; 20 | if (s2 + m * (a / g) >= 0) { 21 | ans = m; 22 | r = m - 1; 23 | } else 24 | l = m + 1; 25 | } 26 | if (ans != -1) { 27 | s1 = s1 - ans * (b / g); 28 | s2 = s2 + ans * (a / g); 29 | } 30 | 31 | l = 0, r = 1e9; 32 | ans = -1; 33 | while (l <= r) { 34 | int m = (l + r) >> 1; 35 | if (s1 + m * (a / g) >= 0) { 36 | ans = m; 37 | r = m - 1; 38 | } else 39 | l = m + 1; 40 | } 41 | if (ans != -1) { 42 | s1 = s1 + ans * (b / g); 43 | s2 = s2 - ans * (a / g); 44 | } 45 | 46 | l = 0, r = 1e9; 47 | ans = -1; 48 | while (l <= r) { 49 | int m = (l + r) >> 1; 50 | if (s1 - m * (a / g) <= s2 + m * (b / g)) { 51 | ans = m; 52 | r = m - 1; 53 | } else 54 | l = m + 1; 55 | } 56 | if (ans != -1) { 57 | s1 = s1 - ans * (b / g); 58 | s2 = s2 + ans * (a / g); 59 | } 60 | 61 | return make_tuple(s1, s2); 62 | } 63 | 64 | tuple ExtendedEuclidean(int a, int b) { 65 | // solves ax+by = gcd(a,b) 66 | // careful when a or b equal to 0 67 | if (a == 0) return make_tuple(0, 1); 68 | int x, y; 69 | tie(x, y) = ExtendedEuclidean(b % a, a); 70 | return make_tuple(y - (b / a) * x, x); 71 | } 72 | 73 | bool FailCoprime = false; 74 | int CoprimeInverse(int a, int m) { 75 | FailCoprime = false; 76 | if (NT::GCD(a, m) != 1) { 77 | FailCoprime = true; 78 | return -1; 79 | } 80 | int s1, s2; 81 | tie(s1, s2) = ExtendedEuclidean(a, m); 82 | return (s1 % m + m) % m; 83 | } 84 | 85 | bool FailDiophantine = false; 86 | 87 | tuple Diophantine(int a, int b, int c, bool shift = true) { 88 | FailDiophantine = false; 89 | // finds a solution for ax+by = c 90 | // given a solution (x,y), all solutions have the form (x + m*(b/gcd(a,b)), y 91 | // - m*(a/(gcd(a,b))), multiplied by (c/g) 92 | 93 | int g = GCD(a, b); 94 | 95 | if (g == 0 || c % g != 0) { 96 | FailDiophantine = true; 97 | return make_tuple(0, 0); 98 | } 99 | 100 | int x, y; 101 | 102 | tie(x, y) = ExtendedEuclidean(a, b); 103 | int s1 = x * (c / g), s2 = y * (c / g); 104 | 105 | // shift 106 | if (!shift) 107 | return make_tuple(s1, s2); 108 | else 109 | return shift_solution(a, b, g, s1, s2); 110 | } 111 | 112 | bool FailCRT = false; 113 | 114 | tuple CRT(vector& a, vector& n) { 115 | FailCRT = false; 116 | for (int i = 0; i < a.size(); i++) a[i] = mod(a[i], n[i]); 117 | int ans = a[0]; 118 | int modulo = n[0]; 119 | 120 | for (int i = 1; i < a.size(); i++) { 121 | int x, y; 122 | tie(x, y) = ExtendedEuclidean(modulo, n[i]); 123 | int g = GCD(modulo, n[i]); 124 | 125 | if (g == 0 || (a[i] - ans) % g != 0) { 126 | FailCRT = true; 127 | return make_tuple(0, 0); 128 | } 129 | 130 | ans = mod(ans + (x * ((a[i] - ans) / g)) % (n[i] / g) * modulo, 131 | modulo * (n[i] / g)); 132 | modulo = modulo * (n[i] / g); 133 | } 134 | 135 | return make_tuple(ans, modulo); 136 | } 137 | 138 | } // namespace NT 139 | -------------------------------------------------------------------------------- /codes/data_structures/splay_tree.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class SplayTree { 3 | public: 4 | struct SplayNode { 5 | SplayNode *parent, *child[2]; 6 | int subtree_sz; 7 | T value; 8 | SplayNode(T value) { 9 | parent = nullptr; 10 | subtree_sz = 1; 11 | this->value = value; 12 | child[0] = nullptr; 13 | child[1] = nullptr; 14 | } 15 | SplayNode(SplayNode* parent, SplayNode* lef, SplayNode* rig, T value) { 16 | this->parent = parent; 17 | this->value = value; 18 | child[0] = lef; 19 | child[1] = rig; 20 | subtree_sz = 1; 21 | } 22 | }; 23 | 24 | SplayNode* create(T value) { return new SplayNode(value); } 25 | 26 | SplayNode* get_root() { return root; } 27 | 28 | int subtree_size(SplayNode* cur) { return (cur ? cur->subtree_sz : 0); } 29 | 30 | void splay(SplayNode* cur) { 31 | while (cur->parent) { 32 | SplayNode* p = cur->parent; 33 | if (p->parent && get_id(p) == get_id(cur)) _rotate(p); 34 | _rotate(cur); 35 | } 36 | _update_subtree_size(cur); 37 | } 38 | 39 | void insert(SplayNode* const x) { 40 | if (!root) { 41 | root = x; 42 | return; 43 | } 44 | SplayNode* cur = root; 45 | while (true) { 46 | SplayNode*& nxt = cur->child[x->value > cur->value]; 47 | if (!nxt) { 48 | nxt = x; 49 | nxt->parent = cur; 50 | splay(nxt); 51 | return; 52 | } else { 53 | cur = nxt; 54 | } 55 | } 56 | } 57 | 58 | void remove(SplayNode* const x) { 59 | splay(x); 60 | 61 | if (!x->child[0] && !x->child[1]) { 62 | root = nullptr; 63 | } else if (!x->child[0]) { 64 | root = x->child[1]; 65 | } else if (!x->child[1]) { 66 | root = x->child[0]; 67 | } else { 68 | SplayNode* nxt = x->child[0]; 69 | while (nxt->child[1]) nxt = nxt->child[1]; 70 | splay(nxt); 71 | nxt->child[1] = x->child[1]; 72 | x->child[1]->parent = nxt; 73 | root = nxt; 74 | } 75 | if (root) root->parent = nullptr; 76 | } 77 | 78 | SplayNode* find_one(T value) { 79 | SplayNode* cur = root; 80 | while (cur && cur->value != value) { 81 | SplayNode* const nxt = cur->child[cur->value < value]; 82 | if (!nxt) splay(cur); 83 | cur = nxt; 84 | } 85 | return cur; 86 | } 87 | 88 | // 1-based 89 | SplayNode* find_kth(int kth) { 90 | SplayNode* cur = root; 91 | while (cur) { 92 | int sz = subtree_size(cur->child[0]); 93 | if (sz + 1 == kth) return cur; 94 | if (kth <= sz) { 95 | cur = cur->child[0]; 96 | } else { 97 | kth -= sz; 98 | cur = cur->child[1]; 99 | } 100 | } 101 | return cur; 102 | } 103 | 104 | private: 105 | SplayNode* root; 106 | bool get_id(SplayNode* cur) { return cur == cur->parent->child[1]; } 107 | 108 | void _rotate(SplayNode* cur) { 109 | SplayNode* p = cur->parent; 110 | int id = get_id(cur); 111 | _set_child(p, cur->child[!id], id); 112 | if (p->parent) { 113 | _set_child(p->parent, cur, get_id(p)); 114 | } else { 115 | cur->parent = nullptr; 116 | root = cur; 117 | } 118 | _set_child(cur, p, !id); 119 | _update_subtree_size(p); 120 | } 121 | 122 | void _update_subtree_size(SplayNode* cur) { 123 | if (!cur) return; 124 | cur->subtree_sz = 125 | subtree_size(cur->child[0]) + 1 + subtree_size(cur->child[1]); 126 | } 127 | 128 | void _set_child(SplayNode* u, SplayNode* v, int ch) { 129 | u->child[ch] = v; 130 | if (v) v->parent = u; 131 | } 132 | }; 133 | -------------------------------------------------------------------------------- /codes/math_nt/simplex.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * I'm not the author. Just adding for simple copy-paste 3 | * Source: kth-competitive-programming / kactl 4 | * Link: 5 | * https://github.com/kth-competitive-programming/kactl/blob/master/content/numerical/Simplex.h 6 | * Simplex slightly modified 7 | */ 8 | namespace LinearProgramming { 9 | /** 10 | * Author: Stanford 11 | * Source: Stanford Notebook 12 | * License: MIT 13 | * Description: Solves a general linear maximization problem: maximize $c^T x$ 14 | * subject to $Ax \le b$, $x \ge 0$. Returns -inf if there is no solution, inf 15 | * if there are arbitrarily good solutions, or the maximum value of $c^T x$ 16 | * otherwise. The input vector is set to an optimal $x$ (or in the unbounded 17 | * case, an arbitrary solution fulfilling the constraints). Numerical stability 18 | * is not guaranteed. For better performance, define variables such that $x = 0$ 19 | * is viable. Usage: vvd A = {{1,-1}, {-1,1}, {-1,-2}}; vd b = {1,1,-4}, c = 20 | * {-1,-1}, x; T val = LPSolver(A, b, c).solve(x); Time: O(NM * \#pivots), where 21 | * a pivot may be e.g. an edge relaxation. O(2^n) in the general case. Status: 22 | * seems to work? 23 | */ 24 | 25 | typedef double T; // long double, Rational, double + mod

... 26 | typedef vector vd; // Vector 27 | typedef vector vvd; // Matrix 28 | 29 | const T eps = 1e-8, inf = 1 / .0; 30 | #define lpsolver_ltj(X) \ 31 | if (s == -1 || mp(X[j], N[j]) < mp(X[s], N[s])) s = j 32 | 33 | struct LPSolver { 34 | int m, n; 35 | vi N, B; 36 | vvd D; 37 | 38 | int sz(const vd& v) { return (int)(v.size()); } 39 | 40 | LPSolver(const vvd& A, const vd& b, const vd& c) 41 | : m(sz(b)), n(sz(c)), N(n + 1), B(m), D(m + 2, vd(n + 2)) { 42 | rep(i, 0, m, 1) rep(j, 0, n, 1) D[i][j] = A[i][j]; 43 | rep(i, 0, m, 1) { 44 | B[i] = n + i; 45 | D[i][n] = -1; 46 | D[i][n + 1] = b[i]; 47 | } 48 | rep(j, 0, n, 1) { 49 | N[j] = j; 50 | D[m][j] = -c[j]; 51 | } 52 | N[n] = -1; 53 | D[m + 1][n] = 1; 54 | } 55 | 56 | void pivot(int r, int s) { 57 | T *a = D[r].data(), inv = 1 / a[s]; 58 | rep(i, 0, m + 2, 1) if (i != r && abs(D[i][s]) > eps) { 59 | T *b = D[i].data(), inv2 = b[s] * inv; 60 | rep(j, 0, n + 2, 1) b[j] -= a[j] * inv2; 61 | b[s] = a[s] * inv2; 62 | } 63 | rep(j, 0, n + 2, 1) if (j != s) D[r][j] *= inv; 64 | rep(i, 0, m + 2, 1) if (i != r) D[i][s] *= -inv; 65 | D[r][s] = inv; 66 | swap(B[r], N[s]); 67 | } 68 | 69 | bool simplex(int phase) { 70 | int x = m + phase - 1; 71 | for (;;) { 72 | int s = -1; 73 | rep(j, 0, n + 1, 1) if (N[j] != -phase) lpsolver_ltj(D[x]); 74 | if (D[x][s] >= -eps) return true; 75 | int r = -1; 76 | rep(i, 0, m, 1) { 77 | if (D[i][s] <= eps) continue; 78 | if (r == -1 || 79 | mp(D[i][n + 1] / D[i][s], B[i]) < mp(D[r][n + 1] / D[r][s], B[r])) 80 | r = i; 81 | } 82 | if (r == -1) return false; 83 | pivot(r, s); 84 | } 85 | } 86 | 87 | T solve(vd& x) { 88 | int r = 0; 89 | rep(i, 1, m, 1) if (D[i][n + 1] < D[r][n + 1]) r = i; 90 | if (D[r][n + 1] < -eps) { 91 | pivot(r, n); 92 | if (!simplex(2) || D[m + 1][n + 1] < -eps) return -inf; 93 | rep(i, 0, m, 1) if (B[i] == -1) { 94 | int s = 0; 95 | rep(j, 1, n + 1, 1) lpsolver_ltj(D[i]); 96 | pivot(i, s); 97 | } 98 | } 99 | bool ok = simplex(1); 100 | x = vd(n); 101 | rep(i, 0, m, 1) if (B[i] < n) x[B[i]] = D[i][n + 1]; 102 | return ok ? D[m][n + 1] : inf; 103 | } 104 | }; 105 | 106 | } // namespace LinearProgramming 107 | -------------------------------------------------------------------------------- /codes/graphs/euler.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Eulerian Path / Circuit 3 | * REMEMBER TO CHECK IF PATH/CIRCUIT HAS THE DESIRED SIZE (OR COVER ALL VERTEX) 4 | */ 5 | 6 | struct EulerianCircuit { 7 | vector> g; 8 | vector> back_ref; 9 | vector walk; 10 | vector deg, indeg, outdeg; 11 | bool directed; 12 | 13 | EulerianCircuit(int n, bool directed) : directed(directed) { 14 | if (directed) { 15 | indeg.resize(n + 1, 0); 16 | outdeg.resize(n + 1, 0); 17 | } else { 18 | deg.resize(n + 1, 0); 19 | back_ref.resize(n + 1); 20 | } 21 | g.resize(n + 1); 22 | } 23 | 24 | void add_directed_edge(int u, int v) { 25 | outdeg[u]++; 26 | indeg[v]++; 27 | g[u].pb(v); 28 | } 29 | 30 | void add_undirected_edge(int u, int v) { 31 | deg[u]++; 32 | deg[v]++; 33 | g[u].pb(v); 34 | g[v].pb(u); 35 | if (u != v) { 36 | int ref_u = g[v].size() - 1; 37 | int ref_v = g[u].size() - 1; 38 | back_ref[u].pb(ref_u); 39 | back_ref[v].pb(ref_v); 40 | } else { 41 | int cur = back_ref[u].size(); 42 | back_ref[u].pb(cur + 1); 43 | back_ref[u].pb(cur); 44 | } 45 | } 46 | 47 | void add_edge(int u, int v) { 48 | if (directed) 49 | add_directed_edge(u, v); 50 | else 51 | add_undirected_edge(u, v); 52 | } 53 | 54 | void undirected_euler(int u) { 55 | while (g[u].size() > 0) { 56 | if (g[u].back() < 0) { 57 | g[u].pop_back(); 58 | back_ref[u].pop_back(); 59 | continue; 60 | } 61 | int v = g[u].back(); 62 | int ref = back_ref[u].back(); 63 | g[u].pop_back(); 64 | back_ref[u].pop_back(); 65 | 66 | if (g[v].size() > ref) g[v][ref] = -1; 67 | 68 | undirected_euler(v); 69 | } 70 | walk.push_back(u); 71 | } 72 | 73 | void directed_euler(int u) { 74 | while (g[u].size() > 0) { 75 | int v = g[u].back(); 76 | 77 | g[u].pop_back(); 78 | 79 | directed_euler(v); 80 | } 81 | 82 | walk.push_back(u); 83 | } 84 | bool process_directed_euler(bool path = false, int root = 1) { 85 | int inp = -1, out = -1; 86 | if (path) { 87 | for (int i = 1; i < g.size(); i++) { 88 | if (outdeg[i] - indeg[i] == 1) { 89 | if (out != -1) return false; 90 | out = i; 91 | } 92 | if (indeg[i] - outdeg[i] == 1) { 93 | if (inp != -1) return false; 94 | inp = i; 95 | } 96 | } 97 | if (inp == -1 || out == -1) return false; 98 | add_directed_edge(inp, out); 99 | directed_euler(inp); 100 | walk.pop_back(); 101 | return true; 102 | } else { 103 | for (int i = 1; i < g.size(); i++) { 104 | if (indeg[i] != outdeg[i]) return false; 105 | } 106 | directed_euler(root); 107 | return true; 108 | } 109 | } 110 | 111 | bool process_undirected_euler(bool path = false, int root = 1) { 112 | vector odds; 113 | if (path) { 114 | for (int i = 1; i < g.size(); i++) { 115 | if (deg[i] % 2) odds.push_back(i); 116 | } 117 | if (odds.size() != 2) return false; 118 | add_undirected_edge(odds[0], odds[1]); 119 | undirected_euler(odds[0]); 120 | walk.pop_back(); 121 | return true; 122 | } else { 123 | for (int i = 1; i < g.size(); i++) { 124 | if (deg[i] % 2) return false; 125 | } 126 | undirected_euler(root); 127 | return true; 128 | } 129 | } 130 | 131 | bool calculate(bool path = false, int root = 1) { 132 | if (directed) { 133 | return process_directed_euler(path, root); 134 | } else { 135 | return process_undirected_euler(path, root); 136 | } 137 | } 138 | }; 139 | -------------------------------------------------------------------------------- /codes/strings/suffix_array.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Suffix Array 3 | */ 4 | 5 | /* Suffix Array using Counting Sort Implementation */ 6 | /* rnk is inverse of sa array */ 7 | /* aux arrays are needed for sorting step */ 8 | /* inverse sorting (using rotating arrays and blocks of power of 2) */ 9 | /* rmq data structure needed for calculating lcp of two non adjacent suffixes 10 | * sorted */ 11 | 12 | struct SuffixArray { 13 | vector rnk, tmp, sa, sa_aux, lcp, pot, sp[22]; 14 | 15 | int block, n; 16 | 17 | string s; 18 | 19 | SuffixArray() {} 20 | 21 | SuffixArray(string t) { 22 | s = t; 23 | n = t.size(); 24 | rnk.resize(n + 1); 25 | for (int i = 0; i < 22; i++) sp[i].resize(n + 1); 26 | pot.resize(n + 1); 27 | tmp.resize(max(257LL, n + 1)); 28 | sa.resize(n + 1); 29 | sa_aux.resize(n + 1); 30 | lcp.resize(n + 1); 31 | block = 0; 32 | } 33 | 34 | bool suffixcmp(int i, int j) { 35 | if (rnk[i] != rnk[j]) return rnk[i] < rnk[j]; 36 | i += block, j += block; 37 | i %= n; 38 | j %= n; 39 | return rnk[i] < rnk[j]; 40 | } 41 | 42 | void suffixSort(int MAX_VAL) { 43 | for (int i = 0; i <= MAX_VAL; i++) tmp[i] = 0; 44 | for (int i = 0; i < n; i++) tmp[rnk[i]]++; 45 | for (int i = 1; i <= MAX_VAL; i++) tmp[i] += tmp[i - 1]; 46 | for (int i = n - 1; i >= 0; i--) { 47 | int aux = sa[i] - block; 48 | aux %= n; 49 | if (aux < 0) aux += n; 50 | sa_aux[--tmp[rnk[aux]]] = aux; 51 | } 52 | for (int i = 0; i < n; i++) sa[i] = sa_aux[i]; 53 | tmp[0] = 0; 54 | for (int i = 1; i < n; i++) 55 | tmp[i] = tmp[i - 1] + suffixcmp(sa[i - 1], sa[i]); 56 | for (int i = 0; i < n; i++) rnk[sa[i]] = tmp[i]; 57 | } 58 | 59 | void calculate() { 60 | s += '\0'; 61 | n++; 62 | for (int i = 0; i < n; i++) { 63 | sa[i] = i; 64 | rnk[i] = s[i]; 65 | tmp[i] = 0; 66 | } 67 | suffixSort(256); 68 | block = 1; 69 | while (tmp[n - 1] != n - 1) { 70 | suffixSort(tmp[n - 1]); 71 | block *= 2; 72 | } 73 | for (int i = 0; i < n - 1; i++) sa[i] = sa[i + 1]; 74 | n--; 75 | tmp[0] = 0; 76 | for (int i = 1; i < n; i++) 77 | tmp[i] = tmp[i - 1] + suffixcmp(sa[i - 1], sa[i]); 78 | for (int i = 0; i < n; i++) rnk[sa[i]] = tmp[i]; 79 | s.pop_back(); 80 | sa.pop_back(); 81 | } 82 | 83 | void calculate_lcp() { 84 | int last = 0; 85 | for (int i = 0; i < n; i++) { 86 | if (rnk[i] == n - 1) continue; 87 | int x = rnk[i]; 88 | lcp[x] = max(0LL, last - 1); 89 | while (sa[x] + lcp[x] < n && sa[x + 1] + lcp[x] < n && 90 | s[sa[x] + lcp[x]] == s[sa[x + 1] + lcp[x]]) { 91 | lcp[x]++; 92 | } 93 | last = lcp[x]; 94 | } 95 | } 96 | 97 | void build_lcp_table() { 98 | int k = 0; 99 | for (int j = 0; (1 << j) <= 2 * n; j++) { 100 | for (; k <= n && k < (1 << j); k++) { 101 | pot[k] = j - 1; 102 | } 103 | } 104 | for (int i = 0; i < n; i++) { 105 | sp[0][i] = lcp[i]; 106 | } 107 | for (int i = 1; (1 << i) <= n; i++) { 108 | for (int j = 0; j + (1 << i) <= n; j++) { 109 | sp[i][j] = min(sp[i - 1][j], sp[i - 1][j + (1 << (i - 1))]); 110 | } 111 | } 112 | } 113 | 114 | int query_lcp(int x, int y) { 115 | if (x == y) return n - x; 116 | if (rnk[x] > rnk[y]) swap(x, y); 117 | int l = rnk[x], r = rnk[y] - 1; 118 | return min(sp[pot[r - l + 1]][l], 119 | sp[pot[r - l + 1]][r - (1LL << pot[r - l + 1]) + 1]); 120 | } 121 | 122 | int number_of_substrings() { 123 | int ans = n - sa[0]; 124 | for (int i = 0; i < n - 1; i++) { 125 | int length = n - sa[i + 1]; 126 | ans += length - lcp[i]; 127 | } 128 | return ans; 129 | } 130 | }; 131 | -------------------------------------------------------------------------------- /codes/data_structures/ImplicitTreap.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Neto */ 2 | /* Implicit Treap */ 3 | /* Example with Range Sum Query / Range Sum Update */ 4 | 5 | namespace Treap { 6 | mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); 7 | 8 | struct Node { 9 | Node *l, *r; 10 | int prior; 11 | int sz; 12 | 13 | /* Edit here */ 14 | int sum; 15 | int lazy; 16 | int val; 17 | 18 | Node(int x = -1) { 19 | prior = rng(); 20 | sz = 1; 21 | l = nullptr; 22 | r = nullptr; 23 | 24 | /* Problem Info */ 25 | sum = x; 26 | val = x; 27 | lazy = 0; 28 | } 29 | 30 | Node(Node *n) { 31 | prior = n->prior; 32 | sz = n->sz; 33 | l = n->l; 34 | r = n->r; 35 | 36 | /* Problem Info */ 37 | sum = n->sum; 38 | val = n->val; 39 | lazy = n->lazy; 40 | } 41 | }; 42 | 43 | void combine(Node *root) { 44 | int left = 0, right = 0; 45 | if (root->l) left = root->l->sum; 46 | if (root->r) right = root->r->sum; 47 | root->sum = root->val + left + right; 48 | } 49 | 50 | int get_sz(Node *root) { return root ? root->sz : 0; } 51 | 52 | void update_sz(Node *root) { 53 | if (root) root->sz = get_sz(root->l) + 1 + get_sz(root->r); 54 | } 55 | 56 | void propagate(Node *root) { 57 | // Check if lazy exists 58 | if (!root || !root->lazy) return; 59 | 60 | // Apply lazy to current node 61 | root->val += root->lazy; 62 | root->sum += (root->lazy) * get_sz(root); 63 | 64 | // Propagate 65 | if (root->l) root->l->lazy += root->lazy; 66 | if (root->r) root->r->lazy += root->lazy; 67 | 68 | // Reset lazy 69 | root->lazy = 0; 70 | } 71 | 72 | void apply(Node *root) { 73 | if (!root) return; 74 | update_sz(root); 75 | propagate(root->l); 76 | propagate(root->r); 77 | combine(root); 78 | } 79 | 80 | void adjust(Node *&root) { 81 | if (!root) return; 82 | Node *max_node = root; 83 | if (root->l && root->l->prior > max_node->prior) { 84 | max_node = root->l; 85 | } 86 | if (root->r && root->r->prior > max_node->prior) { 87 | max_node = root->r; 88 | } 89 | if (max_node != root) { 90 | swap(root->prior, max_node->prior); 91 | adjust(max_node); 92 | } 93 | } 94 | 95 | void build_from(Node *&root, vector &A, int l, int r) { 96 | if (l > r) { 97 | root = nullptr; 98 | return; 99 | } 100 | int mid = (l + r) >> 1; 101 | root = new Node(A[mid]); 102 | build_from(root->l, A, l, mid - 1); 103 | build_from(root->r, A, mid + 1, r); 104 | adjust(root); 105 | apply(root); 106 | } 107 | 108 | void split(Node *root, Node *&l, Node *&r, int pos) { 109 | if (!root) { 110 | l = nullptr; 111 | r = nullptr; 112 | return; 113 | } 114 | propagate(root); 115 | if (get_sz(root->l) <= pos) { 116 | split(root->r, root->r, r, pos - get_sz(root->l) - 1); 117 | l = root; 118 | } else { 119 | split(root->l, l, root->l, pos); 120 | r = root; 121 | } 122 | apply(root); 123 | } 124 | 125 | void merge(Node *&root, Node *l, Node *r) { 126 | propagate(l); 127 | propagate(r); 128 | if (!l || !r) 129 | root = (l ? l : r); 130 | else if (l->prior > r->prior) { 131 | merge(l->r, l->r, r); 132 | root = l; 133 | } else { 134 | merge(r->l, l, r->l); 135 | root = r; 136 | } 137 | apply(root); 138 | } 139 | 140 | Node *get(Node *&root, int l, int r = -1) { 141 | if (r == -1) r = l; 142 | 143 | Node *L, *R, *M; 144 | split(root, L, M, l - 1); 145 | split(M, M, R, r - l); 146 | Node *ret = new Node(M); 147 | merge(L, L, M); 148 | merge(root, L, R); 149 | 150 | return ret; 151 | } 152 | 153 | void update(Node *&root, int x, int l, int r = -1) { 154 | if (r == -1) r = l; 155 | 156 | Node *L, *R, *M; 157 | split(root, L, M, l - 1); 158 | split(M, M, R, r - l); 159 | 160 | /* Alter below */ 161 | M->lazy += x; 162 | /* Alter above*/ 163 | 164 | merge(L, L, M); 165 | merge(root, L, R); 166 | } 167 | 168 | void insert_after(Node *&root, int i, int x) { 169 | Node *L, *R; 170 | split(root, L, R, i); 171 | Node *new_node = new Node(x); 172 | merge(L, L, new_node); 173 | merge(root, L, R); 174 | } 175 | 176 | void insert_before(Node *&root, int i, int x) { 177 | Node *L, *R; 178 | split(root, L, R, i - 1); 179 | Node *new_node = new Node(x); 180 | merge(L, L, new_node); 181 | merge(root, L, R); 182 | } 183 | 184 | Node *remove(Node *&root, int i) { 185 | Node *L, *R, *M; 186 | split(root, L, R, i - 1); 187 | split(R, M, R, 0); 188 | Node *ret = new Node(M); 189 | merge(root, L, R); 190 | return ret; 191 | } 192 | 193 | }; // namespace Treap 194 | -------------------------------------------------------------------------------- /codes/geometry/geo2d_structures.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * 2D Geometry Structures 3 | */ 4 | 5 | namespace Geo2D { 6 | 7 | struct Point { 8 | int x, y; 9 | 10 | Point() { 11 | x = 0; 12 | y = 0; 13 | } 14 | 15 | Point(int x, int y) : x(x), y(y) {} 16 | 17 | Point(Point a, Point b) { 18 | x = b.x - a.x; 19 | y = b.y - a.y; 20 | } 21 | 22 | Point operator+(const Point b) const { return Point(x + b.x, y + b.y); } 23 | 24 | Point operator-(const Point b) const { return Point(x - b.x, y - b.y); } 25 | 26 | int operator*(const Point b) const { return (x * b.x + y * b.y); } 27 | 28 | int operator^(const Point b) const { return x * b.y - y * b.x; } 29 | 30 | Point scale(int n) { return Point(x * n, y * n); } 31 | 32 | void operator=(const Point b) { 33 | x = b.x; 34 | y = b.y; 35 | } 36 | 37 | bool operator==(const Point b) { return x == b.x && y == b.y; } 38 | 39 | double distanceTo(Point b) { 40 | return sqrt((x - b.x) * (x - b.x) + (y - b.y) * (y - b.y)); 41 | } 42 | 43 | int squareDistanceTo(Point b) { 44 | return (x - b.x) * (x - b.x) + (y - b.y) * (y - b.y); 45 | } 46 | 47 | bool operator<(const Point& p) const { return tie(x, y) < tie(p.x, p.y); } 48 | 49 | double size() { return sqrt(x * x + y * y); } 50 | 51 | int squareSize() { return x * x + y * y; } 52 | 53 | // Only with double type 54 | Point normalize() { return Point((double)x / size(), (double)y / size()); } 55 | 56 | void rotate(double ang) { 57 | double xx = x, yy = y; 58 | x = xx * cos(ang) + yy * -sin(ang); 59 | y = xx * sin(ang) + yy * cos(ang); 60 | } 61 | }; 62 | 63 | struct Line { 64 | Point p, q; 65 | Point v; 66 | Point normal; 67 | 68 | int a, b, c; 69 | 70 | Line() { 71 | p = Point(); 72 | q = Point(); 73 | v = Point(); 74 | normal = Point(); 75 | a = 0; 76 | b = 0; 77 | c = 0; 78 | } 79 | 80 | Line(int aa, int bb, int cc) { 81 | a = aa; 82 | b = bb; 83 | c = cc; 84 | normal = Point(a, b); 85 | v = Point(-normal.y, normal.x); 86 | p = Point(); 87 | q = Point(); 88 | } 89 | 90 | void operator=(const Line l) { 91 | a = l.a; 92 | b = l.b; 93 | c = l.c; 94 | p = l.p; 95 | q = l.q; 96 | v = l.v; 97 | normal = l.normal; 98 | } 99 | 100 | Line(Point r, Point s) { 101 | p = r; 102 | q = s; 103 | v = Point(r, s); 104 | normal = Point(-v.y, v.x); 105 | a = -v.y; 106 | b = v.x; 107 | c = -(a * p.x + b * p.y); 108 | } 109 | 110 | void flip_sign() { a = -a, b = -b, c = -c; } 111 | 112 | void normalize() { 113 | if (a < 0) 114 | flip_sign(); 115 | else if (a == 0 && b < 0) 116 | flip_sign(); 117 | else if (a == 0 && b == 0 && c < 0) 118 | flip_sign(); 119 | int g = max(a, max(b, c)); 120 | if (a != 0) g = gcd(g, a); 121 | if (b != 0) g = gcd(g, b); 122 | if (c != 0) g = gcd(g, c); 123 | if (g > 0) a /= g, b /= g, c /= g; 124 | } 125 | 126 | bool operator<(const Line& l) const { 127 | return tie(a, b, c) < tie(l.a, l.b, l.c); 128 | } 129 | }; 130 | 131 | struct Circle { 132 | Point c; 133 | double r; 134 | Circle() {} 135 | Circle(Point center, double radius) : c(center), r(radius) {} 136 | 137 | bool operator=(Circle circ) { 138 | c = circ.c; 139 | r = circ.r; 140 | } 141 | 142 | pair getTangentPoints(Point p) { 143 | // p needs to be outside the circle 144 | double d = p.distanceTo(c); 145 | double ang = asin(1. * r / d); 146 | Point v1(p, c); 147 | v1.rotate(ang); 148 | Point v2(p, c); 149 | v2.rotate(-ang); 150 | v1 = v1.scale(sqrt(d * d - r * r) / d); 151 | v2 = v2.scale(sqrt(d * d - r * r) / d); 152 | Point p1(v1.x + p.x, v1.y + p.y); 153 | Point p2(v2.x + p.x, v2.y + p.y); 154 | return make_pair(p1, p2); 155 | } 156 | 157 | double sectorArea(double ang) { return (ang * r * r) / 2.; } 158 | 159 | double arcLength(double ang) { return ang * r; } 160 | 161 | double sectorArea(Point p1, Point p2) { 162 | double h = p1.distanceTo(p2); 163 | double ang = acos(1. - h * h / r * r); 164 | return sectorArea(ang); 165 | } 166 | 167 | double arcLength(Point p1, Point p2) { 168 | double h = p1.distanceTo(p2); 169 | double ang = acos(1. - (h * h) / (2 * r * r)); 170 | return arcLength(ang); 171 | } 172 | 173 | bool inside(const Point& p) { 174 | if (Point(c, p).size() + EPS < r) 175 | return true; 176 | else if (r + EPS < Point(c, p).size()) 177 | return false; 178 | else 179 | return true; 180 | } 181 | }; 182 | 183 | } // namespace Geo2D 184 | 185 | ////////////////////////////////// End of Geometry Structures 186 | //////////////////////////////// 187 | -------------------------------------------------------------------------------- /codes/graphs/hld.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * heavy-Light Decomposition 3 | */ 4 | 5 | struct HLD { 6 | struct node { 7 | // node values 8 | int val = 0; // sets neutral value for the needed operation 9 | int lazy = 0; 10 | node() {} 11 | node(int val) : val(val) { lazy = 0; } 12 | 13 | node merge(node b) { 14 | node ret; 15 | // merge nodes 16 | return ret; 17 | } 18 | }; 19 | 20 | struct SegmentTree { 21 | vector st; 22 | 23 | SegmentTree() {} 24 | 25 | void construct(int n) { st.resize(4 * n); } 26 | 27 | void propagate(int cur, int l, int r) { 28 | // check if exists operation 29 | 30 | // apply lazy 31 | 32 | if (l != r) { 33 | // propagate lazy 34 | } 35 | 36 | // reset lazy 37 | } 38 | 39 | void build(int cur, int l, int r) { 40 | if (l == r) { 41 | // apply on leaf 42 | return; 43 | } 44 | 45 | int m = (l + r) >> 1; 46 | 47 | build(2 * cur, l, m); 48 | build(2 * cur + 1, m + 1, r); 49 | st[cur] = st[2 * cur].merge(st[2 * cur + 1]); 50 | } 51 | 52 | void update(int cur, int l, int r, int a, int b, int val) { 53 | propagate(cur, l, r); 54 | if (b < l || r < a) return; 55 | if (a <= l && r <= b) { 56 | // apply on lazy 57 | propagate(cur, l, r); 58 | return; 59 | } 60 | int m = (l + r) >> 1; 61 | update(2 * cur, l, m, a, b, val); 62 | update(2 * cur + 1, m + 1, r, a, b, val); 63 | st[cur] = st[2 * cur].merge(st[2 * cur + 1]); 64 | } 65 | 66 | node query(int cur, int l, int r, int a, int b) { 67 | propagate(cur, l, r); 68 | if (b < l || r < a) return node(); 69 | if (a <= l && r <= b) return st[cur]; 70 | int m = (l + r) >> 1; 71 | node lef = query(2 * cur, l, m, a, b); 72 | node rig = query(2 * cur + 1, m + 1, r, a, b); 73 | return lef.merge(rig); 74 | } 75 | 76 | } st; 77 | 78 | vector L, P, ch, subsz, in, out; 79 | int t; 80 | 81 | HLD() {} 82 | 83 | HLD(int n) { 84 | L.resize(n + 1); 85 | P.resize(n + 1); 86 | ch.resize(n + 1); 87 | subsz.resize(n + 1); 88 | in.resize(n + 1); 89 | out.resize(n + 1); 90 | st.construct(n + 1); 91 | t = 0; 92 | for (int i = 0; i <= n; i++) { 93 | ch[i] = i; 94 | P[i] = -1; 95 | L[i] = 0; 96 | } 97 | } 98 | 99 | void precalculate(int u, int p = -1) { 100 | subsz[u] = 1; 101 | for (int &v : adj[u]) { 102 | if (v == p) continue; 103 | P[v] = u; 104 | L[v] = L[u] + 1; 105 | precalculate(v, u); 106 | if (subsz[adj[u][0]] < subsz[v]) swap(adj[u][0], v); 107 | subsz[u] += subsz[v]; 108 | } 109 | } 110 | 111 | void build(int u, int p = -1) { 112 | in[u] = ++t; 113 | for (int v : adj[u]) { 114 | if (v == p) continue; 115 | if (adj[u][0] == v) { 116 | ch[v] = ch[u]; 117 | } 118 | build(v, u); 119 | } 120 | out[u] = t; 121 | } 122 | 123 | void calculate(int root = 1) { 124 | precalculate(root); 125 | build(root); 126 | } 127 | 128 | void build_ds() { st.build(1, 1, t); } 129 | 130 | void path_update(int a, int b, int val, bool edge_update = false) { 131 | while (ch[a] != ch[b]) { 132 | if (L[ch[b]] > L[ch[a]]) swap(a, b); 133 | st.update(1, 1, t, in[ch[a]], in[a], val); 134 | a = P[ch[a]]; 135 | } 136 | if (L[b] < L[a]) swap(a, b); 137 | if (in[a] + edge_update <= in[b]) 138 | st.update(1, 1, t, in[a] + edge_update, in[b], val); 139 | } 140 | 141 | void node_update(int u, int val) { st.update(1, 1, t, in[u], in[u], val); } 142 | 143 | void edge_update(int u, int v, int val) { 144 | if (L[u] > L[v]) swap(u, v); 145 | st.update(1, 1, t, in[v], in[v], val); 146 | } 147 | 148 | void subtree_update(int u, int val, bool edge_update = false) { 149 | if (in[u] + edge_update <= out[u]) 150 | st.update(1, 1, t, in[u] + edge_update, out[u], val); 151 | } 152 | 153 | node path_query(int a, int b, bool edge_query = false) { 154 | node ans; 155 | while (ch[a] != ch[b]) { 156 | if (L[ch[b]] > L[ch[a]]) swap(a, b); 157 | ans = ans.merge(st.query(1, 1, t, in[ch[a]], in[a])); 158 | a = P[ch[a]]; 159 | } 160 | if (L[b] < L[a]) swap(a, b); 161 | if (in[a] + edge_query <= in[b]) 162 | ans = ans.merge(st.query(1, 1, t, in[a] + edge_query, in[b])); 163 | return ans; 164 | } 165 | 166 | node node_query(int u) { return st.query(1, 1, t, in[u], in[u]); } 167 | 168 | node edge_query(int u, int v) { 169 | if (L[u] > L[v]) swap(u, v); 170 | return st.query(1, 1, t, in[v], in[v]); 171 | } 172 | 173 | node subtree_query(int u, bool edge_query = false) { 174 | if (in[u] + edge_query <= out[u]) 175 | return st.query(1, 1, t, in[u] + edge_query, out[u]); 176 | else 177 | return node(); 178 | } 179 | }; 180 | -------------------------------------------------------------------------------- /codes/graphs/Dynacon.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define double long double 4 | #define ff first 5 | #define ss second 6 | #define endl '\n' 7 | #define ii pair 8 | #define mp make_pair 9 | #define mt make_tuple 10 | #define DESYNC \ 11 | ios_base::sync_with_stdio(false); \ 12 | cin.tie(0); \ 13 | cout.tie(0) 14 | #define pb push_back 15 | #define vi vector 16 | #define vii vector 17 | #define all(x) x.begin(), x.end() 18 | #define EPS 1e-9 19 | #define INF 2e18 20 | #define ROOT 1 21 | #define curtime chrono::steady_clock::now().time_since_epoch().count 22 | #define rep(i, beg, n, s) for (int i = beg; i < n; i += s) 23 | const double PI = acos(-1); 24 | const int M = 1000000007; 25 | 26 | using namespace std; 27 | 28 | ifstream fin("connect.in"); 29 | ofstream fout("connect.out"); 30 | 31 | struct RollbackDsu { 32 | int uf[312345]; 33 | int sz[312345]; 34 | stack> history; 35 | RollbackDsu() {} 36 | RollbackDsu(int n) { 37 | rep(i, 0, n + 1, 1) { 38 | uf[i] = i; 39 | sz[i] = 1; 40 | } 41 | } 42 | 43 | int find(int u) { 44 | if (uf[u] == u) 45 | return u; 46 | else 47 | return find(uf[u]); 48 | } 49 | 50 | bool merge(int a, int b) { 51 | int x = find(a); 52 | int y = find(b); 53 | if (x == y) return false; 54 | if (sz[x] < sz[y]) swap(x, y); 55 | 56 | history.emplace(&uf[y], uf[y]); 57 | history.emplace(&sz[x], sz[x]); 58 | uf[y] = x; 59 | sz[x] += sz[y]; 60 | 61 | return true; 62 | } 63 | 64 | int snapshot() { return history.size(); } 65 | 66 | void rollback(int sz) { 67 | while (history.size() > sz) { 68 | *history.top().ff = history.top().ss; 69 | history.pop(); 70 | } 71 | } 72 | }; 73 | 74 | struct Burunduk { 75 | struct Event { 76 | int l, r, u, v; 77 | Event() {} 78 | Event(int l, int r, int u, int v) : l(l), r(r), u(u), v(v) {} 79 | }; 80 | 81 | vector e; 82 | vector queries; 83 | vector answers; 84 | RollbackDsu dsu; 85 | 86 | Burunduk(int n) { dsu = RollbackDsu(n); }; 87 | 88 | void _solve(int l, int r, vector &e, vector &queries, int comps) { 89 | if (e.size() == 0) { 90 | for (int x : queries) { 91 | answers.emplace_back(x, comps); 92 | } 93 | return; 94 | } 95 | 96 | // cout << "at " << l << " " << r << " with: " << endl; 97 | // for (Event ev : e) 98 | // { 99 | // cout << ev.l << " " << ev.r << " " << ev.u << " " << ev.v << endl; 100 | // } 101 | // cout << "/-----------/" << endl; 102 | // for (int x : queries) 103 | // cout << x << " "; 104 | // cout << endl; 105 | // cout << "===> " << comps << endl; 106 | // cout << "//////////////////" << endl; 107 | int m = (l + r) >> 1; 108 | vector lef_queries, rig_queries; 109 | for (int x : queries) { 110 | if (x <= m) 111 | lef_queries.pb(x); 112 | else 113 | rig_queries.pb(x); 114 | } 115 | 116 | // Processing [l, m] 117 | vector lef; 118 | int snap = dsu.snapshot(); 119 | int removed = 0; 120 | for (Event ev : e) { 121 | if (ev.l <= l && m <= ev.r) { 122 | removed += dsu.merge(ev.u, ev.v); 123 | } else if (ev.l <= m) 124 | lef.pb(ev); 125 | } 126 | 127 | _solve(l, m, lef, lef_queries, comps - removed); 128 | dsu.rollback(snap); 129 | 130 | // Processing [m+1, r] 131 | snap = dsu.snapshot(); 132 | removed = 0; 133 | vector rig; 134 | for (Event ev : e) { 135 | if (ev.l <= m + 1 && r <= ev.r) { 136 | removed += dsu.merge(ev.u, ev.v); 137 | } else if (ev.r >= m + 1) 138 | rig.pb(ev); 139 | } 140 | 141 | _solve(m + 1, r, rig, rig_queries, comps - removed); 142 | dsu.rollback(snap); 143 | } 144 | 145 | void solve(int l, int r, int start) { _solve(l, r, e, queries, start); } 146 | }; 147 | 148 | void solution() { 149 | int n, q; 150 | fin >> n >> q; 151 | Burunduk b = Burunduk(n); 152 | map lef; 153 | rep(i, 0, q, 1) { 154 | char op; 155 | fin >> op; 156 | int u, v; 157 | if (op == '?') 158 | b.queries.push_back(i); 159 | else if (op == '+') { 160 | fin >> u >> v; 161 | if (u > v) swap(u, v); 162 | b.e.push_back(Burunduk::Event(i, -1, u, v)); 163 | lef[ii(u, v)] = b.e.size() - 1; 164 | } else { 165 | fin >> u >> v; 166 | if (u > v) swap(u, v); 167 | b.e[lef[ii(u, v)]].r = i; 168 | } 169 | } 170 | for (Burunduk::Event &ev : b.e) { 171 | if (ev.r == -1) ev.r = q; 172 | } 173 | b.solve(0, q - 1, n); 174 | for (ii x : b.answers) { 175 | fout << x.ss << endl; 176 | } 177 | } 178 | 179 | int32_t main() { 180 | DESYNC; 181 | mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); 182 | int t = 1; 183 | #ifdef MULTIPLE_TEST_CASE 184 | cin >> t; 185 | #endif 186 | while (t--) solution(); 187 | } -------------------------------------------------------------------------------- /codes/uncategorized/TwoStackQueue.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Neto 2 | * Example of problem using two stacks as a queue to make two pointers queries 3 | * Stack R is the front, stack L is the back. 4 | * L -----------> x <----------- R 5 | * L contains "suffix sum from L to x" 6 | * R contains "preffix sum from x to R" 7 | * When L is empty, remove from R and push to L 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | // #define int long long 36 | // #define double long double 37 | #define ff first 38 | #define ss second 39 | #define endl '\n' 40 | #define ii pair 41 | #define mp make_pair 42 | #define mt make_tuple 43 | #define DESYNC \ 44 | ios_base::sync_with_stdio(false); \ 45 | cin.tie(0); \ 46 | cout.tie(0) 47 | #define pb push_back 48 | #define vi vector 49 | #define vii vector 50 | #define all(x) x.begin(), x.end() 51 | #define EPS 1e-9 52 | #define INF 1e9 53 | #define ROOT 1 54 | #define curtime chrono::steady_clock::now().time_since_epoch().count 55 | #define rep(i, beg, n, s) for (int i = beg; i < n; i += s) 56 | using ll = long long; 57 | using namespace std; 58 | const double PI = acos(-1); 59 | const int M = 1000000007; 60 | // const int M = 998244353; 61 | mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); 62 | inline int mod(int n, int m = M) { 63 | int ret = n % m; 64 | if (ret < 0) ret += m; 65 | return ret; 66 | } 67 | 68 | int exp(int n, int k, int m = M) { 69 | if (k == 0) return 1; 70 | if (k == 1) return n; 71 | int ax = exp(n, k / 2, m); 72 | ax = mod(ax * ax, m); 73 | if (k % 2) ax = mod(ax * n, m); 74 | return ax; 75 | } 76 | 77 | int gcd(int a, int b) { 78 | if (a == 0) 79 | return b; 80 | else 81 | return gcd(b % a, a); 82 | } 83 | 84 | /* LIBRARY INCLUDES */ 85 | 86 | /* END OF LIBRARY INCLUDES */ 87 | 88 | /* TEMPLATE DEFINES */ 89 | // #define FILE_INPUT 90 | // #define PRINT_TEST_CASE 91 | // #define MULTIPLE_TEST_CASE 92 | 93 | /* SOLUTION CODE */ 94 | 95 | using barr = bitset<1001>; 96 | 97 | barr reverse_barr(barr& b, int sz) { 98 | barr newbs; 99 | newbs.reset(); 100 | for (int i = 0, j = sz; i <= sz; i++, j--) { 101 | newbs[i] = b[j]; 102 | } 103 | return newbs; 104 | } 105 | 106 | void solution(int testcase) { 107 | #ifdef PRINT_TEST_CASE 108 | cout << "Case #" << testcase << ": "; 109 | #endif 110 | // Code starts here 111 | stack> L, R; 112 | barr zerobs; 113 | zerobs.reset(); 114 | zerobs[0] = 1; 115 | int n, s; 116 | cin >> n >> s; 117 | int v[n]; 118 | for (int i = 0; i < n; i++) { 119 | cin >> v[i]; 120 | } 121 | int ans = INF; 122 | for (int i = 0; i < n; i++) { 123 | // cout << "index " << i << endl; 124 | // push to r 125 | 126 | if (R.empty()) // if R is empty, push to R 127 | R.emplace(zerobs | (zerobs << v[i]), i); 128 | else // Push to R taking top element into account 129 | R.emplace(R.top().ff | (R.top().ff << v[i]), i); 130 | 131 | if (R.top().ff[s]) 132 | ans = min(ans, (int)R.size()); // take only R into account to ans 133 | 134 | auto reshape = [&](stack>& L, stack>& R) { 135 | barr newbs; 136 | newbs.reset(); 137 | newbs[0] = 1; 138 | while (!R.empty()) { // Remove preffix of R and push to suffix of L 139 | newbs = newbs | (newbs << v[R.top().ss]); 140 | L.emplace(reverse_barr(newbs, s), R.top().ss); 141 | R.pop(); 142 | if (newbs[s]) 143 | ans = min(ans, (int)L.size()); // take only L into account to ans 144 | } 145 | }; 146 | 147 | auto ok = [&](stack>& L, stack>& R) { 148 | if (L.empty()) reshape(L, R); // pull everything to L if L is empty 149 | 150 | if (R.empty()) { // skips if R is empty 151 | return false; 152 | } else { 153 | auto merge = L.top().ff & R.top().ff; 154 | if (merge.count()) { 155 | ans = min(ans, R.top().ss - L.top().ss + 1); 156 | return true; 157 | } 158 | } 159 | 160 | return false; 161 | }; 162 | 163 | // pop while you can 164 | while (ok(L, R)) { 165 | if (L.size() + R.size() <= 2) break; // Both must have something to calc 166 | if (L.empty()) reshape(L, R); // if nothing to pop, reshape 167 | if (!L.empty()) L.pop(); // pop 168 | } 169 | } 170 | 171 | for (int i = 0; i < n; i++) 172 | if (v[i] == s) ans = 1; 173 | 174 | cout << (ans == INF ? -1 : ans) << endl; 175 | } 176 | 177 | #ifdef FILE_INPUT 178 | freopen("equal.in", "r", stdin); 179 | freopen("equal.out", "w", stdout); 180 | #endif 181 | 182 | int32_t main() { 183 | // DESYNC; 184 | int t = 1; 185 | #ifdef MULTIPLE_TEST_CASE 186 | cin >> t; 187 | #endif 188 | for (int _testcase = 1; _testcase <= t; _testcase++) solution(_testcase); 189 | } -------------------------------------------------------------------------------- /codes/graphs/dinic.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * Max Flow Dinic's + Applications 3 | */ 4 | 5 | struct Dinic { 6 | struct FlowEdge { 7 | int v, rev, c, cap; 8 | FlowEdge() {} 9 | FlowEdge(int v, int c, int cap, int rev) : v(v), c(c), cap(cap), rev(rev) {} 10 | }; 11 | 12 | vector > adj; 13 | vector level, used; 14 | int src, snk; 15 | int sz; 16 | int max_flow; 17 | Dinic() {} 18 | Dinic(int n) { 19 | src = 0; 20 | snk = n + 1; 21 | adj.resize(n + 2, vector()); 22 | level.resize(n + 2); 23 | used.resize(n + 2); 24 | sz = n + 2; 25 | max_flow = 0; 26 | } 27 | 28 | void add_edge(int u, int v, int c) { 29 | int id1 = adj[u].size(); 30 | int id2 = adj[v].size(); 31 | adj[u].pb(FlowEdge(v, c, c, id2)); 32 | adj[v].pb(FlowEdge(u, 0, 0, id1)); 33 | } 34 | 35 | void add_to_src(int v, int c) { adj[src].pb(FlowEdge(v, c, c, -1)); } 36 | 37 | void add_to_snk(int u, int c) { adj[u].pb(FlowEdge(snk, c, c, -1)); } 38 | 39 | bool bfs() { 40 | for (int i = 0; i < sz; i++) { 41 | level[i] = -1; 42 | } 43 | 44 | level[src] = 0; 45 | queue q; 46 | q.push(src); 47 | 48 | while (!q.empty()) { 49 | int cur = q.front(); 50 | q.pop(); 51 | for (FlowEdge e : adj[cur]) { 52 | if (level[e.v] == -1 && e.c > 0) { 53 | level[e.v] = level[cur] + 1; 54 | q.push(e.v); 55 | } 56 | } 57 | } 58 | 59 | return (level[snk] == -1 ? false : true); 60 | } 61 | 62 | int send_flow(int u, int flow) { 63 | if (u == snk) return flow; 64 | 65 | for (int &i = used[u]; i < adj[u].size(); i++) { 66 | FlowEdge &e = adj[u][i]; 67 | 68 | if (level[u] + 1 != level[e.v] || e.c <= 0) continue; 69 | 70 | int new_flow = min(flow, e.c); 71 | int adjusted_flow = send_flow(e.v, new_flow); 72 | 73 | if (adjusted_flow > 0) { 74 | e.c -= adjusted_flow; 75 | if (e.rev != -1) adj[e.v][e.rev].c += adjusted_flow; 76 | return adjusted_flow; 77 | } 78 | } 79 | 80 | return 0; 81 | } 82 | 83 | void calculate() { 84 | if (src == snk) { 85 | max_flow = -1; 86 | return; 87 | } // not sure if needed 88 | 89 | max_flow = 0; 90 | 91 | while (bfs()) { 92 | for (int i = 0; i < sz; i++) used[i] = 0; 93 | while (int inc = send_flow(src, INF)) max_flow += inc; 94 | } 95 | } 96 | 97 | vector mincut() { 98 | bool vis[sz]; 99 | for (int i = 0; i < sz; i++) vis[i] = false; 100 | queue q; 101 | q.push(src); 102 | vis[src] = true; 103 | while (!q.empty()) { 104 | int cur = q.front(); 105 | q.pop(); 106 | for (FlowEdge e : adj[cur]) { 107 | if (e.c > 0 && !vis[e.v]) { 108 | q.push(e.v); 109 | vis[e.v] = true; 110 | } 111 | } 112 | } 113 | vector cut; 114 | for (int i = 1; i <= sz - 2; i++) { 115 | if (!vis[i]) continue; 116 | for (FlowEdge e : adj[i]) { 117 | if (1 <= e.v && e.v <= sz - 2 && !vis[e.v] && e.cap > 0 && e.c == 0) 118 | cut.pb(ii(i, e.v)); 119 | } 120 | } 121 | return cut; 122 | } 123 | 124 | vector min_edge_cover() { 125 | bool covered[sz]; 126 | for (int i = 0; i < sz; i++) covered[i] = false; 127 | vector edge_cover; 128 | for (int i = 1; i < sz - 1; i++) { 129 | for (FlowEdge e : adj[i]) { 130 | if (e.cap == 0 || e.v > sz - 2) continue; 131 | if (e.c == 0) { 132 | edge_cover.pb(ii(i, e.v)); 133 | covered[i] = true; 134 | covered[e.v] = true; 135 | break; 136 | } 137 | } 138 | } 139 | for (int i = 1; i < sz - 1; i++) { 140 | for (FlowEdge e : adj[i]) { 141 | if (e.cap == 0 || e.v > sz - 2) continue; 142 | if (e.c == 0) continue; 143 | if (!covered[i] || !covered[e.v]) { 144 | edge_cover.pb(ii(i, e.v)); 145 | covered[i] = true; 146 | covered[e.v] = true; 147 | } 148 | } 149 | } 150 | return edge_cover; 151 | } 152 | 153 | /* Vertex Cover */ 154 | 155 | vector> vc_g; 156 | vector vc_vis; 157 | vector vc_mrk; 158 | 159 | void vc_dfs(int u) { 160 | vc_vis[u] = true; 161 | for (int v : vc_g[u]) { 162 | if (vc_vis[v]) continue; 163 | vc_dfs(v); 164 | } 165 | } 166 | 167 | vector min_vertex_cover(int left_sz) { 168 | int g_sz = adj.size() - 2; 169 | vc_g.resize(g_sz + 1, vector()); 170 | vc_vis.resize(g_sz + 1, false); 171 | vc_mrk.resize(g_sz + 1, true); 172 | for (int i = 1; i <= left_sz; i++) { 173 | for (auto e : adj[i]) { 174 | if (e.v != src && e.v != snk) { 175 | if (e.c != e.cap) { 176 | // satured goes to right 177 | vc_g[e.v].pb(i); 178 | vc_mrk[i] = false; 179 | } else { 180 | // non saturated goes to left 181 | vc_g[i].pb(e.v); 182 | } 183 | } 184 | } 185 | } 186 | for (int i = 1; i <= left_sz; i++) { 187 | if (vc_mrk[i]) vc_dfs(i); 188 | } 189 | vector cover; 190 | for (int i = 1; i <= g_sz; i++) { 191 | if (!vc_vis[i] && i <= left_sz) 192 | cover.pb(i); 193 | else if (vc_vis[i] && i > left_sz) 194 | cover.pb(i); 195 | } 196 | return cover; 197 | } 198 | 199 | /* End of Vertex Cover */ 200 | }; 201 | -------------------------------------------------------------------------------- /codes/math_nt/fft.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | */ 3 | 4 | /* Fast Fourier Transform Implementation */ 5 | /* Complex numbers implemented by hand */ 6 | /* Poly needs to have degree of next power of 2 (result poly has size 7 | * next_pot2(2*n) */ 8 | /* Uses Roots of Unity (Z^n = 1, divide and conquer strategy) 9 | /* Inverse FFT only changes to the conjugate of Primitive Root of Unity */ 10 | /* Remember to use round to get integer value of Coefficients of Poly C */ 11 | /* Iterative FFT is way faster (bit reversal idea + straightforward conquer for 12 | * each block of each size) */ 13 | /* std::complex doubles the execution time */ 14 | /* FastConvolution receives a Poly A+Bi, and multiply A*B (imaginary part 15 | * doesn't remains the same)*/ 16 | 17 | namespace FFT { 18 | 19 | struct Complex { 20 | double a, b; 21 | 22 | Complex(double a, double b) : a(a), b(b) {} 23 | 24 | Complex() : a(0), b(0) {} 25 | 26 | Complex conjugate() const { return Complex(a, -b); } 27 | 28 | double size2() const { return a * a + b * b; } 29 | 30 | void operator=(const Complex& b) { 31 | this->a = b.a; 32 | this->b = b.b; 33 | } 34 | void operator+=(const Complex& y) { 35 | this->a += y.a; 36 | this->b += y.b; 37 | } 38 | void operator-=(const Complex& y) { 39 | this->a -= y.a; 40 | this->b -= y.b; 41 | } 42 | void operator*=(const Complex& y) { 43 | *this = Complex(a * y.a - b * y.b, a * y.b + b * y.a); 44 | } 45 | Complex operator+(const Complex& y) const { 46 | return Complex(a + y.a, b + y.b); 47 | } 48 | Complex operator-(const Complex& y) const { 49 | return Complex(a - y.a, b - y.b); 50 | } 51 | Complex operator*(const Complex& y) const { 52 | return Complex(a * y.a - b * y.b, a * y.b + b * y.a); 53 | } 54 | Complex operator/(const double& x) const { return Complex(a / x, b / x); } 55 | Complex operator/(const Complex& y) const { 56 | return (*this) * (y.conjugate() / y.size2()); 57 | } 58 | }; 59 | 60 | struct Poly { 61 | vector c; 62 | Poly() {} 63 | 64 | Poly(int n) { 65 | if (n <= 0) n = 1; 66 | c.resize(n); 67 | } 68 | 69 | Poly(const Poly& b) { copy(b); } 70 | 71 | void copy(const Poly& b) { 72 | c.clear(); 73 | for (Complex elem : b.c) c.pb(elem); 74 | } 75 | 76 | void operator+=(const Poly& b) { 77 | while (size() < b.size()) c.pb(Complex(0, 0)); 78 | for (int i = 0; i < b.size(); i++) c[i] += b.c[i]; 79 | } 80 | 81 | void operator-=(const Poly& b) { 82 | while (size() < b.size()) c.pb(Complex(0, 0)); 83 | for (int i = 0; i < b.size(); i++) c[i] -= b.c[i]; 84 | } 85 | 86 | int size() const { return (int)c.size(); } 87 | 88 | Complex& operator[](int idx) { 89 | assert(idx < size()); 90 | return c[idx]; 91 | } 92 | }; 93 | 94 | inline Complex PrimitiveRootOfUnity(int n) { 95 | const double PI = acos(-1); 96 | return Complex(cos(2 * PI / (double)n), sin(2 * PI / (double)n)); 97 | } 98 | 99 | inline Complex InversePrimitiveRootOfUnity(int n) { 100 | const double PI = acos(-1); 101 | return Complex(cos(-2 * PI / (double)n), sin(-2 * PI / (double)n)); 102 | } 103 | 104 | void DFT(Poly& A, bool inverse) { 105 | int n = A.size(); 106 | int lg = 0; 107 | while (n > 0) lg++, n >>= 1; 108 | n = A.size(); 109 | lg -= 2; 110 | 111 | for (int i = 0; i < n; i++) { 112 | int j = 0; 113 | for (int b = 0; b <= lg; b++) { 114 | if (i & (1 << b)) j |= (1 << (lg - b)); 115 | } 116 | if (i < j) swap(A.c[i], A.c[j]); 117 | } 118 | 119 | for (int len = 2; len <= n; len <<= 1) { 120 | Complex w; 121 | if (inverse) 122 | w = InversePrimitiveRootOfUnity(len); 123 | else 124 | w = PrimitiveRootOfUnity(len); 125 | 126 | for (int i = 0; i < n; i += len) { 127 | Complex x(1, 0); 128 | for (int j = 0; j < len / 2; j++) { 129 | Complex u = A.c[i + j], v = x * A.c[i + j + len / 2]; 130 | A.c[i + j] = u + v; 131 | A.c[i + j + len / 2] = u - v; 132 | x *= w; 133 | } 134 | } 135 | } 136 | 137 | if (inverse) 138 | for (int i = 0; i < n; i++) A.c[i] = A.c[i] / n; 139 | } 140 | 141 | Poly FastMultiply(Poly& A, Poly& B) { 142 | Poly F_A(max(A.size(), B.size())); 143 | 144 | for (int i = 0; i < F_A.size(); i++) { 145 | F_A.c[i].a = (A.size() > i ? A.c[i].a : 0); 146 | F_A.c[i].b = (B.size() > i ? B.c[i].a : 0); 147 | } 148 | 149 | int n = 1; 150 | while (n < F_A.size() + F_A.size()) n <<= 1; 151 | F_A.c.resize(n); 152 | 153 | Poly C(F_A.size()); 154 | 155 | DFT(F_A, false); 156 | 157 | for (int i = 0; i < F_A.size(); i++) F_A.c[i] *= F_A.c[i]; 158 | 159 | DFT(F_A, true); 160 | 161 | for (int i = 0; i < F_A.size(); i++) C.c[i] = Complex(F_A.c[i].b / 2, 0); 162 | 163 | return C; 164 | } 165 | 166 | Poly Multiply(Poly& A, Poly& B) { 167 | Poly F_A(A), F_B(B); 168 | 169 | int n = 1; 170 | while (n < F_A.size() + F_B.size()) n <<= 1; 171 | F_A.c.resize(n); 172 | F_B.c.resize(n); 173 | 174 | DFT(F_A, false); 175 | 176 | DFT(F_B, false); 177 | 178 | for (int i = 0; i < F_A.size(); i++) F_A.c[i] *= F_B.c[i]; 179 | 180 | DFT(F_A, true); 181 | 182 | return F_A; 183 | } 184 | 185 | Poly Double(Poly& A) { 186 | Poly F_A(A); 187 | 188 | int n = 1; 189 | while (n < F_A.size() + F_A.size()) n <<= 1; 190 | F_A.c.resize(n); 191 | 192 | DFT(F_A, false); 193 | 194 | for (int i = 0; i < F_A.size(); i++) F_A.c[i] *= F_A.c[i]; 195 | 196 | DFT(F_A, true); 197 | 198 | return F_A; 199 | } 200 | 201 | }; // namespace FFT 202 | -------------------------------------------------------------------------------- /codes/strings/SuffixAutomata.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Suffix Automaton 3 | */ 4 | 5 | #include 6 | 7 | using namespace std; 8 | 9 | struct SuffixAutomaton { 10 | vector> nxt; 11 | vector slink; 12 | vector len; 13 | int lstr; 14 | int root; 15 | vector is_terminal; 16 | int slen; 17 | vector> slink_tree; 18 | // vector terminals; 19 | 20 | SuffixAutomaton(const string& s) { 21 | slen = s.size(); 22 | // add root 23 | nxt.push_back(map()); 24 | len.push_back(0); 25 | slink.push_back(-1); 26 | is_terminal.push_back(false); 27 | lstr = root = 0; 28 | 29 | for (int i = 0; i < s.size(); i++) { 30 | // add r 31 | nxt.push_back(map()); 32 | len.push_back(i + 1); 33 | slink.push_back(0); 34 | is_terminal.push_back(false); 35 | int r = nxt.size() - 1; 36 | 37 | // Find p (longest suffix of last r with edge with new character) 38 | int p = lstr; 39 | while (p >= 0 && nxt[p].count(s[i]) == 0) { 40 | // Add edge with new character 41 | nxt[p][s[i]] = r; 42 | p = slink[p]; 43 | } 44 | if (p != -1) { 45 | // There is an suffix of last r that has edge to new character 46 | int q = nxt[p][s[i]]; 47 | if (len[p] + 1 == len[q]) { 48 | // the longest suffix of new r is the logest of class q 49 | // There is no need to split 50 | slink[r] = q; 51 | } else { 52 | // Need to split 53 | // Add q'. New class that longest sufix of r and q. 54 | nxt.push_back(nxt[q]); // Copy from q 55 | len.push_back(len[p] + 1); 56 | slink.push_back(slink[q]); // Copy from q 57 | is_terminal.push_back(false); 58 | int ql = nxt.size() - 1; 59 | 60 | slink[q] = ql; 61 | slink[r] = ql; 62 | 63 | // q' will have every suffix of p that was previously conected to q 64 | while (p >= 0 && nxt[p][s[i]] == q) { 65 | nxt[p][s[i]] = ql; 66 | p = slink[p]; 67 | } 68 | } 69 | } 70 | lstr = r; 71 | if (i == s.size() - 1) { 72 | p = r; 73 | while (p >= 0) { 74 | // terminals.push_back(p); 75 | is_terminal[p] = true; 76 | p = slink[p]; 77 | } 78 | } 79 | } 80 | } 81 | 82 | bool is_substr(const string& s) { 83 | int cur = root; 84 | for (int i = 0; i < s.size(); i++) { 85 | if (nxt[cur].count(s[i]) == 0) return false; 86 | cur = nxt[cur][s[i]]; 87 | } 88 | return true; 89 | } 90 | bool is_suffix(const string& s) { 91 | int cur = root; 92 | for (int i = 0; i < s.size(); i++) { 93 | if (nxt[cur].count(s[i]) == 0) return false; 94 | cur = nxt[cur][s[i]]; 95 | } 96 | if (is_terminal[cur]) return true; 97 | return false; 98 | } 99 | 100 | void dfs_num_substr(int v, int* dp) { 101 | dp[v] = 1; 102 | for (pair ad : nxt[v]) { 103 | if (dp[ad.second] == -1) dfs_num_substr(ad.second, dp); 104 | dp[v] += dp[ad.second]; 105 | } 106 | } 107 | int num_substr() { 108 | int dp[nxt.size()]; 109 | memset(dp, -1, sizeof dp); 110 | dfs_num_substr(root, dp); 111 | return dp[root] - 1; // Remove empty substring 112 | } 113 | 114 | void dfs_num_matches(int v, int* dp) { 115 | dp[v] = 0; 116 | if (is_terminal[v]) dp[v] = 1; 117 | for (pair ad : nxt[v]) { 118 | if (dp[ad.second] == -1) dfs_num_matches(ad.second, dp); 119 | dp[v] += dp[ad.second]; 120 | } 121 | } 122 | int num_matches(const string& s) { 123 | int cur = root; 124 | for (int i = 0; i < s.size(); i++) { 125 | if (nxt[cur].count(s[i]) == 0) return 0; 126 | cur = nxt[cur][s[i]]; 127 | } 128 | int dp[nxt.size()]; 129 | memset(dp, -1, sizeof dp); 130 | dfs_num_matches(cur, dp); 131 | return dp[cur]; 132 | } 133 | 134 | void dfs_first_match(int v, int* dp) { 135 | dp[v] = 0; 136 | if (is_terminal[v]) dp[v] = 1; 137 | for (pair ad : nxt[v]) { 138 | if (dp[ad.second] == -1) { 139 | dfs_first_match(ad.second, dp); 140 | dp[v] = max(dp[v], dp[ad.second] + 1); 141 | } 142 | } 143 | } 144 | int first_match(const string& s) { 145 | int cur = root; 146 | for (int i = 0; i < s.size(); i++) { 147 | if (nxt[cur].count(s[i]) == 0) return -1; 148 | cur = nxt[cur][s[i]]; 149 | } 150 | int dp[nxt.size()]; 151 | memset(dp, -1, sizeof dp); 152 | dfs_first_match(cur, dp); 153 | return slen - (dp[cur] - 1) - s.size(); 154 | } 155 | 156 | void dfs_all_matches(int v, vector& ans) { 157 | // cout << v << endl; 158 | if (slink_tree[v].size() == 0) ans.push_back(len[v]); 159 | for (int ad : slink_tree[v]) { 160 | dfs_all_matches(ad, ans); 161 | } 162 | } 163 | vector all_matches(const string& s) { 164 | slink_tree = vector>(slink.size()); 165 | for (int i = 0; i < slink.size(); i++) { 166 | if (slink[i] >= 0) slink_tree[slink[i]].push_back(i); 167 | } 168 | int cur = root; 169 | for (int i = 0; i < s.size(); i++) { 170 | if (nxt[cur].count(s[i]) == 0) return vector(); 171 | cur = nxt[cur][s[i]]; 172 | } 173 | vector ans; 174 | dfs_all_matches(cur, ans); 175 | for (int i = 0; i < ans.size(); i++) { 176 | ans[i] -= s.size(); 177 | } 178 | // Last one is not valid 179 | return ans; 180 | } 181 | }; 182 | 183 | int main() { 184 | string s; 185 | cin >> s; 186 | SuffixAutomaton sa(s); 187 | cout << sa.num_substr() << endl; 188 | // cout << sa.terminals.size() << endl; 189 | // for(int ter : sa.terminals) cout << ter << " "; 190 | // cout << endl; 191 | int T; 192 | cin >> T; 193 | string w; 194 | while (T--) { 195 | cin >> w; 196 | cout << sa.is_substr(w) << endl; 197 | cout << sa.is_suffix(w) << endl; 198 | cout << sa.num_matches(w) << endl; 199 | cout << sa.first_match(w) << endl; 200 | SuffixAutomaton sb(s + "$" + w); 201 | vector matches = sb.all_matches(w); 202 | for (int i : matches) cout << i << " "; 203 | cout << endl; 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /codes/math_nt/fast_multipoint.cpp: -------------------------------------------------------------------------------- 1 | /* I am not the author of this code. This code was taken from the original source and updated to fit my code style. Author comment below 2 | * Source: from https://github.com/ecnerwala/icpc-book/blob/master/content/numerical/fft.cpp 3 | */ 4 | 5 | /** 6 | * Author: Andrew He 7 | * Description: FFT/NTT, polynomial mod/log/exp 8 | * Source: http://neerc.ifmo.ru/trains/toulouse/2017/fft2.pdf 9 | * Papers about accuracy: http://www.daemonology.net/papers/fft.pdf, http://www.cs.berkeley.edu/~fateman/papers/fftvsothers.pdf 10 | * For integers rounding works if $(|a| + |b|)\max(a, b) < \mathtt{\sim} 10^9$, or in theory maybe $10^6$. 11 | */ 12 | 13 | namespace FastInterpolation { 14 | const int mod = 998244353, g = 3; 15 | struct num { 16 | int v; 17 | num(ll v_ = 0) : v((int)(v_ % mod)) { 18 | if (v < 0) v += mod; 19 | } 20 | explicit operator int() const { return v; } 21 | }; 22 | 23 | inline num operator+(num a, num b) { return num(a.v + b.v); } 24 | inline num operator-(num a, num b) { return num(a.v + mod - b.v); } 25 | inline num operator*(num a, num b) { return num(1ll * a.v * b.v); } 26 | inline num pow(num a, int b) { 27 | num r = 1; 28 | do { 29 | if (b & 1) r = r * a; 30 | a = a * a; 31 | } while (b >>= 1); 32 | return r; 33 | } 34 | inline num inv(num a) { return pow(a, mod - 2); } 35 | 36 | using vn = vector; 37 | vector rev({0, 1}); 38 | vn rt(2, num(1)), fa, fb; 39 | using poly = vn; 40 | inline int sz(const poly& p) { return p.size(); } 41 | 42 | inline void init(int n) { 43 | if (n <= sz(rt)) return; 44 | rev.resize(n); 45 | for (int i = 0; i < n; i++) rev[i] = (rev[i >> 1] | ((i & 1) * n)) >> 1; 46 | rt.reserve(n); 47 | for (int k = sz(rt); k < n; k *= 2) { 48 | rt.resize(2 * k); 49 | num z = pow(num(g), (mod - 1) / (2 * k)); 50 | for (int i = k / 2; i < k; i++) 51 | rt[2 * i] = rt[i], rt[2 * i + 1] = rt[i] * z; 52 | } 53 | } 54 | 55 | inline void fft(vector& a, int n) { 56 | init(n); 57 | int s = __builtin_ctz(rev.size() / n); 58 | for (int i = 0; i < n; i++) 59 | if (i < (rev[i] >> s)) swap(a[i], a[rev[i] >> s]); 60 | for (int k = 1; k < n; k *= 2) 61 | for (int i = 0; i < n; i += 2 * k) 62 | for (int j = 0; j < k; j++) { 63 | num t = rt[j + k] * a[i + j + k]; 64 | a[i + j + k] = a[i + j] - t; 65 | a[i + j] = a[i + j] + t; 66 | } 67 | } 68 | 69 | vn multiply(vn a, vn b) { 70 | int s = sz(a) + sz(b) - 1; 71 | if (s <= 0) return {}; 72 | int L = s > 1 ? 32 - __builtin_clz(s - 1) : 0, n = 1 << L; 73 | a.resize(n), b.resize(n); 74 | fft(a, n); 75 | fft(b, n); 76 | num d = inv(num(n)); 77 | for (int i = 0; i < n; i++) a[i] = a[i] * b[i] * d; 78 | reverse(a.begin() + 1, a.end()); 79 | fft(a, n); 80 | a.resize(s); 81 | return a; 82 | } 83 | 84 | vn inverse(const vn& a) { 85 | if (a.empty()) return {}; 86 | vn b({inv(a[0])}); 87 | b.reserve(2 * a.size()); 88 | while (sz(b) < sz(a)) { 89 | int n = 2 * sz(b); 90 | b.resize(2 * n, 0); 91 | if (sz(fa) < 2 * n) fa.resize(2 * n); 92 | fill(fa.begin(), fa.begin() + 2 * n, 0); 93 | copy(a.begin(), a.begin() + min(n, sz(a)), fa.begin()); 94 | fft(b, 2 * n); 95 | fft(fa, 2 * n); 96 | num d = inv(num(2 * n)); 97 | for (int i = 0; i < 2 * n; i++) b[i] = b[i] * (2 - fa[i] * b[i]) * d; 98 | reverse(b.begin() + 1, b.end()); 99 | fft(b, 2 * n); 100 | b.resize(n); 101 | } 102 | b.resize(a.size()); 103 | return b; 104 | } 105 | 106 | poly& operator+=(poly& a, const poly& b) { 107 | if (sz(a) < sz(b)) a.resize(b.size()); 108 | for (int i = 0; i < sz(b); i++) a[i] = a[i] + b[i]; 109 | return a; 110 | } 111 | poly operator+(const poly& a, const poly& b) { 112 | poly r = a; 113 | r += b; 114 | return r; 115 | } 116 | poly& operator-=(poly& a, const poly& b) { 117 | if (sz(a) < sz(b)) a.resize(b.size()); 118 | for (int i = 0; i < sz(b); i++) a[i] = a[i] - b[i]; 119 | return a; 120 | } 121 | poly operator-(const poly& a, const poly& b) { 122 | poly r = a; 123 | r -= b; 124 | return r; 125 | } 126 | 127 | poly operator*(const poly& a, const poly& b) { return multiply(a, b); } 128 | 129 | poly operator/(poly a, poly b) { 130 | if (sz(a) < sz(b)) return {}; 131 | int s = sz(a) - sz(b) + 1; 132 | reverse(a.begin(), a.end()); 133 | reverse(b.begin(), b.end()); 134 | a.resize(s); 135 | b.resize(s); 136 | a = a * inverse(move(b)); 137 | a.resize(s); 138 | reverse(a.begin(), a.end()); 139 | return a; 140 | } 141 | poly& operator/=(poly& a, const poly& b) { return a = a / b; } 142 | 143 | poly& operator%=(poly& a, const poly& b) { 144 | if (sz(a) >= sz(b)) { 145 | poly c = (a / b) * b; 146 | a.resize(sz(b) - 1); 147 | for (int i = 0; i < sz(a); i++) a[i] = a[i] - c[i]; 148 | } 149 | return a; 150 | } 151 | 152 | poly operator%(const poly& a, const poly& b) { 153 | poly r = a; 154 | r %= b; 155 | return r; 156 | } 157 | 158 | poly deriv(const poly& a) { 159 | if (a.empty()) return {}; 160 | poly b(sz(a) - 1); 161 | for (int i = 0; i < sz(a); i++) b[i - 1] = a[i] * i; 162 | return b; 163 | } 164 | 165 | vector PolyMultiEvaluation(const poly& a, const vector& x) { 166 | int n = sz(x); 167 | if (!n) return {}; 168 | vector up(2 * n); 169 | for (int i = 0; i < n; i++) up[i + n] = poly({0 - x[i], 1}); 170 | for (int i = n - 1; i >= 1; i--) up[i] = up[2 * i] * up[2 * i + 1]; 171 | vector down(2 * n); 172 | down[1] = a % up[1]; 173 | for (int i = 2; i < 2 * n; i++) down[i] = down[i / 2] % up[i]; 174 | vector y(n); 175 | for (int i = 0; i < n; i++) y[i] = down[i + n][0]; 176 | return y; 177 | } 178 | 179 | vector PolyMultiInterpolation(const vector& x, const vector& y) { 180 | int n = sz(x); 181 | assert(n); 182 | vector up(n * 2); 183 | for (int i = 0; i < n; i++) up[i + n] = poly({0 - x[i], 1}); 184 | for (int i = n - 1; i >= 1; i--) up[i] = up[2 * i] * up[2 * i + 1]; 185 | vector a = PolyMultiEvaluation(deriv(up[1]), x); 186 | vector down(2 * n); 187 | for (int i = 0; i < n; i++) down[i + n] = poly({y[i] * inv(a[i])}); 188 | for (int i = n - 1; i >= 1; i--) 189 | down[i] = down[i * 2] * up[i * 2 + 1] + down[i * 2 + 1] * up[i * 2]; 190 | return down[1]; 191 | } 192 | } // namespace FastInterpolation 193 | -------------------------------------------------------------------------------- /codes/geometry/convex_hull.cpp: -------------------------------------------------------------------------------- 1 | namespace Geo2D { 2 | 3 | struct ConvexHull { 4 | vector v, points, lower, upper; 5 | 6 | ConvexHull() {} 7 | ConvexHull(vector v) : v(v) {} 8 | 9 | void calculate() { 10 | sort(v.begin(), v.end()); 11 | lower.clear(); 12 | upper.clear(); 13 | if (v.size() < 3) { 14 | for (Point p : v) upper.pb(p), lower.pb(p); 15 | return; 16 | } 17 | for (int i = 0; i < v.size(); i++) { 18 | while (upper.size() >= 2 && 19 | (Point(upper[upper.size() - 2], upper.back()) ^ 20 | Point(upper.back(), v[i])) >= 0LL) 21 | upper.pop_back(); 22 | upper.push_back(v[i]); 23 | } 24 | reverse(v.begin(), v.end()); 25 | for (int i = 0; i < v.size(); i++) { 26 | while (lower.size() >= 2 && 27 | (Point(lower[lower.size() - 2], lower.back()) ^ 28 | Point(lower.back(), v[i])) >= 0LL) 29 | lower.pop_back(); 30 | lower.push_back(v[i]); 31 | } 32 | for (int i = upper.size() - 2; i >= 0; i--) points.push_back(upper[i]); 33 | for (int i = lower.size() - 2; i >= 0; i--) points.push_back(lower[i]); 34 | reverse(lower.begin(), lower.end()); 35 | } 36 | 37 | double area() { 38 | double area = points.back().x * points[0].y - points.back().y * points[0].x; 39 | for (int i = 0; i < points.size() - 1; i++) { 40 | area += points[i].x * points[i + 1].y - points[i].y * points[i + 1].x; 41 | } 42 | return area / 2.; 43 | } 44 | 45 | int area2() { 46 | int area2 = points.back().x * points[0].y - points.back().y * points[0].x; 47 | for (int i = 0; i < points.size() - 1; i++) { 48 | area2 += points[i].x * points[i + 1].y - points[i].y * points[i + 1].x; 49 | } 50 | return area2; 51 | } 52 | 53 | double perimeter() { 54 | double val = Point(points[0], points.back()).size(); 55 | for (int i = 0; i < points.size() - 1; i++) { 56 | val += Point(points[i], points[i + 1]).size(); 57 | } 58 | return val; 59 | } 60 | 61 | bool insideHull(Point p) { 62 | auto it = lower_bound(lower.begin(), lower.end(), p); 63 | if (it != lower.end() && *it == p) return true; 64 | it = lower_bound(upper.begin(), upper.end(), p); 65 | if (it != upper.end() && *it == p) return true; 66 | 67 | if (p.x == upper[0].x) { 68 | if (p.y > upper[0].y) { 69 | // upper 70 | if (upper[1].x != upper[0].x) 71 | return false; 72 | else if (p.y <= upper[1].y) 73 | return true; 74 | } else { 75 | // lower 76 | if (lower[1].x != lower[0].x) 77 | return false; 78 | else if (p.y >= lower[1].y) 79 | return true; 80 | } 81 | return false; 82 | } 83 | Point v1, v2; 84 | // upper or lower 85 | int ansu = -1, ansl = -1; 86 | int l = 0, r = upper.size() - 2; 87 | while (l <= r) { 88 | int m = (l + r) >> 1LL; 89 | if (upper[m].x < p.x && p.x <= upper[m + 1].x) { 90 | ansu = m; 91 | break; 92 | } else if (upper[m + 1].x < p.x) 93 | l = m + 1; 94 | else 95 | r = m - 1; 96 | } 97 | l = 0, r = lower.size() - 2; 98 | while (l <= r) { 99 | int m = (l + r) >> 1LL; 100 | if (lower[m].x < p.x && p.x <= lower[m + 1].x) { 101 | ansl = m; 102 | break; 103 | } else if (lower[m + 1].x < p.x) 104 | l = m + 1; 105 | else 106 | r = m - 1; 107 | } 108 | if (ansu == -1 || ansl == -1) return false; 109 | bool oku = false, okl = false; 110 | v1 = Point(upper[ansu], upper[ansu + 1]); 111 | v2 = Point(upper[ansu], p); 112 | oku = ((v1 ^ v2) <= 0); 113 | v1 = Point(lower[ansl], lower[ansl + 1]); 114 | v2 = Point(lower[ansl], p); 115 | okl = ((v1 ^ v2) >= 0); 116 | if (oku && okl) 117 | return true; 118 | else 119 | return false; 120 | } 121 | 122 | int max_dot_product(Point p) { 123 | auto _f_dot_product = [&](Point a, Point b) { 124 | return a.x * b.x + a.y * b.y; 125 | }; 126 | auto _maximize_dot_product = [&](Point p, const vector& envelope) { 127 | if (envelope.size() < 3) { 128 | int result = -INF; 129 | for (Point q : envelope) { 130 | result = max(result, _f_dot_product(p, q)); 131 | } 132 | return result; 133 | } 134 | int l = 0, r = envelope.size() - 2; 135 | int ans = 0; 136 | while (l <= r) { 137 | int m1 = (l + r) >> 1; 138 | int m2 = m1 + 1; 139 | if (_f_dot_product(p, envelope[m1]) <= 140 | _f_dot_product(p, envelope[m2])) { 141 | l = m1 + 1; 142 | } else { 143 | ans = m1; 144 | r = m1 - 1; 145 | } 146 | } 147 | int result = max(_f_dot_product(p, envelope.front()), 148 | _f_dot_product(p, envelope.back())); 149 | result = max(result, _f_dot_product(p, envelope[ans])); 150 | result = max(result, _f_dot_product(p, envelope[ans + 1])); 151 | return result; 152 | }; 153 | if (p.y < 0) { 154 | return _maximize_dot_product(p, lower); 155 | } else { 156 | return _maximize_dot_product(p, upper); 157 | } 158 | } 159 | 160 | bool line_intersection(const ConvexHull& ch, Line& l) { 161 | auto f = [&](const Line& l, const Point& p) { 162 | return l.a * p.x + l.b * p.y + l.c; 163 | }; 164 | 165 | auto query = [&](const vector& v, Line& lin) { 166 | if (v.size() < 3) { 167 | ii ret(false, false); 168 | for (Point p : v) { 169 | if (f(lin, p) >= 0) ret.ff = true; 170 | if (f(lin, p) <= 0) ret.ss = true; 171 | } 172 | return ret; 173 | } 174 | int l = 0, r = v.size() - 2; 175 | int ans = -1; 176 | vector test; 177 | test.pb(v[0]); 178 | test.pb(v.back()); 179 | // maximize 180 | while (l <= r) { 181 | int m1 = (l + r) >> 1; 182 | int m2 = m1 + 1; 183 | if (f(lin, v[m1]) > f(lin, v[m2])) { 184 | ans = m1; 185 | r = m1 - 1; 186 | } else { 187 | l = m1 + 1; 188 | } 189 | } 190 | if (ans != -1) test.pb(v[ans]), test.pb(v[ans + 1]); 191 | 192 | l = 0, r = v.size() - 2; 193 | ans = -1; 194 | // minimize 195 | while (l <= r) { 196 | int m1 = (l + r) >> 1; 197 | int m2 = m1 + 1; 198 | if (f(lin, v[m1]) < f(lin, v[m2])) { 199 | ans = m1; 200 | r = m1 - 1; 201 | } else { 202 | l = m1 + 1; 203 | } 204 | } 205 | if (ans != -1) test.pb(v[ans]), test.pb(v[ans + 1]); 206 | ii ret(false, false); 207 | for (Point p : test) { 208 | if (f(lin, p) >= 0) ret.ff = true; 209 | if (f(lin, p) <= 0) ret.ss = true; 210 | } 211 | return ret; 212 | }; 213 | ii ansu = query(ch.upper, l); 214 | ii ansl = query(ch.lower, l); 215 | if (ansu.ff && ansl.ss) return true; 216 | if (ansu.ss && ansl.ff) return true; 217 | if (ansu.ff && ansu.ss) return true; 218 | if (ansl.ff && ansl.ss) return true; 219 | return false; 220 | } 221 | 222 | int largest_quad(vector& v) { 223 | auto triangle_area2 = [&](Point a, Point b, Point c) { 224 | return abs(Point(a, b) ^ Point(a, c)); 225 | }; 226 | auto solve_non_convex = [&](vector& v, ConvexHull& ch) { 227 | int area2 = ch.area2(); 228 | int best_ans = 0; 229 | for (Point p : v) { 230 | bool inhull = false; 231 | for (Point q : ch.points) 232 | if (p == q) inhull = true; 233 | if (inhull) continue; 234 | int n = ch.points.size(); 235 | for (int cur = 0; cur < n; cur++) { 236 | int nxt = (cur + 1) % n; 237 | best_ans = max(best_ans, area2 - triangle_area2(ch.points[cur], 238 | ch.points[nxt], p)); 239 | } 240 | } 241 | return best_ans; 242 | }; 243 | 244 | auto solve_convex = [&](ConvexHull& ch) { 245 | vector& v = ch.points; 246 | int n = v.size(); 247 | int ans = 0; 248 | for (int i = 0; i < n - 3; i++) { 249 | int l = i + 1; 250 | int r = i + 3; 251 | for (int j = i + 2; j <= n - 2; j++) { 252 | l = max(l, i + 1); 253 | r = max(r, j + 1); 254 | 255 | while (l + 1 < j && triangle_area2(v[i], v[j], v[l]) <= 256 | triangle_area2(v[i], v[j], v[(l + 1)])) 257 | l++; 258 | while (r + 1 < n && triangle_area2(v[i], v[j], v[r]) <= 259 | triangle_area2(v[i], v[j], v[(r + 1)])) 260 | r++; 261 | 262 | ans = max(ans, triangle_area2(v[i], v[j], v[l]) + 263 | triangle_area2(v[i], v[j], v[r])); 264 | } 265 | } 266 | return ans; 267 | }; 268 | 269 | ConvexHull ch = ConvexHull(v); 270 | ch.calculate(); 271 | if (ch.points.size() <= 2) 272 | return 0; 273 | else if (ch.points.size() == 3) 274 | return solve_non_convex(v, ch); 275 | else 276 | return solve_convex(ch); 277 | } 278 | }; 279 | 280 | } // namespace Geo2D 281 | -------------------------------------------------------------------------------- /codes/geometry/geo2d_functions.cpp: -------------------------------------------------------------------------------- 1 | /* Author: Ubiratan Correia Barbosa Neto 2 | * 2D Geometry Algorithms 3 | */ 4 | 5 | namespace Geo2D { 6 | 7 | double distancePointLine(Point p, Line l) { 8 | if (l.normal.squareSize() == 0) return INF; 9 | return (double)(1. * abs(l.a * p.x + l.b * p.y + l.c)) / l.normal.size(); 10 | } 11 | 12 | double distancePointSegment(Point p, Line l) { 13 | int dot1 = Point(l.p, p) * Point(l.p, l.q); 14 | int dot2 = Point(l.q, p) * Point(l.q, l.p); 15 | 16 | if (dot1 >= 0 && dot2 >= 0) 17 | return distancePointLine(p, l); 18 | else 19 | return min(p.distanceTo(l.p), p.distanceTo(l.q)); 20 | } 21 | 22 | double distancePointRay(Point p, Line l) { 23 | int dot = Point(l.p, p) * l.v; 24 | if (dot >= 0) 25 | return distancePointLine(p, l); 26 | else 27 | return p.distanceTo(l.p); 28 | } 29 | 30 | Point closestPointInSegment(Point p, Line s) { 31 | // returns closest point from p in segment s 32 | Point u = s.v.normalize(); 33 | Point w(s.p, p); 34 | Point res = u.scale(u * w); 35 | if (u * w < 0 || u * w > s.p.distanceTo(s.q)) { 36 | if (p.distanceTo(s.p) < p.distanceTo(s.q)) 37 | return s.p; 38 | else 39 | return s.q; 40 | } else 41 | return Point(s.p.x + res.x, s.p.y + res.y); 42 | } 43 | 44 | Point intersectionSegmentSegment(Line s1, Line s2) { 45 | // Assumes that intersection exists 46 | // Assuming that endpoints are ordered by x 47 | if (s1.p.x > s1.q.x) swap(s1.p, s1.q); 48 | if (s2.p.x > s2.q.x) swap(s2.p, s2.q); 49 | 50 | if (abs(s1.v ^ s2.v) <= EPS) { 51 | // parallel segments 52 | Point v1(s2.p, s1.p); 53 | if (s1.p.x == s1.q.x && s2.p.x == s2.q.x && s1.p.x == s2.p.x) { 54 | Point ansl, ansr; 55 | if (s1.p.y > s1.q.y) swap(s1.p, s1.q); 56 | if (s2.p.y > s2.q.y) swap(s2.p, s2.q); 57 | if (s1.p.y <= s2.p.y) 58 | ansl = s2.p; 59 | else 60 | ansl = s1.p; 61 | if (s2.q.y <= s1.q.y) 62 | ansr = s2.q; 63 | else 64 | ansr = s1.q; 65 | if (ansl.x == ansr.x && ansl.y == ansr.y) { 66 | // cout << ansr.x << " " << ansr.y << endl; 67 | return Point(ansr.x, ansr.y); 68 | } else { 69 | if (ansl.x == ansr.x && ansl.y > ansr.y) swap(ansl, ansr); 70 | // cout << ansl.x << " " << ansl.y << endl << ansr.x << " " << ansr.y << 71 | // endl; 72 | return Point(INF, INF); 73 | } 74 | } else if (abs(s1.v ^ v1) <= EPS) { 75 | Point ansl, ansr; 76 | if (s1.p.x <= s2.p.x) 77 | ansl = s2.p; 78 | else 79 | ansl = s1.p; 80 | if (s2.q.x <= s1.q.x) 81 | ansr = s2.q; 82 | else 83 | ansr = s1.q; 84 | if (ansl.x == ansr.x && ansl.y == ansr.y) { 85 | // cout << ansr.x << " " << ansr.y << endl; 86 | return Point(ansr.x, ansr.y); 87 | } else { 88 | if (ansl.x == ansr.x && ansl.y > ansr.y) swap(ansl, ansr); 89 | // cout << ansl.x << " " << ansl.y << endl << ansr.x << " " << ansr.y << 90 | // endl; 91 | return Point(INF, INF); 92 | } 93 | } 94 | 95 | } else { 96 | // general case 97 | int a1 = s1.q.y - s1.p.y; 98 | int b1 = s1.p.x - s1.q.x; 99 | int c1 = a1 * s1.p.x + b1 * s1.p.y; 100 | int a2 = s2.q.y - s2.p.y; 101 | int b2 = s2.p.x - s2.q.x; 102 | int c2 = a2 * s2.p.x + b2 * s2.p.y; 103 | int det = a1 * b2 - a2 * b1; 104 | 105 | double x = (double)(b2 * c1 - b1 * c2) / (double)det * 1.; 106 | double y = (double)(a1 * c2 - a2 * c1) / (double)det * 1.; 107 | // cout << x << " " << y << endl; 108 | return Point(x, y); 109 | } 110 | } 111 | 112 | double distanceSegmentSegment(Line l1, Line l2) { 113 | if (l1.p == l2.p && l1.q == l2.q) return 0; 114 | if (l1.q == l2.p && l1.p == l2.q) return 0; 115 | if ((l1.v ^ l2.v) != 0) { 116 | Line r1(l1.p, l1.q); 117 | Line r2(l1.q, l1.p); 118 | Line r3(l2.p, l2.q); 119 | Line r4(l2.q, l2.p); 120 | 121 | int cross1 = (Point(r3.p, r1.p) ^ r3.v); 122 | int cross2 = (Point(r3.p, r1.q) ^ r3.v); 123 | if (cross2 < cross1) swap(cross1, cross2); 124 | 125 | bool ok1 = (cross1 <= 0 && cross2 >= 0) || 126 | (distancePointLine(r1.p, r3) > distancePointLine(r1.q, r3)); 127 | 128 | cross1 = (Point(r1.p, r3.p) ^ r1.v); 129 | cross2 = (Point(r1.p, r3.q) ^ r1.v); 130 | if (cross2 < cross1) swap(cross1, cross2); 131 | 132 | bool ok2 = (cross1 <= 0 && cross2 >= 0) || 133 | (distancePointLine(r3.p, r1) > distancePointLine(r3.q, r1)); 134 | 135 | cross1 = (Point(r3.p, r2.p) ^ r3.v); 136 | cross2 = (Point(r3.p, r2.q) ^ r3.v); 137 | if (cross2 < cross1) swap(cross1, cross2); 138 | 139 | bool ok3 = (cross1 <= 0 && cross2 >= 0) || 140 | (distancePointLine(r2.p, r3) > distancePointLine(r2.q, r3)); 141 | 142 | cross1 = (Point(r2.p, r3.p) ^ r2.v); 143 | cross2 = (Point(r2.p, r3.q) ^ r2.v); 144 | if (cross2 < cross1) swap(cross1, cross2); 145 | 146 | bool ok4 = (cross1 <= 0 && cross2 >= 0) || 147 | (distancePointLine(r3.p, r2) > distancePointLine(r3.q, r2)); 148 | 149 | cross1 = (Point(r4.p, r1.p) ^ r4.v); 150 | cross2 = (Point(r4.p, r1.q) ^ r4.v); 151 | if (cross2 < cross1) swap(cross1, cross2); 152 | 153 | bool ok5 = (cross1 <= 0 && cross2 >= 0) || 154 | (distancePointLine(r1.p, r4) > distancePointLine(r1.q, r4)); 155 | 156 | cross1 = (Point(r1.p, r4.p) ^ r1.v); 157 | cross2 = (Point(r1.p, r4.q) ^ r1.v); 158 | if (cross2 < cross1) swap(cross1, cross2); 159 | 160 | bool ok6 = (cross1 <= 0 && cross2 >= 0) || 161 | (distancePointLine(r4.p, r1) > distancePointLine(r4.q, r1)); 162 | 163 | cross1 = (Point(r4.p, r2.p) ^ r4.v); 164 | cross2 = (Point(r4.p, r2.q) ^ r4.v); 165 | if (cross2 < cross1) swap(cross1, cross2); 166 | 167 | bool ok7 = (cross1 <= 0 && cross2 >= 0) || 168 | (distancePointLine(r2.p, r4) > distancePointLine(r2.q, r4)); 169 | 170 | cross1 = (Point(r2.p, r4.p) ^ r2.v); 171 | cross2 = (Point(r2.p, r4.q) ^ r2.v); 172 | if (cross2 < cross1) swap(cross1, cross2); 173 | 174 | bool ok8 = (cross1 <= 0 && cross2 >= 0) || 175 | (distancePointLine(r4.p, r2) > distancePointLine(r4.q, r2)); 176 | 177 | if (ok1 && ok2 && ok3 && ok4 && ok5 && ok6 && ok7 && ok8) return 0; 178 | } 179 | 180 | double ans = distancePointSegment(l1.p, l2); 181 | ans = min(ans, distancePointSegment(l1.q, l2)); 182 | ans = min(ans, distancePointSegment(l2.p, l1)); 183 | ans = min(ans, distancePointSegment(l2.q, l1)); 184 | return ans; 185 | } 186 | 187 | double distanceSegmentRay(Line s, Line r) { 188 | if ((s.v ^ r.v) != 0) { 189 | Line r1(s.p, s.q); 190 | Line r2(s.q, s.p); 191 | 192 | int cross1 = (Point(r.p, r1.p) ^ r.v); 193 | int cross2 = (Point(r.p, r1.q) ^ r.v); 194 | if (cross2 < cross1) swap(cross1, cross2); 195 | 196 | bool ok1 = (cross1 <= 0 && cross2 >= 0) || 197 | (distancePointLine(r1.p, r) > distancePointLine(r1.q, r)); 198 | 199 | cross1 = (Point(r1.p, r.p) ^ r1.v); 200 | cross2 = (Point(r1.p, r.q) ^ r1.v); 201 | if (cross2 < cross1) swap(cross1, cross2); 202 | 203 | bool ok2 = (cross1 <= 0 && cross2 >= 0) || 204 | (distancePointLine(r.p, r1) > distancePointLine(r.q, r1)); 205 | 206 | cross1 = (Point(r.p, r2.p) ^ r.v); 207 | cross2 = (Point(r.p, r2.q) ^ r.v); 208 | if (cross2 < cross1) swap(cross1, cross2); 209 | 210 | bool ok3 = (cross1 <= 0 && cross2 >= 0) || 211 | (distancePointLine(r2.p, r) > distancePointLine(r2.q, r)); 212 | 213 | cross1 = (Point(r2.p, r.p) ^ r2.v); 214 | cross2 = (Point(r2.p, r.q) ^ r2.v); 215 | if (cross2 < cross1) swap(cross1, cross2); 216 | 217 | bool ok4 = (cross1 <= 0 && cross2 >= 0) || 218 | (distancePointLine(r.p, r2) > distancePointLine(r.q, r2)); 219 | 220 | if (ok1 && ok2 && ok3 && ok4) return 0; 221 | } 222 | 223 | double ans = INF; 224 | int dot = Point(s.p, r.p) * Point(r.p, s.q); 225 | if (dot >= 0) 226 | ans = min(ans, distancePointLine(r.p, s)); 227 | else 228 | ans = min(ans, min(r.p.distanceTo(s.p), r.p.distanceTo(s.q))); 229 | 230 | dot = Point(r.p, s.p) * r.v; 231 | if (dot >= 0) 232 | ans = min(ans, distancePointLine(s.p, r)); 233 | else 234 | ans = min(ans, r.p.distanceTo(s.p)); 235 | 236 | dot = Point(r.p, s.q) * r.v; 237 | if (dot >= 0) 238 | ans = min(ans, distancePointLine(s.q, r)); 239 | else 240 | ans = min(ans, r.p.distanceTo(s.q)); 241 | 242 | return ans; 243 | } 244 | 245 | double distanceSegmentLine(Line s, Line l) { 246 | if ((s.v ^ l.v) == 0) { 247 | return distancePointLine(s.p, l); 248 | } 249 | 250 | int cross1 = (Point(l.p, s.p) ^ l.v); 251 | int cross2 = (Point(l.p, s.q) ^ l.v); 252 | if (cross2 < cross1) swap(cross1, cross2); 253 | if (cross1 <= 0 && cross2 >= 0) 254 | return 0; 255 | else 256 | return min(distancePointLine(s.p, l), distancePointLine(s.q, l)); 257 | } 258 | 259 | double distanceLineRay(Line l, Line r) { 260 | if ((l.v ^ r.v) == 0) { 261 | return distancePointLine(r.p, l); 262 | } 263 | 264 | int cross1 = (Point(l.p, r.p) ^ l.v); 265 | int cross2 = (Point(l.p, r.q) ^ l.v); 266 | if (cross2 < cross1) swap(cross1, cross2); 267 | if ((cross1 <= 0 && cross2 >= 0) || 268 | (distancePointLine(r.p, l) > distancePointLine(r.q, l))) 269 | return 0; 270 | return distancePointLine(r.p, l); 271 | } 272 | 273 | double distanceLineLine(Line l1, Line l2) { 274 | if ((l1.v ^ l2.v) == 0) { 275 | return distancePointLine(l1.p, l2); 276 | } else 277 | return 0; 278 | } 279 | 280 | double distanceRayRay(Line r1, Line r2) { 281 | if ((r1.v ^ r2.v) != 0) { 282 | int cross1 = (Point(r1.p, r2.p) ^ r1.v); 283 | int cross2 = (Point(r1.p, r2.q) ^ r1.v); 284 | if (cross2 < cross1) swap(cross1, cross2); 285 | bool ok1 = (cross1 <= 0 && cross2 >= 0) || 286 | (distancePointLine(r2.p, r1) > distancePointLine(r2.q, r1)); 287 | 288 | cross1 = (Point(r2.p, r1.p) ^ r2.v); 289 | cross2 = (Point(r2.p, r1.q) ^ r2.v); 290 | if (cross2 < cross1) swap(cross1, cross2); 291 | 292 | bool ok2 = (cross1 <= 0 && cross2 >= 0) || 293 | (distancePointLine(r1.p, r2) > distancePointLine(r1.q, r2)); 294 | 295 | if (ok1 && ok2) return 0; 296 | } 297 | 298 | double ans = INF; 299 | int dot = Point(r2.p, r1.p) * r2.v; 300 | if (dot >= 0) 301 | ans = min(ans, distancePointLine(r1.p, r2)); 302 | else 303 | ans = min(ans, r2.p.distanceTo(r1.p)); 304 | 305 | dot = Point(r1.p, r2.p) * r1.v; 306 | if (dot >= 0) 307 | ans = min(ans, distancePointLine(r2.p, r1)); 308 | else 309 | ans = min(ans, r1.p.distanceTo(r2.p)); 310 | 311 | return ans; 312 | } 313 | 314 | double circleCircleIntersection(Circle c1, Circle c2) { 315 | if ((c1.r + c2.r) * (c1.r + c2.r) <= 316 | (c2.c.x - c1.c.x) * (c2.c.x - c1.c.x) + 317 | (c2.c.y - c1.c.y) * (c2.c.y - c1.c.y)) { 318 | return 0; 319 | } 320 | if ((c1.r - c2.r) * (c1.r - c2.r) >= 321 | (c2.c.x - c1.c.x) * (c2.c.x - c1.c.x) + 322 | (c2.c.y - c1.c.y) * (c2.c.y - c1.c.y)) { 323 | return PI * min(c1.r, c2.r) * min(c1.r, c2.r); 324 | } 325 | double x1 = c1.c.x, x2 = c2.c.x, y1 = c1.c.y, y2 = c2.c.y, r1 = c1.r, 326 | r2 = c2.r; 327 | double d = sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); 328 | double r1sqr = c1.r * c1.r; 329 | double r2sqr = c2.r * c2.r; 330 | double dsqr = d * d; 331 | 332 | double alpha1 = acos(((c1.r + c2.r) * (c1.r - c2.r) + dsqr) / (2. * d * r1)); 333 | double alpha2 = acos(((c2.r + c1.r) * (c2.r - c1.r) + dsqr) / (2. * d * r2)); 334 | double area1 = r1sqr * (alpha1 - sin(alpha1) * cos(alpha1)); 335 | double area2 = r2sqr * (alpha2 - sin(alpha2) * cos(alpha2)); 336 | 337 | return area1 + area2; 338 | } 339 | 340 | vector intersectionLineCircle(Line l, Circle circ) { 341 | // NOT TESTED!!!!!!!! 342 | // no intersection 343 | if ((l.c * l.c) / (circ.r * circ.r) > l.a * l.a + l.b * l.b + EPS) 344 | return vector(); 345 | 346 | double x0 = -l.a * l.c / (l.a * l.a + l.b * l.b), 347 | y0 = -l.b * l.c / (l.a * l.a + l.b * l.b); 348 | // one intersection 349 | if (abs((l.c * l.c) / (circ.r * circ.r) - (l.a * l.a + l.b * l.b)) <= EPS) { 350 | vector ret; 351 | ret.pb(Point(x0, y0)); 352 | return ret; 353 | } 354 | 355 | // general case 356 | double d = circ.r * circ.r - (l.c * l.c) / (l.a * l.a + l.b * l.b); 357 | double mult = sqrt(d / (l.a * l.a + l.b * l.b)); 358 | 359 | Point p1(x0 + l.b * mult, y0 - l.a * mult); 360 | Point p2(x0 - l.b * mult, y0 + l.a * mult); 361 | 362 | vector ret; 363 | ret.pb(p1); 364 | ret.pb(p2); 365 | return ret; 366 | } 367 | 368 | vector intersectionCircleCircle(Circle c1, Circle c2) { 369 | // NOT TESTED!!!!!!!! 370 | // translate first circle to origin 371 | Point translation = c1.c; 372 | c1.c = Point(0, 0); 373 | c2.c = c2.c - translation; 374 | 375 | // check if centers are equal 376 | if (c1.c == c2.c) { 377 | // if radius are equal = infinite intersections(return 3 points to 378 | // indicate), else = no intersection(empty) 379 | if (c1.r == c2.r) { 380 | vector ret; 381 | ret.pb(Point()); 382 | ret.pb(Point()); 383 | ret.pb(Point()); 384 | return ret; 385 | } else 386 | return vector(); 387 | } 388 | 389 | // general case 390 | Line l(-2 * c2.c.x, -2 * c2.c.y, 391 | c2.c.x * c2.c.x + c2.c.y * c2.c.y + c1.r * c1.r - c2.r * c2.r); 392 | 393 | vector ret = intersectionLineCircle(l, c1); 394 | 395 | for (Point &p : ret) { 396 | p = p + translation; 397 | } 398 | 399 | return ret; 400 | } 401 | 402 | Point barycenter(Point &a, Point &b, Point &c, double pA, double pB, 403 | double pC) { 404 | Point ret = (a.scale(pA) + b.scale(pB) + c.scale(pC)); 405 | ret.x /= (pA + pB + pC); 406 | ret.y /= (pA + pB + pC); 407 | return ret; 408 | } 409 | 410 | Point circumcenter(Point &a, Point &b, Point &c) { 411 | double pA = Point(b, c).squareSize(), pB = Point(a, c).squareSize(), 412 | pC = Point(a, b).squareSize(); 413 | return barycenter(a, b, c, pA * (pB + pC - pA), pB * (pC + pA - pB), 414 | pC * (pA + pB - pC)); 415 | } 416 | 417 | Point centroid(Point &a, Point &b, Point &c) { 418 | return barycenter(a, b, c, 1, 1, 1); 419 | } 420 | 421 | Point incenter(Point &a, Point &b, Point &c) { 422 | return barycenter(a, b, c, Point(b, c).size(), Point(a, c).size(), 423 | Point(a, b).size()); 424 | } 425 | 426 | Point excenter(Point &a, Point &b, Point &c) { 427 | return barycenter(a, b, c, -Point(b, c).size(), Point(a, c).size(), 428 | Point(a, b).size()); 429 | } 430 | 431 | Point orthocenter(Point &a, Point &b, Point &c) { 432 | double pA = Point(b, c).squareSize(), pB = Point(a, c).squareSize(), 433 | pC = Point(a, b).squareSize(); 434 | return barycenter(a, b, c, (pA + pB - pC) * (pC + pA - pB), 435 | (pB + pC - pA) * (pA + pB - pC), 436 | (pC + pA - pB) * (pB + pC - pA)); 437 | } 438 | 439 | Circle minimumCircle(vector &v) { 440 | Circle circ(Point(0, 0), 1e-14); 441 | random_shuffle(v.begin(), v.end()); 442 | for (int i = 0; i < v.size(); i++) { 443 | if (!circ.inside(v[i])) { 444 | circ = Circle(v[i], 0); 445 | for (int j = 0; j < i; j++) { 446 | if (!circ.inside(v[j])) { 447 | circ = 448 | Circle((v[i] + v[j]).scale(0.5), Point(v[i], v[j]).size() * 0.5); 449 | for (int k = 0; k < j; k++) { 450 | if (!circ.inside(v[k])) { 451 | Point center = circumcenter(v[i], v[j], v[k]); 452 | circ = Circle(center, Point(center, v[k]).size()); 453 | } 454 | } 455 | } 456 | } 457 | } 458 | } 459 | return circ; 460 | } 461 | 462 | long long ClosestPairOfPoints(vector &a) { 463 | // returns square of distance 464 | long long mid = a[a.size() / 2].x; 465 | int n = a.size(); 466 | 467 | vector l; 468 | vector r; 469 | int i = 0; 470 | for (; i < a.size() / 2; i++) l.push_back(a[i]); 471 | for (; i < a.size(); i++) r.push_back(a[i]); 472 | 473 | long long d = LLONG_MAX; 474 | 475 | if (l.size() > 1) { 476 | d = min(d, ClosestPairOfPoints(l)); 477 | } 478 | if (r.size() > 1) { 479 | d = min(d, ClosestPairOfPoints(r)); 480 | } 481 | 482 | a.clear(); 483 | 484 | vector ll; 485 | vector rr; 486 | 487 | int j = 0; 488 | i = 0; 489 | for (int k = 0; k < n; k++) { 490 | if (i < l.size() && j < r.size()) { 491 | if (r[j].y <= l[i].y) { 492 | if ((r[j].x - mid) * (r[j].x - mid) < d) { 493 | rr.push_back(r[j]); 494 | } 495 | a.push_back(r[j++]); 496 | } else { 497 | if ((l[i].x - mid) * (l[i].x - mid) < d) { 498 | ll.push_back(l[i]); 499 | } 500 | a.push_back(l[i++]); 501 | } 502 | } else if (i < l.size()) { 503 | if ((l[i].x - mid) * (l[i].x - mid) < d) { 504 | ll.push_back(l[i]); 505 | } 506 | a.push_back(l[i++]); 507 | } else { 508 | if ((r[j].x - mid) * (r[j].x - mid) < d) { 509 | rr.push_back(r[j]); 510 | } 511 | a.push_back(r[j++]); 512 | } 513 | } 514 | 515 | for (int i = 0; i < ll.size(); i++) { 516 | int ini = 0, end = rr.size() - 1; 517 | int j; 518 | 519 | while (ini < end) { 520 | j = (ini + end) / 2; 521 | if ((rr[j].y - ll[i].y) * (rr[j].y - ll[i].y) > d && rr[j].y < ll[i].y) 522 | ini = j + 1; 523 | else 524 | end = j; 525 | } 526 | 527 | j = ini; 528 | 529 | for (; j < rr.size(); j++) { 530 | if ((rr[j].y - ll[i].y) * (rr[j].y - ll[i].y) > d) break; 531 | long long cur = (ll[i].x - rr[j].x) * (ll[i].x - rr[j].x) + 532 | (ll[i].y - rr[j].y) * (ll[i].y - rr[j].y); 533 | if (cur < d) { 534 | d = cur; 535 | } 536 | } 537 | } 538 | return d; 539 | } 540 | 541 | } // namespace Geo2D 542 | 543 | ////////////////////////////////// End of Geometry Algorithms 544 | //////////////////////////////// 545 | --------------------------------------------------------------------------------