├── .gitignore ├── LICENSE ├── Preview.png ├── README.md ├── cod ├── data_structures │ ├── bubble_sort.cpp │ ├── merge_sort.cpp │ ├── merge_sort_tree.cpp │ ├── segment_tree_rmq.cpp │ ├── selection_sort.cpp │ ├── sparse_table_rmq.cpp │ ├── sparse_table_rsq.cpp │ └── union_find_disjoint_sets.cpp ├── geometry │ └── point.cpp ├── graph_theory │ ├── adjacency_list.cpp │ ├── articulation_points_and_bridges.cpp │ ├── bellman_ford.cpp │ ├── bi_connected_components.cpp │ ├── bi_partite_graph.cpp │ ├── breadth_first_search.cpp │ ├── connected_components.cpp │ ├── cycle_detection[directedg].cpp │ ├── cycle_detection[undirectedg].cpp │ ├── depth_first_search.cpp │ ├── dijkstra[densegraph].cpp │ ├── dijkstra[grid].cpp │ ├── dijkstra[negativeweightedges].cpp │ ├── dijkstra[sparsegraph].cpp │ ├── directed_cyclic_graph_into_directed_acyclic_graph.cpp │ ├── edge_classification.cpp │ ├── eulerian_tour_tree.cpp │ ├── flood_fill.cpp │ ├── floyd_warshall.cpp │ ├── kruskal.cpp │ ├── kth_ancestor_and_lca[binarylifting].cpp │ ├── lca[euleriantourandrmq].cpp │ ├── minimum_vertex_cover.cpp │ ├── restoring_the_path.cpp │ ├── shortest_path_faster_algorithm.cpp │ ├── single_source_shortest_path.cpp │ ├── single_source_shortest_path[grid].cpp │ ├── tarjan.cpp │ ├── topological_sort[dfs].cpp │ ├── topological_sort[kahnsalgorithm].cpp │ ├── tree_diameter.cpp │ ├── zsingle_pair_shortest_path.cpp │ └── zsingle_pair_shortest_path[grid].cpp ├── mathematics │ ├── euler_phi_sieve.cpp │ ├── euler_totient_function.cpp │ ├── extended_wheel_factorization.cpp │ ├── leastprime_factorization.cpp │ ├── linear_sieve.cpp │ ├── miller_rabin_test.cpp │ ├── mobius_function.cpp │ ├── mobius_sieve.cpp │ ├── phi_factorial.cpp │ ├── pisano_periodic_sequence.cpp │ ├── segmented_sieve.cpp │ ├── simple_sieve_eratosthenes.cpp │ ├── the_stable_marriage_problem.cpp │ └── wheel_sieve.cpp ├── miscellaneous │ ├── cpp_template.cpp │ ├── double_comparison.cpp │ ├── fast_io.cpp │ ├── gcd_lcm.cpp │ ├── modular_calculations.cpp │ ├── mydebugger.cpp │ ├── overloaded_operators_to_accept_128bit_integer.cpp │ ├── policy_based_data_structures.cpp │ ├── pseudo_random_number_generator.cpp │ └── stress_test.cpp ├── more_advanced_topics │ ├── a*_algorithm.cpp │ ├── mo's_algorithm.cpp │ └── square_root_decomposition.cpp ├── setup │ ├── compile │ ├── vimrc │ └── xmodmap └── string_processing │ ├── knuth_morris_pratt.cpp │ └── trie.cpp ├── reference_material.pdf ├── reference_material.tex └── src ├── commands.tex ├── headers.tex ├── sections.tex └── styles.tex /.gitignore: -------------------------------------------------------------------------------- 1 | *.out 2 | *.toc 3 | *.log 4 | *.aux 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Abd El-Twab M. Fakhry 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbdeltwabMF/reference-materials/78f0da299502f87e4d7b46ee215a83c116323312/Preview.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ICPC Team Reference Material 2 | 3 | ## Preview 4 | ![](Preview.png) 5 | -------------------------------------------------------------------------------- /cod/data_structures/bubble_sort.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | Bubble sort consists of n rounds. On each round, the algorithm iterates 3 | through the elements of the array. Whenever two consecutive elements are found 4 | that are not in correct order, the algorithm swaps them. The algorithm can be 5 | implemented as follows: 6 | **/ 7 | 8 | template 9 | void bubble_sort(T _begin, T _end, int round) { 10 | const int sz = _end - _begin; 11 | int localArray[sz]; 12 | 13 | __typeof(_begin) k = _begin; 14 | for(int j = 0; k != _end; ++k, ++j) 15 | localArray[j] = *k; 16 | 17 | round = min(round, sz); 18 | for(int i = 0; i < round; ++i) /* n rounds -> n_th element **/ 19 | for(int j = 0; j < sz - 1; ++j) if(localArray[j] > localArray[j + 1]) 20 | swap(localArray[j], localArray[j + 1]); 21 | 22 | k = _begin; 23 | for(int j = 0; k != _end; ++k, ++j) 24 | *k = localArray[j]; 25 | } 26 | 27 | /** 28 | After the first round of the algorithm, the largest element will be in the correct 29 | position, and in general, after k rounds, the k largest elements will be in the 30 | correct positions. 31 | **/ 32 | -------------------------------------------------------------------------------- /cod/data_structures/merge_sort.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | Time Complexity: Sorting arrays on different machines. Merge Sort is a recursive algorithm and time complexity can be expressed as following recurrence relation. 3 | 4 | T(n) = 2T(n/2) + theta(n) 5 | 6 | The above recurrence can be solved either using the Recurrence Tree method or the Master method. It falls in case II of Master Method and the solution of the recurrence is theta(nLogn). Time complexity of Merge Sort is theta(nLogn) in all 3 cases (worst, average and best) as merge sort always divides the array into two halves and takes linear time to merge two halves. 7 | Auxiliary Space: O(n) 8 | Algorithmic Paradigm: Divide and Conquer 9 | Sorting In Place: No in a typical implementation 10 | Count Inversion of array: yes 11 | https://discuss.codechef.com/t/iiti15-editorial/4427 12 | Stable: Yes 13 | **/ 14 | 15 | ll inversions; 16 | 17 | template 18 | void merge(T localArr [], int l, int mid, int r) { 19 | int l_size = mid - l + 1; 20 | int r_size = r - mid; 21 | 22 | T L[l_size + 1]; 23 | T R[r_size + 1]; 24 | 25 | for(int i = 0; i < l_size; ++i) L[i] = localArr[i + l]; 26 | for(int i = 0; i < r_size; ++i) R[i] = localArr[i + mid + 1]; 27 | 28 | T Mx; 29 | if(sizeof(T) == 4) Mx = INT_MAX; 30 | else Mx = LONG_MAX; 31 | 32 | L[l_size] = R[r_size] = Mx; 33 | 34 | for(int k = l, i = 0, j = 0; k <= r; ++k) 35 | if(L[i] <= R[j]) 36 | localArr[k] = L[i], i += (L[i] != Mx); 37 | else 38 | localArr[k] = R[j], j += (R[j] != Mx), inversions += l_size - i; 39 | } 40 | 41 | template 42 | void merge_sort(T localArr [], int l, int r) { 43 | if(r - l) 44 | { 45 | int mid = (l + r) >> 1; 46 | merge_sort(localArr, l, mid); 47 | merge_sort(localArr, mid + 1, r); 48 | merge(localArr, l, mid, r); 49 | } 50 | } 51 | 52 | template 53 | void merge_sort(T _begin, T _end) { 54 | const int sz = _end - _begin; 55 | __typeof(*_begin) localArray[sz]; 56 | 57 | __typeof(_begin) k = _begin; 58 | for(int i = 0; k != _end; ++i, ++k) 59 | localArray[i] = *k; 60 | 61 | merge_sort(localArray, 0, sz - 1); 62 | 63 | k = _begin; 64 | for(int i = 0; k != _end; ++i, ++k) 65 | *k = localArray[i]; 66 | } 67 | -------------------------------------------------------------------------------- /cod/data_structures/merge_sort_tree.cpp: -------------------------------------------------------------------------------- 1 | /** https://www.spoj.com/problems/KQUERY/ 2 | **/ 3 | 4 | class SegmentTree { 5 | vector > sTree; 6 | vector localArr; 7 | int NP2, oo = 0x3f3f3f3f; 8 | 9 | public : 10 | template 11 | SegmentTree(T _begin, T _end) { 12 | NP2 = 1; 13 | int n = _end - _begin; 14 | while(NP2 < n) NP2 <<= 1; 15 | 16 | sTree.assign(NP2 << 1, vector ()); 17 | localArr.assign(NP2 + 1, 0); 18 | 19 | __typeof(_begin) i = _begin; 20 | for(int j = 1; i != _end; i++, ++j) 21 | localArr[j] = *i; 22 | 23 | build(1, 1, NP2); 24 | } 25 | 26 | void build(int p, int l, int r) { 27 | if(l == r) { 28 | sTree[p].push_back(localArr[l]); 29 | return; 30 | } 31 | 32 | build(left(p), l, mid(l, r)); 33 | build(right(p), mid(l, r) + 1, r); 34 | 35 | merge(p); 36 | } 37 | 38 | int query(int ql, int qr, int k) { 39 | return query(ql, qr, k, 1, 1, NP2); 40 | } 41 | 42 | private : 43 | int query(int ql, int qr, int k, int p, int l, int r) { 44 | if(isOutside(ql, qr, l, r)) 45 | return 0; 46 | 47 | if(isInside(ql, qr, l, r)) { 48 | return sTree[p].end() - upper_bound(sTree[p].begin(), sTree[p].end(), k); 49 | } 50 | 51 | return query(ql, qr, k, left(p), l, mid(l, r)) + query(ql, qr, k, right(p), mid(l, r) + 1, r); 52 | } 53 | 54 | void merge(int p) { 55 | vector & L = sTree[left(p)]; 56 | vector & R = sTree[right(p)]; 57 | 58 | int l_size = L.size(); 59 | int r_size = R.size(); 60 | int p_size = l_size + r_size; 61 | 62 | L.push_back(INT_MAX); 63 | R.push_back(INT_MAX); 64 | 65 | sTree[p].resize(p_size); 66 | 67 | for(int k = 0, i = 0, j = 0; k < p_size; ++k) 68 | if(L[i] <= R[j]) 69 | sTree[p][k] = L[i], i += (L[i] != INT_MAX); 70 | else 71 | sTree[p][k] = R[j], j += (R[j] != INT_MAX); 72 | 73 | L.pop_back(); 74 | R.pop_back(); 75 | } 76 | 77 | inline bool isInside(int ql, int qr, int sl, int sr) { 78 | return (ql <= sl && sr <= qr); 79 | } 80 | 81 | inline bool isOutside(int ql, int qr, int sl, int sr) { 82 | return (sr < ql || qr < sl); 83 | } 84 | 85 | inline int mid (int l, int r) { 86 | return ((l + r) >> 1); 87 | } 88 | 89 | inline int left(int p) { 90 | return (p << 1); 91 | } 92 | 93 | inline int right(int p) { 94 | return ((p << 1) | 1); 95 | } 96 | }; 97 | -------------------------------------------------------------------------------- /cod/data_structures/segment_tree_rmq.cpp: -------------------------------------------------------------------------------- 1 | /** resources: 2 | 1. https://codeforces.com/blog/entry/15729 3 | 2. https://codeforces.com/blog/entry/15890 4 | 3. https://codeforces.com/blog/entry/18051 5 | 4. https://www.hackerearth.com/practice/data-structures/advanced-data-structures/segment-trees/practice-problems/algorithm/range-minimum-query/description/ 6 | **/ 7 | 8 | template > 9 | class SegmentTree { 10 | vector _A; 11 | vector ST; 12 | vector LT; 13 | F func; 14 | int _N; 15 | 16 | public : 17 | template 18 | SegmentTree(iter _begin, iter _end, const F _func = [](T a, T b) {return a <= b ? a : b;}) : func(_func) { 19 | _N = distance(_begin, _end); 20 | _N = (1 << (int)ceil(log2(_N))); 21 | 22 | _A.assign(_N + 1, 0); 23 | ST.assign(_N << 1, 0); 24 | LT.assign(_N << 1, 0); 25 | 26 | __typeof(_begin) i = _begin; 27 | for(int j = 1; i != _end; ++i, ++j) 28 | _A[j] = *i; 29 | 30 | build(1, 1, _N); 31 | } 32 | 33 | void build(int p, int l, int r) { 34 | if(l == r) { 35 | ST[p] = _A[l]; 36 | return; 37 | } 38 | 39 | int mid = (l + r) >> 1; 40 | 41 | build(p + p, l, mid); 42 | build(p + p + 1, mid + 1, r); 43 | 44 | const T & x = ST[p + p]; 45 | const T & y = ST[p + p + 1]; 46 | 47 | ST[p] = func(x, y); 48 | } 49 | 50 | void update_range(int ul, int ur, int delta) { 51 | update_range(ul, ur, delta, 1, 1, _N); 52 | } 53 | 54 | T query(int ql, int qr) { 55 | return query(ql, qr, 1, 1, _N); 56 | } 57 | 58 | void update_point(int inx, int delta) { 59 | inx += _N - 1; 60 | ST[inx] = delta; 61 | 62 | while(inx > 1) { 63 | inx >>= 1; 64 | 65 | const T & x = ST[inx + inx]; 66 | const T & y = ST[inx + inx + 1]; 67 | 68 | ST[inx] = func(x, y); 69 | } 70 | } 71 | 72 | private : 73 | void update_range(int ul, int ur, int delta, int p, int l, int r) { 74 | if(r < ul || ur < l) 75 | return; 76 | 77 | if(ul <= l && r <= ur) { 78 | ST[p] += delta; 79 | LT[p] += delta; 80 | return; 81 | } 82 | 83 | propagate(p); 84 | 85 | int mid = (l + r) >> 1; 86 | 87 | update_range(ul, ur, delta, p + p, l, mid); 88 | update_range(ul, ur, delta, p + p + 1, mid + 1, r); 89 | 90 | const T & x = ST[p + p]; 91 | const T & y = ST[p + p + 1]; 92 | 93 | ST[p] = func(x, y); 94 | } 95 | 96 | T query(int ql, int qr, int p, int l, int r) { 97 | if(r < ql || qr < l) 98 | return INT_MAX; 99 | 100 | if(ql <= l && r <= qr) 101 | return ST[p]; 102 | 103 | propagate(p); 104 | 105 | int mid = (l + r) >> 1; 106 | 107 | const T & x = query(ql, qr, p + p, l, mid); 108 | const T & y = query(ql, qr, p + p + 1, mid + 1, r); 109 | 110 | return func(x, y); 111 | } 112 | 113 | void propagate(int p) { 114 | if(LT[p]) { 115 | ST[p + p] += LT[p]; 116 | ST[p + p + 1] += LT[p]; 117 | LT[p + p] += LT[p]; 118 | LT[p + p + 1] += LT[p]; 119 | LT[p] = 0; 120 | } 121 | } 122 | }; 123 | 124 | -------------------------------------------------------------------------------- /cod/data_structures/selection_sort.cpp: -------------------------------------------------------------------------------- 1 | template 2 | void selection_sort(T _begin, T _end, int round) { 3 | const int sz = _end - _begin; 4 | int localArray[sz]; 5 | 6 | __typeof(_begin) k = _begin; 7 | for(int i = 0; k != _end; ++i, ++k) 8 | localArray[i] = *k; 9 | 10 | int MnInx; 11 | round = min(sz, round); 12 | for(int i = 0; i < round; ++i) { 13 | MnInx = i; 14 | for(int j = i + 1; j < sz; ++j) 15 | if(localArray[j] < localArray[MnInx]) 16 | MnInx = j; 17 | swap(localArray[MnInx], localArray[i]); 18 | } 19 | 20 | k = _begin; 21 | for(int i = 0; k != _end; ++i, ++k) 22 | *k = localArray[i]; 23 | } 24 | -------------------------------------------------------------------------------- /cod/data_structures/sparse_table_rmq.cpp: -------------------------------------------------------------------------------- 1 | template > 2 | class SparseTable { 3 | int _N; 4 | int _LOG; 5 | vector _A; 6 | vector < vector > ST; 7 | vector Log; 8 | F func; 9 | 10 | public : 11 | SparseTable() = default; 12 | 13 | template 14 | SparseTable(iter _begin, iter _end, const F _func = less ()) : func(_func) { 15 | _N = distance(_begin, _end); 16 | 17 | Log.assign(_N + 1, 0); 18 | for(int i = 2; i <= _N; ++i) 19 | Log[i] = Log[i >> 1] + 1; 20 | 21 | _LOG = Log[_N]; 22 | 23 | _A.assign(_N + 1, 0); 24 | ST.assign(_N + 1, vector (_LOG + 1, 0)); 25 | 26 | __typeof(_begin) i = _begin; 27 | for(int j = 1; i != _end; ++i, ++j) 28 | _A[j] = *i; 29 | 30 | build(); 31 | } 32 | 33 | void build() { 34 | for(int i = 1; i <= _N; ++i) 35 | ST[i][0] = i; 36 | 37 | for(int j = 1, k, d; j <= _LOG; ++j) { // the two nested loops below have overall time complexity = O(n log n) 38 | k = (1 << j); 39 | d = (k >> 1); 40 | 41 | for(int i = 1; i + k - 1 <= _N; ++i) { 42 | T const & x = ST[i][j - 1]; // starting subarray at index = i with length = 2^{j - 1} 43 | T const & y = ST[i + d][j - 1]; // starting subarray at index = i + d with length = 2^{j - 1} 44 | 45 | ST[i][j] = func(_A[x], _A[y]) ? x : y; 46 | } 47 | } 48 | } 49 | 50 | T query(int l, int r) { // this query is O(1) 51 | int d = r - l + 1; 52 | T const & x = ST[l][Log[d]]; 53 | T const & y = ST[l + d - (1 << Log[d])][Log[d]]; 54 | 55 | return func(_A[x], _A[y]) ? x : y; 56 | } 57 | }; 58 | 59 | -------------------------------------------------------------------------------- /cod/data_structures/sparse_table_rsq.cpp: -------------------------------------------------------------------------------- 1 | template > 2 | class SparseTable { 3 | int _N; 4 | int _LOG; 5 | vector _A; 6 | vector < vector > ST; 7 | vector Log; 8 | F func; 9 | 10 | public : 11 | SparseTable() = default; 12 | 13 | template 14 | SparseTable(iter _begin, iter _end, F _func = [](T a, T b) { return a + b; }) : func(_func) { 15 | _N = distance(_begin, _end); 16 | 17 | Log.assign(_N + 1, 0); 18 | for(int i = 2; i <= _N; ++i) 19 | Log[i] = Log[i >> 1] + 1; 20 | 21 | _LOG = Log[_N]; 22 | 23 | _A.assign(_N + 1, 0); 24 | ST.assign(_N + 1, vector (_LOG + 1, 0)); 25 | 26 | __typeof(_begin) i = _begin; 27 | for(int j = 1; i != _end; ++i, ++j) 28 | _A[j] = *i; 29 | 30 | build(); 31 | } 32 | 33 | void build() { 34 | for(int i = 1; i <= _N; ++i) 35 | ST[i][0] = _A[i]; 36 | 37 | for(int j = 1, k, d; j <= _LOG; ++j) { 38 | k = (1 << j); 39 | d = (k >> 1); 40 | 41 | for(int i = 1; i + k - 1 <= _N; ++i) { 42 | T const & x = ST[i][j - 1]; // starting subarray at index = i with length = 2^{j - 1} 43 | T const & y = ST[i + d][j - 1]; // starting subarray at index = i + d with length = 2^{j - 1} 44 | 45 | ST[i][j] = func(x, y); 46 | } 47 | } 48 | } 49 | 50 | T query(int l, int r) { 51 | int d = r - l + 1; 52 | T ret = 0; 53 | 54 | for(int i = l; d; i += lastBit(d), d -= lastBit(d)) 55 | ret = func(ret, ST[i][Log[lastBit(d)]]); 56 | 57 | return ret; 58 | } 59 | 60 | int lastBit(int a) { 61 | return (a & -a); 62 | } 63 | }; 64 | 65 | -------------------------------------------------------------------------------- /cod/data_structures/union_find_disjoint_sets.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | Maintain a set of elements partitioned into non-overlapping subsets. Each 3 | partition is assigned a unique representative known as the parent, or root. The 4 | following implements two well-known optimizations known as union-by-size and 5 | path compression. This version is simplified to only work on integer elements. 6 | 7 | - find_set(u) returns the unique representative of the partition containing u. 8 | - same_set(u, v) returns whether elements u and v belong to the same partition. 9 | - union_set(u, v) replaces the partitions containing u and v with a single new 10 | partition consisting of the union of elements in the original partitions. 11 | 12 | Time Complexity: 13 | - O(a(n)) per call to find_set(), same_set(), and union_set(), where n is the 14 | number of elements, and a(n) is the extremely slow growing inverse of the Ackermann function 15 | (effectively a very small constant for all practical values of n). 16 | 17 | Space Complexity: 18 | - O(n) for storage of the disjoint set forest elements. 19 | - O(1) auxiliary for all operations. 20 | **/ 21 | 22 | class UnionFind { 23 | vector par; 24 | vector siz; 25 | int num_sets; 26 | size_t sz; 27 | 28 | public: 29 | UnionFind() : par(1, -1), siz(1, 1), num_sets(0), sz(0) {} 30 | UnionFind(int n) : par(n + 1, -1), siz(n + 1, 1), num_sets(n), sz(n) {} 31 | 32 | int find_set(int u) { 33 | assert(u <= sz); 34 | 35 | int leader; 36 | for(leader = u; ~par[leader]; leader = par[leader]); 37 | 38 | for(int next = par[u]; u != leader; next = par[next]) { 39 | par[u] = leader; 40 | u = next; 41 | } 42 | return leader; 43 | } 44 | 45 | bool same_set(int u, int v) { 46 | return find_set(u) == find_set(v); 47 | } 48 | 49 | bool union_set(int u, int v) { 50 | if(same_set(u, v)) return false; 51 | 52 | int x = find_set(u); 53 | int y = find_set(v); 54 | 55 | if(siz[x] < siz[y]) swap(x, y); 56 | 57 | par[y] = x; 58 | siz[x] += siz[y]; 59 | 60 | --num_sets; 61 | return true; 62 | } 63 | 64 | int number_of_sets() { 65 | return num_sets; 66 | } 67 | 68 | int size_of_set(int u) { 69 | return siz[find_set(u)]; 70 | } 71 | 72 | size_t size() { 73 | return sz; 74 | } 75 | 76 | void clear() { 77 | par.clear(); 78 | siz.clear(); 79 | sz = num_sets = 0; 80 | } 81 | 82 | void assign(size_t n) { 83 | par.assign(n + 1, -1); 84 | siz.assign(n + 1, 1); 85 | sz = num_sets = n; 86 | } 87 | 88 | map < int, vector > groups(int st) { 89 | map < int, vector > ret; 90 | 91 | for(size_t i = st; i < sz + st; ++i) 92 | ret[find_set(i)].push_back(i); 93 | 94 | return ret; 95 | } 96 | }; 97 | 98 | -------------------------------------------------------------------------------- /cod/geometry/point.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | notes: 3 | EPS = 1e-9 4 | ------------------------------------ 5 | Integers | Doubles | 6 | ------------------------------------ 7 | a == b | fabs(a - b) < EPS | 8 | a <= b | a < b + EPS | 9 | a >= b | a + EPS > b | 10 | a < b | a + EPS < b | 11 | a > b | a > b + EPS | 12 | x >= 0.0 | x > -EPS | 13 | x <= 0.0 | x < EPS | 14 | ----------------------------------- 15 | **/ 16 | 17 | class point { 18 | public : 19 | ld x, y; 20 | 21 | point() = default; 22 | point(ld _x, ld _y) : x(_x), y(_y) {} 23 | 24 | bool operator < (point other) const { 25 | if(fabs(x - other.x) > EPS) // if(x != other.x) 26 | return x < other.x; 27 | return y < other.y; 28 | } 29 | 30 | bool operator == (point other) const { 31 | return ((fabs(x - other.x) < EPS) && (fabs(y - other.y) < EPS)); // " < EPS " equal to " == zero " 32 | } 33 | 34 | bool operator > (point other) const { 35 | if(fabs(x - other.x) > EPS) 36 | return x > other.x; 37 | return y > other.y; 38 | } 39 | 40 | ld dist(point other) { // Euclidean distance 41 | ld dx = this->x - other.x; 42 | ld dy = this->y - other.y; 43 | return sqrtl(dx * dx + dy * dy); 44 | } 45 | 46 | ld DEG_to_RAD(ld theta) { 47 | return theta * PI / 180.0; 48 | } 49 | 50 | ld RAD_to_DEG(ld theta) { 51 | return theta * 180.0 / PI; 52 | } 53 | 54 | point rotate(ld theta) { 55 | ld rad = DEG_to_RAD(theta); 56 | return point(cos(theta) * x - sin(theta) * y, 57 | sin(theta) * x + cos(theta) * y); 58 | } 59 | }; 60 | -------------------------------------------------------------------------------- /cod/graph_theory/adjacency_list.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class Graph { 3 | public: 4 | vector _head, _next, _to; 5 | vector _cost; 6 | int edge_number; 7 | bool isDirected; 8 | 9 | Graph() = default; 10 | Graph(int V, int E, bool isDirec) { 11 | isDirected = isDirec; 12 | _head.assign(V + 9, 0); 13 | _next.assign(isDirected ? E + 9 : E * 2 + 9, 0); 14 | _to.assign(isDirected ? E + 9 : E * 2 + 9, 0); 15 | // _cost.assign(isDirected ? E + 9 : E * 2 + 9, 0); 16 | edge_number = 0; 17 | } 18 | 19 | void addEdge(int u, int v, T w = 0) { 20 | _next[++edge_number] = _head[u]; 21 | _to[edge_number] = v; 22 | // _cost[edge_number] = w; 23 | _head[u] = edge_number; 24 | } 25 | 26 | void addBiEdge(int u, int v, int w = 0) { 27 | addEdge(u, v, w); 28 | addEdge(v, u, w); 29 | } 30 | 31 | void dfs(int node) { 32 | vis[node] = true; 33 | for(int i = _head[node]; i; i = _next[i]) if(!vis[_to[i]]) { 34 | dfs(_to[i]); 35 | } 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /cod/graph_theory/articulation_points_and_bridges.cpp: -------------------------------------------------------------------------------- 1 | const int N = 1e5 + 9, M = 2e6 + 9, oo = 0x3f3f3f3f, Mod = 1e9 + 7; 2 | ll INF = 0x3f3f3f3f3f3f3f3f; 3 | 4 | int Head[N], Next[M], To[M], Cost[M]; 5 | int Par[N], dfs_num[N], dfs_low[N]; 6 | int ne, n, m, u, v, w; 7 | int root, rootChildren, dfs_timer, bridgeInx; 8 | bool Art[N]; 9 | vector < pair > bridges(M); 10 | 11 | void addEdge(int from, int to, int cost = 0) { 12 | Next[++ne] = Head[from]; 13 | Head[from] = ne; 14 | Cost[ne] = cost; 15 | To[ne] = to; 16 | } 17 | 18 | void _clear() { 19 | memset(Head, 0, sizeof(Head[0]) * (n + 2)); 20 | memset(dfs_num, 0, sizeof(dfs_num[0]) * (n + 2)); 21 | memset(Par, -1, sizeof(Par[0]) * (n + 2)); 22 | memset(Art, 0, sizeof(Art[0]) * (n + 2)); 23 | ne = dfs_timer = bridgeInx = 0; 24 | } 25 | 26 | void Tarjan(int node) { 27 | dfs_num[node] = dfs_low[node] = ++dfs_timer; 28 | 29 | for(int i = Head[node]; i; i = Next[i]) { 30 | if(dfs_num[To[i]] == 0) 31 | { 32 | if(node == root) ++rootChildren; 33 | 34 | Par[To[i]] = node; 35 | Tarjan(To[i]); 36 | dfs_low[node] = Min(dfs_low[node], dfs_low[To[i]]); 37 | 38 | if(dfs_low[To[i]] >= dfs_num[node]) 39 | Art[node] = true; 40 | 41 | if(dfs_low[To[i]] > dfs_num[node]) 42 | bridges[bridgeInx++] = make_pair(node, To[i]); 43 | } 44 | else if(To[i] != Par[node]) 45 | dfs_low[node] = Min(dfs_low[node], dfs_num[To[i]]); 46 | } 47 | } 48 | 49 | int main() { 50 | cin >> n >> m; 51 | _clear(); 52 | 53 | while(m--) { 54 | cin >> u >> v; 55 | addEdge(u, v); 56 | addEdge(v, u); 57 | } 58 | 59 | for(int i = 1; i <= n; ++i) 60 | if(dfs_num[i] == 0) { 61 | root = i; 62 | rootChildren = 0; 63 | Tarjan(i); 64 | Art[root] = (rootChildren > 1); 65 | } 66 | 67 | cout << "Art Points :\n"; 68 | for(int i = 1; i <= n; ++i) if(Art[i]) 69 | cout << i << " "; 70 | 71 | cout << "\nBridges :\n"; 72 | for(int i = 0; i < bridgeInx; ++i) 73 | cout << bridges[i].first << " - " << bridges[i].second << endl; 74 | } 75 | 76 | -------------------------------------------------------------------------------- /cod/graph_theory/bellman_ford.cpp: -------------------------------------------------------------------------------- 1 | // Bellman-Ford Algorithm 2 | // In programming contests, the slowness of Bellman Ford and its negative cycle detection feature 3 | // causes it to be used only to solve the SSSP problem on small graph 4 | // which is not guaranteed to be free from negative weight cycle 5 | 6 | const int N = 1e5 + 9, M = 2e5 + 9, oo = 0x3f3f3f3f; 7 | ll INF = 0x3f3f3f3f3f3f3f3f; 8 | 9 | int Head[N], Par[N], Next[M], To[M], Cost[M], ne, n, m, u, v, st, tr, tax; 10 | ll dis[N]; 11 | 12 | void addEdge(int from, int to, int cost) { 13 | Next[++ne] = Head[from]; 14 | Head[from] = ne; 15 | Cost[ne] = cost; 16 | To[ne] = to; 17 | } 18 | 19 | void _clear() { 20 | memset(Head, 0, sizeof(Head[0]) * (n + 2)); 21 | ne = 0; 22 | } 23 | 24 | bool hasNC() { 25 | for(int i = 1; i <= n; ++i) 26 | for(int j = Head[i]; j; j = Next[j]) 27 | if(dis[i] < INF && dis[i] + Cost[j] < dis[To[j]]) 28 | return true; 29 | 30 | return false; 31 | } 32 | 33 | bool Bellman_Ford(int src) { 34 | memset(dis, 0x3f, sizeof(dis[0]) * (n + 2)); 35 | memset(Par, -1, sizeof(Par[0]) * (n + 2)); 36 | 37 | dis[src] = 0; 38 | bool newRelaxation = true; 39 | 40 | for(int i = 2; i <= n && newRelaxation; ++i) { 41 | newRelaxation = false; 42 | for(int i = 1; i <= n; ++i) 43 | for(int j = Head[i]; j; j = Next[j]) 44 | if(dis[i] < INF && dis[i] + Cost[j] < dis[To[j]]) { 45 | dis[To[j]] = dis[i] + Cost[j]; 46 | Par[To[j]] = i; 47 | newRelaxation = true; 48 | } 49 | } 50 | return hasNC(); 51 | } 52 | -------------------------------------------------------------------------------- /cod/graph_theory/bi_connected_components.cpp: -------------------------------------------------------------------------------- 1 | const int N = 1e5 + 9, M = 2e5 + 9, oo = 0x3f3f3f3f, Mod = 1e9 + 7; 2 | const ll INF = 0x3f3f3f3f3f3f3f3f; 3 | 4 | int Head[N], Next[M], To[M]; 5 | int Par[N], dfs_num[N], dfs_low[N]; 6 | int ne, n, m, u, v; 7 | int root, rootChildren, dfs_timer; 8 | int Stack[N], top, ID; 9 | bool Art[N]; 10 | vector < vector > BiCCs(N), BiCCIDs(N); 11 | 12 | void addEdge(int from, int to) { 13 | Next[++ne] = Head[from]; 14 | Head[from] = ne; 15 | To[ne] = to; 16 | } 17 | 18 | void _clear() { 19 | memset(Head, 0, sizeof(Head[0]) * (n + 2)); 20 | memset(dfs_num, 0, sizeof(dfs_num[0]) * (n + 2)); 21 | memset(Par, -1, sizeof(Par[0]) * (n + 2)); 22 | memset(Art, 0, sizeof(Art[0]) * (n + 2)); 23 | ne = dfs_timer = top = ID = 0; 24 | BiCCs = BiCCIDs = vector < vector > (N); 25 | } 26 | 27 | void Tarjan(int node) { 28 | dfs_num[node] = dfs_low[node] = ++dfs_timer; 29 | Stack[top++] = node; 30 | 31 | for(int i = Head[node]; i; i = Next[i]) { 32 | if(dfs_num[To[i]] == 0) { 33 | if(node == root) ++rootChildren; 34 | 35 | Par[To[i]] = node; 36 | Tarjan(To[i]); 37 | 38 | dfs_low[node] = Min(dfs_low[node], dfs_low[To[i]]); 39 | 40 | if(dfs_low[To[i]] >= dfs_num[node]) { 41 | Art[node] = true; 42 | ++ID; 43 | for(int x = -1; x ^ To[i];) { 44 | x = Stack[--top]; 45 | BiCCIDs[x].emplace_back(ID); 46 | BiCCs[ID].emplace_back(x); 47 | } 48 | BiCCIDs[node].emplace_back(ID); 49 | BiCCs[ID].emplace_back(node); 50 | } 51 | } 52 | else if(To[i] != Par[node]) 53 | dfs_low[node] = Min(dfs_low[node], dfs_num[To[i]]); 54 | } 55 | } 56 | 57 | int main() { 58 | cin >> n >> m; 59 | _clear(); 60 | 61 | while(m--) { 62 | cin >> u >> v; 63 | addEdge(u, v); 64 | addEdge(v, u); 65 | } 66 | 67 | for(int i = 1; i <= n; ++i) 68 | if(dfs_num[i] == 0) { // O(n + m) 69 | root = i; 70 | rootChildren = 0; 71 | Tarjan(i); 72 | Art[root] = (rootChildren > 1); 73 | } 74 | 75 | for(int i = 1; i <= ID; ++i) { 76 | cout << "Component : " << i << " contains : "; 77 | for(int j = 0; j < (int)BiCCs[i].size(); ++j) 78 | cout << BiCCs[i][j] << " \n"[j == BiCCs[i].size() - 1]; 79 | } 80 | } 81 | 82 | -------------------------------------------------------------------------------- /cod/graph_theory/bi_partite_graph.cpp: -------------------------------------------------------------------------------- 1 | const int N = 1e5 + 9, M = 2e5 + 9, oo = 0x3f3f3f3f; 2 | ll INF = 0x3f3f3f3f3f3f3f3f; 3 | 4 | int Head[N], Par[N], Next[M], To[M], Cost[M], ne, n, m, u, v, st, tr, tax; 5 | ll dis[N]; 6 | bool color[N], vis[N]; 7 | 8 | void addEdge(int from, int to) { 9 | Next[++ne] = Head[from]; 10 | Head[from] = ne; 11 | To[ne] = to; 12 | } 13 | 14 | bool checkBiPartite(int node, int par = 0) { 15 | if(vis[node]) 16 | return color[par] != color[node]; 17 | 18 | color[node] = color[par] ^ 1; 19 | 20 | vis[node] = true; 21 | bool ok = true; 22 | for(int i = Head[node]; i; i = Next[i]) 23 | if(To[i] != par) 24 | ok &= checkBiPartite(To[i], node); 25 | 26 | return ok; 27 | } 28 | 29 | int main() { 30 | cin >> n >> m; 31 | while(m--) { 32 | cin >> u >> v; 33 | addEdge(u, v); 34 | addEdge(v, u); 35 | } 36 | 37 | bool isBiPartite = true; 38 | for(int i = 1; i <= n; ++i) if(!vis[i]) 39 | isBiPartite &= checkBiPartite(i); 40 | 41 | cout << (isBiPartite ? "YES" : "NO") << endl; 42 | } 43 | 44 | -------------------------------------------------------------------------------- /cod/graph_theory/breadth_first_search.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | typedef int64_t ll; 4 | 5 | const int N = 1e5 + 9, M = 2e5 + 9, oo = 0x3f3f3f3f; 6 | ll INF = 0x3f3f3f3f3f3f3f3f; 7 | 8 | int Head[N], Par[N], Next[M], To[M], Cost[M], ne, n, m, u, v, st, tr, tax; 9 | ll dis[N]; 10 | 11 | void addEdge(int from, int to, int cost) { 12 | Next[++ne] = Head[from]; 13 | Head[from] = ne; 14 | Cost[ne] = cost; 15 | To[ne] = to; 16 | } 17 | 18 | void _clear() { 19 | memset(Head, 0, sizeof(Head[0]) * (n + 2)); 20 | ne = 0; 21 | } 22 | 23 | void BFS(int src) { 24 | memset(dis, 0x3f, sizeof(dis[0]) * (n + 2)); 25 | memset(Par, -1, sizeof(Par[0]) * (n + 2)); 26 | 27 | queue q; 28 | q.push(src); 29 | dis[src] = 0; 30 | 31 | int u; 32 | while(q.size()) { 33 | u = q.front(); q.pop(); 34 | for(int i = Head[u]; i; i = Next[i]) 35 | if(dis[To[i]] == oo) { 36 | dis[To[i]] = dis[u] + 1; 37 | Par[To[i]] = u; 38 | q.push(To[i]); 39 | } 40 | } 41 | } 42 | 43 | int main() 44 | { 45 | cin >> n >> m >> st >> tr; 46 | while(m--) { 47 | cin >> u >> v >> tax; 48 | addEdge(u, v, tax); 49 | addEdge(v, u, tax); 50 | } 51 | 52 | BFS(st); 53 | cout << dis[tr] << endl; 54 | } 55 | 56 | -------------------------------------------------------------------------------- /cod/graph_theory/connected_components.cpp: -------------------------------------------------------------------------------- 1 | const int N = 1e5 + 9, M = 1e6 + 9; 2 | 3 | int Head[N], Next[M], To[M], ne, u, v, n, m, CCs; 4 | bool visited[N]; 5 | 6 | void addEdge(int from, int to) { 7 | Next[++ne] = Head[from]; 8 | Head[from] = ne; 9 | To[ne] = to; 10 | } 11 | 12 | void DFS(int node) { 13 | visited[node] = true; 14 | for(int e = Head[node]; e; e = Next[e]) 15 | if(!visited[To[e]]) 16 | DFS(To[e]); 17 | } 18 | 19 | int main() { 20 | cin >> n >> m; 21 | while(m--) { 22 | cin >> u >> v; 23 | addEdge(u, v); 24 | addEdge(v, u); 25 | } 26 | 27 | for(int node = 1; node <= n; ++node) if(!visited[node]) 28 | ++CCs, DFS(node); 29 | 30 | cout << CCs << endl; 31 | } 32 | 33 | -------------------------------------------------------------------------------- /cod/graph_theory/cycle_detection[directedg].cpp: -------------------------------------------------------------------------------- 1 | const int N = 1e5 + 9, M = 2e5 + 9, oo = 0x3f3f3f3f; 2 | ll INF = 0x3f3f3f3f3f3f3f3f; 3 | 4 | int Head[N], Par[N], Next[M], To[M], Cost[M], ne, n, m, u, v, st, tr, tax; 5 | ll dis[N]; 6 | bool hasCycle; 7 | char visited[N]; 8 | 9 | void addEdge(int from, int to) { 10 | Next[++ne] = Head[from]; 11 | Head[from] = ne; 12 | To[ne] = to; 13 | } 14 | 15 | void DFS(int node) { 16 | if(hasCycle |= visited[node] == 1) 17 | return; /** Oops, revisiting active node **/ 18 | visited[node] = 1; /** current node legend mode has been activated **/ 19 | 20 | for(int i = Head[node]; i; i = Next[i]) 21 | if(visited[To[i]] != 2) 22 | DFS(To[i]); 23 | 24 | visited[node] = 2; /** done with this node and mark it as visited **/ 25 | } 26 | 27 | int main() { 28 | cin >> n >> m; 29 | while(m--) { 30 | cin >> u >> v; 31 | addEdge(u, v); 32 | } 33 | 34 | for(int i = 1; i <= n; ++i) 35 | if(!visited[i]) 36 | DFS(i); 37 | 38 | cout << (hasCycle ? "YES" : "NO") << endl; 39 | } 40 | 41 | -------------------------------------------------------------------------------- /cod/graph_theory/cycle_detection[undirectedg].cpp: -------------------------------------------------------------------------------- 1 | const int N = 1e5 + 9, M = 2e5 + 9, oo = 0x3f3f3f3f; 2 | ll INF = 0x3f3f3f3f3f3f3f3f; 3 | 4 | int Head[N], Par[N], Next[M], To[M], Cost[M], ne, n, m, u, v, st, tr, tax; 5 | ll dis[N]; 6 | bool visited[N], hasCycle; 7 | 8 | void addEdge(int from, int to) { 9 | Next[++ne] = Head[from]; 10 | Head[from] = ne; 11 | To[ne] = to; 12 | } 13 | 14 | void DFS(int node, int parent = -1) { 15 | if(hasCycle |= visited[node]) 16 | return; 17 | visited[node] = true; 18 | 19 | for(int i = Head[node]; i; i = Next[i]) 20 | if(To[i] != parent) 21 | DFS(To[i], node); 22 | } 23 | 24 | int main() { 25 | cin >> n >> m; 26 | while(m--) { 27 | cin >> u >> v; 28 | addEdge(u, v); 29 | addEdge(v, u); 30 | } 31 | 32 | for(int i = 1; i <= n; ++i) 33 | if(!visited[i]) 34 | DFS(i); 35 | 36 | cout << (hasCycle ? "YES" : "NO") << endl; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /cod/graph_theory/depth_first_search.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | typedef int64_t ll; 4 | 5 | const int N = 1e5 + 9, M = 2e5 + 9, oo = 0x3f3f3f3f; 6 | ll INF = 0x3f3f3f3f3f3f3f3f; 7 | 8 | int Head[N], Par[N], Next[M], To[M], Cost[M], ne, n, m, u, v, st, tr, tax; 9 | ll dis[N]; 10 | bool vis[N]; 11 | 12 | void addEdge(int from, int to, int cost) { 13 | Next[++ne] = Head[from]; 14 | Head[from] = ne; 15 | Cost[ne] = cost; 16 | To[ne] = to; 17 | } 18 | 19 | void _clear() { 20 | memset(Head, 0, sizeof(Head[0]) * (n + 2)); 21 | ne = 0; 22 | } 23 | 24 | void DFS(int node) { 25 | vis[node] = true; 26 | for(int i = Head[node]; i; i = Next[i]) 27 | if(!vis[To[i]]) 28 | DFS(To[i]); 29 | } 30 | 31 | int main() { 32 | cin >> n >> m; 33 | while(m--) { 34 | cin >> u >> v; 35 | addEdge(u, v); 36 | addEdge(v, u); 37 | } 38 | 39 | for(int i = 1; i <= n; ++i) 40 | if(!vis[i]) 41 | DFS(i); 42 | } 43 | 44 | -------------------------------------------------------------------------------- /cod/graph_theory/dijkstra[densegraph].cpp: -------------------------------------------------------------------------------- 1 | /** Dijkstra on dense graphs 2 | complexity : O(n^2 + m) 3 | **/ 4 | 5 | const int N = 1e5 + 9, M = 2e5 + 9, oo = 0x3f3f3f3f; 6 | ll INF = 0x3f3f3f3f3f3f3f3f; 7 | 8 | int Head[N], Par[N], Next[M], To[M], Cost[M], ne, n, m, u, v, st, tr, tax; 9 | ll dis[N]; 10 | 11 | void addEdge(int from, int to, int cost) { 12 | Next[++ne] = Head[from]; 13 | Head[from] = ne; 14 | Cost[ne] = cost; 15 | To[ne] = to; 16 | } 17 | 18 | void _clear() { 19 | memset(Head, 0, sizeof(Head[0]) * (n + 2)); 20 | ne = 0; 21 | } 22 | 23 | void Dijkstra(int src, int V) { 24 | memset(dis, 0x3f, sizeof(dis[0]) * (n + 2)); 25 | memset(Par, -1, sizeof(Par[0]) * (n + 2)); 26 | 27 | vector mark(V + 1, false); 28 | 29 | dis[src] = 0; 30 | for(int i = 1; i <= V; ++i) { 31 | int node = 0; 32 | for(int j = 1; j <= V; ++j) 33 | if(!mark[j] && dis[j] < dis[node]) 34 | node = j; 35 | 36 | if(dis[node] == INF) break; 37 | 38 | mark[node] = true; 39 | for(int i = Head[node]; i; i = Next[i]) 40 | if(dis[node] + Cost[i] < dis[To[i]]) { 41 | dis[To[i]] = dis[node] + Cost[i]; 42 | Par[To[i]] = node; 43 | } 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /cod/graph_theory/dijkstra[grid].cpp: -------------------------------------------------------------------------------- 1 | const int dr[] = { 1, -1, 0, 0, 1, 1, -1, -1 }; 2 | const int dc[] = { 0, 0, 1, -1, 1, -1, 1, -1 }; 3 | const char dir[] = {'D', 'U', 'R', 'L'}; 4 | 5 | const int N = 1e3 + 9, M = 2e5 + 9, oo = 0x3f3f3f3f; 6 | 7 | int grid[N][N], dis[N][N], n, m; 8 | 9 | bool valid(int r, int c) { 10 | return r >= 1 && r <= n && c >= 1 && c <= m; 11 | } 12 | 13 | void Dijkstra(int sr, int sc) { 14 | memset(dis, 0x3f, sizeof (dis)); // memset(dis, 0x3f, n * m) we don't do that here 15 | 16 | priority_queue > Q; 17 | 18 | dis[sr][sc] = grid[sr][sc]; 19 | Q.push({-grid[sr][sc], sr, sc}); 20 | 21 | int cost, r, c, nr, nc; 22 | while(Q.size()) { 23 | tie(cost, r, c) = Q.top(); Q.pop(); 24 | if((-cost) > dis[r][c]) continue; // lazy deletion 25 | 26 | for(int i = 0; i < 4; ++i) { 27 | nr = r + dr[i]; 28 | nc = c + dc[i]; 29 | 30 | if(!valid(nr, nc)) continue; 31 | 32 | if(dis[r][c] + grid[nr][nc] < dis[nr][nc]) { 33 | dis[nr][nc] = dis[r][c] + grid[nr][nc]; 34 | Q.push({-dis[nr][nc], nr, nc}); 35 | } 36 | } 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /cod/graph_theory/dijkstra[negativeweightedges].cpp: -------------------------------------------------------------------------------- 1 | const int N = 1e5 + 9, M = 2e5 + 9, oo = 0x3f3f3f3f; 2 | ll INF = 0x3f3f3f3f3f3f3f3f; 3 | 4 | int Head[N], Par[N], Next[M], To[M], Cost[M], ne, n, m, u, v, st, tr, tax; 5 | ll dis[N]; 6 | 7 | void addEdge(int from, int to, int cost) { 8 | Next[++ne] = Head[from]; 9 | Head[from] = ne; 10 | Cost[ne] = cost; 11 | To[ne] = to; 12 | } 13 | 14 | void _clear() { 15 | memset(Head, 0, sizeof(Head[0]) * (n + 2)); 16 | ne = 0; 17 | } 18 | 19 | void Dijkstra(int src) { 20 | memset(dis, 0x3f, sizeof(dis[0]) * (n + 2)); 21 | memset(Par, -1, sizeof(Par[0]) * (n + 2)); 22 | 23 | priority_queue > Q; 24 | 25 | dis[src] = 0; 26 | Q.push({-dis[src], src}); 27 | 28 | int node; 29 | ll cost; 30 | while(Q.size()) { 31 | tie(cost, node) = Q.top(); Q.pop(); 32 | if((-cost) > dis[node]) continue; 33 | 34 | for(int i = Head[node]; i; i = Next[i]) 35 | if(dis[node] + Cost[i] < dis[To[i]]) { 36 | dis[To[i]] = dis[node] + Cost[i]; 37 | Q.push({-dis[To[i]], To[i]}); 38 | Par[To[i]] = node; 39 | } 40 | } 41 | } 42 | 43 | 44 | -------------------------------------------------------------------------------- /cod/graph_theory/dijkstra[sparsegraph].cpp: -------------------------------------------------------------------------------- 1 | /** Dijkstra on sparse graphs 2 | - complexity : O(n + m)logn -> O(nlogn + m) 3 | - Single Source Single Destination Shortest Path Problem 4 | - Positive Weight Edges only 5 | * Subpaths of shortest paths from u to v are shortest paths! 6 | **/ 7 | 8 | const int N = 1e5 + 9, M = 2e5 + 9, oo = 0x3f3f3f3f; 9 | ll INF = 0x3f3f3f3f3f3f3f3f; 10 | 11 | int Head[N], Par[N], Next[M], To[M], Cost[M], ne, n, m, u, v, st, tr, tax; 12 | ll dis[N]; 13 | 14 | void addEdge(int from, int to, int cost) { 15 | Next[++ne] = Head[from]; 16 | Head[from] = ne; 17 | Cost[ne] = cost; 18 | To[ne] = to; 19 | } 20 | 21 | void _clear() { 22 | memset(Head, 0, sizeof(Head[0]) * (n + 2)); 23 | ne = 0; 24 | } 25 | 26 | void Dijkstra(int src, int trg) { 27 | memset(dis, 0x3f, sizeof(dis[0]) * (n + 2)); 28 | memset(Par, -1, sizeof(Par[0]) * (n + 2)); 29 | 30 | priority_queue > Q; 31 | 32 | dis[src] = 0; 33 | Q.push({-dis[src], src}); 34 | 35 | int node; 36 | ll cost; 37 | while(Q.size()) { 38 | tie(cost, node) = Q.top(); Q.pop(); 39 | 40 | if((-cost) > dis[node]) continue; // lazy deletion 41 | if(node == trg) return; // cheapest cost in case of positive weight edges 42 | 43 | for(int i = Head[node]; i; i = Next[i]) 44 | if(dis[node] + Cost[i] < dis[To[i]]) { 45 | dis[To[i]] = dis[node] + Cost[i]; 46 | Q.push({-dis[To[i]], To[i]}); 47 | Par[To[i]] = node; 48 | } 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /cod/graph_theory/directed_cyclic_graph_into_directed_acyclic_graph.cpp: -------------------------------------------------------------------------------- 1 | const int N = 1e5 + 9, M = 2e6 + 9, oo = 0x3f3f3f3f, Mod = 1e9 + 7; 2 | ll INF = 0x3f3f3f3f3f3f3f3f; 3 | 4 | int Head[N], To[M], Next[M], Cost[M]; 5 | int dfs_num[N], dfs_low[N], out[N]; 6 | int Stack[N], compID[N], compSize[N]; 7 | int ne, n, m, u, v, w; 8 | int dfs_timer, top, ID; 9 | bool in_stack[N]; 10 | 11 | int HeadDAG[N], ToDAG[M], NextDAG[M], CostDAG[M], neDAG; 12 | 13 | void addEdge(int from, int to, int cost = 0) { 14 | Next[++ne] = Head[from]; 15 | Head[from] = ne; 16 | Cost[ne] = cost; 17 | To[ne] = to; 18 | } 19 | 20 | void addEdgeDAG(int from, int to, int cost = 0) { 21 | NextDAG[++neDAG] = HeadDAG[from]; 22 | HeadDAG[from] = neDAG; 23 | CostDAG[ne] = cost; 24 | ToDAG[neDAG] = to; 25 | ++out[from]; 26 | } 27 | 28 | void _clear() { 29 | memset(Head, 0, sizeof(Head[0]) * (n + 2)); 30 | memset(dfs_num, 0, sizeof(dfs_num[0]) * (n + 2)); 31 | memset(compID, 0, sizeof(compID[0]) * (n + 2)); 32 | memset(compSize, 0, sizeof(compSize[0]) * (n + 2)); 33 | memset(HeadDAG, 0, sizeof(HeadDAG[0]) * (n + 2)); 34 | memset(out, 0, sizeof(out[0]) * (n + 2)); 35 | ne = dfs_timer = top = neDAG = ID = 0; 36 | } 37 | 38 | void Tarjan(int node) { 39 | dfs_num[node] = dfs_low[node] = ++dfs_timer; 40 | in_stack[Stack[top++] = node] = true; 41 | 42 | for(int i = Head[node]; i; i = Next[i]) { 43 | if(dfs_num[To[i]] == 0) 44 | Tarjan(To[i]); 45 | 46 | if(in_stack[To[i]]) 47 | dfs_low[node] = Min(dfs_low[node], dfs_low[To[i]]); 48 | } 49 | 50 | if(dfs_num[node] == dfs_low[node]) { 51 | ++ID; 52 | for(int cur = -1; cur ^ node;) { 53 | in_stack[cur = Stack[--top]] = false; 54 | compID[cur] = ID; 55 | ++compSize[ID]; 56 | } 57 | } 58 | } 59 | 60 | void Tarjan() { 61 | for(int i = 1; i <= n; ++i) 62 | if(dfs_num[i] == 0) 63 | Tarjan(i); 64 | } 65 | 66 | void DFS(int node) { 67 | dfs_num[node] = 1; 68 | for(int i = Head[node]; i; i = Next[i]) { 69 | if(compID[node] != compID[To[i]]) 70 | addEdgeDAG(compID[node], compID[To[i]]); 71 | 72 | if(dfs_num[To[i]] == 0) 73 | DFS(To[i]); 74 | } 75 | } 76 | 77 | void construct_dag() { 78 | memset(dfs_num, 0, sizeof(dfs_num[0]) * (n + 2)); 79 | 80 | for(int i = 1; i <= n; ++i) 81 | if(dfs_num[i] == 0) 82 | DFS(i); 83 | } 84 | 85 | -------------------------------------------------------------------------------- /cod/graph_theory/edge_classification.cpp: -------------------------------------------------------------------------------- 1 | #pragma GCC optimize ("Ofast") 2 | 3 | #include 4 | 5 | #define UNVISITED 0 6 | #define EXPLORED 1 7 | #define VISITED 2 8 | 9 | using namespace std; 10 | 11 | typedef int64_t ll; 12 | 13 | const int N = 1e5 + 9, M = 2e5 + 9, oo = 0x3f3f3f3f; 14 | ll INF = 0x3f3f3f3f3f3f3f3f; 15 | 16 | int Head[N], Next[M], To[M], Par[N], in_time[N], ne, n, m, u, v, dfs_timer; 17 | char dfs_num[N]; 18 | 19 | void addEdge(int from, int to) { 20 | Next[++ne] = Head[from]; 21 | Head[from] = ne; 22 | To[ne] = to; 23 | } 24 | 25 | void edgeClassification(int node) { 26 | dfs_num[node] = EXPLORED; 27 | in_time[node] = ++dfs_timer; 28 | 29 | for(int i = Head[node]; i; i = Next[i]) { 30 | if(dfs_num[To[i]] == UNVISITED) { 31 | cout << "Tree Edge : " << node << " -> " << To[i] << endl; 32 | 33 | Par[To[i]] = node; 34 | edgeClassification(To[i]); 35 | } 36 | else if(dfs_num[To[i]] == VISITED) { 37 | /** Cross Edges only occur in directed graph */ 38 | if(in_time[To[i]] < in_time[node]) 39 | cout << "Cross Edge : " << node << " -> " << To[i] << endl; 40 | else 41 | cout << "Forward Edge : " << node << " -> " << To[i] << endl; 42 | } 43 | else if(dfs_num[To[i]] == EXPLORED) { 44 | if(Par[node] == To[i]) 45 | cout << "Bi-Directional Edge : " << node << " -> " << To[i] << endl; 46 | else 47 | cout << "Backward Edge : " << node << " -> " << To[i] << " (Cycle)" << endl; 48 | } 49 | } 50 | 51 | dfs_num[node] = VISITED; 52 | } 53 | 54 | int main() { 55 | cin >> n >> m; 56 | while(m--) { 57 | cin >> u >> v; 58 | addEdge(u, v); 59 | } 60 | 61 | for(int i = 1; i <= n; ++i) 62 | if(!dfs_num[i]) 63 | edgeClassification(i); 64 | } 65 | 66 | -------------------------------------------------------------------------------- /cod/graph_theory/eulerian_tour_tree.cpp: -------------------------------------------------------------------------------- 1 | int Head[N], To[M], Next[M], Cost[M]; 2 | int ne, n, m, u, v, w; 3 | 4 | int Last[N], First[N], euler_tour[1 + N << 1]; 5 | ll Height[1 + N << 1]; 6 | int euler_timer; 7 | 8 | void addEdge(int from, int to, int cost = 0) { 9 | Next[++ne] = Head[from]; 10 | Head[from] = ne; 11 | Cost[ne] = cost; 12 | To[ne] = to; 13 | } 14 | 15 | void _clear() { 16 | memset(Head, 0, sizeof(Head[0]) * (n + 2)); 17 | memset(Last, 0, sizeof(Last[0]) * (n + 2)); 18 | memset(First, 0, sizeof(First[0]) * (n + 2)); 19 | ne = euler_timer = 0; 20 | } 21 | 22 | /** 23 | euler_tour[1 .. n * 2 - 1] = which records the sequence of visited nodes 24 | Height[1 .. n * 2 - 1] = which records the depth of each visited node 25 | 26 | First[1 .. n] = records the index of the first occurrence of node i in euler_tour 27 | Last[1 .. n] = records the index of the last occurrence of node i in euler_tour 28 | **/ 29 | 30 | void EulerianTour(int node, ll depth = 0) { 31 | euler_tour[++euler_timer] = node; 32 | Height[euler_timer] = depth; 33 | First[node] = euler_timer; 34 | 35 | for(int i = Head[node]; i; i = Next[i]) 36 | if(First[To[i]] == 0) { 37 | EulerianTour(To[i], depth + Cost[i]); 38 | 39 | euler_tour[++euler_timer] = node; 40 | Height[euler_timer] = depth; 41 | } 42 | 43 | Last[node] = euler_timer; 44 | } 45 | 46 | void show() { 47 | for(int i = 1; i < (n << 1); ++i) cout << euler_tour[i] << " ";cout << endl; 48 | for(int i = 1; i < (n << 1); ++i) cout << Height[i] << " "; cout << endl; 49 | for(int i = 1; i <= n; ++i) cout << First[i] << " "; cout << endl; 50 | for(int i = 1; i <= n; ++i) cout << Last[i] << " "; cout << endl; 51 | } 52 | 53 | int main() { 54 | cin >> n >> m; 55 | _clear(); 56 | 57 | while(m--) { 58 | cin >> u >> v >> w; 59 | addEdge(u, v, w); 60 | addEdge(v, u, w); 61 | } 62 | 63 | EulerianTour(1); 64 | show(); 65 | } 66 | -------------------------------------------------------------------------------- /cod/graph_theory/flood_fill.cpp: -------------------------------------------------------------------------------- 1 | /** check if there is a path from (0, 0) to (n - 1, m - 1) using '.' only **/ 2 | 3 | int dr[4] = {1, -1, 0, 0}; 4 | int dc[4] = {0, 0, 1, -1}; 5 | char grid[N][M]; 6 | int n, m; 7 | 8 | bool valid(int r, int c) { 9 | return r >= 0 && r < n && c >= 0 && c < m && grid[r][c] == '.'; 10 | } 11 | 12 | bool isDis(int r, int c) { 13 | return r == n - 1 && c == m - 1; 14 | } 15 | 16 | bool FloodFill(int r, int c) { 17 | if(!valid(r, c)) return false; 18 | if(isDis(r, c)) return true; 19 | 20 | grid[r][c] = '#'; 21 | for(int i = 0; i < 4; ++i) 22 | if(FloodFill(r + dr[i], c + dc[i])) 23 | return true; 24 | return false; 25 | } 26 | 27 | int main() { 28 | cin >> n >> m; 29 | for(int i = 0; i < n; ++i) 30 | for(int j = 0; j < m; ++j) 31 | cin >> grid[i][j]; 32 | 33 | cout << (FloodFill(0, 0) ? "YES" : "NO") << endl; 34 | } 35 | 36 | -------------------------------------------------------------------------------- /cod/graph_theory/floyd_warshall.cpp: -------------------------------------------------------------------------------- 1 | /** -The graph has a 'negative cycle' if at the end of the algorithm, 2 | the distance from a vertex v to itself is negative. 3 | 4 | - before k-th phase the value of d[i][j] is equal to the length of 5 | the shortest path from vertex i to the vertex j, 6 | if this path is allowed to enter only the vertex with numbers smaller than k 7 | (the beginning and end of the path are not restricted by this property). 8 | **/ 9 | 10 | const int N = 500 + 9, M = 2e5 + 9, oo = 0x3f3f3f3f; 11 | const i64 INF = 0x3f3f3f3f3f3f3f3f; 12 | 13 | int Par[N][N], n, m, u, v, tax; 14 | i64 adj[N][N], dis[N][N]; 15 | 16 | vector restorePath(int st, int tr) { 17 | vector path; 18 | if(dis[st][tr] == INF) return path; 19 | 20 | for(int i = tr; st ^ i; i = Par[st][i]) 21 | path.push_back(i); 22 | 23 | path.push_back(st); 24 | reverse(path.begin(), path.end()); 25 | return path; 26 | } 27 | 28 | void Floyd_Warshall() { 29 | for(int i = 1; i <= n; ++i) 30 | for(int j = 1; j <= n; ++j) 31 | Par[i][j] = i; 32 | 33 | for(int k = 1; k <= n; ++k) 34 | for(int i = 1; i <= n; ++i) 35 | for(int j = 1; j <= n; ++j) 36 | if(dis[i][k] + dis[k][j] < dis[i][j]) { 37 | dis[i][j] = dis[i][k] + dis[k][j]; 38 | Par[i][j] = Par[k][j]; 39 | } 40 | } 41 | 42 | -------------------------------------------------------------------------------- /cod/graph_theory/kruskal.cpp: -------------------------------------------------------------------------------- 1 | class UnionFind { 2 | vector par; 3 | vector siz; 4 | int num_sets; 5 | size_t sz; 6 | 7 | public: 8 | UnionFind() : par(1, -1), siz(1, 1), num_sets(0), sz(0) {} 9 | UnionFind(int n) : par(n + 1, -1), siz(n + 1, 1), num_sets(n), sz(n) {} 10 | 11 | int find_set(int u) { 12 | assert(u <= sz); 13 | 14 | int leader; 15 | for(leader = u; ~par[leader]; leader = par[leader]); 16 | 17 | for(int next = par[u]; u != leader; next = par[next]) { 18 | par[u] = leader; 19 | u = next; 20 | } 21 | return leader; 22 | } 23 | 24 | bool same_set(int u, int v) { 25 | return find_set(u) == find_set(v); 26 | } 27 | 28 | bool union_set(int u, int v) { 29 | if(same_set(u, v)) return false; 30 | 31 | int x = find_set(u); 32 | int y = find_set(v); 33 | 34 | if(siz[x] < siz[y]) swap(x, y); 35 | 36 | par[y] = x; 37 | siz[x] += siz[y]; 38 | 39 | --num_sets; 40 | return true; 41 | } 42 | 43 | int number_of_sets() { 44 | return num_sets; 45 | } 46 | 47 | int size_of_set(int u) { 48 | return siz[find_set(u)]; 49 | } 50 | 51 | size_t size() { 52 | return sz; 53 | } 54 | 55 | void clear() { 56 | par.clear(); 57 | siz.clear(); 58 | sz = num_sets = 0; 59 | } 60 | 61 | void assign(size_t n) { 62 | par.assign(n + 1, -1); 63 | siz.assign(n + 1, 1); 64 | sz = num_sets = n; 65 | } 66 | 67 | map < int, vector > groups(int st) { 68 | map < int, vector > ret; 69 | 70 | for(size_t i = st; i < sz + st; ++i) 71 | ret[find_set(i)].push_back(i); 72 | 73 | return ret; 74 | } 75 | }; 76 | 77 | int n, m, u, v, w; 78 | vector < tuple > edges; 79 | UnionFind uf; 80 | 81 | pair < ll, vector < pair > > Kruskal() { 82 | sort(edges.begin(), edges.end()); 83 | 84 | vector < pair > mstEdges; 85 | int from, to, cost; 86 | ll minWieght = 0; 87 | 88 | for(tuple edge : edges) { 89 | tie(cost, from, to) = edge; 90 | if(uf.union_set(from, to)) { 91 | minWieght += cost; 92 | mstEdges.push_back(make_pair(from, to)); 93 | } 94 | } 95 | 96 | if(mstEdges.size() == n - 1) 97 | return make_pair(minWieght, mstEdges); 98 | 99 | return make_pair(-1, vector < pair > ()); 100 | } 101 | 102 | -------------------------------------------------------------------------------- /cod/graph_theory/kth_ancestor_and_lca[binarylifting].cpp: -------------------------------------------------------------------------------- 1 | const int N = 1e5 + 9, M = 2e5 + 9, oo = 0x3f3f3f3f, Mod = 1e9 + 7; 2 | const int LOG = 20; 3 | 4 | int Head[N], To[M], Next[M], Par[N]; 5 | int up[N][LOG + 1]; 6 | int Log[N], Level[N]; 7 | int ne, n, u, v, q; 8 | 9 | void addEdge(int from, int to) { 10 | Next[++ne] = Head[from]; 11 | Head[from] = ne; 12 | To[ne] = to; 13 | } 14 | 15 | void _clear() { 16 | memset(Head, 0, sizeof(Head[0]) * (n + 2)); 17 | memset(Par, 0, sizeof(Par[0]) * (n + 2)); 18 | memset(Level, 0, sizeof(Level[0]) * (n + 2)); 19 | ne = 0; 20 | } 21 | 22 | int lastBit(int a) { 23 | return (a & -a); 24 | } 25 | 26 | void logCalc() { 27 | Log[1] = 0; 28 | for(int i = 2; i < N; ++i) 29 | Log[i] = Log[i >> 1] + 1; 30 | } 31 | 32 | void DFS(int node, int depth = 0) { 33 | Level[node] = depth; 34 | up[node][0] = Par[node]; // Par[root] = root 35 | 36 | for(int i = 1; i <= LOG; ++i) { 37 | up[node][i] = up[up[node][i - 1]][i - 1]; 38 | } 39 | 40 | for(int i = Head[node]; i; i = Next[i]) 41 | if(To[i] != Par[node]) { 42 | Par[To[i]] = node; 43 | DFS(To[i], depth + 1); 44 | } 45 | } 46 | 47 | int KthAncestor(int u, int k) { 48 | if(k > Level[u]) return -1; 49 | 50 | for(int i = lastBit(k); k; k -= lastBit(k), i = lastBit(k)) 51 | u = up[u][Log[i]]; 52 | 53 | return u; 54 | } 55 | 56 | int LCA(int u, int v) { 57 | if(Level[u] < Level[v]) swap(u, v); 58 | int k = Level[u] - Level[v]; 59 | 60 | u = KthAncestor(u, k); 61 | if(u == v) return u; 62 | 63 | for(int i = LOG; i >= 0; --i) 64 | if(up[u][i] ^ up[v][i]) 65 | { 66 | u = up[u][i]; 67 | v = up[v][i]; 68 | } 69 | 70 | return up[u][0]; 71 | } 72 | 73 | int main() { 74 | cin >> n; 75 | _clear(); 76 | 77 | for(int i = 1; i < n; ++i) { 78 | cin >> u >> v; 79 | addEdge(u, v); 80 | addEdge(v, u); 81 | } 82 | 83 | logCalc(); 84 | for(int i = 1; i <= n; ++i) if(Par[i] == 0) { 85 | Par[i] = i; 86 | DFS(i); 87 | } 88 | 89 | cin >> q; 90 | while(q--) { 91 | cin >> u >> v; 92 | cout << LCA(u, v) << endl; 93 | } 94 | } 95 | 96 | -------------------------------------------------------------------------------- /cod/graph_theory/lca[euleriantourandrmq].cpp: -------------------------------------------------------------------------------- 1 | template > 2 | class SparseTable { 3 | int _N; 4 | int _LOG; 5 | vector _A; 6 | vector < vector > ST; 7 | vector Log; 8 | F func; 9 | 10 | public : 11 | SparseTable() = default; 12 | 13 | template 14 | SparseTable(iter _begin, iter _end, const F _func = less ()) : func(_func) { 15 | _N = distance(_begin, _end); 16 | Log.assign(_N + 1, 0); 17 | for(int i = 2; i <= _N; ++i) 18 | Log[i] = Log[i >> 1] + 1; 19 | 20 | _LOG = Log[_N]; 21 | 22 | _A.assign(_N + 1, 0); 23 | ST.assign(_N + 1, vector (_LOG + 1, 0)); 24 | 25 | __typeof(_begin) i = _begin; 26 | for(int j = 1; i != _end; ++i, ++j) 27 | _A[j] = *i; 28 | 29 | build(); 30 | } 31 | 32 | void build() { 33 | for(int i = 1; i <= _N; ++i) 34 | ST[i][0] = i; 35 | 36 | for(int j = 1, k, d; j <= _LOG; ++j) { 37 | k = (1 << j); 38 | d = (k >> 1); 39 | 40 | for(int i = 1; i + k - 1 <= _N; ++i) { 41 | T const & x = ST[i][j - 1]; 42 | T const & y = ST[i + d][j - 1]; 43 | 44 | ST[i][j] = func(_A[x], _A[y]) ? x : y; 45 | } 46 | } 47 | } 48 | 49 | T query(int l, int r) { 50 | int d = r - l + 1; 51 | T const & x = ST[l][Log[d]]; 52 | T const & y = ST[l + d - (1 << Log[d])][Log[d]]; 53 | 54 | return func(_A[x], _A[y]) ? x : y; 55 | } 56 | }; 57 | 58 | const int N = 1e5 + 9, M = 2e5 + 9, oo = 0x3f3f3f3f, Mod = 1e9 + 7; 59 | const ll INF = 0x3f3f3f3f3f3f3f3f; 60 | 61 | int Head[N], To[M], Next[M], Cost[M]; 62 | int ne, n, m, u, v, w, q; 63 | 64 | int Last[N], First[N], euler_tour[N << 1]; 65 | int Height[N << 1]; 66 | int euler_timer; 67 | 68 | void addEdge(int from, int to, int cost = 1) { 69 | Next[++ne] = Head[from]; 70 | Head[from] = ne; 71 | Cost[ne] = cost; 72 | To[ne] = to; 73 | } 74 | 75 | void _clear() { 76 | memset(Head, 0, sizeof(Head[0]) * (n + 2)); 77 | memset(Last, 0, sizeof(Last[0]) * (n + 2)); 78 | memset(First, 0, sizeof(First[0]) * (n + 2)); 79 | ne = euler_timer = 0; 80 | } 81 | 82 | void EulerianTour(int node, int depth = 0) { 83 | euler_tour[++euler_timer] = node; 84 | Height[euler_timer] = depth; 85 | First[node] = euler_timer; 86 | 87 | for(int i = Head[node]; i; i = Next[i]) 88 | if(First[To[i]] == 0) { 89 | EulerianTour(To[i], depth + Cost[i]); 90 | 91 | euler_tour[++euler_timer] = node; 92 | Height[euler_timer] = depth; 93 | } 94 | 95 | Last[node] = euler_timer; 96 | } 97 | 98 | int main() { 99 | cin >> n >> m; 100 | _clear(); 101 | 102 | while(m--) { 103 | cin >> u >> v; 104 | addEdge(u, v); 105 | addEdge(v, u); 106 | } 107 | 108 | EulerianTour(1); 109 | 110 | SparseTable st(Height + 1, Height + euler_timer + 1, [&](int a, int b) { return a <= b; }); 111 | 112 | int l, r; cin >> q; 113 | while(q--) { 114 | cin >> l >> r; 115 | 116 | int left = Last[l]; 117 | int right = Last[r]; 118 | if(left > right) swap(left, right); 119 | 120 | cout << euler_tour[ st.query(left, right) ] << endl; 121 | } 122 | } 123 | 124 | -------------------------------------------------------------------------------- /cod/graph_theory/minimum_vertex_cover.cpp: -------------------------------------------------------------------------------- 1 | const int N = 1e5 + 9; 2 | 3 | int Head[N], Next[N << 1], To[N << 1], ne, u, v, n, MVC; 4 | 5 | void addEdge(int from, int to) { 6 | Next[++ne] = Head[from]; 7 | Head[from] = ne; 8 | To[ne] = to; 9 | } 10 | 11 | bool DFS(int node, int par = -1) { 12 | bool black = false; 13 | for(int e = Head[node]; e; e = Next[e]) 14 | if(To[e] != par) 15 | black |= DFS(To[e], node); 16 | 17 | MVC += black; 18 | return !black; 19 | } 20 | 21 | int main() { 22 | cin >> n; 23 | while(--n) { 24 | cin >> u >> v; 25 | addEdge(u, v); 26 | addEdge(v, u); 27 | } 28 | 29 | DFS(1); 30 | cout << MVC << endl; 31 | } 32 | 33 | -------------------------------------------------------------------------------- /cod/graph_theory/restoring_the_path.cpp: -------------------------------------------------------------------------------- 1 | const int dr [] = {-1, 0, 1, 0}; 2 | const int dc [] = {0, 1, 0, -1}; 3 | const char dir [] = {'U', 'R', 'D', 'L'}; 4 | map inv = { {'U', 0}, {'R', 1}, {'D', 2}, {'L', 3}}; 5 | 6 | /** Implicit Graphs 7 | 8 | - in BFS, Dijkstra or Bellman-Ford function write -> Par[nr][nc] = dir[i ^ 2] 9 | - char Par[N][N] initialize with -1 10 | - si start i 11 | - sj strat j 12 | - fi target i 13 | - fj target j 14 | - char dir and its map inv 15 | - dr, dc 16 | **/ 17 | 18 | string restorePath(int si, int sj, int fi, int fj) { 19 | string s; 20 | if(Par[ei][ej] == -1) return s; 21 | 22 | int ei = fi, ej = fj; 23 | for(char i = Par[fi][fj]; (si ^ fi) || (sj ^ fj); i = Par[fi][fj]) { 24 | s += dir[inv[i] ^ 2]; 25 | fi += dr[inv[i]]; 26 | fj += dc[inv[i]]; 27 | } 28 | 29 | reverse(s.begin(), s.end()); 30 | return s; 31 | } 32 | 33 | /** Explicit Graphs (BFS, Dijkstra or Bellman-Ford) 34 | 35 | - int Par[N] initialize with -1 36 | - ll dis[N] initialize with 0x3f 37 | - ll INF = 0x3f3f3f3f3f3f3f3f 38 | **/ 39 | 40 | vector restorePath(int dest) { 41 | vector path; 42 | if(dis[dest] == INF) return path; 43 | 44 | for(int i = dest; ~i; i = Par[i]) 45 | path.push_back(i); 46 | 47 | reverse(path.begin(), path.end()); 48 | return path; 49 | } 50 | 51 | /** in case of Floyd-Warshall: 52 | 53 | - ll dis[N][N] initialize with 0x3f 54 | - ll INF = 0x3f3f3f3f3f3f3f3f 55 | - int Par[N][N] initialize with Par[i][j] = i; 56 | - in Floyd-Warshall function write -> Par[i][j] = Par[k][j]; 57 | **/ 58 | 59 | vector restorePath(int st, int tr) { 60 | vector path; 61 | if(dis[st][tr] == INF) return path; 62 | 63 | for(int i = tr; st ^ i; i = Par[st][i]) 64 | path.push_back(i); 65 | 66 | path.push_back(st); 67 | reverse(path.begin(), path.end()); 68 | return path; 69 | } 70 | 71 | -------------------------------------------------------------------------------- /cod/graph_theory/shortest_path_faster_algorithm.cpp: -------------------------------------------------------------------------------- 1 | /** Shortest Path Faster Algorithm : 2 | - This algorithm runs in O(kE) where k is a number depending on the graph. 3 | - The maximum k can be V (which is the same as the time complexity of Bellman Fords). 4 | - However, in practice SPFA (which uses a queue) is as fast as Dijkstras (which uses a priority queue). 5 | - SPFA can deal with negative weight edge. If the graph has no negative cycle, SPFA runs well on it. 6 | - If the graph has negative cycle(s), SPFA can also detect it as there must be some vertex (those on the negative cycle) 7 | that enters the queue for over V , 1 times. 8 | **/ 9 | 10 | const int N = 1e5 + 9, M = 2e5 + 9, oo = 0x3f3f3f3f; 11 | ll INF = 0x3f3f3f3f3f3f3f3f; 12 | ll mINF = 0xc0c0c0c0c0c0c0c0; 13 | 14 | int Head[N], Par[N], Next[M], To[M], Cost[M], Cnt[N], ne, n, m, u, v, st, tax; 15 | ll dis[N]; 16 | bool Inq[N]; 17 | 18 | void addEdge(int from, int to, int cost) { 19 | Next[++ne] = Head[from]; 20 | Head[from] = ne; 21 | Cost[ne] = cost; 22 | To[ne] = to; 23 | } 24 | 25 | void _clear() { 26 | memset(Head, 0, sizeof(Head[0]) * (n + 2)); 27 | ne = 0; 28 | } 29 | 30 | void _set() { 31 | memset(dis, 0x3f, sizeof(dis[0]) * (n + 2)); 32 | memset(Par, -1, sizeof(Par[0]) * (n + 2)); 33 | memset(Cnt, 0, sizeof(Cnt[0]) * (n + 2)); 34 | memset(Inq, 0, sizeof(Inq[0]) * (n + 2)); 35 | } 36 | 37 | bool SPFA(int src) { 38 | _set(); 39 | 40 | deque Q; 41 | Q.push_front(src); 42 | 43 | dis[src] = 0; 44 | Cnt[src] = 1; 45 | Inq[src] = 1; 46 | 47 | int node; 48 | while(Q.size()) { 49 | node = Q.front(); Q.pop_front(); Inq[node] = 0; 50 | 51 | for(int i = Head[node]; i; i = Next[i]) 52 | if(dis[node] + Cost[i] < dis[To[i]]) { 53 | dis[To[i]] = dis[node] + Cost[i]; 54 | Par[To[i]] = node; 55 | 56 | if(!Inq[To[i]]) { 57 | if(++Cnt[To[i]] == n) 58 | return true; // graph has a negative weight cycle 59 | 60 | if(Q.size() && dis[To[i]] > dis[Q.front()]) 61 | Q.push_back(To[i]); 62 | else 63 | Q.push_front(To[i]); 64 | 65 | Inq[To[i]] = true; 66 | } 67 | } 68 | } 69 | return false; 70 | } 71 | -------------------------------------------------------------------------------- /cod/graph_theory/single_source_shortest_path.cpp: -------------------------------------------------------------------------------- 1 | const int N = 1e5 + 9, M = 2e5 + 9, oo = 0x3f3f3f3f; 2 | ll INF = 0x3f3f3f3f3f3f3f3f; 3 | 4 | int Head[N], Par[N], Next[M], To[M], ne, n, m, u, v, st, tr; 5 | ll dis[N]; 6 | 7 | void addEdge(int from, int to) { 8 | Next[++ne] = Head[from]; 9 | Head[from] = ne; 10 | To[ne] = to; 11 | } 12 | 13 | void _clear() { 14 | memset(Head, 0, sizeof(Head[0]) * (n + 2)); 15 | ne = 0; 16 | } 17 | 18 | void BFS(int src) { 19 | memset(dis, 0x3f, sizeof(dis[0]) * (n + 2)); 20 | memset(Par, -1, sizeof(Par[0]) * (n + 2)); 21 | 22 | queue Q; 23 | Q.push(src); 24 | dis[src] = 0; 25 | 26 | int node; 27 | while(Q.size()) { 28 | node = Q.front(); Q.pop(); 29 | for(int i = Head[node]; i; i = Next[i]) if(dis[To[i]] == INF) { 30 | dis[To[i]] = dis[node] + 1; 31 | Par[To[i]] = node; 32 | Q.push(To[i]); 33 | } 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /cod/graph_theory/single_source_shortest_path[grid].cpp: -------------------------------------------------------------------------------- 1 | const int N = 1e3 + 9, M = 2e5 + 9, oo = 0x3f3f3f3f; 2 | ll INF = 0x3f3f3f3f3f3f3f3f; 3 | 4 | const int dr [] = {-1, 0, 1, 0}; 5 | const int dc [] = {0, 1, 0, -1}; 6 | const char dir [] = {'U', 'R', 'D', 'L'}; 7 | map inv = { {'U', 0}, {'R', 1}, {'D', 2}, {'L', 3}}; 8 | 9 | int dis[N][N], n, m; 10 | char Par[N][N]; 11 | 12 | bool valid(int r, int c) { 13 | return r >= 1 && r <= n && c >= 1 && c <= m && dis[r][c] == oo; 14 | } 15 | 16 | void BFS(int sr, int sc) { 17 | memset(dis, 0x3f, sizeof(dis)); 18 | memset(Par, -1, sizeof(Par)); 19 | 20 | queue < pair > Q; 21 | dis[sr][sc] = 0; 22 | Q.push({sr, sc}); 23 | 24 | int r, c, nr, nc; 25 | while(Q.size()) { 26 | tie(r, c) = Q.front(); Q.pop(); 27 | 28 | for(int i = 0; i < 4; ++i) { 29 | nr = r + dr[i]; 30 | nc = c + dc[i]; 31 | 32 | if(!valid(nr, nc)) continue; 33 | 34 | dis[nr][nc] = dis[r][c] + 1; 35 | Par[nr][nc] = dir[i ^ 2]; 36 | Q.push({nr, nc}); 37 | } 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /cod/graph_theory/tarjan.cpp: -------------------------------------------------------------------------------- 1 | const int N = 1e5 + 9, M = 2e6 + 9, oo = 0x3f3f3f3f, Mod = 1e9 + 7; 2 | ll INF = 0x3f3f3f3f3f3f3f3f; 3 | 4 | int Head[N], To[M], Next[M], Cost[M]; 5 | int dfs_num[N], dfs_low[N]; 6 | int Stack[N], compID[N], compSize[N]; 7 | int ne, n, m, u, v, w; 8 | int dfs_timer, top, ID; 9 | bool in_stack[N]; 10 | 11 | void addEdge(int from, int to, int cost = 0) { 12 | Next[++ne] = Head[from]; 13 | Head[from] = ne; 14 | Cost[ne] = cost; 15 | To[ne] = to; 16 | } 17 | 18 | void _clear() { 19 | memset(Head, 0, sizeof(Head[0]) * (n + 2)); 20 | memset(dfs_num, 0, sizeof(dfs_num[0]) * (n + 2)); 21 | memset(compID, 0, sizeof(compID[0]) * (n + 2)); 22 | memset(compSize, 0, sizeof(compSize[0]) * (n + 2)); 23 | ne = dfs_timer = top = ID = 0; 24 | } 25 | 26 | void Tarjan(int node) { 27 | dfs_num[node] = dfs_low[node] = ++dfs_timer; 28 | in_stack[Stack[top++] = node] = true; 29 | 30 | for(int i = Head[node]; i; i = Next[i]) { 31 | if(dfs_num[To[i]] == 0) 32 | Tarjan(To[i]); 33 | 34 | if(in_stack[To[i]]) 35 | dfs_low[node] = Min(dfs_low[node], dfs_low[To[i]]); 36 | } 37 | 38 | if(dfs_num[node] == dfs_low[node]) { 39 | ++ID; 40 | for(int cur = -1; cur ^ node;) { 41 | in_stack[cur = Stack[--top]] = false; 42 | compID[cur] = ID; 43 | ++compSize[ID]; 44 | } 45 | } 46 | } 47 | 48 | void Tarjan() { 49 | for(int i = 1; i <= n; ++i) 50 | if(dfs_num[i] == 0) 51 | Tarjan(i); 52 | } 53 | 54 | -------------------------------------------------------------------------------- /cod/graph_theory/topological_sort[dfs].cpp: -------------------------------------------------------------------------------- 1 | int Head[N], Next[M], To[M], ne, n, m, u, v; 2 | bool vis[N]; 3 | vector t_sort; 4 | 5 | void addEdge(int from, int to) { 6 | Next[++ne] = Head[from]; 7 | Head[from] = ne; 8 | To[ne] = to; 9 | } 10 | 11 | void DFS(int node) { 12 | vis[node] = true; 13 | for(int i = Head[node]; i; i = Next[i]) 14 | if(!vis[To[i]]) 15 | DFS(To[i]); 16 | 17 | t_sort.push_back(node); 18 | } 19 | 20 | vector topological_sort(int n) { 21 | 22 | t_sort.clear(); 23 | for(int i = 1; i <= n; ++i) if(!vis[i]) 24 | DFS(i); 25 | 26 | reverse(t_sort.begin(), t_sort.end()); 27 | return t_sort; 28 | } 29 | 30 | int main() { 31 | cin >> n >> m; 32 | while(m--) { 33 | cin >> u >> v; 34 | addEdge(u, v); 35 | } 36 | 37 | vector v = topological_sort(n); 38 | for(int i : v) 39 | cout << i << ' '; 40 | } 41 | 42 | -------------------------------------------------------------------------------- /cod/graph_theory/topological_sort[kahnsalgorithm].cpp: -------------------------------------------------------------------------------- 1 | int Head[N], Next[M], To[M], in[N], ne, n, m, u, v; 2 | 3 | void addEdge(int from, int to) { 4 | Next[++ne] = Head[from]; 5 | Head[from] = ne; 6 | To[ne] = to; 7 | } 8 | 9 | vector kahn(int n) { 10 | vector ready, ret; 11 | 12 | for(int i = 1; i <= n; ++i) 13 | if(!in[i]) 14 | ready.push_back(i); 15 | 16 | int node; 17 | while(!ready.empty()) { 18 | node = ready.back(); ready.pop_back(); 19 | ret.push_back(node); 20 | 21 | for(int i = Head[node]; i; i = Next[i]) 22 | if(--in[To[i]] == 0) 23 | ready.push_back(To[i]); 24 | } 25 | return ret; 26 | } 27 | 28 | int main() { 29 | cin >> n >> m; 30 | while(m--) { 31 | cin >> u >> v; 32 | addEdge(u, v); 33 | ++in[v]; 34 | } 35 | 36 | vector v = kahn(n); 37 | if((int)v.size() == n) for(int i : v) 38 | cout << i << ' '; 39 | else 40 | cout << "not a DAG!" << endl; 41 | } 42 | 43 | -------------------------------------------------------------------------------- /cod/graph_theory/tree_diameter.cpp: -------------------------------------------------------------------------------- 1 | const int N = 3e5 + 9, M = 6e5 + 9, oo = 0x3f3f3f3f, Mod = 1e9 + 7; 2 | ll INF = 0x3f3f3f3f3f3f3f3f; 3 | 4 | int Head[N], Next[M], To[M], Par[N], toLeaf[N], maxLength[N], ne, n, m, u, v, w; 5 | 6 | void addEdge(int from, int to) { 7 | Next[++ne] = Head[from]; 8 | Head[from] = ne; 9 | To[ne] = to; 10 | } 11 | 12 | void _clear() { 13 | memset(Head, 0, sizeof(Head[0]) * (n + 2)); 14 | memset(Par, -1, sizeof(Par[0]) * (n + 2)); 15 | ne = 0; 16 | } 17 | 18 | void dfs_toLeaf(int node, int par = -1) 19 | { 20 | toLeaf[node] = 0; 21 | for(int i = Head[node]; i; i = Next[i]) 22 | if(To[i] != par) { 23 | dfs_toLeaf(To[i], node); 24 | if(toLeaf[To[i]] + 1 > toLeaf[node]) 25 | toLeaf[node] = toLeaf[To[i]] + 1; 26 | } 27 | } 28 | 29 | void dfs_maxLength(int node, int par = -1) 30 | { 31 | int firstMax = -1; 32 | int secondMax = -1; 33 | for(int i = Head[node]; i; i = Next[i]) 34 | if(To[i] != par) { 35 | dfs_maxLength(To[i], node); 36 | 37 | if(toLeaf[To[i]] > firstMax) { 38 | if(firstMax > secondMax) 39 | secondMax = firstMax; 40 | firstMax = toLeaf[To[i]]; 41 | } else if(toLeaf[To[i]] > secondMax) 42 | secondMax = toLeaf[To[i]]; 43 | } 44 | maxLength[node] = firstMax + secondMax + 2; 45 | } 46 | 47 | void Solve() 48 | { 49 | cin >> n; 50 | _clear(); 51 | 52 | for(int i = 1; i < n; ++i) { 53 | cin >> u >> v; 54 | addEdge(u, v); 55 | addEdge(v, u); 56 | } 57 | 58 | dfs_toLeaf(1); 59 | dfs_maxLength(1); 60 | 61 | int diameter = 0; 62 | for(int i = 1; i <= n; ++i) 63 | if(maxLength[i] > diameter) 64 | diameter = maxLength[i]; 65 | 66 | cout << diameter << endl; 67 | } 68 | -------------------------------------------------------------------------------- /cod/graph_theory/zsingle_pair_shortest_path.cpp: -------------------------------------------------------------------------------- 1 | const int N = 1e5 + 9, M = 2e5 + 9, oo = 0x3f3f3f3f; 2 | ll INF = 0x3f3f3f3f3f3f3f3f; 3 | 4 | int Head[N], Par[N], Next[M], To[M], Cost[M], ne, n, m, u, v, st, tr, tax; 5 | ll dis[N]; 6 | 7 | void addEdge(int from, int to, int cost) { 8 | Next[++ne] = Head[from]; 9 | Head[from] = ne; 10 | Cost[ne] = cost; 11 | To[ne] = to; 12 | } 13 | 14 | void _clear() { 15 | memset(Head, 0, sizeof(Head[0]) * (n + 2)); 16 | ne = 0; 17 | } 18 | 19 | void BFS(int src, int trg) { 20 | memset(dis, 0x3f, sizeof(dis[0]) * (n + 2)); 21 | memset(Par, -1, sizeof(Par[0]) * (n + 2)); 22 | 23 | deque Q; 24 | Q.push_front(src); 25 | dis[src] = 0; 26 | 27 | int node; 28 | while(Q.size()) { 29 | node = Q.front(); Q.pop_front(); 30 | if(node == trg) return; 31 | 32 | for(int i = Head[node]; i; i = Next[i]) 33 | if(dis[node] + Cost[i] < dis[To[i]]) { 34 | dis[To[i]] = dis[node] + Cost[i]; 35 | if(Cost[i]) 36 | Q.push_back(To[i]); 37 | else 38 | Q.push_front(To[i]); 39 | } 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /cod/graph_theory/zsingle_pair_shortest_path[grid].cpp: -------------------------------------------------------------------------------- 1 | const int dr[] = { -1, -1, 0, 1, 1, 1, 0, -1 }; 2 | const int dc[] = { 0, 1, 1, 1, 0, -1, -1, -1 }; 3 | const char dir[] = {'D', 'U', 'R', 'L'}; 4 | 5 | const int N = 1e3 + 9, M = 2e5 + 9, oo = 0x3f3f3f3f; 6 | 7 | int dis[N][N], n, m, si, sj, ti, tj; 8 | char grid[N][N]; 9 | 10 | bool valid(int r, int c) { 11 | return r >= 1 && r <= n && c >= 1 && c <= m; 12 | } 13 | 14 | int ZBFS(int sr, int sc, int tr, int tc) { 15 | memset(dis, 0x3f, sizeof (dis)); // memset(dis, 0x3f, n * m) we don't do that here 16 | 17 | deque > Q; 18 | 19 | dis[sr][sc] = 0; 20 | Q.push_front({sr, sc}); 21 | 22 | int r, c, nr, nc, ncost; 23 | while(Q.size()) { 24 | tie(r, c) = Q.front(); Q.pop_front(); 25 | if(r == tr && c == tc) return dis[r][c]; 26 | 27 | for(int i = 0; i < 8; ++i) { 28 | nr = r + dr[i]; 29 | nc = c + dc[i]; 30 | 31 | if(!valid(nr, nc)) continue; 32 | ncost = (i != grid[r][c]); 33 | 34 | if(dis[r][c] + ncost < dis[nr][nc]) { 35 | dis[nr][nc] = dis[r][c] + ncost; 36 | 37 | if(ncost) 38 | Q.push_back({nr, nc}); 39 | else 40 | Q.push_front({nr, nc}); 41 | } 42 | } 43 | } 44 | return oo; 45 | } 46 | 47 | -------------------------------------------------------------------------------- /cod/mathematics/euler_phi_sieve.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Constraints: 3 | 1 <= n <= 1e7 4 | 5 | Time Complexity: 6 | Phi_sieve takes O(n * ln(ln(n))) 7 | 8 | Space Complexity: 9 | MaxN 10 | */ 11 | 12 | int EulerPhi[N]; 13 | 14 | void Phi_sieve(int n) { 15 | for (int i = 1; i <= n; ++i) { 16 | EulerPhi[i] = i; 17 | } 18 | for (int i = 2; i <= n; ++i) { 19 | if (EulerPhi[i] == i) 20 | for (int j = i; j <= n; j += i) { 21 | EulerPhi[j] -= EulerPhi[j] / i; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /cod/mathematics/euler_totient_function.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | Constraints: 3 | 1 <= n <= 1e7 4 | 2 <= a <= 10^{14} 5 | 6 | Time Complexity: 7 | linear_sieve takes O(n) 8 | Phi takes O(n / (ln(n) - 1.08)) 9 | 10 | Space Complexity: 11 | O(MaxN + n / (ln(n) - 1.08)) 12 | 13 | Explanation: 14 | Phi(n) = n * ((p1 - 1) / p1) * ((p2 - 1) / p2) *...* ((pk - 1) / pk) 15 | Phi(n) = n * (1 - (1 / p1)) * (1 - (1 / p2)) *...* (1 - (1 / pk)) 16 | 17 | Applications: 18 | Eulers theorem: 19 | a^phi(m) cong 1 (mod m) if a and m are relatively prime. 20 | 21 | Fermats little theorem: 22 | when m is a prime: 23 | a^{m minus 1} cong 1 (mod m) 24 | 25 | As immediate consequence we also get the equivalence: 26 | a^n cong a^{n mod phi(m)} (mod m) 27 | This allows computing x^n mod m for very big n, especially if n is the result of another computation, 28 | as it allows to compute n under a modulo. 29 | **/ 30 | 31 | int lp[N], Primes[664580], pnx; /** size of Primes = n / (ln(n) - 1.08) */ 32 | 33 | void linear_sieve(int n) { 34 | for (int i = 2; i <= n; ++i) { 35 | if (lp[i] == 0) { 36 | lp[i] = Primes[pnx++] = i; 37 | } 38 | for (int j = 0, comp; j < pnx && Primes[j] <= lp[i] && (comp = i * Primes[j]) <= n; ++j) { 39 | lp[comp] = Primes[j]; 40 | } 41 | } 42 | } 43 | 44 | ll Phi(ll a) { // for Queries 45 | ll ret = a, p; 46 | for (int i = 0; i < pnx && (p = Primes[i], true); ++i) { 47 | if (p * p > a) break; 48 | if (a % p) continue; 49 | ret -= ret / p; 50 | while (a % p == 0) a /= p; 51 | } 52 | if (a > 1) ret -= ret / a; 53 | return ret; 54 | } 55 | -------------------------------------------------------------------------------- /cod/mathematics/extended_wheel_factorization.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Constraints: 3 | 1 <= n <= 1e7 4 | 2 <= a <= 1e{14} 5 | 6 | Time Complexity: 7 | linear_sieve takes O(n) 8 | Factorization takes O(n / (ln(n) - 1.08)) 9 | 10 | Space Complexity: 11 | O(MaxN + n / (ln(n) - 1.08) 12 | */ 13 | 14 | int lp[N]; 15 | int Primes[664580], pnx; /** size of Primes = n / (ln(n) - 1.08) */ 16 | 17 | void linear_sieve(int n) { 18 | for (int i = 2; i <= n; ++i) { 19 | if (lp[i] == 0) { 20 | lp[i] = Primes[pnx++] = i; 21 | } 22 | for (int j = 0, comp; j < pnx && Primes[j] <= lp[i] && (comp = i * Primes[j]) <= n; ++j) { 23 | lp[comp] = Primes[j]; 24 | } 25 | } 26 | } 27 | 28 | vector> Factorization(ll a) { 29 | vector > ret; 30 | ll p; 31 | for (int i = 0, cnt; i < pnx && (p = Primes[i], true) && p * p <= a; ++i) { 32 | if (a % p) continue; 33 | cnt = 0; 34 | while (a % p == 0) a /= p, ++cnt; 35 | ret.emplace_back(p, cnt); 36 | } 37 | if (a > 1) ret.emplace_back(a, 1); 38 | return ret; 39 | } 40 | -------------------------------------------------------------------------------- /cod/mathematics/leastprime_factorization.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Constraints: 3 | 1 <= n <= 1e7 4 | 5 | Time Complexity: 6 | linear_sieve takes O(n) 7 | Factorization takes O(log(n)) 8 | 9 | Space Complexity: 10 | O(MaxN + n / (ln(n) - 1.08) 11 | */ 12 | 13 | int lp[N]; 14 | int Primes[664580], pnx; /** size of Primes = n / (ln(n) - 1.08) */ 15 | 16 | void linear_sieve(int n) { 17 | for (int i = 2; i <= n; ++i) { 18 | if (lp[i] == 0) { 19 | lp[i] = Primes[pnx++] = i; 20 | } 21 | for (int j = 0, comp; j < pnx && Primes[j] <= lp[i] && (comp = i * Primes[j]) <= n; ++j) { 22 | lp[comp] = Primes[j]; 23 | } 24 | } 25 | } 26 | 27 | vector> Factorization(int n) { 28 | vector> ret; 29 | while (n > 1) { 30 | int p = leastPrime[n], cnt = 0; 31 | while (n % p == 0) n /= p, ++cnt; 32 | ret.emplace_back(p, cnt); 33 | } 34 | return ret; 35 | } 36 | -------------------------------------------------------------------------------- /cod/mathematics/linear_sieve.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | Constraints: 3 | 1 <= n <= 1e7 4 | 5 | Time Complexity: 6 | linear_sieve takes O(n) 7 | 8 | Space Complexity: 9 | O(MaxN + n / (ln(n) - 1.08)) 10 | **/ 11 | 12 | int lp[N]; 13 | int Primes[664580], pnx; /** size of Primes = n / (ln(n) - 1.08) */ 14 | 15 | void linear_sieve(int n) { 16 | for (int i = 2; i <= n; ++i) { 17 | if (lp[i] == 0) { 18 | lp[i] = Primes[pnx++] = i; 19 | } 20 | for (int j = 0, comp; j < pnx && Primes[j] <= lp[i] && (comp = i * Primes[j]) <= n; ++j) { 21 | lp[comp] = Primes[j]; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /cod/mathematics/miller_rabin_test.cpp: -------------------------------------------------------------------------------- 1 | ll ModExp(ll base, ll e, ll mod) { 2 | ll result; 3 | base %= mod; 4 | 5 | for(result = 1; e; e >>= 1ll) { 6 | if(e & 1ll) 7 | result = ((i128)result * base) % mod; 8 | base = ((i128)base * base) % mod; 9 | } 10 | return result; 11 | } 12 | 13 | bool CheckComposite(ll n, ll p, ll d, int r) { 14 | ll a = ModExp(p, d, n); 15 | if(a == 1 || a == n - 1) 16 | return false; 17 | 18 | for(int i = 1; i < r; ++i) { 19 | a = ((i128)a * a) % n; 20 | if(a == n - 1) 21 | return false; 22 | } 23 | return true; 24 | } 25 | 26 | bool Miller(ll n) { 27 | if(n < 2) return false; 28 | 29 | int r; ll d; 30 | for(r = 0, d = n - 1; (d & 1ll) == 0; d >>= 1ll, ++r); 31 | 32 | for(int p : {2, 3, 7, 11, 13, 17, 19, 23, 29, 31, 37}) { 33 | if(n == p) 34 | return true; 35 | if(CheckComposite(n, p, d, r)) 36 | return false; 37 | } 38 | return true; 39 | } 40 | -------------------------------------------------------------------------------- /cod/mathematics/mobius_function.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | Constraints: 3 | 1 <= x <= 1e7 4 | 2 <= n <= 10^{14} 5 | 6 | Time Complexity: 7 | linear_sieve takes O(x) 8 | mobius takes O(n / (ln(n) - 1.08)) 9 | 10 | Space Complexity: 11 | O(MaxN + n / (ln(n) - 1.08)) 12 | */ 13 | 14 | int lp[N], Primes[664580], pnx; /** size of Primes = n / (ln(n) - 1.08) */ 15 | 16 | void linear_sieve(int x) { 17 | for (int i = 2; i <= x; ++i) { 18 | if (lp[i] == 0) { 19 | lp[i] = Primes[pnx++] = i; 20 | } 21 | 22 | for (int j = 0, comp; j < pnx && Primes[j] <= lp[i] && (comp = i * Primes[j]) <= x; ++j) { 23 | lp[comp] = Primes[j]; 24 | } 25 | } 26 | } 27 | 28 | int mobius(ll n) { 29 | ll p, pp; 30 | char mob = 1; 31 | for (int i = 0; i < pnx && (p = Primes[i], pp = p * p, true); ++i) { 32 | if (pp > n) break; 33 | if (n % p) continue; 34 | if (n % pp == 0) return 0; 35 | n /= p; 36 | mob = -mob; 37 | } 38 | if (n > 1) mob = -mob; 39 | return mob; 40 | } 41 | -------------------------------------------------------------------------------- /cod/mathematics/mobius_sieve.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Constraints: 3 | 1 <= n <= 1e7 4 | 5 | Time Complexity: 6 | mu_sieve takes O(n) 7 | 8 | Space Complexity: 9 | O(MaxN) 10 | */ 11 | 12 | int mu[N], lp[N], Primes[78522], pnx; 13 | 14 | void mu_sieve(int n) { 15 | mu[1] = 1; 16 | fill(mu, mu + N, 1); 17 | for (int i = 2; i <= n; ++i) { 18 | if (lp[i] == 0) { 19 | lp[i] = Primes[pnx++] = i; 20 | mu[i] = -1; 21 | } 22 | for (int j = 0, nxt; j < pnx && Primes[j] <= lp[i] && (nxt = i * Primes[j]) <= n; ++j) { 23 | lp[nxt] = Primes[j]; 24 | mu[nxt] = (lp[i] == Primes[j] ? 0 : -mu[i]); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /cod/mathematics/phi_factorial.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | Constraints: 3 | 1 <= x <= 1e7 4 | 2 <= n <= 1e7 5 | 6 | Time Complexity: 7 | linear_sieve takes O(x) 8 | phi_factorial takes O(n) 9 | 10 | Space Complexity: 11 | O(MaxN + n / (ln(n) - 1.08)) 12 | */ 13 | 14 | int lp[N], Primes[664580], pnx; /** number of primes = n / (ln(n) - 1.08) **/ 15 | 16 | void linear_sieve(int x) { 17 | for (int i = 2; i <= x; ++i) { 18 | if (lp[i] == 0) { 19 | lp[i] = Primes[pnx++] = i; 20 | } 21 | 22 | for (int j = 0, comp; j < pnx && Primes[j] <= lp[i] && (comp = i * Primes[j]) <= x; ++j) { 23 | lp[comp] = Primes[j]; 24 | } 25 | } 26 | } 27 | 28 | ll phi_factorial(int n) { 29 | ll ret = 1; 30 | for (int i = 2; i <= n; ++i) { 31 | ret = ret * (lp[i] == i ? i - 1 : i); 32 | } 33 | return ret; 34 | } 35 | 36 | -------------------------------------------------------------------------------- /cod/mathematics/pisano_periodic_sequence.cpp: -------------------------------------------------------------------------------- 1 | /** Algorithm 1: **/ 2 | 3 | /** Constraints : 4 | 1 <= n <= CR 5 | Where CR stands for your computing resources. In my case, 6 | CR = 100,000,000 7 | ---------------- 8 | The algorithm is constructed around the ideas that a Pisano sequence always starts with 0 and 1, and that this sequence of Fibonacci 9 | numbers taken modulo n can be constructed for each number by adding the previous remainders and taking into account the modulo n. 10 | ---------------- 11 | 12 | definition: 13 | The sequence of Fibonacci numbers {F_n} is periodic modulo any modulus m (Wall 1960), and the period (mod m) 14 | is the known as the Pisano period pi(m) (Wrench 1969). For m=1, 2, ..., the values of pi(m) are 15 | 1, 3, 8, 6, 20, 24, 16, 12, 24, 60, 10, ... (OEIS A001175). 16 | 17 | Since pi(10)=60, the last digit of F_n repeats with period 60, as first noted by Lagrange in 1774 (Livio 2002, p. 105). 18 | The last two digits repeat with a period of 300, and the last three with a period of 1500. 19 | In 1963, Geller found that the last four digits have a period of 15000 and the last five a period of 150000. 20 | Jarden subsequently showed that for d>=3, the last d digits have a period of 15*10^(d minus 1) (Livio 2002, pp. 105-106). 21 | The sequence of Pisano periods for n=1, 10, 100, 1000, ... are therefore 60, 300, 1500, 15000, 150000, 1500000, ... (OEIS A096363). 22 | pi(m) is even if m>2 (Wall 1960). pi(m)=m iff m=24*5^(k-1) for some integer k>1 (Fulton and Morris 1969, Wrench 1969). 23 | 24 | resources : 25 | 1. https://webbox.lafayette.edu/~reiterc/nt/qr_fib_ec_preprint.pdf 26 | 2. https://www.youtube.com/watch?v=Nu-lW-Ifyec&ab_channel=Numberphile 27 | 4. http://webspace.ship.edu/msrenault/fibonacci/fib.htm 28 | 5. https://www.theoremoftheday.org/Binomial/PeriodicFib/TotDPeriodic.pdf 29 | 7. http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/Fibonacci/fibmaths.html#fibmod 30 | 8. http://webspace.ship.edu/msrenault/fibonacci/FibThesis.pdf 31 | 9. https://www.fq.math.ca/Scanned/1-2/vinson.pdf 32 | **/ 33 | 34 | vector pisano_periodic_sequence(int n) { 35 | vector period; 36 | 37 | int current = 0, next = 1; 38 | period.push_back(current); 39 | 40 | if(n < 2) return period; 41 | current = (next += current) - current; 42 | 43 | while(current != 0 || next != 1) { 44 | period.push_back(current); 45 | current = current + next >= n ? (next += current - n) + (n - current) : (next += current) - current; 46 | } 47 | return period; 48 | } 49 | 50 | /** ************************************************************************************** **/ 51 | /** Algorithm 2: **/ 52 | 53 | /** constraints: 54 | 1 <= n <= 10^{18} 55 | -------------- 56 | problem statement (https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4479): 57 | For any integer n, the sequence of Fibonacci numbers F_i taken mod n is periodic. 58 | define K(n) = the length of the period of the Fibonacci sequence reduced mod n. 59 | The task is to print the length of the period of this sequence K(n). 60 | -------------- 61 | Definition: 62 | The Pisano period pi(n) is a multiplicative function, that is if a and b are coprime than pi(ab) = pi(a) * pi(b). 63 | So we need only concern ourselves with the value of pi(p^k) for prime p. 64 | (Factoring even a large number is still better than brute force periodicity search.) 65 | 66 | It is hypothesized that p(p^k) = p^{k - 1} * pi(p) and since no counterexamples are known to exist, 67 | you might as well use that in your algorithm. 68 | 69 | So, how to calculate pi(p) efficiently? There are two special cases and two general cases 70 | 71 | pi(2^k) = 3*2^{k - 1} 72 | pi(5^k) = 4*5^k 73 | 74 | If p cong 1 or p cong 9 (mod10) then pi(p) | p - 1 75 | If p cong 3 or p cong 7 (mod10) then pi(p) | 2 * (p + 1) , and by an odd divisor too. 76 | 77 | The last two statements give us a relatively small number of cases to try (after factoring p - 1 or 2*(p + 1) .) 78 | Now use your favorite formula to calculate large values of the Fibonacci numbers F(x) (mod p). 79 | [See Michal answer to What is a fast algorithm to find the remainder of the division of a huge Fibonacci number by some big integer?](https://www.quora.com/Whats-a-fast-algorithm-to-find-the-remainder-of-the-division-of-a-huge-Fibonacci-number-by-some-big-integer/answer/Michal-Fori%C5%A1ek) . 80 | To test a candidate period R , calculate F(R) (mod p) and F(R + 1) (mod p). 81 | If these are equal to F(0) = 0 and F(1) = 1 , then pi(p) | R. 82 | 83 | It might be that p - 1 or 2*(p + 1) have a lot of divisors, but we dont need to try them all. 84 | Suppose q^k | R for some prime q. 85 | Then test R/q . If that doesnt produce a cycle, then pi(p) must have factor q^k , 86 | and we can leave it in and go on to other factors. 87 | Otherwise, we can use R/q as our new starting point and repeat the process. 88 | Thus we have to do a number of checks proportional to Omega(2*(p + 1)) , not d(2*(p + 1)). 89 | 90 | ------------ 91 | Donald Wall proved several other properties, some of which you may find interesting: 92 | If m > 2, k(m) is even. 93 | For any even integer n > 2, there exists m such that k(m) = n. 94 | k(m) <= (m^2) - 1 95 | k(2^n) = 3 * 2^{n - 1} 96 | k(5^n) = 4 * 5^n 97 | If n > 2, k(10^n) = 15 * 10^{n - 1} 98 | k(2 * 5^n) = 6n 99 | **/ 100 | 101 | #pragma GCC optimize ("Ofast") 102 | 103 | #include 104 | 105 | #define endl '\n' 106 | 107 | using namespace std; 108 | 109 | typedef long long ll; 110 | typedef __int128 i128; 111 | typedef __int128_t ui128; 112 | 113 | template 114 | using matrix = vector < vector >; 115 | 116 | template string to_string(T x) { 117 | int sn = 1; 118 | if(x < 0) sn = -1, x *= sn; 119 | string s = ""; 120 | do { 121 | s = "0123456789"[x % 10] + s, x /= 10; 122 | } while(x); 123 | return (sn == -1 ? "-" : "") + s; 124 | } 125 | 126 | auto str_to_int(string x) { 127 | ui128 ret = (x[0] == '-' ? 0 : x[0] - '0'); 128 | for(int i = 1; i < (int)x.size(); ++i) ret = ret * 10 + (x[i] - '0'); 129 | return (x[0] == '-' ? -1 * (i128)ret : ret); 130 | } 131 | 132 | istream & operator >> (istream & in, i128 & i) noexcept { 133 | string s; 134 | in >> s; 135 | i = str_to_int(s); 136 | return in; 137 | } 138 | 139 | ostream & operator << (ostream & os, const i128 i) noexcept { 140 | os << to_string(i); 141 | return os; 142 | } 143 | 144 | void Fast() { 145 | cin.sync_with_stdio(0); 146 | cin.tie(0); 147 | cout.tie(0); 148 | } 149 | 150 | ll n; 151 | vector primes; 152 | matrix fibMatrix = {{1, 1}, 153 | {1, 0} 154 | }; 155 | 156 | i128 gcd(i128 a, i128 b) { 157 | while (a && b) 158 | a > b ? a %= b : b %= a; 159 | return a + b; 160 | } 161 | 162 | i128 lcm(i128 a, i128 b) { 163 | return a / gcd(a, b) * b; 164 | } 165 | 166 | vector < array > factorize(ll x) { 167 | vector < array > ret; 168 | for(int i = 0; 1ll * primes[i] * primes[i] <= x; ++i) { 169 | if(x % primes[i]) continue; 170 | 171 | int cnt = 0; 172 | while (x % primes[i] == 0) { 173 | cnt++; 174 | x /= primes[i]; 175 | } 176 | ret.push_back({primes[i], cnt}); 177 | } 178 | 179 | if(x > 1) ret.push_back({x, 1}); 180 | return ret; 181 | } 182 | 183 | matrix MatMul(matrix A, matrix B, ll mod) { 184 | int ra = A.size(), cb = B[0].size(), ca = A[0].size(); 185 | matrix C(ra, vector (cb)); 186 | 187 | for(int i = 0; i < ra; ++i) 188 | for (int j = 0; j < cb; ++j) { 189 | C[i][j] = 0; 190 | for(int k = 0; k < ca; ++k) 191 | C[i][j] = (C[i][j] + (i128)A[i][k] * B[k][j]); 192 | } 193 | 194 | matrix ret(ra, vector (cb)); 195 | for(int i = 0; i < ra; ++i) 196 | for (int j = 0; j < cb; ++j) 197 | ret[i][j] = C[i][j] % mod; 198 | 199 | return ret; 200 | } 201 | 202 | matrix MatPow(matrix A, ll p, ll mod) { 203 | int r = A.size(), c = A[0].size(); 204 | assert(r == c && p); 205 | matrix result = A; 206 | p--; 207 | 208 | while(p) { 209 | if(p & 1ll) result = MatMul(result, A, mod); 210 | A = MatMul(A, A, mod); 211 | p >>= 1ll; 212 | } 213 | return result; 214 | } 215 | 216 | i128 ModExp(i128 a, ll p) { 217 | i128 result = 1; 218 | while(p) { 219 | if(p & 1ll) result = result * a; 220 | a *= a; 221 | p >>= 1ll; 222 | } 223 | return result; 224 | } 225 | 226 | ll nthFib(ll n, ll mod) { 227 | return MatPow(fibMatrix, n, mod)[0][1]; 228 | } 229 | 230 | bool is_period(ll n, ll mod) { 231 | return nthFib(n, mod) == 0 && nthFib(n + 1, mod) == 1; 232 | } 233 | 234 | ll solver(ll x, ll mod) { 235 | vector < array > factors = factorize(x); 236 | for(int i = 0; i < (int)factors.size(); ++i) { 237 | while(x % factors[i][0] == 0 && is_period(x / factors[i][0], mod)) 238 | x /= factors[i][0]; 239 | } 240 | return x; 241 | } 242 | 243 | ll pisano_prime(ll val) { 244 | if(val == 2) return 3; 245 | if(val == 5) return 20; 246 | if(val % 10 == 1 || val % 10 == 9) 247 | return solver(val - 1, val); 248 | 249 | return solver(2 * (val + 1), val); 250 | } 251 | 252 | const int N = 1e7 + 9; 253 | bitset isPrime; 254 | 255 | void Precomputation_Sieve() { 256 | isPrime.set(); 257 | int _sqrt = sqrtl(N); 258 | 259 | for(int i = 5; i <= _sqrt; i += 6) { 260 | if(isPrime[i]) for (int j = i * i; j < N; j += i + i) isPrime.reset(j); 261 | i += 2; 262 | if(isPrime[i]) for (int j = i * i; j < N; j += i + i) isPrime.reset(j); 263 | i -= 2; 264 | } 265 | } 266 | 267 | vector Primes(int n) { 268 | vector _Primes; 269 | 270 | if(n >= 2) _Primes.push_back(2); 271 | if(n >= 3) _Primes.push_back(3); 272 | 273 | for (int i = 5; i <= n; i += 6) { 274 | if(isPrime[i]) _Primes.push_back(i); 275 | i += 2; 276 | if(isPrime[i]) _Primes.push_back(i); 277 | i -= 2; 278 | } 279 | return _Primes; 280 | } 281 | 282 | void initialize() 283 | { 284 | Precomputation_Sieve(); 285 | primes = Primes(N); 286 | } 287 | 288 | void Solve() { 289 | initialize(); 290 | cin >> n; 291 | vector < array > factors = factorize(n); 292 | 293 | i128 ans = 1; 294 | for (int i = 0; i < (int)factors.size(); ++i) { 295 | ans = lcm(ans, (i128)pisano_prime(factors[i][0]) * ModExp(factors[i][0], factors[i][1] - 1)); 296 | } 297 | cout << ans << endl; 298 | } 299 | -------------------------------------------------------------------------------- /cod/mathematics/segmented_sieve.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | constraints: 3 | 1 <= l, r <= 1e{14} 4 | 1 <= r - l + 1 <= 1e7 5 | 2 <= x <= 1e7 6 | 7 | Time complexity: 8 | segmented_sieve takes O((r - l + 1) * ln(ln(r))) 9 | linear_sieve takes O(n) 10 | 11 | Space Complexity: 12 | O(2 * MaxN + n / (ln(n) - 1.08)) 13 | **/ 14 | 15 | int lp[N]; 16 | int Primes[664580], pnx; /** size of Primes = n / (ln(n) - 1.08) */ 17 | bool isPrime[N]; 18 | 19 | void linear_sieve(int n) { 20 | for (int i = 2; i <= n; ++i) { 21 | if (lp[i] == 0) { 22 | lp[i] = Primes[pnx++] = i; 23 | } 24 | for (int j = 0, comp; j < pnx && Primes[j] <= lp[i] && (comp = i * Primes[j]) <= n; ++j) { 25 | lp[comp] = Primes[j]; 26 | } 27 | } 28 | } 29 | 30 | vector segmented_sieve(ll l, ll r) { 31 | l += l == 1; 32 | int limit = r - l + 1; 33 | vector ret; 34 | memset(isPrime, true, sizeof(isPrime)); 35 | 36 | ll p; 37 | for (int i = 0; i < pnx && (p = Primes[i], true); ++i) { 38 | for (ll j = max(p * p, (l + p - 1) / p * p); j <= r; j += p) 39 | isPrime[j - l] = false; 40 | } 41 | 42 | for (int i = 0; i < limit; ++i) 43 | if (isPrime[i]) 44 | ret.emplace_back(i + l); 45 | return ret; 46 | } 47 | -------------------------------------------------------------------------------- /cod/mathematics/simple_sieve_eratosthenes.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | constraints: 3 | 1 <= n <= 1e8 4 | 5 | Time complexity: 6 | O(n * ln(ln(sqrt(n))) + n) 7 | 8 | Space Complexity: 9 | O(MaxN + n / (ln(n) - 1.08)) 10 | **/ 11 | 12 | bool isPrime[N]; 13 | int Primes[664580], pnx; /** size of Primes = n / (ln(n) - 1.08) */ 14 | 15 | void sieve(int x) { 16 | int basis[3] = {2, 3, 5}; 17 | int wheel[8] = {7, 11, 13, 17, 19, 23, 29, 1}; 18 | int inc[8] = {4, 2, 4, 2, 4, 6, 2, 6}; 19 | int inx[31]; 20 | 21 | memset(inx, 0, sizeof(inx)); 22 | memset(isPrime, true, sizeof(isPrime)); 23 | 24 | for (int p : basis) if (x > p) Primes[pnx++] = p; 25 | for (int i = 0; i < 8; ++i) inx[wheel[i]] = i; 26 | 27 | int c = 0; 28 | for (int i = 7; i <= x; i += inc[c++]) { 29 | if (isPrime[i]) { 30 | Primes[pnx++] = i; 31 | int d = inx[i % 30]; 32 | for (ll j = i * 1ll * i; j <= x; j += i * inc[d++]) { 33 | isPrime[j] = false; 34 | if (d == 8) d = 0; 35 | } 36 | } 37 | if (c == 8) c = 0; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /cod/mathematics/the_stable_marriage_problem.cpp: -------------------------------------------------------------------------------- 1 | const int N = 1e3+ 9, M = 1e3 + 9, oo = 0x3f3f3f3f; 2 | queue Q; 3 | 4 | int husband[N], wife[N], Next[N], order[N][N], pref[N][N], n, v; 5 | 6 | void _clear() { 7 | memset(wife, 0, sizeof(wife[0]) * (n + 2)); 8 | memset(husband, 0, sizeof(husband[0]) * (n + 2)); 9 | memset(Next, 0, sizeof(Next[0]) * (n + 2)); 10 | } 11 | 12 | void engage(int man, int woman) { 13 | int exWife = wife[man]; 14 | wife[man] = woman; 15 | husband[woman] = man; 16 | 17 | if(exWife) 18 | Q.push(exWife); 19 | } 20 | 21 | void Solve() { 22 | _clear(); 23 | cin >> n; 24 | 25 | for(int i = 1; i <= n; ++i) 26 | for(int j = 1; j <= n; ++j) 27 | cin >> pref[i][j]; 28 | 29 | for(int i = 1; i <= n; ++i) 30 | for(int j = 1; j <= n; ++j) { 31 | cin >> v; 32 | order[i][v] = j; 33 | } 34 | 35 | for(int i = 1; i <= n; ++i) 36 | Q.push(i); 37 | 38 | int man, woman; 39 | while(Q.size()) { 40 | woman = Q.front(); Q.pop(); 41 | man = pref[woman][++Next[woman]]; 42 | 43 | if(!wife[man] || order[man][woman] < order[man][wife[man]]) 44 | engage(man, woman); 45 | else 46 | Q.push(woman); 47 | } 48 | 49 | for(int i = 1; i <= n; ++i) 50 | cout << husband[i] << endl; 51 | } 52 | -------------------------------------------------------------------------------- /cod/mathematics/wheel_sieve.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | Constraints: 3 | 1 <= n <= 1e9 4 | 2 <= x <= 9700000 5 | 6 | Time Complexity: 7 | wheel_sieve takes O(n / ln(ln(n))) 8 | coPrimes takes O(x * ln(ln(x))) 9 | 10 | Space Complexity: 11 | O(MaxN / 32 + n / (ln(n) - 1.08) + x) 12 | **/ 13 | 14 | bitset isPrime; 15 | int inx[30100]; 16 | int Primes[50908031], pnx; /** size of Primes = n / (ln(n) - 1.08) */ 17 | 18 | vector coPrimes(int x) { 19 | int basis[5] = {3, 5, 7, 11, 13}; 20 | 21 | vector ret; 22 | bitset<30100> isCoprime; 23 | isCoprime.set(); 24 | 25 | for (int b : basis) 26 | for (int d = b * b; d <= x; d += b << 1) 27 | isCoprime.reset(d); 28 | 29 | for (int i = 17; i <= x; i += 2) 30 | if (isCoprime[i]) ret.push_back(i); 31 | 32 | ret.push_back(x + 1); 33 | ret.push_back(x + 17); 34 | return ret; 35 | } 36 | 37 | void wheel_sieve(int n) { 38 | int basis[6] = {2, 3, 5, 7, 11, 13}; 39 | vector wheel = coPrimes(2 * 3 * 5 * 7 * 11 * 13); 40 | int sz = wheel.size(); 41 | 42 | for (int k = 0; k < sz; ++k) 43 | inx[wheel[k]] = k; 44 | 45 | isPrime.set(); 46 | inx[1] = sz - 2; 47 | int inc[sz - 1]; 48 | 49 | for (int i = 1; i < sz; ++i) 50 | inc[i - 1] = wheel[i] - wheel[i - 1]; 51 | 52 | for (int p : basis) { 53 | if (n >= p) 54 | Primes[pnx++] = p; 55 | } 56 | 57 | int c = 0; 58 | for (ll i = 17; i <= n; i += inc[c++]) { 59 | if (isPrime[i]) { 60 | Primes[pnx++] = i; 61 | int d = inx[i % 30030]; 62 | for (ll j = i * i; j <= n; j += i * inc[d++]) { 63 | isPrime.reset(j); 64 | if (d == sz - 1) d = 0; 65 | } 66 | } 67 | if (c == sz - 1) c = 0; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /cod/miscellaneous/cpp_template.cpp: -------------------------------------------------------------------------------- 1 | #pragma GCC optimize("Ofast") 2 | 3 | #include 4 | 5 | #define endl '\n' 6 | #define read(a, n) for(int i = 0; i < n; cin >> a[i++]); 7 | 8 | #define debug(args ...) { \ 9 | string _s = #args; \ 10 | replace(_s.begin(), _s.end(), ',', ' '); \ 11 | stringstream _ss(_s); \ 12 | istream_iterator _it(_ss); \ 13 | err(_it, args); \ 14 | } 15 | 16 | using namespace std; 17 | 18 | using i128 = __int128_t; 19 | using i64 = int64_t; 20 | using i32 = int32_t; 21 | 22 | using u128 = __uint128_t; 23 | using u64 = uint64_t; 24 | using u32 = uint32_t; 25 | using ld = long double; 26 | 27 | const int N = 2e5 + 9, M = 3e7 + 9, oo = 0x3f3f3f3f, Mod = 1e9 + 7; 28 | const ld eps = 1e-9; 29 | 30 | void err(istream_iterator it) {} 31 | template 32 | void err(istream_iterator it, T a, Args ... args) { 33 | cerr << *it << " = " << a << endl; 34 | err(++it, args ...); 35 | } 36 | 37 | void fast() { 38 | ios_base::sync_with_stdio(false); 39 | cin.tie(nullptr); 40 | } 41 | 42 | void file() { 43 | freopen("input.in", "r", stdin); 44 | freopen("output.out", "w", stdout); 45 | } 46 | 47 | void Solve() { 48 | 49 | } 50 | 51 | int main() { 52 | fast(); 53 | // file(); 54 | 55 | int t = 1; // cin >> t; 56 | for(int i = 1; i <= t; ++i) { 57 | Solve(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /cod/miscellaneous/double_comparison.cpp: -------------------------------------------------------------------------------- 1 | bool approximatelyEqual(double a, double b, double epsilon) { 2 | return fabs(a - b) <= ((fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * epsilon); 3 | } 4 | 5 | bool essentiallyEqual(double a, double b, double epsilon) { 6 | return fabs(a - b) <= ((fabs(a) > fabs(b) ? fabs(b) : fabs(a)) * epsilon); 7 | } 8 | 9 | bool definitelyGreaterThan(double a, double b, double epsilon) { 10 | return (a - b) > ((fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * epsilon); 11 | } 12 | 13 | bool definitelyLessThan(double a, double b, double epsilon) { 14 | return (b - a) > ((fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * epsilon); 15 | } 16 | -------------------------------------------------------------------------------- /cod/miscellaneous/fast_io.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | Fast Input/Output method for C++: 3 | 1. cin(with sync_with_stdio(false) & cin.tie(nullptr)): 4 | - int: 5 | - |n = 5e6| => 420ms 6 | - |n = 1e7| => 742ms 7 | - ll: 8 | - |n = 5e6| => 895ms 9 | 10 | 2. read (using getchar()): 11 | - int: 12 | - |n = 5e6| => 173ms 13 | - |n = 1e7| => 172ms 14 | - ll: 15 | - |n = 5e6| => 340ms 16 | **/ 17 | 18 | ll readll () { 19 | bool minus = false; 20 | unsigned long long result = 0; 21 | char ch; 22 | ch = getchar(); 23 | 24 | while (true) { 25 | if (ch == '-') break; 26 | if (ch >= '0' && ch <= '9') break; 27 | ch = getchar(); 28 | } 29 | 30 | if (ch == '-') minus = true; 31 | else result = ch - '0'; 32 | 33 | while (true) { 34 | ch = getchar(); 35 | if (ch < '0' || ch > '9') break; 36 | result = result * 10 + (ch - '0'); 37 | } 38 | 39 | if (minus) return -(ll)result; 40 | return result; 41 | } 42 | 43 | int readi () { 44 | bool minus = false; 45 | unsigned int result = 0; 46 | char ch; 47 | ch = getchar(); 48 | 49 | while (true) { 50 | if (ch == '-') break; 51 | if (ch >= '0' && ch <= '9') break; 52 | ch = getchar(); 53 | } 54 | 55 | if (ch == '-') minus = true; 56 | else result = ch - '0'; 57 | 58 | while (true) { 59 | ch = getchar(); 60 | if (ch < '0' || ch > '9') break; 61 | result = result * 10 + (ch - '0'); 62 | } 63 | 64 | if (minus) return -(int)result; 65 | return result; 66 | } 67 | -------------------------------------------------------------------------------- /cod/miscellaneous/gcd_lcm.cpp: -------------------------------------------------------------------------------- 1 | i64 gcd(i64 a, i64 b) { // binary GCD uses about 60% fewer bit operations 2 | if (!a) return b; 3 | 4 | u64 shift = __builtin_ctzll(a | b); 5 | a >>= __builtin_ctzll(a); 6 | 7 | while (b) { 8 | b >>= __builtin_ctzll(b); 9 | 10 | if (a > b) 11 | swap(a, b); 12 | b -= a; 13 | } 14 | return a << shift; 15 | } 16 | 17 | i64 lcm(i64 a, i64 b) { 18 | return a / gcd(a, b) * b; 19 | } 20 | 21 | -------------------------------------------------------------------------------- /cod/miscellaneous/modular_calculations.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | - It also has important applications in many tasks unrelated to arithmetic, since it can be used with any operations that have the property of associativity: 3 | */ 4 | 5 | // 1. Modular Exponentiation 6 | 7 | i64 binExp(i64 a, i64 b, i64 p) { 8 | i64 res; 9 | for (res = 1; b; b >>= 1) { 10 | if (b & 1ll) 11 | res = res * a % p; 12 | a = a * a % p; 13 | } 14 | return res; 15 | } 16 | 17 | // 2. Modular Multiplication 18 | 19 | i64 binMul(i64 a, i64 b, i64 p) { 20 | i64 res; 21 | a %= p; 22 | for (res = 0; b; b >>= 1) { 23 | if (b & 1ll) 24 | res = (res + a) % p; 25 | a = (a + a) % p; 26 | } 27 | return res; 28 | } 29 | 30 | // 3. Modular Multiplicative Inverse 31 | 32 | i64 modInv(i64 b, i64 p) { 33 | return binExp(b, p - 2, p); // Guaranteed that p is a Prime Number 34 | } 35 | 36 | -------------------------------------------------------------------------------- /cod/miscellaneous/mydebugger.cpp: -------------------------------------------------------------------------------- 1 | #define rforeach(_it, c) for(__typeof((c).rbegin()) _it = (c).rbegin(); _it != (c).rend(); ++_it) 2 | #define foreach(_it, c) for(__typeof((c).begin()) _it = (c).begin(); _it != (c).end(); ++_it) 3 | #define all(a) (a).begin(), (a).end() 4 | #define sz(a) (int)a.size() 5 | #define endl '\n' 6 | 7 | typedef int64_t ll; 8 | 9 | #if __cplusplus >= 201402L 10 | 11 | mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); 12 | template T rnd_in_rng(T a, T b) 13 | { return uniform_int_distribution (a, b)(rng); /** [a, b] **/} 14 | 15 | template 16 | ostream & operator << (ostream & os, const pair & p) 17 | { return os << "(" << p.first << ", " << p.second << ")"; } 18 | 19 | template 20 | ostream & operator << (ostream & os, const map & _mp) 21 | { os << "["; foreach(it, _mp) { if(it != _mp.begin()) os << ", "; os << it->first << " = " << it->second; } return os << "]"; } 22 | 23 | template 24 | ostream & operator << (ostream & os, const vector & _v) 25 | { os << "["; foreach(it, _v) { if(it != _v.begin()) os << ", "; os << *it; } return os << "]"; } 26 | 27 | template 28 | ostream & operator << (ostream & os, const set & _st) 29 | { os << "["; foreach(it, _st) { if(it != _st.begin() ) os << ", "; os << *it; } return os << "]"; } 30 | 31 | template 32 | ostream & operator << (ostream & os, const array & _ar) 33 | { os << "["; foreach(it, _ar) { if(it != _ar.begin() ) os << ", "; os << *it; } return os << "]"; } 34 | 35 | template void write(T _begin, T _end) 36 | { for(auto i = _begin; i != _end; ++i) cout << (*i) << ' '; cout << endl; } 37 | 38 | template void read(T _begin, T _end) 39 | { for(auto i = _begin; i != _end; ++i) cin >> (*i); } 40 | 41 | #endif 42 | 43 | clock_t start_time; 44 | string run_time() 45 | { return to_string((clock() - (double)start_time) / CLOCKS_PER_SEC) + " sec"; } 46 | 47 | #ifndef ONLINE_JUDGE 48 | #include 49 | void resize_stack() 50 | { 51 | rlimit rlim; 52 | getrlimit(RLIMIT_STACK, &rlim); 53 | rlim.rlim_cur = (1 << 28); 54 | setrlimit(RLIMIT_STACK, &rlim); 55 | } 56 | #else 57 | void resize_stack() {}; 58 | #endif 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /cod/miscellaneous/overloaded_operators_to_accept_128bit_integer.cpp: -------------------------------------------------------------------------------- 1 | typedef __uint128_t ui128; 2 | typedef __int128 i128; 3 | 4 | template string to_string(T x) { 5 | int sn = 1; if(x < 0) sn = -1, x *= sn; string s = ""; 6 | do { s = "0123456789"[x % 10] + s, x /= 10; } while(x); 7 | return (sn == -1 ? "-" : "") + s; 8 | } 9 | 10 | auto str_to_int(string x) { 11 | ui128 ret = (x[0] == '-' ? 0 : x[0] - '0'); 12 | for(int i = 1; i < x.size(); ++i) ret = ret * 10 + (x[i] - '0'); 13 | return (x[0] == '-' ? -1 * (i128)ret : ret); 14 | } 15 | 16 | istream & operator >> (istream & in, i128 & i) noexcept { string s; in >> s; i = str_to_int(s); return in; } 17 | ostream & operator << (ostream & os, const i128 i) noexcept { os << to_string(i); return os; } 18 | istream & operator >> (istream & in, ui128 & i) noexcept { string s; in >> s; i = str_to_int(s); return in; } 19 | ostream & operator << (ostream & os, const ui128 i) noexcept { os << to_string(i); return os; } 20 | 21 | -------------------------------------------------------------------------------- /cod/miscellaneous/policy_based_data_structures.cpp: -------------------------------------------------------------------------------- 1 | #if __cplusplus >= 201402L 2 | #include 3 | #include 4 | #endif 5 | 6 | #if __cplusplus >= 201402L 7 | using namespace __gnu_cxx; 8 | using namespace __gnu_pbds; 9 | #endif 10 | 11 | template > 12 | using indexed_set = tree ; 13 | 14 | template > 15 | using indexed_map = tree ; 16 | 17 | -------------------------------------------------------------------------------- /cod/miscellaneous/pseudo_random_number_generator.cpp: -------------------------------------------------------------------------------- 1 | /** pseudo-random number generator | C++xx >= C++11 **/ 2 | 3 | mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count()); 4 | 5 | T myRand(T a, T b) { 6 | return uniform_int_distribution (a, b)(rng); 7 | } 8 | -------------------------------------------------------------------------------- /cod/miscellaneous/stress_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | #define endl '\n' 6 | 7 | using i128 = __int128_t; 8 | using i64 = int64_t; 9 | using i32 = int32_t; 10 | using i16 = int16_t; 11 | using i8 = int8_t; 12 | 13 | using u128 = __uint128_t; 14 | using u64 = uint64_t; 15 | using u32 = uint32_t; 16 | using u16 = uint16_t; 17 | using u8 = uint8_t; 18 | 19 | void fast() { 20 | ios_base::sync_with_stdio(false); 21 | cin.tie(nullptr); 22 | } 23 | 24 | mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count()); 25 | 26 | /** 64-bit signed int Generator 27 | **/ 28 | i64 int64(i64 a, i64 b) { 29 | return uniform_int_distribution (a, b)(rng); 30 | } 31 | 32 | /** Customize your Generator depending on the input 33 | **/ 34 | void gen () { 35 | ofstream cout("input.in"); 36 | i32 t = 2; 37 | cout << t << endl; 38 | 39 | while (t--) { 40 | i32 n = int64(1, 100), m = int64(1, 100); 41 | cout << n << " " << m << endl; 42 | 43 | while (m--) { 44 | i32 u = int64(1, n), v = int64(1, n), c = int64(1, 4); 45 | cout << u << " " << v << " " << c << endl; 46 | } 47 | } 48 | } 49 | 50 | i32 main (i32 arg, char* args[]) { 51 | fast(); 52 | 53 | i32 tc = 0; 54 | i32 limit = 100; 55 | if(arg != 3) return 0; 56 | 57 | string flags = "g++ -Wall -Wextra -Wshadow -Og -g -Ofast -std=c++17 -D_GLIBCXX_ASSERTIONS -DDEBUG -ggdb3 -fsanitize=address,undefined -fmax-errors=2 -o "; 58 | string ex = ".cpp", bf, oz, pr; 59 | 60 | bf = flags + args[1] + " " + args[1] + ex; 61 | oz = flags + args[2] + " " + args[2] + ex; 62 | char bff[bf.size() + 1]; 63 | char ozz[oz.size() + 1]; 64 | strcpy(bff, bf.c_str()); 65 | strcpy(ozz, oz.c_str()); 66 | 67 | // compile command 68 | system(bff); 69 | system(ozz); 70 | 71 | ex = ".out"; 72 | pr = "./"; 73 | bf = pr + args[1] + " < input.in > " + args[1] + ex; 74 | oz = pr + args[2] + " < input.in > " + args[2] + ex; 75 | strcpy(bff, bf.c_str()); 76 | strcpy(ozz, oz.c_str()); 77 | 78 | while (++tc <= limit) { 79 | gen(); 80 | cerr << tc << endl; 81 | // run command 82 | system(bff); 83 | system(ozz); 84 | 85 | ifstream brute_forces("brute_force.out"); 86 | ifstream optimizes("optimized.out"); 87 | 88 | string brute_force, optimized; 89 | getline(brute_forces, brute_force, (char)EOF); 90 | getline(optimizes, optimized, (char)EOF); 91 | 92 | if(brute_force != optimized) { 93 | cerr << "Wrong Answer" << endl; 94 | break; 95 | } else if (tc == limit) { 96 | cout << "Accepted insha'a Allah" << endl; 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /cod/more_advanced_topics/a*_algorithm.cpp: -------------------------------------------------------------------------------- 1 | const int dr [] = {-1, 0, 1, 0}; 2 | const int dc [] = {0, 1, 0, -1}; 3 | const char dir [] = {'U', 'R', 'D', 'L'}; 4 | map inv = { {'U', 0}, {'R', 1}, {'D', 2}, {'L', 3}}; 5 | 6 | const int N = 1e3 + 9, M = 2e5 + 9, oo = 0x3f3f3f3f; 7 | const ll INF = 0x3f3f3f3f3f3f3f3f; 8 | 9 | char grid[N][N], Par[N][N]; 10 | int dis[N][N], n, m, si, sj, ti, tj; 11 | 12 | vector < pair > restorePath(int sr, int sc, int tr, int tc) { 13 | vector < pair > ret; 14 | if(dis[tr][tc] == oo) return ret; 15 | 16 | for(char i = Par[tr][tc]; (sr ^ tr) || (sc ^ tc); i = Par[tr][tc]) { 17 | ret.push_back({tr, tc}); 18 | tr += dr[inv[i]]; 19 | tc += dc[inv[i]]; 20 | } 21 | 22 | ret.push_back({sr, sc}); 23 | reverse(ret.begin(), ret.end()); 24 | return ret; 25 | } 26 | 27 | bool valid(int r, int c) { 28 | return r >= 0 && r < n && c >= 0 && c < m && grid[r][c] != '%'; 29 | } 30 | 31 | /** admissible heuristic **/ 32 | int manhattanDistance(int x1, int y1, int x2, int y2) { 33 | return (abs(x1 - x2) + abs(y1 - y2)); 34 | } 35 | 36 | int Astar(int sr, int sc, int tr, int tc) { 37 | memset(dis, 0x3f, sizeof (dis)); 38 | memset(Par, -1, sizeof (Par)); 39 | 40 | priority_queue > Q; 41 | 42 | dis[sr][sc] = 0; 43 | Q.push({-manhattanDistance(sr, sc, tr, tc), sr, sc}); 44 | 45 | int hcost, r, c, nr, nc; 46 | while(Q.size()) { 47 | tie(hcost, r, c) = Q.top(); Q.pop(); 48 | if(r == tr && c == tc) return dis[r][c]; 49 | 50 | for(int i = 0; i < 4; ++i) { 51 | nr = r + dr[i]; 52 | nc = c + dc[i]; 53 | 54 | if(!valid(nr, nc)) continue; 55 | 56 | if(dis[r][c] + 1 < dis[nr][nc]) { 57 | dis[nr][nc] = dis[r][c] + 1; 58 | Par[nr][nc] = dir[i ^ 2]; 59 | Q.push({-dis[nr][nc] -manhattanDistance(nr, nc, tr, tc), nr, nc}); 60 | } 61 | } 62 | } 63 | return -1; 64 | } 65 | 66 | void Solve() { 67 | cin >> si >> sj >> ti >> tj >> n >> m; 68 | for(int i = 0; i < n; ++i) 69 | for(int j = 0; j < m; ++j) 70 | cin >> grid[i][j]; 71 | 72 | cout << Astar(si, sj, ti, tj) << endl; 73 | vector < pair > path = restorePath(si, sj, ti, tj); 74 | 75 | for(auto point : path) 76 | cout << point.first << " " << point.second << endl; 77 | } 78 | -------------------------------------------------------------------------------- /cod/more_advanced_topics/mo's_algorithm.cpp: -------------------------------------------------------------------------------- 1 | const int N = 3e4 + 9, M = 2e5 + 9, oo = 0x3f3f3f3f, Mod = 1e9 + 7; 2 | const ll INF = 0x3f3f3f3f3f3f3f3f; 3 | const int BLK = 256; 4 | 5 | struct query { 6 | int l, r, id, blk; 7 | 8 | query() = default; 9 | query(int _l, int _r, int _id) { 10 | l = _l; 11 | r = _r; 12 | id = _id; 13 | blk = l / BLK; 14 | } 15 | 16 | bool operator < (const query other) const { 17 | if(blk ^ other.blk) 18 | return blk < other.blk; 19 | return (blk & 1) ? r < other.r : r > other.r; 20 | } 21 | } queries[M]; 22 | 23 | int res[M], freq[M << 3], cur; 24 | 25 | void add(int id) { 26 | cur += (++freq[id] == 1); 27 | } 28 | 29 | void remove(int id) { 30 | cur -= (--freq[id] == 0); 31 | } 32 | 33 | int get_res() { 34 | return cur; 35 | } 36 | 37 | int cur_l, cur_r, l, r, n, q, a[N]; 38 | 39 | void Solve() { 40 | cin >> n; 41 | for(int i = 1; i <= n; ++i) cin >> a[i]; 42 | 43 | cin >> q; 44 | for(int i = 1; i <= q; ++i) { 45 | cin >> l >> r; 46 | queries[i] = query(l, r, i); 47 | } 48 | 49 | sort(queries + 1, queries + 1 + q); 50 | 51 | cur_l = 1, cur_r = 0; // assign to right invalid index 52 | for(int i = 1; i <= q; ++i) { 53 | int ql = queries[i].l; 54 | int qr = queries[i].r; 55 | 56 | // Add right 57 | while(cur_r < qr) add(a[++cur_r]); 58 | // Add left 59 | while(cur_l > ql) add(a[--cur_l]); 60 | // Remove right 61 | while(cur_r > qr) remove(a[cur_r--]); 62 | // Remove left 63 | while(cur_l < ql) remove(a[cur_l++]); 64 | 65 | res[queries[i].id] = get_res(); 66 | } 67 | 68 | for(int i = 1; i <= q; ++i) 69 | cout << res[i] << "\n"; 70 | } 71 | -------------------------------------------------------------------------------- /cod/more_advanced_topics/square_root_decomposition.cpp: -------------------------------------------------------------------------------- 1 | const int N = 5e5 + 9, M = 1e3 + 9, oo = 0x3f3f3f3f, Mod = 1e9 + 7; 2 | const ll INF = 0x3f3f3f3f3f3f3f3f; 3 | const int BLK = 256; 4 | 5 | int n, q, a[N], type, x, y, z; 6 | vector bs[M]; 7 | 8 | int query(int l, int r, int val) { 9 | int cur_l = l / BLK; 10 | int cur_r = r / BLK; 11 | int ans = 0; 12 | 13 | if(cur_l == cur_r) { 14 | for (int i = l; i <= r; ++i) 15 | ans += (a[i] >= val); 16 | } else { 17 | for(int i = l, _end = (cur_l + 1) * BLK; i < _end; ++i) 18 | ans += (a[i] >= val); 19 | for(int i = cur_l + 1; i <= cur_r - 1; ++i) 20 | ans += bs[i].end() - lower_bound(bs[i].begin(), bs[i].end(), val); 21 | for(int i = cur_r * BLK; i <= r; ++i) 22 | ans += (a[i] >= val); 23 | } 24 | return ans; 25 | } 26 | 27 | void build() { 28 | for(int i = 0; i < n; ++i) 29 | bs[i / BLK].emplace_back(a[i]); 30 | 31 | for(int i = 0; i < M; ++i) 32 | sort(bs[i].begin(), bs[i].end()); 33 | } 34 | 35 | void update(int id, int delta) { 36 | int pos = lower_bound(bs[id / BLK].begin(), bs[id / BLK].end(), a[id]) - bs[id / BLK].begin(); 37 | bs[id / BLK][pos] = delta; 38 | sort(bs[id / BLK].begin(), bs[id / BLK].end()); 39 | a[id] = delta; 40 | } 41 | 42 | void Solve() { 43 | cin >> n; 44 | for(int i = 1; i <= n; ++i) cin >> a[i]; 45 | 46 | build(); 47 | cin >> q; 48 | while(q--) { 49 | cin >> type >> x >> y; 50 | if(type == 0) { 51 | cin >> z; 52 | cout << query(x, y, z) << endl; 53 | } 54 | else 55 | update(x, y); 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /cod/setup/compile: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # put this file in .local/bin or add its dir to the PATH variable 3 | compile() { 4 | g++ -Wall -Wextra -Wshadow -Ofast -std=c++17 -pedantic -Wformat=2 -Wconversion -Wlogical-op -Wshift-overflow=2 -Wduplicated-cond -Wfloat-equal -fno-sanitize-recover -fstack-protector -fsanitize=address,undefined -fmax-errors=2 -o "$1"{,.cpp} 5 | } 6 | compile "$1" 7 | -------------------------------------------------------------------------------- /cod/setup/vimrc: -------------------------------------------------------------------------------- 1 | let mapleader = "\" 2 | syntax on 3 | filetype plugin on 4 | set nocompatible 5 | set autoread 6 | set foldmethod=marker 7 | set autoindent 8 | set clipboard+=unnamedplus 9 | set number relativenumber 10 | set shiftwidth=2 softtabstop=2 expandtab 11 | map c :w! && !compile %:p:r 12 | vmap < >gv 14 | -------------------------------------------------------------------------------- /cod/setup/xmodmap: -------------------------------------------------------------------------------- 1 | setxkbmap -layout us 2 | xmodmap -e 'clear Lock' 3 | xmodmap -e 'keycode 66 = Escape' 4 | -------------------------------------------------------------------------------- /cod/string_processing/knuth_morris_pratt.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * KMP(Knuth-Morris-Pratt) Algorithm 3 | ** Longest Prefix 4 | *** proper prefix = all prefixes except the whole string 5 | *** propre suffix = all suffixes except the whole string 6 | ** Prefix Function = Failure Function 7 | *** Given String P of len m, Find F[m]; 8 | *** let t = P[0....i] 9 | *** f[i] = length of the longest proper prefix of t that is suffix of t 10 | *** calculating i different ways 11 | *** match the pattern against itself 12 | *** O(m) for failure function 13 | *** O(n) for KMP 14 | **/ 15 | 16 | vector LongestPrefix(string &p) { 17 | int psz = p.size(); 18 | vector longest_prefix(psz, 0); 19 | 20 | for(int i = 1, k = 0; i < psz; ++i) { 21 | while(k && p[k] != p[i]) k = longest_prefix[k - 1]; 22 | longest_prefix[i] = (p[k] == p[i] ? ++k : k); 23 | } 24 | return longest_prefix; 25 | } 26 | 27 | vector KMP(string &s, string &p) { 28 | int ssz = s.size(), psz = p.size(); 29 | 30 | vector longest_prefix = LongestPrefix(p), matches; 31 | 32 | for(int i = 0, k = 0; i < ssz; ++i) { 33 | while(k && p[k] != s[i]) k = longest_prefix[k - 1]; // Fail go back 34 | k += (p[k] == s[i]); 35 | 36 | if(k == psz) { 37 | matches.emplace_back(i - psz + 1); 38 | k = longest_prefix[k - 1]; // faill safe and find another pattern 39 | } 40 | } 41 | return matches; 42 | } 43 | -------------------------------------------------------------------------------- /cod/string_processing/trie.cpp: -------------------------------------------------------------------------------- 1 | class Trie { 2 | private: 3 | Trie* children[26]; // Pointer = 8 Byte; 8*26 = 208 Byte 4 | int prefixs, words; // 8 Byte 5 | bool iseow; // 1 Byte 6 | char cur_letter; // 1 Byte 7 | vector lex; 8 | priority_queue , vector >, greater >> occurrence; // small at top 9 | 10 | public: 11 | Trie(char lett = '\0') { 12 | memset(children, 0, sizeof(children)); 13 | prefixs = words = 0; 14 | iseow = false; 15 | cur_letter = lett; 16 | } 17 | 18 | void insert(string &str) { // O(l) 19 | Trie* cur = this; 20 | int inx, strsz = str.size(); 21 | for(int i = 0; i < strsz; ++i) { 22 | inx = str[i] - 'a'; 23 | if(cur->children[inx] == nullptr) 24 | cur->children[inx] = new Trie(str[i]); 25 | 26 | cur = cur->children[inx]; 27 | cur->prefixs++; 28 | } 29 | cur->iseow = true; 30 | cur->words++; 31 | } 32 | 33 | int search_word(string &str) { // O(l) 34 | Trie* cur = this; 35 | int inx, strsz = str.size(); 36 | for(int i = 0; i < strsz; ++i) { 37 | inx = str[i] - 'a'; 38 | if(cur->children[inx] == nullptr) { 39 | return 0; 40 | } 41 | cur = cur->children[inx]; 42 | } 43 | return cur->words; 44 | } 45 | 46 | int search_prefix(string &str) { // O(l) 47 | Trie* cur = this; 48 | int inx = 0, strsz = str.size(); 49 | for(int i = 0; i < strsz; ++i) { 50 | inx = str[i] - 'a'; 51 | if(cur->children[inx] == nullptr) { 52 | return 0; 53 | } 54 | cur = cur->children[inx]; 55 | } 56 | return cur->prefixs; 57 | } 58 | 59 | bool erase(string &str) { 60 | if(!search_word(str)) 61 | return false; 62 | 63 | Trie* cur = this; 64 | int inx, strsz = str.size(); 65 | for(int i = 0; i < strsz; ++i) { 66 | inx = str[i] - 'a'; 67 | if(--cur->children[inx]->prefixs == 0) { 68 | cur->children[inx] = nullptr; 69 | return true; 70 | } 71 | cur = cur->children[inx]; 72 | } 73 | if(--cur->words == 0) { 74 | cur->iseow = false; 75 | } 76 | return true; 77 | } 78 | 79 | private: 80 | void dfs(Trie* node, string s) { // lex order dfs -> traverse all the strings starting from root 81 | if(node->iseow) { 82 | lex.emplace_back(s); 83 | } 84 | 85 | for(int j = 0; j < 26; ++j) 86 | if(node->children[j] != nullptr) { 87 | dfs(node->children[j], s + string(1, node->children[j]->cur_letter)); 88 | } 89 | } 90 | 91 | void dfs2(Trie* node, string s) { // autocomplete dfs -> traverse all the strings starting from the end of the given prefix 92 | if(node->iseow) { 93 | if(occurrence.size() < 10) { 94 | occurrence.push(make_pair(node->words, s)); 95 | } else { 96 | if(node->words > occurrence.top().first) { 97 | occurrence.pop(); 98 | occurrence.push(make_pair(node->words, s)); 99 | } 100 | } 101 | } 102 | 103 | for(int i = 0; i < 26; ++i) if(node->children[i] != nullptr) { 104 | dfs2(node->children[i], s + string(1, node->children[i]->cur_letter)); 105 | } 106 | } 107 | 108 | public: 109 | vector lex_order() { // all strings in lexicographical order 110 | lex.clear(); 111 | Trie* cur = this; 112 | for(int i = 0; i < 26; ++i) if(cur->children[i] != nullptr) { 113 | dfs(cur->children[i], string(1, cur->children[i]->cur_letter)); 114 | } 115 | return lex; 116 | } 117 | 118 | void autocomplete(string &pref) { // suggest top ten words with max frequency 119 | if(!search_prefix(pref)) 120 | return; 121 | 122 | Trie* cur = this; 123 | int inx, presz = pref.size(); 124 | for(int i = 0; i < presz; ++i) { 125 | inx = pref[i] - 'a'; 126 | cur = cur->children[inx]; 127 | } 128 | 129 | for(int i = 0; i < 26; ++i) if(cur->children[i] != nullptr) { 130 | dfs2(cur->children[i], string(1, cur->children[i]->cur_letter)); 131 | } 132 | 133 | vector st; 134 | while(!occurrence.empty()) { 135 | st.emplace_back(pref + occurrence.top().second); 136 | occurrence.pop(); 137 | } 138 | if(cur->iseow) { 139 | st.emplace_back(pref); 140 | } 141 | while(!st.empty()) { 142 | cout << st.back() << endl; 143 | st.pop_back(); 144 | } 145 | } 146 | }; 147 | 148 | -------------------------------------------------------------------------------- /reference_material.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbdeltwabMF/reference-materials/78f0da299502f87e4d7b46ee215a83c116323312/reference_material.pdf -------------------------------------------------------------------------------- /reference_material.tex: -------------------------------------------------------------------------------- 1 | \documentclass[10pt]{article} 2 | 3 | \input src/headers.tex 4 | \input src/commands.tex 5 | \input src/styles.tex 6 | 7 | \title{\vspace{-4ex}\Large{ICPC Team Reference Material}} 8 | \author{} 9 | \date{} 10 | 11 | \begin{document} 12 | 13 | \begin{landscape} 14 | 15 | \begin{multicols}{2} 16 | 17 | \maketitle 18 | \vspace{-13ex} 19 | 20 | \tableofcontents 21 | 22 | \pagestyle{fancy} 23 | 24 | \input src/sections.tex 25 | 26 | \end{multicols} 27 | 28 | \end{landscape} 29 | 30 | \end{document} 31 | -------------------------------------------------------------------------------- /src/commands.tex: -------------------------------------------------------------------------------- 1 | \renewcommand*{\ttdefault}{pcr} 2 | \renewcommand\cftsecfont{\fontsize{8}{9}\bfseries} 3 | \renewcommand\cftsecpagefont{\fontsize{8}{9}\mdseries} 4 | \renewcommand\cftsecafterpnum{\vspace{-1ex}} 5 | 6 | \renewcommand\cftsubsecfont{\fontsize{5}{6}\mdseries} 7 | \renewcommand\cftsubsecpagefont{\fontsize{5}{6}\mdseries} 8 | \renewcommand\cftsubsecafterpnum{\vspace{-1ex}} 9 | 10 | \renewcommand\cftsubsubsecfont{\fontsize{5}{6}\mdseries} 11 | \renewcommand\cftsubsubsecpagefont{\fontsize{5}{6}\mdseries} 12 | \renewcommand\cftsubsubsecafterpnum{\vspace{-1ex}} 13 | -------------------------------------------------------------------------------- /src/headers.tex: -------------------------------------------------------------------------------- 1 | \usepackage[left=0.4in,right=0.4in,top=0.7in,bottom=0.4in]{geometry} 2 | \usepackage[hidelinks]{hyperref} 3 | \usepackage[dvipsnames]{xcolor} 4 | \usepackage{fontawesome5} 5 | \usepackage{pdflscape} 6 | \usepackage{listings} 7 | \usepackage{multicol} 8 | \usepackage{latexsym} 9 | \usepackage{titlesec} 10 | \usepackage{inputenc} 11 | \usepackage{marvosym} 12 | \usepackage{enumitem} 13 | \usepackage{fancyhdr} 14 | \usepackage{tabularx} 15 | \usepackage{tocloft} 16 | \usepackage{tikz} 17 | -------------------------------------------------------------------------------- /src/sections.tex: -------------------------------------------------------------------------------- 1 | \section{Setup} 2 | \subsection{Vimrc} 3 | \raggedbottom\lstinputlisting[style=others]{cod/setup/vimrc} 4 | \hrulefill 5 | \subsection{Capslock as escape} 6 | \raggedbottom\lstinputlisting[style=others]{cod/setup/xmodmap} 7 | \hrulefill 8 | \subsection{Compilation} 9 | \raggedbottom\lstinputlisting[style=others]{cod/setup/compile} 10 | \hrulefill 11 | 12 | 13 | \section{Graph algorithms} 14 | \subsection{Adjacency list representation} 15 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/adjacency_list.cpp} 16 | \hrulefill 17 | \subsection{Articulation points and bridges} 18 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/articulation_points_and_bridges.cpp} 19 | \hrulefill 20 | \subsection{Bellman ford} 21 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/bellman_ford.cpp} 22 | \hrulefill 23 | \subsection{Bi-connected components} 24 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/bi_connected_components.cpp} 25 | \hrulefill 26 | \subsection{Bi-partite graph} 27 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/bi_partite_graph.cpp} 28 | \hrulefill 29 | \subsection{Breadth first search (bfs)} 30 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/breadth_first_search.cpp} 31 | \hrulefill 32 | \subsection{Connected components} 33 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/connected_components.cpp} 34 | \hrulefill 35 | \subsection{Cycle detection (directed graph)} 36 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/cycle_detection[directedg].cpp} 37 | \hrulefill 38 | \subsection{Cycle detection (undirected graph)} 39 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/cycle_detection[undirectedg].cpp} 40 | \hrulefill 41 | \subsection{Depth first search (dfs)} 42 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/depth_first_search.cpp} 43 | \hrulefill 44 | \subsection{Dijkstra (dense graph)} 45 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/dijkstra[densegraph].cpp} 46 | \hrulefill 47 | \subsection{Dijkstra (grid)} 48 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/dijkstra[grid].cpp} 49 | \hrulefill 50 | \subsection{Dijkstra (negative weighted graph)} 51 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/dijkstra[negativeweightedges].cpp} 52 | \hrulefill 53 | \subsection{Dijkstra (sparse graph)} 54 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/dijkstra[sparsegraph].cpp} 55 | \hrulefill 56 | \subsection{Directed cyclic graph into acyclic} 57 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/directed_cyclic_graph_into_directed_acyclic_graph.cpp} 58 | \hrulefill 59 | \subsection{Edge classification} 60 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/edge_classification.cpp} 61 | \hrulefill 62 | \subsection{Eulerian tour tree} 63 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/eulerian_tour_tree.cpp} 64 | \hrulefill 65 | \subsection{Flood fill} 66 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/flood_fill.cpp} 67 | \hrulefill 68 | \subsection{Floyd warshall (all pairs shortest path)} 69 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/floyd_warshall.cpp} 70 | \hrulefill 71 | \subsection{Minimum spanning tree (kruskal)} 72 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/kruskal.cpp} 73 | \hrulefill 74 | \subsection{Kth ancestor and lowest common ancestor (binary lifting)} 75 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/kth_ancestor_and_lca[binarylifting].cpp} 76 | \hrulefill 77 | \subsection{Lowest common ancestor (euler tour)} 78 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/lca[euleriantourandrmq].cpp} 79 | \hrulefill 80 | \subsection{Minimum vertex cover} 81 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/minimum_vertex_cover.cpp} 82 | \hrulefill 83 | \subsection{Restoring the path} 84 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/restoring_the_path.cpp} 85 | \hrulefill 86 | \subsection{Shortest path faster algorithml (spfa)} 87 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/shortest_path_faster_algorithm.cpp} 88 | \hrulefill 89 | \subsection{Single source shortest path} 90 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/single_source_shortest_path.cpp} 91 | \hrulefill 92 | \subsection{Single source shortest path (grid)} 93 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/single_source_shortest_path[grid].cpp} 94 | \hrulefill 95 | \subsection{Tarjan (strongly connected components)} 96 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/tarjan.cpp} 97 | \hrulefill 98 | \subsection{Topological sort (dfs)} 99 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/topological_sort[dfs].cpp} 100 | \hrulefill 101 | \subsection{Topological sort (kahns algorithm)} 102 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/topological_sort[kahnsalgorithm].cpp} 103 | \hrulefill 104 | \subsection{Tree diameter} 105 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/tree_diameter.cpp} 106 | \hrulefill 107 | \subsection{0-1 bfs} 108 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/zsingle_pair_shortest_path.cpp} 109 | \hrulefill 110 | \subsection{0-1 bfs (grid)} 111 | \raggedbottom\lstinputlisting[style=cpp]{cod/graph_theory/zsingle_pair_shortest_path[grid].cpp} 112 | \hrulefill 113 | 114 | 115 | \section{Data structures} 116 | \subsection{Union find disjoint sets} 117 | \raggedbottom\lstinputlisting[style=cpp]{cod/data_structures/union_find_disjoint_sets.cpp} 118 | \hrulefill 119 | \subsection{Segment tree (rmq)} 120 | \raggedbottom\lstinputlisting[style=cpp]{cod/data_structures/segment_tree_rmq.cpp} 121 | \hrulefill 122 | \subsection{Merge sort tree} 123 | \raggedbottom\lstinputlisting[style=cpp]{cod/data_structures/merge_sort_tree.cpp} 124 | \hrulefill 125 | \subsection{Sparse table (rmq)} 126 | \raggedbottom\lstinputlisting[style=cpp]{cod/data_structures/sparse_table_rmq.cpp} 127 | \hrulefill 128 | \subsection{Sparse table (rsq)} 129 | \raggedbottom\lstinputlisting[style=cpp]{cod/data_structures/sparse_table_rsq.cpp} 130 | \hrulefill 131 | \subsection{Merge sort} 132 | \raggedbottom\lstinputlisting[style=cpp]{cod/data_structures/merge_sort.cpp} 133 | \hrulefill 134 | \subsection{Selection sort} 135 | \raggedbottom\lstinputlisting[style=cpp]{cod/data_structures/selection_sort.cpp} 136 | \hrulefill 137 | \subsection{Bubble sort} 138 | \raggedbottom\lstinputlisting[style=cpp]{cod/data_structures/bubble_sort.cpp} 139 | \hrulefill 140 | 141 | 142 | \section{Mathematics} 143 | \subsection{Euler totient function} 144 | \raggedbottom\lstinputlisting[style=cpp]{cod/mathematics/euler_totient_function.cpp} 145 | \hrulefill 146 | \subsection{Euler phi (sieve)} 147 | \raggedbottom\lstinputlisting[style=cpp]{cod/mathematics/euler_phi_sieve.cpp} 148 | \hrulefill 149 | \subsection{Extended wheel factorization} 150 | \raggedbottom\lstinputlisting[style=cpp]{cod/mathematics/extended_wheel_factorization.cpp} 151 | \hrulefill 152 | \subsection{Least prime factorization} 153 | \raggedbottom\lstinputlisting[style=cpp]{cod/mathematics/leastprime_factorization.cpp} 154 | \hrulefill 155 | \subsection{Miller rabin test} 156 | \raggedbottom\lstinputlisting[style=cpp]{cod/mathematics/miller_rabin_test.cpp} 157 | \hrulefill 158 | \subsection{Mobius function} 159 | \raggedbottom\lstinputlisting[style=cpp]{cod/mathematics/mobius_function.cpp} 160 | \hrulefill 161 | \subsection{Mobius (sieve)} 162 | \raggedbottom\lstinputlisting[style=cpp]{cod/mathematics/mobius_sieve.cpp} 163 | \hrulefill 164 | \subsection{Phi factorial} 165 | \raggedbottom\lstinputlisting[style=cpp]{cod/mathematics/phi_factorial.cpp} 166 | \hrulefill 167 | \subsection{Pisano periodic sequence} 168 | \raggedbottom\lstinputlisting[style=cpp]{cod/mathematics/pisano_periodic_sequence.cpp} 169 | \hrulefill 170 | \subsection{Simple sieve} 171 | \raggedbottom\lstinputlisting[style=cpp]{cod/mathematics/simple_sieve_eratosthenes.cpp} 172 | \hrulefill 173 | \subsection{wheel sieve} 174 | \raggedbottom\lstinputlisting[style=cpp]{cod/mathematics/wheel_sieve.cpp} 175 | \hrulefill 176 | \subsection{Linear sieve} 177 | \raggedbottom\lstinputlisting[style=cpp]{cod/mathematics/linear_sieve.cpp} 178 | \hrulefill 179 | \subsection{Segmented sieve} 180 | \raggedbottom\lstinputlisting[style=cpp]{cod/mathematics/segmented_sieve.cpp} 181 | \hrulefill 182 | \subsection{The stable marriage problem} 183 | \raggedbottom\lstinputlisting[style=cpp]{cod/mathematics/the_stable_marriage_problem.cpp} 184 | \hrulefill 185 | 186 | 187 | \section{String processing} 188 | \subsection{Trie} 189 | \raggedbottom\lstinputlisting[style=cpp]{cod/string_processing/trie.cpp} 190 | \hrulefill 191 | \subsection{Knuth Morris Pratt (kmp)} 192 | \raggedbottom\lstinputlisting[style=cpp]{cod/string_processing/knuth_morris_pratt.cpp} 193 | \hrulefill 194 | 195 | 196 | \section{Geometry} 197 | \subsection{Point} 198 | \raggedbottom\lstinputlisting[style=cpp]{cod/geometry/point.cpp} 199 | \hrulefill 200 | 201 | 202 | \section{More advanced topics} 203 | \subsection{A* algorithm} 204 | \raggedbottom\lstinputlisting[style=cpp]{cod/more_advanced_topics/a*_algorithm.cpp} 205 | \hrulefill 206 | \subsection{Mo's algorithm} 207 | \raggedbottom\lstinputlisting[style=cpp]{cod/more_advanced_topics/mo's_algorithm.cpp} 208 | \hrulefill 209 | \subsection{Square root decomposition} 210 | \raggedbottom\lstinputlisting[style=cpp]{cod/more_advanced_topics/square_root_decomposition.cpp} 211 | \hrulefill 212 | 213 | 214 | \section{Miscellaneous} 215 | \subsection{C++ template} 216 | \raggedbottom\lstinputlisting[style=cpp]{cod/miscellaneous/cpp_template.cpp} 217 | \hrulefill 218 | \subsection{Double comparison} 219 | \raggedbottom\lstinputlisting[style=cpp]{cod/miscellaneous/double_comparison.cpp} 220 | \hrulefill 221 | \subsection{Fast input/output} 222 | \raggedbottom\lstinputlisting[style=cpp]{cod/miscellaneous/fast_io.cpp} 223 | \hrulefill 224 | \subsection{Gcd \& Lcm} 225 | \raggedbottom\lstinputlisting[style=cpp]{cod/miscellaneous/gcd_lcm.cpp} 226 | \hrulefill 227 | \subsection{Modular calculations} 228 | \raggedbottom\lstinputlisting[style=cpp]{cod/miscellaneous/modular_calculations.cpp} 229 | \hrulefill 230 | \subsection{Debugging tools} 231 | \raggedbottom\lstinputlisting[style=cpp]{cod/miscellaneous/mydebugger.cpp} 232 | \hrulefill 233 | \subsection{Overloaded operators to accept 128 bit integer} 234 | \raggedbottom\lstinputlisting[style=cpp]{cod/miscellaneous/overloaded_operators_to_accept_128bit_integer.cpp} 235 | \hrulefill 236 | \subsection{Policy based data structures} 237 | \raggedbottom\lstinputlisting[style=cpp]{cod/miscellaneous/policy_based_data_structures.cpp} 238 | \hrulefill 239 | \subsection{Pseudo random number generator} 240 | \raggedbottom\lstinputlisting[style=cpp]{cod/miscellaneous/pseudo_random_number_generator.cpp} 241 | \hrulefill 242 | \subsection{Stress test} 243 | \raggedbottom\lstinputlisting[style=cpp]{cod/miscellaneous/stress_test.cpp} 244 | \hrulefill 245 | -------------------------------------------------------------------------------- /src/styles.tex: -------------------------------------------------------------------------------- 1 | \lstdefinestyle{shared} { 2 | tabsize=2, 3 | belowcaptionskip=1\baselineskip, 4 | breaklines=true, 5 | xleftmargin=\parindent, 6 | showstringspaces=false, 7 | basicstyle=\fontsize{5.5}{6}\ttfamily, 8 | numbers=left, 9 | numberstyle=\tiny\color{black}, 10 | numbersep=6pt, 11 | showspaces=false, 12 | } 13 | 14 | \lstdefinestyle{cpp} { 15 | style=shared, 16 | language=C++, 17 | otherkeywords={size, front, back, cin, cout, endl, sizeof, memset}, 18 | keywordstyle=\bfseries\color{Blue}, 19 | commentstyle=\itshape\color{RoyalPurple}, 20 | identifierstyle=\color{Black}, 21 | stringstyle=\color{OliveGreen}, 22 | } 23 | 24 | \lstdefinelanguage{all} { 25 | % list of keywords 26 | morekeywords={ set, let, map, nmap, filetype, on, off, autocmd, call, syntax, vmap, , keycode, clear, xmodmap, setxkbmap}, 27 | morecomment=[l]{\#}, % l is for line comment 28 | morestring=[b]' % defines that strings are enclosed in double quotes 29 | } 30 | 31 | \lstdefinestyle{others} { 32 | style=shared, 33 | language=all, 34 | keywordstyle=\bfseries\color{PineGreen}, 35 | commentstyle=\itshape\color{JungleGreen}, 36 | identifierstyle=\color{Orchid}, 37 | stringstyle=\color{OliveGreen}, 38 | } 39 | 40 | \lstset{escapechar=@} 41 | 42 | \pagestyle{fancy} 43 | \fancyhead[L]{Al-Azhar University} 44 | \fancyhead[R]{\thepage} 45 | \fancyfoot[C]{} 46 | 47 | \fancypagestyle{plain} { 48 | \fancyhead[L]{Al-Azhar University} 49 | \fancyhead[R]{\thepage} 50 | \fancyfoot[C]{} 51 | } 52 | --------------------------------------------------------------------------------