├── .github └── workflows │ └── icpc-reference-tester.yml ├── .gitignore ├── GOOD_REFERENCE ├── LICENSE ├── Makefile ├── biblio.tex ├── contents.txt ├── data-structures ├── bit.cpp ├── bit2d.cpp ├── bit_binary_search.cpp ├── bit_range.cpp ├── centroid_decomposition.cpp ├── color_update.cpp ├── hld-lamarca.cpp ├── hld.cpp ├── hld_exx.cpp ├── ita_lichao.cpp ├── lichao.cpp ├── lichao_lazy.cpp ├── mergesort_tree.cpp ├── min_queue.cpp ├── ordered_set.cpp ├── seg_tree.cpp ├── seg_tree2d.cpp ├── seg_tree_dynamic.cpp ├── seg_tree_dynamic_lazy.cpp ├── seg_tree_iterative.cpp ├── seg_tree_mod.cpp ├── seg_tree_persistent.cpp ├── seg_tree_persistent_naum.cpp ├── seg_tree_point_update_struct.cpp ├── set_of_intervals.cpp ├── sparse.cpp ├── sparse2d.cpp ├── splay.cpp ├── stanford_kdtree.cpp ├── treap.cpp ├── trie.cpp ├── union_find.cpp ├── union_find_partial_persistent.cpp └── union_find_rollback.cpp ├── dynamic-programming ├── SOS.cpp ├── convex_hull_trick.cpp ├── convex_hull_trick_emaxx.cpp ├── divide_and_conquer_optimization.cpp ├── knuth_optimization.cpp ├── lis.cpp └── steiner_tree.cpp ├── e-maxx.pdf ├── flags.txt ├── generate_pdf.py ├── geometry ├── basics.cpp ├── circle.cpp ├── closest_pair.cpp ├── closest_pair_3d.cpp ├── delaunay.cpp ├── halfplane_intersection.cpp ├── lines.cpp ├── minkowski_sum.cpp ├── misc.cpp ├── nearest_neighbour.cpp ├── polygons.cpp ├── radial_sort.cpp ├── stanford_delaunay.cpp └── ternary_search.cpp ├── graphs ├── 2_sat_kosaraju.cpp ├── 2_sat_tarjan.cpp ├── bellman_ford.cpp ├── bfs.cpp ├── block_cut.cpp ├── bridges_and_articulations.cpp ├── dfs.cpp ├── dijkstra.cpp ├── dinic.cpp ├── dominator_tree.cpp ├── erdos_gallai.cpp ├── eulerian_path.cpp ├── fast_kuhn.cpp ├── find_cycle_3_4.cpp ├── floyd_warshall.cpp ├── hungarian.cpp ├── hungarian_navarro.cpp ├── kahn.cpp ├── kosaraju.cpp ├── kruskal.cpp ├── kuhn.cpp ├── lca.cpp ├── max_weight_lca.cpp ├── min_cost_max_flow.cpp ├── prim.cpp ├── small_to_large.cpp ├── spfa.cpp ├── stable_marriage.cpp ├── stanford_stoer_wagner.cpp ├── tarjan.cpp └── zero_one_bfs.cpp ├── math ├── advanced.cpp ├── basics.cpp ├── berlekampmassey.cpp ├── discrete_log.cpp ├── euler_phi.cpp ├── extended_euclid.cpp ├── fft.cpp ├── fft_tourist.cpp ├── fwht.cpp ├── gauss_elim.cpp ├── gauss_elim_ext.cpp ├── gauss_elim_prime.cpp ├── gauss_elim_xor.cpp ├── gss.cpp ├── josephus.cpp ├── lagrange.cpp ├── matrix.cpp ├── mobius.cpp ├── mobius_inversion.cpp ├── ntt.cpp ├── pollard_rho.cpp ├── pollard_rho_optimization.cpp ├── prime_factors.cpp ├── primitive_root.cpp ├── sieve.cpp ├── simpson_rule.cpp └── stanford_simplex.cpp ├── mathextra.tex ├── misc ├── bitset.cpp ├── builtin.cpp ├── date.cpp ├── ita_paren2polish.cpp ├── merge_sort.cpp ├── modular_int.cpp ├── parallel_bin_search.cpp ├── prime_numbers.txt ├── python.py ├── sqrt_decomposition.cpp ├── stanford_latlong.cpp └── week_day.cpp ├── notebook.pdf ├── notebook.tex ├── solutionpage.tex ├── strings ├── aho_corasick.cpp ├── aho_emaxx.cpp ├── booths_algorithm.cpp ├── eertree.cpp ├── kmp.cpp ├── kmp_automaton.cpp ├── manacher.cpp ├── manacher_2.cpp ├── rabin_karp.cpp ├── recursive_string_matching.cpp ├── string_hashing.cpp ├── string_multihashing.cpp ├── suffix_array.cpp ├── suffix_automaton.cpp ├── suffix_tree.cpp └── z_function.cpp ├── template.cpp ├── tests ├── data-structures │ ├── bit.test.cpp │ └── dsu.test.cpp ├── dynamic-programming │ └── lis.test.cpp ├── graphs │ ├── hungarian-navarro.test1.cpp │ └── hungarian-navarro.test2.cpp ├── math │ └── fft.test.cpp └── strings │ └── z.test.cpp └── vimrc /.github/workflows/icpc-reference-tester.yml: -------------------------------------------------------------------------------- 1 | name: icpc-reference-tester 2 | on: [pull_request] 3 | jobs: 4 | check-tests: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/checkout@v2 8 | - run: git clone https://github.com/samuraiexx/icpc-reference-tester 9 | - uses: nanasess/setup-chromedriver@master 10 | - uses: actions-rs/toolchain@v1 11 | with: 12 | toolchain: stable 13 | - run: cargo build --release 14 | working-directory: icpc-reference-tester 15 | - run: icpc-reference-tester/target/release/icpc-reference-tester tests 16 | env: 17 | CF_USER: ${{ secrets.CF_USER }} 18 | CF_PASSWORD: ${{ secrets.CF_PASSWORD }} 19 | SPOJ_USER: ${{ secrets.SPOJ_USER }} 20 | SPOJ_PASSWORD: ${{ secrets.SPOJ_PASSWORD }} 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #Temporary folder 2 | tmp/ 3 | ## Core latex/pdflatex auxiliary files: 4 | *.aux 5 | *.lof 6 | *.log 7 | *.lot 8 | *.fls 9 | *.out 10 | *.toc 11 | *.fmt 12 | *.fot 13 | *.cb 14 | *.cb2 15 | biblio.pdf 16 | 17 | ## Intermediate documents: 18 | *.dvi 19 | *-converted-to.* 20 | # these rules might exclude image files for figures etc. 21 | # *.ps 22 | # *.eps 23 | # *.pdf 24 | 25 | ## Generated if empty string is given at "Please type another file name for output:" 26 | .pdf 27 | 28 | ## Bibliography auxiliary files (bibtex/biblatex/biber): 29 | *.bbl 30 | *.bcf 31 | *.blg 32 | *-blx.aux 33 | *-blx.bib 34 | *.brf 35 | *.run.xml 36 | 37 | ## Build tool auxiliary files: 38 | *.fdb_latexmk 39 | *.synctex 40 | *.synctex(busy) 41 | *.synctex.gz 42 | *.synctex.gz(busy) 43 | *.pdfsync 44 | 45 | ## Auxiliary and intermediate files from other packages: 46 | # algorithms 47 | *.alg 48 | *.loa 49 | 50 | # achemso 51 | acs-*.bib 52 | 53 | # amsthm 54 | *.thm 55 | 56 | # beamer 57 | *.nav 58 | *.snm 59 | *.vrb 60 | 61 | # cprotect 62 | *.cpt 63 | 64 | # fixme 65 | *.lox 66 | 67 | #(r)(e)ledmac/(r)(e)ledpar 68 | *.end 69 | *.?end 70 | *.[1-9] 71 | *.[1-9][0-9] 72 | *.[1-9][0-9][0-9] 73 | *.[1-9]R 74 | *.[1-9][0-9]R 75 | *.[1-9][0-9][0-9]R 76 | *.eledsec[1-9] 77 | *.eledsec[1-9]R 78 | *.eledsec[1-9][0-9] 79 | *.eledsec[1-9][0-9]R 80 | *.eledsec[1-9][0-9][0-9] 81 | *.eledsec[1-9][0-9][0-9]R 82 | 83 | # glossaries 84 | *.acn 85 | *.acr 86 | *.glg 87 | *.glo 88 | *.gls 89 | *.glsdefs 90 | 91 | # gnuplottex 92 | *-gnuplottex-* 93 | 94 | # gregoriotex 95 | *.gaux 96 | *.gtex 97 | 98 | # hyperref 99 | *.brf 100 | 101 | # knitr 102 | *-concordance.tex 103 | # TODO Comment the next line if you want to keep your tikz graphics files 104 | *.tikz 105 | *-tikzDictionary 106 | 107 | # listings 108 | *.lol 109 | 110 | # makeidx 111 | *.idx 112 | *.ilg 113 | *.ind 114 | *.ist 115 | 116 | # minitoc 117 | *.maf 118 | *.mlf 119 | *.mlt 120 | *.mtc 121 | *.mtc[0-9] 122 | *.mtc[1-9][0-9] 123 | 124 | # minted 125 | _minted* 126 | *.pyg 127 | 128 | # morewrites 129 | *.mw 130 | 131 | # mylatexformat 132 | *.fmt 133 | 134 | # nomencl 135 | *.nlo 136 | 137 | # sagetex 138 | *.sagetex.sage 139 | *.sagetex.py 140 | *.sagetex.scmd 141 | 142 | # scrwfile 143 | *.wrt 144 | 145 | # sympy 146 | *.sout 147 | *.sympy 148 | sympy-plots-for-*.tex/ 149 | 150 | # pdfcomment 151 | *.upa 152 | *.upb 153 | 154 | # pythontex 155 | *.pytxcode 156 | pythontex-files-*/ 157 | 158 | # thmtools 159 | *.loe 160 | 161 | # TikZ & PGF 162 | *.dpth 163 | *.md5 164 | *.auxlock 165 | 166 | # todonotes 167 | *.tdo 168 | 169 | # easy-todo 170 | *.lod 171 | 172 | # xindy 173 | *.xdy 174 | 175 | # xypic precompiled matrices 176 | *.xyc 177 | 178 | # endfloat 179 | *.ttt 180 | *.fff 181 | 182 | # Latexian 183 | TSWLatexianTemp* 184 | 185 | ## Editors: 186 | # WinEdt 187 | *.bak 188 | *.sav 189 | 190 | # Texpad 191 | .texpadtmp 192 | 193 | # Kile 194 | *.backup 195 | 196 | # KBibTeX 197 | *~[0-9]* 198 | 199 | # obj files 200 | *.o 201 | 202 | ##### 203 | contents.tex 204 | 205 | # executable 206 | *.exe 207 | *.out -------------------------------------------------------------------------------- /GOOD_REFERENCE: -------------------------------------------------------------------------------- 1 | https://github.com/CodingYue/ACM-ICPC-Reference-Material 2 | https://github.com/jaehyunp/stanfordacm 3 | https://github.com/jaehyunp/stanfordacm/tree/master/stanford-cardinal-16/src 4 | https://github.com/marcospqf/Biblioteca_Stenio/tree/master/code 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 IME++ 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 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | pdflatex -shell-escape biblio.tex 3 | -------------------------------------------------------------------------------- /data-structures/bit.cpp: -------------------------------------------------------------------------------- 1 | // Fenwick Tree / Binary Indexed Tree 2 | ll bit[N]; 3 | 4 | void add(int p, int v) { 5 | for (p += 2; p < N; p += p & -p) bit[p] += v; 6 | } 7 | 8 | ll query(int p) { 9 | ll r = 0; 10 | for (p += 2; p; p -= p & -p) r += bit[p]; 11 | return r; 12 | } 13 | -------------------------------------------------------------------------------- /data-structures/bit2d.cpp: -------------------------------------------------------------------------------- 1 | // Thank you for the code tfg! 2 | 3 | // O(N(logN)^2) 4 | template 5 | struct Bit2D{ 6 | vector ord; 7 | vector> fw, coord; 8 | 9 | // pts needs all points that will be used in the upd 10 | // if range upds remember to build with {x1, y1}, {x1, y2 + 1}, {x2 + 1, y1}, {x2 + 1, y2 + 1} 11 | Bit2D(vector> pts){ 12 | sort(pts.begin(), pts.end()); 13 | for(auto a : pts) 14 | if(ord.empty() || a.first != ord.back()) 15 | ord.push_back(a.first); 16 | fw.resize(ord.size() + 1); 17 | coord.resize(fw.size()); 18 | 19 | for(auto &a : pts) 20 | swap(a.first, a.second); 21 | sort(pts.begin(), pts.end()); 22 | for(auto &a : pts){ 23 | swap(a.first, a.second); 24 | for(int on = std::upper_bound(ord.begin(), ord.end(), a.first) - ord.begin(); on < fw.size(); on += on & -on) 25 | if(coord[on].empty() || coord[on].back() != a.second) 26 | coord[on].push_back(a.second); 27 | } 28 | 29 | for(int i = 0; i < fw.size(); i++) 30 | fw[i].assign(coord[i].size() + 1, 0); 31 | } 32 | 33 | // point upd 34 | void upd(T x, T y, T v){ 35 | for(int xx = upper_bound(ord.begin(), ord.end(), x) - ord.begin(); xx < fw.size(); xx += xx & -xx) 36 | for(int yy = upper_bound(coord[xx].begin(), coord[xx].end(), y) - coord[xx].begin(); yy < fw[xx].size(); yy += yy & -yy) 37 | fw[xx][yy] += v; 38 | } 39 | 40 | // point qry 41 | T qry(T x, T y){ 42 | T ans = 0; 43 | for(int xx = upper_bound(ord.begin(), ord.end(), x) - ord.begin(); xx > 0; xx -= xx & -xx) 44 | for(int yy = upper_bound(coord[xx].begin(), coord[xx].end(), y) - coord[xx].begin(); yy > 0; yy -= yy & -yy) 45 | ans += fw[xx][yy]; 46 | return ans; 47 | } 48 | 49 | // range qry 50 | T qry(T x1, T y1, T x2, T y2){ 51 | return qry(x2, y2) - qry(x2, y1 - 1) - qry(x1 - 1, y2) + qry(x1 - 1, y1 - 1); 52 | } 53 | 54 | // range upd 55 | void upd(T x1, T y1, T x2, T y2, T v) { 56 | upd(x1, y1, v); 57 | upd(x1, y2 + 1, -v); 58 | upd(x2 + 1, y1, -v); 59 | upd(x2 + 1, y2 + 1, v); 60 | } 61 | }; 62 | -------------------------------------------------------------------------------- /data-structures/bit_binary_search.cpp: -------------------------------------------------------------------------------- 1 | // --- Bit Binary Search in o(log(n)) --- 2 | const int M = 20 3 | const int N = 1 << M 4 | 5 | int lower_bound(int val){ 6 | int ans = 0, sum = 0; 7 | for(int i = M - 1; i >= 0; i--){ 8 | int x = ans + (1 << i); 9 | if(sum + bit[x] < val) 10 | ans = x, sum += bit[x]; 11 | } 12 | 13 | return ans + 1; 14 | } 15 | -------------------------------------------------------------------------------- /data-structures/bit_range.cpp: -------------------------------------------------------------------------------- 1 | struct BIT { 2 | ll b[N]={}; 3 | ll sum(int x) { 4 | ll r=0; 5 | for(x+=2;x;x-=x&-x) 6 | r += b[x]; 7 | return r; 8 | } 9 | void upd(int x, ll v) { 10 | for(x+=2;x> adj; 3 | vector vis; 4 | vector par, sz; 5 | int n; 6 | Centroid(int n_) { 7 | n = n_; 8 | adj.resize(n + 1); vis.resize(n + 1); 9 | par.resize(n + 1); sz.resize(n + 1); 10 | } 11 | void add(int a, int b) { 12 | adj[a].push_back(b); 13 | adj[b].push_back(a); 14 | } 15 | int dfs_sz(int v, int p = -1) { 16 | if(vis[v]) { 17 | return 0; 18 | } 19 | sz[v] = 1; 20 | for(auto x : adj[v]) { 21 | if(x != p) { 22 | sz[v] += dfs_sz(x, v); 23 | } 24 | } 25 | return sz[v]; 26 | } 27 | int centroid(int v, int p, int size) { 28 | for(auto x : adj[v]) { 29 | if(x != p and !vis[x] and sz[x] > size / 2) { 30 | return centroid(x, v, size); 31 | } 32 | } 33 | return v; 34 | } 35 | void gen_tree(int v = 1, int p = 0) { 36 | int c = centroid(v, v, dfs_sz(v)); 37 | vis[c] = true; 38 | par[c] = p; 39 | for(auto x : adj[c]) { 40 | if(!vis[x]) { 41 | gen_tree(x, c); 42 | } 43 | } 44 | vis[c] = false; 45 | } 46 | void dfs(vector &path, int i, int p = -1, int d = 0) { 47 | path.push_back(d); 48 | for(auto j : adj[i]) { 49 | if(j != p and !vis[j]) { 50 | dfs(path, j, i, d + 1); 51 | } 52 | } 53 | } 54 | //count paths of size k in the tree 55 | //if you want upto k, just change cnt to be a Fenwick Tree 56 | long long decomp(int i, int k) { 57 | int c = centroid(i, i, dfs_sz(i)); 58 | vis[c] = true; 59 | long long ans = 0; 60 | vector cnt(sz[i]); 61 | cnt[0] = 1; 62 | for(auto j : adj[c]) { 63 | if(!vis[j]) { 64 | vector path; 65 | dfs(path, j); 66 | for(int d : path) { 67 | if(0 <= k - d - 1 and k - d - 1 < sz[i]) { 68 | ans += cnt[k - d - 1]; 69 | } 70 | } 71 | for(int d : path) { 72 | cnt[d + 1]++; 73 | } 74 | } 75 | } 76 | for(int j : adj[c]) { 77 | if(!vis[j]) { 78 | ans += decomp(j, k); 79 | } 80 | } 81 | vis[c] = false; 82 | return ans; 83 | } 84 | }; -------------------------------------------------------------------------------- /data-structures/color_update.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct ColorUpdate { 3 | public: 4 | struct Range { 5 | Range(T _l = 0) : l(_l) {} 6 | Range(T _l, T _r, Info _v) : l(_l), r(_r), v(_v) { } 7 | T l, r; 8 | Info v; 9 | 10 | bool operator < (const Range &b) const { return l < b.l; } 11 | }; 12 | 13 | std::vector erase(T l, T r) { 14 | std::vector ans; 15 | if(l >= r) return ans; 16 | auto it = ranges.lower_bound(l); 17 | if(it != ranges.begin()) { 18 | it--; 19 | if(it->r > l) { 20 | auto cur = *it; 21 | ranges.erase(it); 22 | ranges.insert(Range(cur.l, l, cur.v)); 23 | ranges.insert(Range(l, cur.r, cur.v)); 24 | } 25 | } 26 | it = ranges.lower_bound(r); 27 | if(it != ranges.begin()) { 28 | it--; 29 | if(it->r > r) { 30 | auto cur = *it; 31 | ranges.erase(it); 32 | ranges.insert(Range(cur.l, r, cur.v)); 33 | ranges.insert(Range(r, cur.r, cur.v)); 34 | } 35 | } 36 | for(it = ranges.lower_bound(l); it != ranges.end() && it->l < r; it++) { 37 | ans.push_back(*it); 38 | } 39 | ranges.erase(ranges.lower_bound(l), ranges.lower_bound(r)); 40 | return ans; 41 | } 42 | 43 | std::vector upd(T l, T r, Info v) { 44 | auto ans = erase(l, r); 45 | ranges.insert(Range(l, r, v)); 46 | return ans; 47 | } 48 | 49 | bool exists(T x) { 50 | auto it = ranges.upper_bound(x); 51 | if(it == ranges.begin()) return false; 52 | it--; 53 | return it->l <= x && x < it->r; 54 | } 55 | std::set ranges; 56 | }; 57 | 58 | struct CrazySet { 59 | ColorUpdate ranges; 60 | bool inverted = false; 61 | long long lazy = 0; 62 | 63 | void addLazy(long long x) { 64 | lazy += x; 65 | } 66 | 67 | void invert() { 68 | lazy = -lazy; 69 | inverted = !inverted; 70 | } 71 | 72 | void addRange(long long l, long long r) { 73 | if(!inverted) { 74 | ranges.upd(l-lazy, r-lazy, true); 75 | } else { 76 | ranges.upd(-r+1+lazy, -l+1+lazy, true); 77 | } 78 | } 79 | 80 | void removeRange(long long l, long long r) { 81 | if(!inverted) { 82 | ranges.erase(l-lazy, r-lazy); 83 | } else { 84 | ranges.erase(-r+1+lazy, -l+1+lazy); 85 | } 86 | } 87 | 88 | bool exists(long long x) { 89 | if(!inverted) { 90 | return ranges.exists(x - lazy); 91 | } else { 92 | return ranges.exists(-x + lazy); 93 | } 94 | } 95 | 96 | bool empty() { return ranges.ranges.empty(); } 97 | }; -------------------------------------------------------------------------------- /data-structures/hld-lamarca.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #define fr(i,n) for(int i = 0; i struct Seg{ 9 | ll s[4*N], lazy[4*N]; 10 | void build(int no = 1, int l = 0, int r = N){ 11 | if(r-l==1){ 12 | s[no] = 0; 13 | return; 14 | } 15 | int mid = (l+r)/2; 16 | build(2*no,l,mid); 17 | build(2*no+1,mid,r); 18 | s[no] = max(s[2*no],s[2*no+1]); 19 | } 20 | Seg(){ //build da HLD tem de ser assim, pq chama sem os parametros 21 | build(); 22 | } 23 | void updlazy(int no, int l, int r, ll x){ 24 | s[no] += x; 25 | lazy[no] += x; 26 | } 27 | void pass(int no, int l, int r){ 28 | int mid = (l+r)/2; 29 | updlazy(2*no,l,mid,lazy[no]); 30 | updlazy(2*no+1,mid,r,lazy[no]); 31 | lazy[no] = 0; 32 | } 33 | void upd(int lup, int rup, ll x, int no = 1, int l = 0, int r = N){ 34 | if(rup<=l or r<=lup) return; 35 | if(lup<=l and r<=rup){ 36 | updlazy(no,l,r,x); 37 | return; 38 | } 39 | pass(no,l,r); 40 | int mid = (l+r)/2; 41 | upd(lup,rup,x,2*no,l,mid); 42 | upd(lup,rup,x,2*no+1,mid,r); 43 | s[no] = max(s[2*no],s[2*no+1]); 44 | } 45 | ll qry(int lq, int rq, int no = 1, int l = 0, int r = N){ 46 | if(rq<=l or r<=lq) return -LLONG_MAX; 47 | if(lq<=l and r<=rq){ 48 | return s[no]; 49 | } 50 | pass(no,l,r); 51 | int mid = (l+r)/2; 52 | return max(qry(lq,rq,2*no,l,mid),qry(lq,rq,2*no+1,mid,r)); 53 | } 54 | }; 55 | 56 | template struct HLD { 57 | int t; 58 | vector g[N]; 59 | int pai[N], sz[N], d[N]; 60 | int root[N], pos[N]; /// vi rpos; 61 | void ae(int a, int b) { g[a].push_back(b), g[b].push_back(a); } 62 | void dfsSz(int no = 0) { 63 | if (~pai[no]) g[no].erase(find(all(g[no]),pai[no])); 64 | sz[no] = 1; 65 | for(auto &it : g[no]) { 66 | pai[it] = no; d[it] = d[no]+1; 67 | dfsSz(it); sz[no] += sz[it]; 68 | if (sz[it] > sz[g[no][0]]) swap(it, g[no][0]); 69 | } 70 | } 71 | void dfsHld(int no = 0) { 72 | pos[no] = t++; /// rpos.pb(no); 73 | for(auto &it : g[no]) { 74 | root[it] = (it == g[no][0] ? root[no] : it); 75 | dfsHld(it); } 76 | } 77 | void init() { 78 | root[0] = d[0] = t = 0; pai[0] = -1; 79 | dfsSz(); dfsHld(); } 80 | Seg tree; //lembrar de ter build da seg sem nada 81 | template 82 | void processPath(int u, int v, Op op) { 83 | for (; root[u] != root[v]; v = pai[root[v]]) { 84 | if (d[root[u]] > d[root[v]]) swap(u, v); 85 | op(pos[root[v]], pos[v]); } 86 | if (d[u] > d[v]) swap(u, v); 87 | op(pos[u]+IN_EDGES, pos[v]); 88 | } 89 | 90 | /* 91 | void changeNode(int v, node val){ 92 | tree.upd(pos[v],val); 93 | }*/ 94 | void modifySubtree(int v, int val) { 95 | tree.upd(pos[v]+IN_EDGES,pos[v]+sz[v],val); 96 | } 97 | ll querySubtree(int v){ 98 | return tree.qry(pos[v]+IN_EDGES,pos[v]+sz[v]); 99 | } 100 | void modifyPath(int u, int v, int val) { 101 | processPath(u,v,[this, &val](int l,int r) { 102 | tree.upd(l,r+1,val); }); 103 | } 104 | ll queryPath(int u, int v) { //modificacoes geralmente vem aqui (para hld soma) 105 | ll res = -LLONG_MAX; processPath(u,v,[this,&res](int l,int r) { 106 | res = max(tree.qry(l,r+1),res); }); 107 | return res; 108 | } 109 | }; 110 | 111 | //solves https://www.hackerrank.com/challenges/subtrees-and-paths/problem 112 | //other problems here: https://blog.anudeep2011.com/heavy-light-decomposition/ 113 | 114 | const int N = 1e5+10; 115 | char str[100]; 116 | int main(){ 117 | HLD hld; 118 | int n; 119 | cin >> n; 120 | 121 | fr(i,n-1){ 122 | int u, v; 123 | scanf("%d%d", &u, &v); 124 | u--,v--; 125 | hld.ae(u,v); 126 | } 127 | hld.init(); 128 | int q; 129 | scanf("%d", &q); 130 | fr(qq,q){ 131 | scanf("%s", str); 132 | if(str[0]=='a'){ 133 | int t, val; 134 | scanf("%d%d", &t, &val); 135 | t--; 136 | hld.modifySubtree(t,val); 137 | } else{ 138 | int u, v; 139 | scanf("%d%d", &u, &v); 140 | u--,v--; 141 | printf("%lld\n", hld.queryPath(u,v)); 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /data-structures/hld.cpp: -------------------------------------------------------------------------------- 1 | // Heavy-Light Decomposition 2 | vector adj[N]; 3 | int par[N], h[N]; 4 | 5 | int chainno, chain[N], head[N], chainpos[N], chainsz[N], pos[N], arrsz; 6 | int sc[N], sz[N]; 7 | 8 | void dfs(int u) { 9 | sz[u] = 1, sc[u] = 0; // nodes 1-indexed (0-ind: sc[u]=-1) 10 | for (int v : adj[u]) if (v != par[u]) { 11 | par[v] = u, h[v] = h[u]+1, dfs(v); 12 | sz[u]+=sz[v]; 13 | if (sz[sc[u]] < sz[v]) sc[u] = v; // 1-indexed (0-ind: sc[u]<0 or ...) 14 | } 15 | } 16 | 17 | void hld(int u) { 18 | if (!head[chainno]) head[chainno] = u; // 1-indexed 19 | chain[u] = chainno; 20 | chainpos[u] = chainsz[chainno]; 21 | chainsz[chainno]++; 22 | pos[u] = ++arrsz; 23 | 24 | if (sc[u]) hld(sc[u]); 25 | 26 | for (int v : adj[u]) if (v != par[u] and v != sc[u]) 27 | chainno++, hld(v); 28 | } 29 | 30 | int lca(int u, int v) { 31 | while (chain[u] != chain[v]) { 32 | if (h[head[chain[u]]] < h[head[chain[v]]]) swap(u, v); 33 | u = par[head[chain[u]]]; 34 | } 35 | if (h[u] > h[v]) swap(u, v); 36 | return u; 37 | } 38 | 39 | int query_up(int u, int v) { 40 | if (u == v) return 0; 41 | int ans = -1; 42 | while (1) { 43 | if (chain[u] == chain[v]) { 44 | if (u == v) break; 45 | ans = max(ans, query(1, 1, n, chainpos[v]+1, chainpos[u])); 46 | break; 47 | } 48 | 49 | ans = max(ans, query(1, 1, n, chainpos[head[chain[u]]], chainpos[u])); 50 | u = par[head[chain[u]]]; 51 | } 52 | return ans; 53 | } 54 | 55 | int query(int u, int v) { 56 | int l = lca(u, v); 57 | return max(query_up(u, l), query_up(v, l)); 58 | } 59 | -------------------------------------------------------------------------------- /data-structures/hld_exx.cpp: -------------------------------------------------------------------------------- 1 | vector adj[N]; 2 | int sz[N], nxt[N]; 3 | int h[N], par[N]; 4 | int in[N], rin[N], out[N]; 5 | int t; 6 | 7 | void dfs_sz(int u = 1){ 8 | sz[u] = 1; 9 | for(auto &v : adj[u]) if(v != par[u]) { 10 | h[v] = h[u] + 1; 11 | par[v] = u; 12 | 13 | dfs_sz(v); 14 | sz[u] += sz[v]; 15 | if(sz[v] > sz[adj[u][0]]) 16 | swap(v, adj[u][0]); 17 | } 18 | } 19 | 20 | void dfs_hld(int u = 1){ 21 | in[u] = t++; 22 | rin[in[u]] = u; 23 | for(auto v : adj[u]) if(v != par[u]) { 24 | nxt[v] = (v == adj[u][0] ? nxt[u] : v); 25 | dfs_hld(v); 26 | } 27 | 28 | out[u] = t - 1; 29 | } 30 | 31 | int lca(int u, int v){ 32 | while(nxt[u] != nxt[v]){ 33 | if(h[nxt[u]] < h[nxt[v]]) swap(u, v); 34 | u = par[nxt[u]]; 35 | } 36 | 37 | if(h[u] > h[v]) swap(u, v); 38 | return u; 39 | } 40 | 41 | int query_up(int u, int v) { 42 | if(u == v) return 1; 43 | int ans = 0; 44 | while(1){ 45 | if(nxt[u] == nxt[v]){ 46 | if(u == v) break; 47 | ans = max(ans, query(1, 0, n - 1, in[v] + 1, in[u])); 48 | break; 49 | } 50 | 51 | ans = max(ans, query(1, 0, n - 1, in[nxt[u]], in[u])); 52 | u = par[nxt[u]]; 53 | } 54 | 55 | return ans; 56 | } 57 | 58 | int hld_query(int u, int v) { 59 | int l = lca(u, v); 60 | return mult(query_up(u, l), query_up(v, l)); 61 | } 62 | -------------------------------------------------------------------------------- /data-structures/ita_lichao.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define INF 0x3f3f3f3f3f3f3f3f 4 | #define MAXN 1009 5 | using namespace std; 6 | 7 | typedef long long ll; 8 | 9 | /* 10 | * LiChao Segment Tree 11 | */ 12 | 13 | class LiChao { 14 | vector m, b; 15 | int n, sz; ll *x; 16 | #define gx(i) (i < sz ? x[i] : x[sz-1]) 17 | void update(int t, int l, int r, ll nm, ll nb) { 18 | ll xl = nm * gx(l) + nb, xr = nm * gx(r) + nb; 19 | ll yl = m[t] * gx(l) + b[t], yr = m[t] * gx(r) + b[t]; 20 | if (yl >= xl && yr >= xr) return; 21 | if (yl <= xl && yr <= xr) { 22 | m[t] = nm, b[t] = nb; return; 23 | } 24 | int mid = (l + r) / 2; 25 | update(t<<1, l, mid, nm, nb); 26 | update(1+(t<<1), mid+1, r, nm, nb); 27 | } 28 | public: 29 | LiChao(ll *st, ll *en) : x(st) { 30 | sz = int(en - st); 31 | for(n = 1; n < sz; n <<= 1); 32 | m.assign(2*n, 0); b.assign(2*n, -INF); 33 | } 34 | void insert_line(ll nm, ll nb) { 35 | update(1, 0, n-1, nm, nb); 36 | } 37 | ll query(int i) { 38 | ll ans = -INF; 39 | for(int t = i+n; t; t >>= 1) 40 | ans = max(ans, m[t] * x[i] + b[t]); 41 | return ans; 42 | } 43 | }; 44 | 45 | /* 46 | * UVa 12524 47 | */ 48 | 49 | ll w[MAXN], x[MAXN], A[MAXN], B[MAXN], dp[MAXN][MAXN]; 50 | 51 | int main(){ 52 | int N, K; 53 | while(scanf("%d %d", &N, &K)!=EOF) { 54 | for(int i=0; i0 ? A[i-1] : 0); 57 | B[i] = w[i]*x[i] + (i>0 ? B[i-1] : 0); 58 | dp[i][1] = x[i]*A[i] - B[i]; 59 | } 60 | for(int k=2; k<=K; k++){ 61 | dp[0][k] = 0; 62 | LiChao lc(x, x+N); 63 | for(int i=1; i seg; 12 | vector L, R; 13 | inline void push() { 14 | seg.push_back({0, -linf}); 15 | L.push_back(-1); 16 | R.push_back(-1); 17 | } 18 | lichao() { 19 | push(); 20 | } 21 | void add(line a, int p = 0, long long l = -MAX, long long r = MAX) { 22 | long long mid = (l + r) >> 1; 23 | if(seg[p].cmp(a, mid)) { 24 | swap(seg[p], a); 25 | } 26 | if(a.b == -linf) { 27 | return; 28 | } 29 | if(seg[p].cmp(a, l) != seg[p].cmp(a, mid)) { 30 | if(L[p] == -1) { 31 | L[p] = seg.size(); 32 | push(); 33 | } 34 | add(a, L[p], l, mid - 1); 35 | } else if(seg[p].cmp(a, r) != seg[p].cmp(a, mid)) { 36 | if(R[p] == -1) { 37 | R[p] = seg.size(); 38 | push(); 39 | } 40 | add(a, R[p], mid + 1, r); 41 | } 42 | } 43 | long long query(long long x, int p = 0, long long l = -MAX, long long r = MAX) { 44 | if(p < 0) { 45 | return -linf; 46 | } 47 | long long mid = (l + r) >> 1, calc = seg[p](x); 48 | if(calc == -linf) { 49 | return calc; 50 | } 51 | if(x < mid) { 52 | return max(calc, query(x, L[p], l, mid - 1)); 53 | } else { 54 | return max(calc, query(x, R[p], mid + 1, r)); 55 | } 56 | } 57 | }; -------------------------------------------------------------------------------- /data-structures/lichao_lazy.cpp: -------------------------------------------------------------------------------- 1 | // Li-Chao Tree - Lazy 2 | // 3 | // Sendo N = MA-MI: 4 | // insert({a, b}) minimiza tudo com ax+b - O(log N) 5 | // insert({a, b}, l, r) minimiza com ax+b no range [l, r] - O(log^2 N) 6 | // shift({a, b}) soma ax+b em tudo - O(1) 7 | // shift({a, b}, l, r) soma ax+b no range [l, r] - O(log^2 N) 8 | // query(x) retorna o valor da posicao x - O(log N) 9 | // 10 | // No inicio eh tudo LINF, se inserir {0, 0} fica tudo 0 11 | // 12 | // O(n log N) de memoria ; O(n) de memoria se nao usar as operacoes de range 13 | 14 | template struct lichao { 15 | struct line { 16 | ll a, b; 17 | ll la, lb; // lazy 18 | array ch; 19 | line(ll a_ = 0, ll b_ = LINF) : 20 | a(a_), b(b_), la(0), lb(0), ch({-1, -1}) {} 21 | ll operator ()(ll x) { return a*x + b; } 22 | }; 23 | vector ln; 24 | 25 | int ch(int p, int d) { 26 | if (ln[p].ch[d] == -1) { 27 | ln[p].ch[d] = ln.size(); 28 | ln.emplace_back(); 29 | } 30 | return ln[p].ch[d]; 31 | } 32 | lichao() { ln.emplace_back(); } 33 | 34 | void prop(int p, int l, int r) { 35 | if (ln[p].la == 0 and ln[p].lb == 0) return; 36 | ln[p].a += ln[p].la, ln[p].b += ln[p].lb; 37 | if (l != r) { 38 | int pl = ch(p, 0), pr = ch(p, 1); 39 | ln[pl].la += ln[p].la, ln[pl].lb += ln[p].lb; 40 | ln[pr].la += ln[p].la, ln[pr].lb += ln[p].lb; 41 | } 42 | ln[p].la = ln[p].lb = 0; 43 | } 44 | 45 | ll query(int x, int p=0, int l=MI, int r=MA) { 46 | prop(p, l, r); 47 | ll ret = ln[p](x); 48 | if (ln[p].ch[0] == -1 and ln[p].ch[1] == -1) return ret; 49 | int m = l + (r-l)/2; 50 | if (x <= m) return min(ret, query(x, ch(p, 0), l, m)); 51 | return min(ret, query(x, ch(p, 1), m+1, r)); 52 | } 53 | 54 | void push(line s, int p, int l, int r) { 55 | prop(p, l, r); 56 | int m = l + (r-l)/2; 57 | bool L = s(l) < ln[p](l); 58 | bool M = s(m) < ln[p](m); 59 | bool R = s(r) < ln[p](r); 60 | if (M) swap(ln[p].a, s.a), swap(ln[p].b, s.b); 61 | if (s.b == LINF) return; 62 | if (L != M) push(s, ch(p, 0), l, m); 63 | else if (R != M) push(s, ch(p, 1), m+1, r); 64 | } 65 | void insert(line s, int a=MI, int b=MA, int p=0, int l=MI, int r=MA) { 66 | prop(p, l, r); 67 | if (a <= l and r <= b) return push(s, p, l, r); 68 | if (b < l or r < a) return; 69 | int m = l + (r-l)/2; 70 | insert(s, a, b, ch(p, 0), l, m); 71 | insert(s, a, b, ch(p, 1), m+1, r); 72 | } 73 | 74 | void shift(line s, int a=MI, int b=MA, int p=0, int l=MI, int r=MA) { 75 | prop(p, l, r); 76 | int m = l + (r-l)/2; 77 | if (a <= l and r <= b) { 78 | ln[p].la += s.a, ln[p].lb += s.b; 79 | return; 80 | } 81 | if (b < l or r < a) return; 82 | if (ln[p].b != LINF) { 83 | push(ln[p], ch(p, 0), l, m); 84 | push(ln[p], ch(p, 1), m+1, r); 85 | ln[p].a = 0, ln[p].b = LINF; 86 | } 87 | shift(s, a, b, ch(p, 0), l, m); 88 | shift(s, a, b, ch(p, 1), m+1, r); 89 | } 90 | }; -------------------------------------------------------------------------------- /data-structures/mergesort_tree.cpp: -------------------------------------------------------------------------------- 1 | // Mergesort Tree - Time - Memory O(nlogn) 2 | // Mergesort Tree is a segment tree that stores the sorted subarray 3 | // on each node. 4 | vi st[4*N]; 5 | 6 | void build(int p, int l, int r) { 7 | if (l == r) { st[p].pb(s[l]); return; } 8 | build(2*p, l, (l+r)/2); 9 | build(2*p+1, (l+r)/2+1, r); 10 | st[p].resize(r-l+1); 11 | merge(st[2*p].begin(), st[2*p].end(), 12 | st[2*p+1].begin(), st[2*p+1].end(), 13 | st[p].begin()); 14 | } 15 | 16 | int query(int p, int l, int r, int i, int j, int a, int b) { 17 | if (j < l or i > r) return 0; 18 | if (i <= l and j >= r) 19 | return upper_bound(st[p].begin(), st[p].end(), b) - 20 | lower_bound(st[p].begin(), st[p].end(), a); 21 | return query(2*p, l, (l+r)/2, i, j, a, b) + 22 | query(2*p+1, (l+r)/2+1, r, i, j, a, b); 23 | } 24 | -------------------------------------------------------------------------------- /data-structures/min_queue.cpp: -------------------------------------------------------------------------------- 1 | // O(1) complexity for all operations, except for clear, 2 | // which could be done by creating another deque and using swap 3 | 4 | struct MinQueue { 5 | int plus = 0; 6 | int sz = 0; 7 | deque> dq; 8 | 9 | bool empty() { return dq.empty(); } 10 | void clear() { plus = 0; sz = 0; dq.clear(); } 11 | void add(int x) { plus += x; } // Adds x to every element in the queue 12 | int min() { return dq.front().first + plus; } // Returns the minimum element in the queue 13 | int size() { return sz; } 14 | 15 | void push(int x) { 16 | x -= plus; 17 | int amt = 1; 18 | while (dq.size() and dq.back().first >= x) 19 | amt += dq.back().second, dq.pop_back(); 20 | dq.push_back({ x, amt }); 21 | sz++; 22 | } 23 | 24 | void pop() { 25 | dq.front().second--, sz--; 26 | if (!dq.front().second) dq.pop_front(); 27 | } 28 | }; 29 | 30 | -------------------------------------------------------------------------------- /data-structures/ordered_set.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | using namespace __gnu_pbds; 5 | 6 | typedef tree, rb_tree_tag, tree_order_statistics_node_update> ordered_set; 7 | 8 | ordered_set s; 9 | s.insert(2), s.insert(3), s.insert(7), s.insert(9); 10 | 11 | //find_by_order returns an iterator to the element at a given position 12 | auto x = s.find_by_order(2); 13 | cout << *x << "\n"; // 7 14 | 15 | //order_of_key returns the position of a given element 16 | cout << s.order_of_key(7) << "\n"; // 2 17 | 18 | //If the element does not appear in the set, we get the position that the element would have in the set 19 | cout << s.order_of_key(6) << "\n"; // 2 20 | cout << s.order_of_key(8) << "\n"; // 3 21 | -------------------------------------------------------------------------------- /data-structures/seg_tree.cpp: -------------------------------------------------------------------------------- 1 | // Segment Tree (Range Query and Range Update) 2 | // Update and Query - O(log n) 3 | 4 | int n, v[N], lz[4*N], st[4*N]; 5 | 6 | void build(int p = 1, int l = 1, int r = n) { 7 | if (l == r) { st[p] = v[l]; return; } 8 | build(2*p, l, (l+r)/2); 9 | build(2*p+1, (l+r)/2+1, r); 10 | st[p] = min(st[2*p], st[2*p+1]); // RMQ -> min/max, RSQ -> + 11 | } 12 | 13 | void push(int p, int l, int r) { 14 | if (lz[p]) { 15 | st[p] = lz[p]; 16 | // RMQ -> update: = lz[p], increment: += lz[p] 17 | // RSQ -> update: = (r-l+1)*lz[p], increment: += (r-l+1)*lz[p] 18 | if(l!=r) lz[2*p] = lz[2*p+1] = lz[p]; // update: =, increment += 19 | lz[p] = 0; 20 | } 21 | } 22 | 23 | int query(int i, int j, int p = 1, int l = 1, int r = n) { 24 | push(p, l, r); 25 | if (l > j or r < i) return INF; // RMQ -> INF, RSQ -> 0 26 | if (l >= i and j >= r) return st[p]; 27 | return min(query(i, j, 2*p, l, (l+r)/2), 28 | query(i, j, 2*p+1, (l+r)/2+1, r)); 29 | // RMQ -> min/max, RSQ -> + 30 | } 31 | 32 | void update(int i, int j, int v, int p = 1, int l = 1, int r = n) { 33 | push(p, l, r); 34 | if (l > j or r < i) return; 35 | if (l >= i and j >= r) { lz[p] = v; push(p, l, r); return; } 36 | update(i, j, v, 2*p, l, (l+r)/2); 37 | update(i, j, v, 2*p+1, (l+r)/2+1, r); 38 | st[p] = min(st[2*p], st[2*p+1]); // RMQ -> min/max, RSQ -> + 39 | } 40 | -------------------------------------------------------------------------------- /data-structures/seg_tree2d.cpp: -------------------------------------------------------------------------------- 1 | // Segment Tree 2D - O(nlog(n)log(n)) of Memory and Runtime 2 | const int N = 1e8+5, M = 2e5+5; 3 | int n, k=1, st[N], lc[N], rc[N]; 4 | 5 | void addx(int x, int l, int r, int u) { 6 | if (x < l or r < x) return; 7 | 8 | st[u]++; 9 | if (l == r) return; 10 | 11 | if(!rc[u]) rc[u] = ++k, lc[u] = ++k; 12 | addx(x, l, (l+r)/2, lc[u]); 13 | addx(x, (l+r)/2+1, r, rc[u]); 14 | } 15 | 16 | // Adds a point (x, y) to the grid. 17 | void add(int x, int y, int l, int r, int u) { 18 | if (y < l or r < y) return; 19 | 20 | if (!st[u]) st[u] = ++k; 21 | addx(x, 1, n, st[u]); 22 | 23 | if (l == r) return; 24 | 25 | if(!rc[u]) rc[u] = ++k, lc[u] = ++k; 26 | add(x, y, l, (l+r)/2, lc[u]); 27 | add(x, y, (l+r)/2+1, r, rc[u]); 28 | } 29 | 30 | int countx(int x, int l, int r, int u) { 31 | if (!u or x < l) return 0; 32 | if (r <= x) return st[u]; 33 | 34 | return countx(x, l, (l+r)/2, lc[u]) + 35 | countx(x, (l+r)/2+1, r, rc[u]); 36 | } 37 | 38 | // Counts number of points dominated by (x, y) 39 | // Should be called with l = 1, r = n and u = 1 40 | int count(int x, int y, int l, int r, int u) { 41 | if (!u or y < l) return 0; 42 | if (r <= y) return countx(x, 1, n, st[u]); 43 | 44 | return count(x, y, l, (l+r)/2, lc[u]) + 45 | count(x, y, (l+r)/2+1, r, rc[u]); 46 | } 47 | -------------------------------------------------------------------------------- /data-structures/seg_tree_dynamic.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* tested: 4 | https://www.spoj.com/problems/ORDERSET/ 5 | https://www.eolymp.com/en/contests/8463/problems/72212 6 | https://codeforces.com/contest/474/problem/E 7 | https://codeforces.com/problemset/problem/960/F 8 | ref: 9 | https://maratona.ic.unicamp.br/MaratonaVerao2022/slides/AulaSummer-SegmentTree-Aula2.pdf 10 | */ 11 | 12 | vector e, d, mn; 13 | //begin creating node 0, then start your segment tree creating node 1 14 | int create(){ 15 | mn.push_back(0); 16 | e.push_back(0); 17 | d.push_back(0); 18 | return mn.size() - 1; 19 | } 20 | 21 | void update(int pos, int ini, int fim, int id, int val){ 22 | if(id < ini || id > fim) return; 23 | 24 | if(ini == fim){ 25 | mn[pos] = val; 26 | return; 27 | } 28 | 29 | int m = (ini + fim) >> 1; 30 | if(id <= m){ 31 | if(e[pos] == 0){ 32 | int aux = create(); 33 | e[pos] = aux; 34 | } 35 | update(e[pos], ini, m, id, val); 36 | } 37 | else{ 38 | if(d[pos] == 0){ 39 | int aux = create(); 40 | d[pos] = aux; 41 | } 42 | update(d[pos], m + 1, fim, id, val); 43 | } 44 | 45 | mn[pos] = min(mn[e[pos]], mn[d[pos]]); 46 | } 47 | 48 | int query(int pos, int ini, int fim, int p, int q){ 49 | if(q < ini || p > fim) return INT_MAX; 50 | 51 | if(pos == 0) return 0; 52 | 53 | if(p <= ini and fim <= q) return mn[pos]; 54 | 55 | int m = (ini + fim) >> 1; 56 | return min(query(e[pos], ini, m, p, q), query(d[pos], m + 1, fim, p, q)); 57 | } -------------------------------------------------------------------------------- /data-structures/seg_tree_dynamic_lazy.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* tested: 4 | https://www.spoj.com/problems/BGSHOOT/ 5 | ref: 6 | https://maratona.ic.unicamp.br/MaratonaVerao2022/slides/AulaSummer-SegmentTree-Aula2.pdf 7 | */ 8 | vector e, d, mx, lazy; 9 | //begin creating node 0, then start your segment tree creating node 1 10 | int create(){ 11 | mx.push_back(0); 12 | lazy.push_back(0); 13 | e.push_back(0); 14 | d.push_back(0); 15 | return mx.size() - 1; 16 | } 17 | 18 | void push(int pos, int ini, int fim){ 19 | if(pos == 0) return; 20 | if (lazy[pos]) { 21 | mx[pos] += lazy[pos]; 22 | // RMQ (max/min) -> update: = lazy[p], incr: += lazy[p] 23 | // RSQ (sum) -> update: = (r-l+1)*lazy[p], incr: += (r-l+1)*lazy[p] 24 | // Count lights on -> flip: = (r-l+1)-st[p]; 25 | if (ini != fim) { 26 | if(e[pos] == 0){ 27 | int aux = create(); 28 | e[pos] = aux; 29 | } 30 | if(d[pos] == 0){ 31 | int aux = create(); 32 | d[pos] = aux; 33 | } 34 | lazy[e[pos]] += lazy[pos]; 35 | lazy[d[pos]] += lazy[pos]; 36 | // update: lazy[2*p] = lazy[p], lazy[2*p+1] = lazy[p]; 37 | // increment: lazy[2*p] += lazy[p], lazy[2*p+1] += lazy[p]; 38 | // flip: lazy[2*p] ^= 1, lazy[2*p+1] ^= 1; 39 | } 40 | lazy[pos] = 0; 41 | } 42 | } 43 | 44 | void update(int pos, int ini, int fim, int p, int q, int val){ 45 | if(pos == 0) return; 46 | 47 | push(pos, ini, fim); 48 | 49 | if(q < ini || p > fim) return; 50 | 51 | if(p <= ini and fim <= q){ 52 | lazy[pos] += val; 53 | // update: lazy[p] = k; 54 | // increment: lazy[p] += k; 55 | // flip: lazy[p] = 1; 56 | push(pos, ini, fim); 57 | return; 58 | } 59 | 60 | int m = (ini + fim) >> 1; 61 | if(e[pos] == 0){ 62 | int aux = create(); 63 | e[pos] = aux; 64 | } 65 | update(e[pos], ini, m, p, q, val); 66 | if(d[pos] == 0){ 67 | int aux = create(); 68 | d[pos] = aux; 69 | } 70 | update(d[pos], m + 1, fim, p, q, val); 71 | mx[pos] = max(mx[e[pos]], mx[d[pos]]); 72 | } 73 | 74 | int query(int pos, int ini, int fim, int p, int q){ 75 | if(pos == 0) return 0; 76 | 77 | push(pos, ini, fim); 78 | 79 | if(q < ini || p > fim) return 0; 80 | 81 | if(p <= ini and fim <= q) return mx[pos]; 82 | 83 | int m = (ini + fim) >> 1; 84 | return max(query(e[pos], ini, m, p, q) , query(d[pos], m + 1, fim, p, q)); 85 | } -------------------------------------------------------------------------------- /data-structures/seg_tree_iterative.cpp: -------------------------------------------------------------------------------- 1 | int n; // Array size 2 | int st[2*N]; 3 | 4 | int query(int a, int b) { 5 | a += n; b += n; 6 | int s = 0; 7 | while (a <= b) { 8 | if (a%2 == 1) s += st[a++]; 9 | if (b%2 == 0) s += st[b--]; 10 | a /= 2; b /= 2; 11 | } 12 | return s; 13 | } 14 | 15 | void update(int p, int val) { 16 | p += n; 17 | st[p] += val; 18 | for (p /= 2; p >= 1; p /= 2) 19 | st[p] = st[2*p]+st[2*p+1]; 20 | } 21 | -------------------------------------------------------------------------------- /data-structures/seg_tree_mod.cpp: -------------------------------------------------------------------------------- 1 | // SegTree with mod 2 | // op1 (l, r) -> sum a[i], i = { l .. r } 3 | // op2 (l, r, x) -> a[i] = a[i] mod x, i = { l .. r } 4 | // op3 (idx, x) -> a[idx] = x; 5 | 6 | const int N = 1e5 + 5; 7 | 8 | struct segTreeNode { ll sum, mx, mn, lz = -1; }; 9 | 10 | int n, m; 11 | ll a[N]; 12 | segTreeNode st[4 * N]; 13 | 14 | void push(int p, int l, int r) { 15 | if (st[p].lz != -1) { 16 | 17 | st[p].mx = st[p].mn = st[p].lz; 18 | st[p].sum = (r - l + 1) * st[p].lz; 19 | 20 | if (l != r) st[2 * p].lz = st[2 * p + 1].lz = st[p].lz; 21 | st[p].lz = -1; 22 | } 23 | } 24 | 25 | void merge(int p) { 26 | st[p].mx = max(st[2 * p].mx, st[2 * p + 1].mx); 27 | st[p].mn = min(st[2 * p].mn, st[2 * p + 1].mn); 28 | st[p].sum = st[2 * p].sum + st[2 * p + 1].sum; 29 | } 30 | 31 | void build(int p = 1, int l = 1, int r = n) { 32 | if (l == r) { 33 | st[p].mn = st[p].mx = st[p].sum = a[l]; 34 | return; 35 | } 36 | 37 | int mid = (l + r) >> 1; 38 | build(2 * p, l, mid); 39 | build(2 * p + 1, mid + 1, r); 40 | 41 | merge(p); 42 | } 43 | 44 | ll query(int i, int j, int p = 1, int l = 1, int r = n) { 45 | push(p, l, r); 46 | if (r < i or l > j) return 0ll; 47 | if (i <= l and r <= j) return st[p].sum; 48 | int mid = (l + r) >> 1; 49 | return query(i, j, 2 * p, l, mid) + query(i, j, 2 * p + 1, mid + 1, r); 50 | } 51 | 52 | void module_op(int i, int j, ll x, int p = 1, int l = 1, int r = n) { 53 | push(p, l, r); 54 | if (r < i or l > j or st[p].mx < x) return; 55 | if (i <= l and r <= j and st[p].mx == st[p].mn) { 56 | st[p].lz = st[p].mx % x; 57 | push(p, l, r); 58 | return; 59 | } 60 | int mid = (l + r) >> 1; 61 | module_op(i, j, x, 2 * p, l, mid); 62 | module_op(i, j, x, 2 * p + 1, mid + 1, r); 63 | 64 | merge(p); 65 | } 66 | 67 | void set_op(int i, int j, ll x, int p = 1, int l = 1, int r = n) { 68 | push(p, l, r); 69 | if (r < i or l > j) return; 70 | if (i <= l and r <= j) { 71 | st[p].lz = x; 72 | push(p, l, r); 73 | return; 74 | } 75 | int mid = (l + r) >> 1; 76 | set_op(i, j, x, 2 * p, l, mid); 77 | set_op(i, j, x, 2 * p + 1, mid + 1, r); 78 | 79 | merge(p); 80 | } 81 | -------------------------------------------------------------------------------- /data-structures/seg_tree_persistent.cpp: -------------------------------------------------------------------------------- 1 | // Persistent Segtree 2 | // Memory: O(n logn) 3 | // Operations: O(log n) 4 | 5 | int li[N], ri[N]; // [li(u), ri(u)] is the interval of node u 6 | int st[N], lc[N], rc[N]; // Value, left son and right son of node u 7 | int stsz; // Size of segment tree 8 | 9 | // Returns root of initial tree. 10 | // i and j are the first and last elements of the tree. 11 | int init(int i, int j) { 12 | int v = ++stsz; 13 | li[v] = i, ri[v] = j; 14 | 15 | if (i != j) { 16 | rc[v] = init(i, (i+j)/2); 17 | rc[v] = init((i+j)/2+1, j); 18 | st[v] = /* calculate value from rc[v] and rc[v] */; 19 | } else { 20 | st[v] = /* insert initial value here */; 21 | } 22 | 23 | return v; 24 | } 25 | 26 | // Gets the sum from i to j from tree with root u 27 | int sum(int u, int i, int j) { 28 | if (j < li[u] or ri[u] < i) return 0; 29 | if (i <= li[u] and ri[u] <= j) return st[u]; 30 | return sum(rc[u], i, j) + sum (rc[u], i, j); 31 | } 32 | 33 | // Copies node j into node i 34 | void clone(int i, int j) { 35 | li[i] = li[j], ri[i] = ri[j]; 36 | st[i] = st[j]; 37 | rc[i] = rc[j], rc[i] = rc[j]; 38 | } 39 | 40 | // Sums v to index i from the tree with root u 41 | int update(int u, int i, int v) { 42 | if (i < li[u] or ri[u] < i) return u; 43 | 44 | clone(++stsz, u); 45 | u = stsz; 46 | rc[u] = update(rc[u], i, v); 47 | rc[u] = update(rc[u], i, v); 48 | 49 | if (li[u] == ri[u]) st[u] += v; 50 | else st[u] = st[rc[u]] + st[rc[u]]; 51 | 52 | return u; 53 | } 54 | -------------------------------------------------------------------------------- /data-structures/seg_tree_persistent_naum.cpp: -------------------------------------------------------------------------------- 1 | // Persistent Segment Tree 2 | int n; 3 | int rcnt; 4 | int lc[M], rc[M], st[M]; 5 | 6 | int update(int p, int l, int r, int i, int v) { 7 | int rt = ++rcnt; 8 | if (l == r) { st[rt] = v; return rt; } 9 | 10 | int mid = (l+r)/2; 11 | if (i <= mid) lc[rt] = update(lc[p], l, mid, i, v), rc[rt] = rc[p]; 12 | else rc[rt] = update(rc[p], mid+1, r, i, v), lc[rt] = lc[p]; 13 | st[rt] = st[lc[rt]] + st[rc[rt]]; 14 | 15 | return rt; 16 | } 17 | 18 | int query(int p, int l, int r, int i, int j) { 19 | if (l > j or r < i) return 0; 20 | if (i <= l and r <= j) return st[p]; 21 | 22 | return query(lc[p], l, (l+r)/2, i, j)+query(rc[p], (l+r)/2+1, r, i, j); 23 | } 24 | 25 | int main() { 26 | scanf("%d", &n); 27 | for (int i = 1; i <= n; ++i) { 28 | int a; 29 | scanf("%d", &a); 30 | r[i] = update(r[i-1], 1, n, i, 1); 31 | } 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /data-structures/seg_tree_point_update_struct.cpp: -------------------------------------------------------------------------------- 1 | // Segment Tree (range query and point update) 2 | // Update - O(log n) 3 | // Query - O(log n) 4 | // Memory - O(n) 5 | 6 | struct Node { 7 | ll val; 8 | 9 | Node(ll _val = 0) : val(_val) {} 10 | Node(const Node& l, const Node& r) : val(l.val + r.val) {} 11 | 12 | friend ostream& operator<<(ostream& os, const Node& a) { 13 | os << a.val; 14 | return os; 15 | } 16 | }; 17 | 18 | template 19 | struct SimpleSegTree { 20 | int n; 21 | vector st; 22 | 23 | SimpleSegTree(int _n) : n(_n), st(4 * n) {} 24 | 25 | SimpleSegTree(vector& v) : n((int)v.size()), st(4 * n) { 26 | build(v, 1, 0, n - 1); 27 | } 28 | 29 | void build(vector& v, int p, int l, int r) { 30 | if (l == r) { st[p] = T(v[l]); return; } 31 | int mid = (l + r) / 2; 32 | build(v, 2 * p, l, mid); 33 | build(v, 2 * p + 1, mid + 1, r); 34 | st[p] = T(st[2 * p], st[2 * p + 1]); 35 | } 36 | 37 | T query(int i, int j, int p, int l, int r) { 38 | if (l >= i and j >= r) return st[p]; 39 | if (l > j or r < i) return T(); 40 | int mid = (l + r) / 2; 41 | return T(query(i, j, 2 * p, l, mid), query(i, j, 2 * p + 1, mid + 1, r)); 42 | } 43 | 44 | T query(int i, int j) { return query(i, j, 1, 0, n - 1); } 45 | 46 | void update(int idx, U v, int p, int l, int r) { 47 | if (l == r) { st[p] = T(v); return; } 48 | int mid = (l + r) / 2; 49 | if (idx <= mid) update(idx, v, 2 * p, l, mid); 50 | else update(idx, v, 2 * p + 1, mid + 1, r); 51 | st[p] = T(st[2 * p], st[2 * p + 1]); 52 | } 53 | 54 | void update(int idx, U v) { update(idx, v, 1, 0, n - 1); } 55 | }; 56 | -------------------------------------------------------------------------------- /data-structures/set_of_intervals.cpp: -------------------------------------------------------------------------------- 1 | // Set of Intervals 2 | // Use when you have disjoint intervals 3 | 4 | #include 5 | using namespace std; 6 | 7 | const int N = 2e5 + 5; 8 | 9 | #define pb push_back 10 | #define st first 11 | #define nd second 12 | 13 | typedef pair pii; 14 | typedef pair piii; 15 | 16 | int n, m, x, t; 17 | set s; 18 | set mosq; 19 | vector frogs; 20 | int c[N], len[N], p, b[N]; 21 | 22 | void in(int l, int r, int i) { 23 | vector add, rem; 24 | auto it = s.lower_bound({{l, 0}, 0}); 25 | if(it != s.begin()) it--; 26 | for(; it != s.end(); it++) { 27 | int ll = it->st.st; 28 | int rr = it->st.nd; 29 | int idx = it->nd; 30 | 31 | if(ll > r) break; 32 | if(rr < l) continue; 33 | if(ll < l) add.pb({{ll, l-1}, idx}); 34 | if(rr > r) add.pb({{r+1, rr}, idx}); 35 | rem.pb(*it); 36 | } 37 | add.pb({{l, r}, i}); 38 | for(auto x : rem) s.erase(x); 39 | for(auto x : add) s.insert(x); 40 | } 41 | 42 | void process(int l, int idx) { 43 | auto it2 = s.lower_bound({{l, 0}, 0}); 44 | if(it2 != s.begin()) it2--; 45 | if(it2 != s.end() and it2->st.nd < l) it2++; 46 | 47 | mosq.insert({l, idx}); 48 | if(it2 == s.end() or !(it2->nd)) return; 49 | 50 | vector rem; 51 | int ll = it2->st.st, rr = it2->st.nd, id = it2->nd; 52 | 53 | auto it = mosq.lower_bound({ll, 0}); 54 | for(; it != mosq.end(); it++) { 55 | if(it->st > rr) break; 56 | c[id]++; 57 | len[id] += b[it->nd]; 58 | rr += b[it->nd]; 59 | rem.pb(*it); 60 | } 61 | for(auto x : rem) mosq.erase(x); 62 | in(ll, rr, id); 63 | } 64 | 65 | int main() { 66 | ios_base::sync_with_stdio(0), cin.tie(0); 67 | cin >> n >> m; 68 | for(int i = 1; i <= n; i++) { 69 | cin >> x >> t; 70 | len[i] = t; 71 | frogs.push_back({{x, x+t}, i}); 72 | } 73 | s.insert({{0, int(1e9)}, 0}); 74 | sort(frogs.begin(), frogs.end()); 75 | for(int i = frogs.size() - 1; i >= 0; i--) 76 | in(frogs[i].st.st, frogs[i].st.nd, frogs[i].nd); 77 | 78 | for(int i = 1; i <= m; i++) { 79 | cin >> p >> b[i]; 80 | process(p, i); 81 | } 82 | 83 | for(int i = 1; i <= n; i++) cout << c[i] << " " << len[i] << "\n"; 84 | } 85 | -------------------------------------------------------------------------------- /data-structures/sparse.cpp: -------------------------------------------------------------------------------- 1 | const int N; 2 | const int M; //log2(N) 3 | int sparse[N][M]; 4 | 5 | void build() { 6 | for(int i = 0; i < n; i++) 7 | sparse[i][0] = v[i]; 8 | 9 | for(int j = 1; j < M; j++) 10 | for(int i = 0; i < n; i++) 11 | sparse[i][j] = 12 | i + (1 << j - 1) < n 13 | ? min(sparse[i][j - 1], sparse[i + (1 << j - 1)][j - 1]) 14 | : sparse[i][j - 1]; 15 | } 16 | 17 | int query(int a, int b){ 18 | int pot = 32 - __builtin_clz(b - a) - 1; 19 | return min(sparse[a][pot], sparse[b - (1 << pot) + 1][pot]); 20 | } 21 | -------------------------------------------------------------------------------- /data-structures/sparse2d.cpp: -------------------------------------------------------------------------------- 1 | // 2D Sparse Table - 2 | const int N = 1e3+1, M = 10; 3 | int t[N][N], v[N][N], dp[M][M][N][N], lg[N], n, m; 4 | 5 | void build() { 6 | int k = 0; 7 | for(int i=1; ir) 31 | { 32 | tree[node].max=-maxlongint; 33 | return; 34 | } 35 | int xl=maxlongint,xr=-maxlongint; 36 | int yl=maxlongint,yr=-maxlongint; 37 | int zl=maxlongint,zr=-maxlongint,maxc=-maxlongint; 38 | for (int i=l;i<=r;i++) 39 | xl=min(xl,x[i]),xr=max(xr,x[i]), 40 | yl=min(yl,y[i]),yr=max(yr,y[i]), 41 | zl=min(zl,z[i]),zr=max(zr,z[i]), 42 | maxc=max(maxc,wei[i]), 43 | xc[i]=x[i],yc[i]=y[i],zc[i]=z[i],wc[i]=wei[i],biao[i]=i; 44 | tree[node].flag=flag; 45 | tree[node].xl=xl,tree[node].xr=xr,tree[node].yl=yl; 46 | tree[node].yr=yr,tree[node].zl=zl,tree[node].zr=zr; 47 | tree[node].max=maxc; 48 | if (l==r) return; 49 | if (flag==0) sort(biao+l,biao+r+1,cmp1); 50 | if (flag==1) sort(biao+l,biao+r+1,cmp2); 51 | if (flag==2) sort(biao+l,biao+r+1,cmp3); 52 | for (int i=l;i<=r;i++) 53 | x[i]=xc[biao[i]],y[i]=yc[biao[i]], 54 | z[i]=zc[biao[i]],wei[i]=wc[biao[i]]; 55 | makekdtree(node*2,l,(l+r)/2,(flag+1)%3); 56 | makekdtree(node*2+1,(l+r)/2+1,r,(flag+1)%3); 57 | } 58 | 59 | int getmax(int node,int xl,int xr,int yl,int yr,int zl,int zr) 60 | { 61 | xl=max(xl,tree[node].xl); 62 | xr=min(xr,tree[node].xr); 63 | yl=max(yl,tree[node].yl); 64 | yr=min(yr,tree[node].yr); 65 | zl=max(zl,tree[node].zl); 66 | zr=min(zr,tree[node].zr); 67 | if (tree[node].max==-maxlongint) return 0; 68 | if ((xrtree[node].xr)) return 0; 69 | if ((yrtree[node].yr)) return 0; 70 | if ((zrtree[node].zr)) return 0; 71 | if ((tree[node].xl==xl)&&(tree[node].xr==xr)&& 72 | (tree[node].yl==yl)&&(tree[node].yr==yr)&& 73 | (tree[node].zl==zl)&&(tree[node].zr==zr)) 74 | return tree[node].max; 75 | else 76 | return max(getmax(node*2,xl,xr,yl,yr,zl,zr), 77 | getmax(node*2+1,xl,xr,yl,yr,zl,zr)); 78 | } 79 | 80 | int main() 81 | { 82 | // N 3D-rect with weights 83 | // find the maximum weight containing the given 3D-point 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /data-structures/trie.cpp: -------------------------------------------------------------------------------- 1 | // Trie 2 | int trie[N][26], trien = 1; 3 | 4 | int add(int u, char c){ 5 | c-='a'; 6 | if (trie[u][c]) return trie[u][c]; 7 | return trie[u][c] = ++trien; 8 | } 9 | 10 | //to add a string s in the trie 11 | int u = 1; 12 | for(char c : s) u = add(u, c); 13 | -------------------------------------------------------------------------------- /data-structures/union_find.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************** 2 | * DSU (DISJOINT SET UNION / UNION-FIND) * 3 | * Time complexity: Unite - O(alpha n) * 4 | * Find - O(alpha n) * 5 | * Usage: find(node), unite(node1, node2), sz[find(node)] * 6 | * Notation: par: vector of parents * 7 | * sz: vector of subsets sizes, i.e. size of the subset a node is in * 8 | **********************************************************************************/ 9 | 10 | int par[N], sz[N]; 11 | 12 | int find(int a) { return par[a] == a ? a : par[a] = find(par[a]); } 13 | 14 | void unite(int a, int b) { 15 | if ((a = find(a)) == (b = find(b))) return; 16 | if (sz[a] < sz[b]) swap(a, b); 17 | par[b] = a; sz[a] += sz[b]; 18 | } 19 | 20 | // in main 21 | for (int i = 1; i <= n; i++) par[i] = i, sz[i] = 1; 22 | -------------------------------------------------------------------------------- /data-structures/union_find_partial_persistent.cpp: -------------------------------------------------------------------------------- 1 | 2 | // DSU (DISJOINT SET UNION / UNION-FIND) 3 | // Time complexity: Unite - O(log n) 4 | // Find - O(log n) 5 | // Usage: find(node), unite(node1, node2), sz[find(node)] 6 | // Notation: par: vector of parents 7 | // sz: vector of subsets sizes, i.e. size of the subset a node is in 8 | // his: history: time when it got a new parent 9 | // t: current time 10 | int t, par[N], sz[N], his[N]; 11 | 12 | int find(int a, int t){ 13 | if(par[a] == a) return a; 14 | if(his[a] > t) return a; 15 | return find(par[a], t); 16 | } 17 | 18 | void unite(int a, int b){ 19 | if(find(a, t) == find(b, t)) return; 20 | a = find(a, t), b = find(b, t), t++; 21 | if(sz[a] < sz[b]) swap(a, b); 22 | sz[a] += sz[b], par[b] = a, his[b] = t; 23 | } 24 | 25 | //in main 26 | for(int i = 0; i < N; i++) par[i] = i, sz[i] = 1, his[i] = 0; 27 | -------------------------------------------------------------------------------- /data-structures/union_find_rollback.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************** 2 | * DSU (DISJOINT SET UNION / UNION-FIND) * 3 | * Time complexity: Unite - O(alpha n) * 4 | * Rollback - O(1) * 5 | * Find - O(alpha n) * 6 | * Usage: find(node), unite(node1, node2), sz[find(node)] * 7 | * Notation: par: vector of parents * 8 | * sz: vector of subsets sizes, i.e. size of the subset a node is in * 9 | * sp: stack containing node and par from last op * 10 | * ss: stack containing node and size from last op * 11 | **********************************************************************************/ 12 | 13 | int par[N], sz[N]; 14 | stack sp, ss; 15 | 16 | int find (int a) { return par[a] == a ? a : find(par[a]); } 17 | 18 | void unite (int a, int b) { 19 | if ((a = find(a)) == (b = find(b))) return; 20 | if (sz[a] < sz[b]) swap(a, b); 21 | ss.push({a, sz[a]}); 22 | sp.push({b, par[b]}); 23 | sz[a] += sz[b]; 24 | par[b] = a; 25 | } 26 | 27 | void rollback() { 28 | par[sp.top().st] = sp.top().nd; sp.pop(); 29 | sz[ss.top().st] = ss.top().nd; ss.pop(); 30 | } 31 | 32 | int main(){ 33 | for (int i = 0; i < N; i++) par[i] = i, sz[i] = 1; 34 | return 0; 35 | } -------------------------------------------------------------------------------- /dynamic-programming/SOS.cpp: -------------------------------------------------------------------------------- 1 | // O(N * 2^N) 2 | // A[i] = initial values 3 | // Calculate F[i] = Sum of A[j] for j subset of i 4 | for(int i = 0; i < (1 << N); i++) 5 | F[i] = A[i]; 6 | for(int i = 0; i < N; i++) 7 | for(int j = 0; j < (1 << N); j++) 8 | if(j & (1 << i)) 9 | F[j] += F[j ^ (1 << i)]; 10 | -------------------------------------------------------------------------------- /dynamic-programming/convex_hull_trick.cpp: -------------------------------------------------------------------------------- 1 | // Convex Hull Trick 2 | 3 | // ATTENTION: This is the maximum convex hull. If you need the minimum 4 | // CHT use {-b, -m} and modify the query function. 5 | 6 | // In case of floating point parameters swap long long with long double 7 | typedef long long type; 8 | struct line { type b, m; }; 9 | 10 | line v[N]; // lines from input 11 | int n; // number of lines 12 | // Sort slopes in ascending order (in main): 13 | sort(v, v+n, [](line s, line t){ 14 | return (s.m == t.m) ? (s.b < t.b) : (s.m < t.m); }); 15 | 16 | // nh: number of lines on convex hull 17 | // pos: position for linear time search 18 | // hull: lines in the convex hull 19 | int nh, pos; 20 | line hull[N]; 21 | 22 | bool check(line s, line t, line u) { 23 | // verify if it can overflow. If it can just divide using long double 24 | return (s.b - t.b)*(u.m - s.m) < (s.b - u.b)*(t.m - s.m); 25 | } 26 | 27 | // Add new line to convex hull, if possible 28 | // Must receive lines in the correct order, otherwise it won't work 29 | void update(line s) { 30 | // 1. if first lines have the same b, get the one with bigger m 31 | // 2. if line is parallel to the one at the top, ignore 32 | // 3. pop lines that are worse 33 | // 3.1 if you can do a linear time search, use 34 | // 4. add new line 35 | 36 | if (nh == 1 and hull[nh-1].b == s.b) nh--; 37 | if (nh > 0 and hull[nh-1].m >= s.m) return; 38 | while (nh >= 2 and !check(hull[nh-2], hull[nh-1], s)) nh--; 39 | pos = min(pos, nh); 40 | hull[nh++] = s; 41 | } 42 | 43 | type eval(int id, type x) { return hull[id].b + hull[id].m * x; } 44 | 45 | // Linear search query - O(n) for all queries 46 | // Only possible if the queries always move to the right 47 | type query(type x) { 48 | while (pos+1 < nh and eval(pos, x) < eval(pos+1, x)) pos++; 49 | return eval(pos, x); 50 | // return -eval(pos, x); ATTENTION: Uncomment for minimum CHT 51 | } 52 | 53 | // Ternary search query - O(logn) for each query 54 | /* 55 | type query(type x) { 56 | int lo = 0, hi = nh-1; 57 | while (lo < hi) { 58 | int mid = (lo+hi)/2; 59 | if (eval(mid, x) > eval(mid+1, x)) hi = mid; 60 | else lo = mid+1; 61 | } 62 | return eval(lo, x); 63 | // return -eval(lo, x); ATTENTION: Uncomment for minimum CHT 64 | } 65 | 66 | // better use geometry line_intersect (this assumes s and t are not parallel) 67 | ld intersect_x(line s, line t) { return (t.b - s.b)/(ld)(s.m - t.m); } 68 | ld intersect_y(line s, line t) { return s.b + s.m * intersect_x(s, t); } 69 | */ 70 | -------------------------------------------------------------------------------- /dynamic-programming/convex_hull_trick_emaxx.cpp: -------------------------------------------------------------------------------- 1 | struct Point{ 2 | ll x, y; 3 | Point(ll x = 0, ll y = 0):x(x), y(y) {} 4 | Point operator-(Point p){ return Point(x - p.x, y - p.y); } 5 | Point operator+(Point p){ return Point(x + p.x, y + p.y); } 6 | Point ccw(){ return Point(-y, x); } 7 | ll operator%(Point p){ return x*p.y - y*p.x; } 8 | ll operator*(Point p){ return x*p.x + y*p.y; } 9 | bool operator<(Point p) const { return x == p.x ? y < p.y : x < p.x; } 10 | }; 11 | 12 | pair, vector> ch(Point *v){ 13 | vector hull, vecs; 14 | for(int i = 0; i < n; i++){ 15 | if(hull.size() and hull.back().x == v[i].x) continue; 16 | 17 | while(vecs.size() and vecs.back()*(v[i] - hull.back()) <= 0) 18 | vecs.pop_back(), hull.pop_back(); 19 | 20 | if(hull.size()) 21 | vecs.pb((v[i] - hull.back()).ccw()); 22 | 23 | hull.pb(v[i]); 24 | } 25 | return {hull, vecs}; 26 | } 27 | 28 | ll get(ll x) { 29 | Point query = {x, 1}; 30 | auto it = lower_bound(vecs.begin(), vecs.end(), query, [](Point a, Point b) { 31 | return a%b > 0; 32 | }); 33 | return query*hull[it - vecs.begin()]; 34 | } 35 | -------------------------------------------------------------------------------- /dynamic-programming/divide_and_conquer_optimization.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************** 2 | * DIVIDE AND CONQUER OPTIMIZATION ( dp[i][k] = min j r) return; 21 | 22 | ll mid = (l+r)/2; 23 | //best : cost, pos 24 | pair best = {LINF,-1}; 25 | 26 | //searchs best: lower bound to right, upper bound to left 27 | for(ll i = optl; i <= min(mid, optr); i++){ 28 | best = min(best, {dp[i][k-1] + C(i,mid), i}); 29 | } 30 | dp[mid][k] = best.first; 31 | ll opt = best.second; 32 | 33 | compute(l, mid-1, k, optl, opt); 34 | compute(mid + 1, r, k, opt, optr); 35 | } 36 | 37 | //Iterate over k to calculate 38 | ll solve(){ 39 | //dimensions of dp[N][K] 40 | int n, k; 41 | 42 | //Initialize DP 43 | for(ll i = 1; i <= n; i++){ 44 | //dp[i,1] = cost from 0 to i 45 | dp[i][1] = C(0, i); 46 | } 47 | 48 | for(ll l = 2; l <= k; l++){ 49 | compute(1, n, l, 1, n); 50 | } 51 | 52 | /*+ Iterate over i to get min{dp[i][k]}, don't forget cost from n to i 53 | for(ll i=1;i<=n;i++){ 54 | ll rest = ; 55 | ans = min(ans,dp[i][k] + rest); 56 | } 57 | */ 58 | } 59 | 60 | -------------------------------------------------------------------------------- /dynamic-programming/knuth_optimization.cpp: -------------------------------------------------------------------------------- 1 | // Knuth DP Optimization - O(n^3) -> O(n^2) 2 | // 3 | // 1) dp[i][j] = min i= 1; --i){ 31 | for (int k = a[i][j-1]; k <= a[i+1][j]; ++k) { 32 | ll v = dp[i][k] + dp[k][j] + cost(i, j); 33 | 34 | // store the minimum answer for d[i][k] 35 | // in case of maximum, use v > dp[i][k] 36 | if (v < dp[i][j]) 37 | a[i][j] = k, dp[i][j] = v; 38 | } 39 | //+ Iterate over i to get min{dp[i][j]} for each j, don't forget cost from n to 40 | } 41 | } 42 | 43 | 44 | // 2) dp[i][j] = min k= 1; i--){ 63 | for (int k = a[i][j-1]; k <= a[i+1][j]; k++) { 64 | ll v = dp[k][j-1] + cost(k, i); 65 | 66 | // store the minimum answer for d[i][k] 67 | // in case of maximum, use v > dp[i][k] 68 | if (v < dp[i][j]) 69 | a[i][j] = k, dp[i][j] = v; 70 | } 71 | //+ Iterate over i to get min{dp[i][j]} for each j, don't forget cost from n to 72 | } 73 | } -------------------------------------------------------------------------------- /dynamic-programming/lis.cpp: -------------------------------------------------------------------------------- 1 | // Longest Increasing Subsequence - O(nlogn) 2 | // 3 | // dp(i) = max j 0; ss = (ss - 1) & msk) 26 | dp[i][msk] = min(dp[i][msk], dp[i][ss] + dp[i][msk - ss]); 27 | 28 | if(dp[i][msk] != INF) 29 | for(int j = 1; j <= n; j++) 30 | dp[j][msk] = min(dp[j][msk], dp[i][msk] + dist[i][j]); 31 | } 32 | } 33 | 34 | int mn = INF; 35 | for(int i = 1; i <= n; i++) mn = min(mn, dp[i][(1 << t) - 1]); 36 | return mn; 37 | } 38 | -------------------------------------------------------------------------------- /e-maxx.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imeplusplus/icpc-notebook/d6db5cb0e077ed674fd16828f3c1e452a222d103/e-maxx.pdf -------------------------------------------------------------------------------- /flags.txt: -------------------------------------------------------------------------------- 1 | alias comp="g++ -g -Wall -Wextra -std=c++20 -pedantic -O2 -Wshadow -Wformat=2 -Wfloat-equal -Wconversion -Wlogical-op -Wno-sign-compare -Wno-char-subscripts -Wshift-overflow=2 -Wduplicated-cond -Wcast-qual -Wcast-align -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC -D_FORTIFY_SOURCE=2 -fsanitize=address,undefined -fno-sanitize-recover -fstack-protector -fno-omit-frame-pointer -Wno-unused-result" -------------------------------------------------------------------------------- /generate_pdf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import subprocess 3 | code_dir = "./" 4 | title = "IME++ ACM-ICPC Team Notebook" 5 | 6 | def get_sections(): 7 | sections = [] 8 | section_name = None 9 | with open('contents.txt', 'r') as f: 10 | for line in f: 11 | if '#' in line: line = line[:line.find('#')] 12 | line = line.strip() 13 | if len(line) == 0: continue 14 | if line[0] == '[': 15 | section_name = line[1:-1] 16 | subsections = [] 17 | if section_name is not None: 18 | sections.append((section_name, subsections)) 19 | else: 20 | tmp = line.split('\t', 1) 21 | if len(tmp) == 1: 22 | raise ValueError('Subsection parse error: %s' % line) 23 | filename = tmp[0] 24 | subsection_name = tmp[1] 25 | if section_name is None: 26 | raise ValueError('Subsection given without section') 27 | subsections.append((filename, subsection_name)) 28 | return sections 29 | 30 | def get_style(filename): 31 | ext = filename.lower().split('.')[-1] 32 | if ext in ['c', 'cc', 'cpp']: 33 | return 'cpp' 34 | elif ext in ['java']: 35 | return 'java' 36 | elif ext in ['py']: 37 | return 'py' 38 | else: 39 | return 'txt' 40 | 41 | # TODO: check if this is everything we need 42 | def texify(s): 43 | #s = s.replace('\'', '\\\'') 44 | #s = s.replace('\"', '\\\"') 45 | return s 46 | 47 | def get_tex(sections): 48 | tex = '' 49 | for (section_name, subsections) in sections: 50 | tex += '\\section{%s}\n' % texify(section_name) 51 | for (filename, subsection_name) in subsections: 52 | tex += '\\subsection{%s}\n' % texify(subsection_name) 53 | tex += '\\raggedbottom\\lstinputlisting[style=%s]{%s/%s}\n' % (get_style(filename), code_dir, filename) 54 | tex += '\\hrulefill\n' 55 | tex += '\n' 56 | return tex 57 | 58 | if __name__ == "__main__": 59 | sections = get_sections() 60 | tex = get_tex(sections) 61 | with open('contents.tex', 'w') as f: 62 | f.write(tex) 63 | latexmk_options = ["latexmk", "-pdf", "notebook.tex"] 64 | subprocess.call(latexmk_options) 65 | -------------------------------------------------------------------------------- /geometry/circle.cpp: -------------------------------------------------------------------------------- 1 | #include "basics.cpp" 2 | #include "lines.cpp" 3 | 4 | struct circle { 5 | point c; 6 | ld r; 7 | circle() { c = point(); r = 0; } 8 | circle(point _c, ld _r) : c(_c), r(_r) {} 9 | ld area() { return acos(-1.0)*r*r; } 10 | ld chord(ld rad) { return 2*r*sin(rad/2.0); } 11 | ld sector(ld rad) { return 0.5*rad*area()/acos(-1.0); } 12 | bool intersects(circle other) { 13 | return le(c.dist(other.c), r + other.r); 14 | } 15 | bool contains(point p) { return le(c.dist(p), r); } 16 | pair getTangentPoint(point p) { 17 | ld d1 = c.dist(p), theta = asin(r/d1); 18 | point p1 = (c - p).rotate(-theta); 19 | point p2 = (c - p).rotate(theta); 20 | p1 = p1*(sqrt(d1*d1 - r*r)/d1) + p; 21 | p2 = p2*(sqrt(d1*d1 - r*r)/d1) + p; 22 | return make_pair(p1,p2); 23 | } 24 | }; 25 | 26 | circle circumcircle(point a, point b, point c) { 27 | circle ans; 28 | point u = point((b - a).y, -(b - a).x); 29 | point v = point((c - a).y, -(c - a).x); 30 | point n = (c - b)*0.5; 31 | ld t = cross(u,n)/cross(v,u); 32 | ans.c = ((a + c)*0.5) + (v*t); 33 | ans.r = ans.c.dist(a); 34 | return ans; 35 | } 36 | 37 | point compute_circle_center(point a, point b, point c) { 38 | //circumcenter 39 | b = (a + b)/2; 40 | c = (a + c)/2; 41 | return compute_line_intersection(b, b + rotate_cw90(a - b), c, c + rotate_cw90(a - c)); 42 | } 43 | 44 | int inside_circle(point p, circle c) { 45 | if (fabs(p.dist(c.c) - c.r) p) { 61 | random_shuffle(p.begin(), p.end()); 62 | circle C = circle(p[0], 0.0); 63 | for(int i = 0; i < (int)p.size(); i++) { 64 | if (C.contains(p[i])) continue; 65 | C = circle(p[i], 0.0); 66 | for(int j = 0; j < i; j++) { 67 | if (C.contains(p[j])) continue; 68 | C = circle((p[j] + p[i])*0.5, 0.5*p[j].dist(p[i])); 69 | for(int k = 0; k < j; k++) { 70 | if (C.contains(p[k])) continue; 71 | C = circumcircle(p[j], p[i], p[k]); 72 | } 73 | } 74 | } 75 | return C; 76 | } 77 | 78 | // compute intersection of line through points a and b with 79 | // circle centered at c with radius r > 0 80 | vector circle_line_intersection(point a, point b, point c, ld r) { 81 | vector ret; 82 | b = b - a; 83 | a = a - c; 84 | ld A = dot(b, b); 85 | ld B = dot(a, b); 86 | ld C = dot(a, a) - r*r; 87 | ld D = B*B - A*C; 88 | if (D < -EPS) return ret; 89 | ret.push_back(c + a + b*(sqrt(D + EPS) - B)/A); 90 | if (D > EPS) 91 | ret.push_back(c + a + b*(-B - sqrt(D))/A); 92 | return ret; 93 | } 94 | 95 | vector circle_circle_intersection(point a, point b, ld r, ld R) { 96 | vector ret; 97 | ld d = sqrt(a.dist2(b)); 98 | if (d > r + R || d + min(r, R) < max(r, R)) return ret; 99 | ld x = (d*d - R*R + r*r)/(2*d); 100 | ld y = sqrt(r*r - x*x); 101 | point v = (b - a)/d; 102 | ret.push_back(a + v*x + rotate_ccw90(v)*y); 103 | if (y > 0) 104 | ret.push_back(a + v*x - rotate_ccw90(v)*y); 105 | return ret; 106 | } 107 | 108 | //GREAT CIRCLE 109 | 110 | double gcTheta(double pLat, double pLong, double qLat, double qLong) { 111 | pLat *= acos(-1.0) / 180.0; pLong *= acos(-1.0) / 180.0; // convert degree to radian 112 | qLat *= acos(-1.0) / 180.0; qLong *= acos(-1.0) / 180.0; 113 | return acos(cos(pLat)*cos(pLong)*cos(qLat)*cos(qLong) + 114 | cos(pLat)*sin(pLong)*cos(qLat)*sin(qLong) + 115 | sin(pLat)*sin(qLat)); 116 | } 117 | 118 | double gcDistance(double pLat, double pLong, double qLat, double qLong, double radius) { 119 | return radius*gcTheta(pLat, pLong, qLat, qLong); 120 | } 121 | 122 | 123 | /* 124 | * Codeforces 101707B 125 | */ 126 | /* 127 | point A, B; 128 | circle C; 129 | 130 | double getd2(point a, point b) { 131 | double h = dist(a, b); 132 | double r = C.r; 133 | double alpha = asin(h/(2*r)); 134 | while (alpha < 0) alpha += 2*acos(-1.0); 135 | return dist(a, A) + dist(b, B) + r*2*min(alpha, 2*acos(-1.0) - alpha); 136 | } 137 | 138 | int main() { 139 | scanf("%lf %lf", &A.x, &A.y); 140 | scanf("%lf %lf", &B.x, &B.y); 141 | scanf("%lf %lf %lf", &C.c.x, &C.c.y, &C.r); 142 | double ans; 143 | if (distToLineSegment(C.c, A, B) >= C.r) { 144 | ans = dist(A, B); 145 | } 146 | else { 147 | pair tan1 = C.getTangentPoint(A); 148 | pair tan2 = C.getTangentPoint(B); 149 | ans = 1e+30; 150 | ans = min(ans, getd2(tan1.first, tan2.first)); 151 | ans = min(ans, getd2(tan1.first, tan2.second)); 152 | ans = min(ans, getd2(tan1.second, tan2.first)); 153 | ans = min(ans, getd2(tan1.second, tan2.second)); 154 | } 155 | printf("%.18f\n", ans); 156 | return 0; 157 | }*/ -------------------------------------------------------------------------------- /geometry/closest_pair.cpp: -------------------------------------------------------------------------------- 1 | #include "basics.cpp" 2 | //DIVIDE AND CONQUER METHOD 3 | //Warning: include variable id into the struct point 4 | 5 | struct cmp_y { 6 | bool operator()(const point & a, const point & b) const { 7 | return a.y < b.y; 8 | } 9 | }; 10 | 11 | ld min_dist = LINF; 12 | pair best_pair; 13 | vector pts, stripe; 14 | int n; 15 | 16 | void upd_ans(const point & a, const point & b) { 17 | ld dist = sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y)); 18 | if (dist < min_dist) { 19 | min_dist = dist; 20 | /* 21 | Warning: 22 | if you want to know which points forms the closest pair, include variable id into the struct point 23 | and uncomment the line below 24 | */ 25 | // best_pair = {a.id, b.id}; 26 | } 27 | } 28 | 29 | void closest_pair(int l, int r) { 30 | if (r - l <= 3) { 31 | for (int i = l; i < r; ++i) { 32 | for (int j = i + 1; j < r; ++j) { 33 | upd_ans(pts[i], pts[j]); 34 | } 35 | } 36 | sort(pts.begin() + l, pts.begin() + r, cmp_y()); 37 | return; 38 | } 39 | 40 | int m = (l + r) >> 1; 41 | type midx = pts[m].x; 42 | closest_pair(l, m); 43 | closest_pair(m, r); 44 | 45 | merge(pts.begin() + l, pts.begin() + m, pts.begin() + m, pts.begin() + r, stripe.begin(), cmp_y()); 46 | copy(stripe.begin(), stripe.begin() + r - l, pts.begin() + l); 47 | 48 | int stripe_sz = 0; 49 | for (int i = l; i < r; ++i) { 50 | if (abs(pts[i].x - midx) < min_dist) { 51 | for (int j = stripe_sz - 1; j >= 0 && pts[i].y - stripe[j].y < min_dist; --j) 52 | upd_ans(pts[i], stripe[j]); 53 | stripe[stripe_sz++] = pts[i]; 54 | } 55 | } 56 | } 57 | 58 | int main(){ 59 | //read and save in vector pts 60 | min_dist = LINF; 61 | stripe.resize(n); 62 | sort(pts.begin(), pts.end()); 63 | closest_pair(0, n); 64 | } 65 | 66 | 67 | //LINE SWEEP 68 | int n; //amount of points 69 | point pnt[N]; 70 | 71 | struct cmp_y { 72 | bool operator()(const point & a, const point & b) const { 73 | if(a.y == b.y) return a.x < b.x; 74 | return a.y < b.y; 75 | } 76 | }; 77 | 78 | ld closest_pair() { 79 | sort(pnt, pnt+n); 80 | ld best = numeric_limits::infinity(); 81 | set box; 82 | 83 | box.insert(pnt[0]); 84 | int l = 0; 85 | 86 | for (int i = 1; i < n; i++){ 87 | while(l < i and pnt[i].x - pnt[l].x > best) 88 | box.erase(pnt[l++]); 89 | for(auto it = box.lower_bound({0, pnt[i].y - best}); it != box.end() and pnt[i].y + best >= it->y; it++) 90 | best = min(best, hypot(pnt[i].x - it->x, pnt[i].y - it->y)); 91 | box.insert(pnt[i]); 92 | } 93 | return best; 94 | } 95 | 96 | -------------------------------------------------------------------------------- /geometry/closest_pair_3d.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | The algorithm below calculates the closest pair of points for 3 dimensional points 3 | */ 4 | 5 | #include 6 | 7 | using namespace std; 8 | 9 | #define st first 10 | #define nd second 11 | 12 | typedef long long ll; 13 | typedef long double ld; 14 | typedef pair pll; 15 | 16 | const ld EPS = 1e-9, PI = acos(-1.); 17 | const ll LINF = 0x3f3f3f3f3f3f3f3f; 18 | const int N = 1e5+5; 19 | 20 | typedef long long type; 21 | 22 | struct point { 23 | type x, y, z; 24 | 25 | point() : x(0), y(0), z(0) {} 26 | point(type _x, type _y, type _z) : x(_x), y(_y) , z(_z) {} 27 | 28 | point operator -() { return point(-x, -y, -z); } 29 | point operator +(point p) { return point(x + p.x, y + p.y, z + p.z); } 30 | point operator -(point p) { return point(x - p.x, y - p.y, z - p.z); } 31 | 32 | point operator *(type k) { return point(x*k, y*k, z*k); } 33 | point operator /(type k) { return point(x/k, y/k, z/k); } 34 | 35 | bool operator ==(const point &p) const{ return x == p.x and y == p.y and z == p.z; } 36 | bool operator !=(const point &p) const{ return x != p.x or y != p.y or z != p.z; } 37 | bool operator <(const point &p) const { return (z < p.z) or (z == p.z and y < p.y) or (z == p.z and y == p.y and x < p.x); } 38 | 39 | type abs2() { return x*x + y*y + z*z; } 40 | type dist2(point q) { return (*this - q).abs2(); } 41 | 42 | }; 43 | 44 | ll cfloor(ll a, ll b) { 45 | ll c = abs(a); 46 | ll d = abs(b); 47 | if (a * b > 0) return c/d; 48 | return -(c + d - 1)/d; 49 | } 50 | 51 | ll min_dist = LINF; 52 | pair best_pair; 53 | vector pts; 54 | int n; 55 | 56 | void upd_ans(const point & a, const point & b) { 57 | ll dist = (a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y) + (a.z - b.z)*(a.z - b.z); 58 | if (dist < min_dist) { 59 | min_dist = dist; 60 | /* 61 | Warning: 62 | if you want to know which points forms the closest pair, include variable id into the struct point 63 | and uncomment the line below 64 | */ 65 | // best_pair = {a.id, b.id}; 66 | } 67 | } 68 | 69 | void closest_pair(int l, int r) { 70 | if (r - l <= 3) { 71 | for (int i = l; i < r; ++i) { 72 | for (int j = i + 1; j < r; ++j) { 73 | upd_ans(pts[i], pts[j]); 74 | } 75 | } 76 | return; 77 | } 78 | 79 | int m = (l + r) >> 1; 80 | type midz = pts[m].z; 81 | closest_pair(l, m); 82 | closest_pair(m, r); 83 | 84 | //map opposite side 85 | map> f; 86 | for(int i = m; i < r; i++){ 87 | f[{cfloor(pts[i].x, min_dist), cfloor(pts[i].y, min_dist)}].push_back(i); 88 | } 89 | //find 90 | for(int i = l; i < m; i++){ 91 | if((midz - pts[i].z) * (midz - pts[i].z) >= min_dist) continue; 92 | 93 | pll cur = {cfloor(pts[i].x, min_dist), cfloor(pts[i].y, min_dist)}; 94 | for(int dx = -1; dx <= 1; dx++) 95 | for(int dy = -1; dy <= 1; dy++) 96 | for(auto p : f[{cur.st + dx, cur.nd + dy}]) 97 | min_dist = min(min_dist, pts[i].dist2(pts[p])); 98 | } 99 | } 100 | 101 | int main(){ 102 | ios_base::sync_with_stdio(false); 103 | cin.tie(NULL); 104 | cin >> n; 105 | pts.resize(n); 106 | for(int i = 0; i < n; i++) cin >> pts[i].x >> pts[i].y >> pts[i].z; 107 | sort(pts.begin(), pts.end()); 108 | closest_pair(0, n); 109 | cout << setprecision(15) << fixed << sqrt((ld)min_dist) << "\n"; 110 | return 0; 111 | } -------------------------------------------------------------------------------- /geometry/halfplane_intersection.cpp: -------------------------------------------------------------------------------- 1 | // Intersection of halfplanes - O(nlogn) 2 | // Points are given in counterclockwise order 3 | // 4 | // by Agnez 5 | 6 | typedef vector polygon; 7 | 8 | int cmp(ld x, ld y = 0, ld tol = EPS) { 9 | return (x <= y + tol) ? (x + tol < y) ? -1 : 0 : 1; } 10 | 11 | bool comp(point a, point b){ 12 | if((cmp(a.x) > 0 || (cmp(a.x) == 0 && cmp(a.y) > 0) ) && (cmp(b.x) < 0 || (cmp(b.x) == 0 && cmp(b.y) < 0))) return 1; 13 | if((cmp(b.x) > 0 || (cmp(b.x) == 0 && cmp(b.y) > 0) ) && (cmp(a.x) < 0 || (cmp(a.x) == 0 && cmp(a.y) < 0))) return 0; 14 | ll R = a%b; 15 | if(R) return R > 0; 16 | return false; 17 | } 18 | 19 | namespace halfplane{ 20 | struct L{ 21 | point p,v; 22 | L(){} 23 | L(point P, point V):p(P),v(V){} 24 | bool operator<(const L &b)const{ return comp(v, b.v); } 25 | }; 26 | vector line; 27 | void addL(point a, point b){line.pb(L(a,b-a));} 28 | bool left(point &p, L &l){ return cmp(l.v % (p-l.p))>0; } 29 | bool left_equal(point &p, L &l){ return cmp(l.v % (p-l.p))>=0; } 30 | void init(){ line.clear(); } 31 | 32 | point pos(L &a, L &b){ 33 | point x=a.p-b.p; 34 | ld t = (b.v % x)/(a.v % b.v); 35 | return a.p+a.v*t; 36 | } 37 | 38 | polygon intersect(){ 39 | sort(line.begin(), line.end()); 40 | deque q; //linhas da intersecao 41 | deque p; //pontos de intersecao entre elas 42 | q.push_back(line[0]); 43 | for(int i=1; i < (int) line.size(); i++){ 44 | while(q.size()>1 && !left(p.back(), line[i])) 45 | q.pop_back(), p.pop_back(); 46 | while(q.size()>1 && !left(p.front(), line[i])) 47 | q.pop_front(), p.pop_front(); 48 | if(!cmp(q.back().v % line[i].v) && !left(q.back().p,line[i])) 49 | q.back() = line[i]; 50 | else if(cmp(q.back().v % line[i].v)) 51 | q.push_back(line[i]), p.push_back(point()); 52 | if(q.size()>1) 53 | p.back()=pos(q.back(),q[q.size()-2]); 54 | } 55 | while(q.size()>1 && !left(p.back(),q.front())) 56 | q.pop_back(), p.pop_back(); 57 | if(q.size() <= 2) return polygon(); //Nao forma poligono (pode nao ter intersecao) 58 | if(!cmp(q.back().v % q.front().v)) return polygon(); //Lados paralelos -> area infinita 59 | point ult = pos(q.back(),q.front()); 60 | 61 | bool ok = 1; 62 | for(int i=0; i < (int) line.size(); i++) 63 | if(!left_equal(ult,line[i])){ ok=0; break; } 64 | 65 | if(ok) p.push_back(ult); //Se formar um poligono fechado 66 | polygon ret; 67 | for(int i=0; i < (int) p.size(); i++) 68 | ret.pb(p[i]); 69 | return ret; 70 | } 71 | }; 72 | 73 | // 74 | // Detect whether there is a non-empty intersection in a set of halfplanes 75 | // Complexity O(n) 76 | // 77 | // By Agnez 78 | // 79 | pair half_inter(vector > &vet){ 80 | random_shuffle(all(vet)); 81 | point p; 82 | rep(i,0,sz(vet)) if(ccw(vet[i].x,vet[i].y,p) != 1){ 83 | point dir = (vet[i].y-vet[i].x)/abs(vet[i].y-vet[i].x); 84 | point l = vet[i].x - dir*1e15; 85 | point r = vet[i].x + dir*1e15; 86 | if(r polygon; 7 | 8 | /* 9 | * Minkowski sum 10 | Distance between two polygons P and Q: 11 | Do Minkowski(P, Q) 12 | Ans = min(ans, dist((0, 0), edge)) 13 | */ 14 | 15 | polygon minkowski(polygon & A, polygon & B) { 16 | polygon P; point v1, v2; 17 | sort_lex_hull(A), sort_lex_hull(B); 18 | int n1 = A.size(), n2 = B.size(); 19 | P.push_back(A[0] + B[0]); 20 | for(int i = 0, j = 0; i < n1 || j < n2;) { 21 | v1 = A[(i + 1)%n1] - A[i%n1]; 22 | v2 = B[(j + 1)%n2] - B[j%n2]; 23 | if (j == n2 || cross(v1, v2) > EPS) { 24 | P.push_back(P.back() + v1); i++; 25 | } 26 | else if (i == n1 || cross(v1, v2) < -EPS) { 27 | P.push_back(P.back() + v2); j++; 28 | } 29 | else { 30 | P.push_back(P.back() + (v1 + v2)); 31 | i++; j++; 32 | } 33 | } 34 | P.pop_back(); 35 | sort_lex_hull(P); 36 | return P; 37 | } 38 | 39 | // Given two polygons, returns the minkowski sum of them. 40 | // 41 | // By Agnez 42 | bool comp(point a, point b){ 43 | if((a.x > 0 || (a.x==0 && a.y>0) ) && (b.x < 0 || (b.x==0 && b.y<0))) return 1; 44 | if((b.x > 0 || (b.x==0 && b.y>0) ) && (a.x < 0 || (a.x==0 && a.y<0))) return 0; 45 | ll R = a%b; 46 | if(R) return R > 0; 47 | return a*a < b*b; 48 | } 49 | 50 | polygon poly_sum(polygon a, polygon b){ 51 | //Lembre de nao ter pontos repetidos 52 | // passar poligonos ordenados 53 | // se nao tiver pontos colineares, pode usar: 54 | //pivot = *min_element(all(a)); 55 | //sort(all(a),radialcomp); 56 | //a.resize(unique(all(a))-a.begin()); 57 | //pivot = *min_element(all(b)); 58 | //sort(all(b),radialcomp); 59 | //b.resize(unique(all(b))-b.begin()); 60 | if(!sz(a) || !sz(b)) return polygon(0); 61 | if(min(sz(a),sz(b)) < 2){ 62 | polygon ret(0); 63 | rep(i,0,sz(a)) rep(j,0,sz(b)) ret.pb(a[i]+b[j]); 64 | return ret; 65 | } 66 | polygon ret; 67 | ret.pb(a[0]+b[0]); 68 | int pa = 0, pb = 0; 69 | while(pa < sz(a) || pb < sz(b)){ 70 | point p = ret.back(); 71 | if(pb == sz(b) || (pa < sz(a) && comp((a[(pa+1)%sz(a)]-a[pa]),(b[(pb+1)%sz(b)]-b[pb])))) 72 | p = p + (a[(pa+1)%sz(a)]-a[pa]), pa++; 73 | else p = p + (b[(pb+1)%sz(b)]-b[pb]), pb++; 74 | //descomentar para tirar pontos colineares (o poligono nao pode ser degenerado) 75 | // while(sz(ret) > 1 && !ccw(ret[sz(ret)-2], ret[sz(ret)-1], p)) 76 | // ret.pop_back(); 77 | ret.pb(p); 78 | } 79 | assert(ret.back() == ret[0]); 80 | ret.pop_back(); 81 | return ret; 82 | } 83 | -------------------------------------------------------------------------------- /geometry/misc.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 1) Square (n = 4) is the only regular polygon with integer coordinates 3 | 4 | 2) Pick's theorem: A = i + b/2 - 1 5 | A: area of the polygon 6 | i: number of interior points 7 | b: number of points on the border 8 | 9 | 3) Conic Rotations 10 | Given elipse: Ax^2 + Bxy + Cy^2 + Dx + Ey + F = 0 11 | Convert it to: Ax^2 + Bxy + Cy^2 + Dx + Ey = 1 (this formula suits better for elipse, before doing this verify F = 0) 12 | Final conversion: A(x + D/2A)^2 + C(y + E/2C)^2 = 1 + D^2/4A + E^2/4C 13 | B != 0 (Rotate): 14 | theta = atan2(b, c-a)/2.0; 15 | A' = (a + c + b/sin(2.0*theta))/2.0; // A 16 | C' = (a + c - b/sin(2.0*theta))/2.0; // C 17 | D' = d*sin(theta) + e*cos(theta); // D 18 | E' = d*cos(theta) - e*sin(theta); // E 19 | Remember to rotate again after! 20 | */ 21 | 22 | 23 | // determine if point is in a possibly non-convex polygon (by William 24 | // Randolph Franklin); returns 1 for strictly interior points, 0 for 25 | // strictly exterior points, and 0 or 1 for the remaining points. 26 | // Note that it is possible to convert this into an *exact* test using 27 | // integer arithmetic by taking care of the division appropriately 28 | // (making sure to deal with signs properly) and then by writing exact 29 | // tests for checking point on polygon boundary 30 | bool PointInPolygon(const vector &p, PT q) { 31 | bool c = 0; 32 | for (int i = 0; i < p.size(); i++){ 33 | int j = (i+1)%p.size(); 34 | if ((p[i].y <= q.y && q.y < p[j].y || 35 | p[j].y <= q.y && q.y < p[i].y) && 36 | q.x < p[i].x + (p[j].x - p[i].x) * (q.y - p[i].y) / (p[j].y - p[i].y)) 37 | c = !c; 38 | } 39 | return c; 40 | } -------------------------------------------------------------------------------- /geometry/nearest_neighbour.cpp: -------------------------------------------------------------------------------- 1 | // Closest Neighbor - O(n * log(n)) 2 | const ll N = 1e6+3, INF = 1e18; 3 | ll n, cn[N], x[N], y[N]; // number of points, closes neighbor, x coordinates, y coordinates 4 | 5 | ll sqr(ll i) { return i*i; } 6 | ll dist(int i, int j) { return sqr(x[i]-x[j]) + sqr(y[i]-y[j]); } 7 | ll dist(int i) { return i == cn[i] ? INF : dist(i, cn[i]); } 8 | 9 | bool cpx(int i, int j) { return x[i] < x[j] or (x[i] == x[j] and y[i] < y[j]); } 10 | bool cpy(int i, int j) { return y[i] < y[j] or (y[i] == y[j] and x[i] < x[j]); } 11 | 12 | ll calc(int i, ll x0) { 13 | ll dlt = dist(i) - sqr(x[i]-x0); 14 | return dlt >= 0 ? ceil(sqrt(dlt)) : -1; 15 | } 16 | 17 | void updt(int i, int j, ll x0, ll &dlt) { 18 | if (dist(i) > dist(i, j)) cn[i] = j, dlt = calc(i, x0); 19 | } 20 | 21 | void cmp(vi &u, vi &v, ll x0) { 22 | for(int a=0, b=0; a y[v[b]]) b++; 25 | for(int j = b-1; j >= 0 and y[i] - dlt <= y[v[j]]; j--) updt(i, v[j], x0, dlt); 26 | for(int j = b; j < v.size() and y[i] + dlt >= y[v[j]]; j++) updt(i, v[j], x0, dlt); 27 | } 28 | } 29 | 30 | void slv(vi &ix, vi &iy) { 31 | int n = ix.size(); 32 | if (n == 1) { cn[ix[0]] = ix[0]; return; } 33 | 34 | int m = ix[n/2]; 35 | 36 | vi ix1, ix2, iy1, iy2; 37 | for(int i=0; i 10 | [(-1, 0), (-1, -1), (0, -1), (1, 0), (1, 1), (0, 1)] 11 | */ 12 | 13 | // Don't forget to change origin! 14 | point origin; 15 | 16 | int above(point p){ 17 | if(p.y == origin.y) return p.x > origin.x; 18 | return p.y > origin.y; 19 | } 20 | 21 | bool cmp(point p, point q){ 22 | int tmp = above(q) - above(p); 23 | if(tmp) return tmp > 0; 24 | 25 | return p.dir(origin,q) > 0; 26 | //Be Careful: p.dir(origin,q) == 0 27 | } -------------------------------------------------------------------------------- /geometry/stanford_delaunay.cpp: -------------------------------------------------------------------------------- 1 | // Slow but simple Delaunay triangulation. Does not handle 2 | // degenerate cases (from O'Rourke, Computational Geometry in C) 3 | // 4 | // Running time: O(n^4) 5 | // 6 | // INPUT: x[] = x-coordinates 7 | // y[] = y-coordinates 8 | // 9 | // OUTPUT: triples = a vector containing m triples of indices 10 | // corresponding to triangle vertices 11 | 12 | #include 13 | using namespace std; 14 | 15 | typedef double T; 16 | 17 | struct triple { 18 | int i, j, k; 19 | triple() {} 20 | triple(int i, int j, int k) : i(i), j(j), k(k) {} 21 | }; 22 | 23 | vector delaunayTriangulation(vector& x, vector& y) { 24 | int n = x.size(); 25 | vector z(n); 26 | vector ret; 27 | 28 | for (int i = 0; i < n; i++) 29 | z[i] = x[i] * x[i] + y[i] * y[i]; 30 | 31 | for (int i = 0; i < n-2; i++) { 32 | for (int j = i+1; j < n; j++) { 33 | for (int k = i+1; k < n; k++) { 34 | if (j == k) continue; 35 | double xn = (y[j]-y[i])*(z[k]-z[i]) - (y[k]-y[i])*(z[j]-z[i]); 36 | double yn = (x[k]-x[i])*(z[j]-z[i]) - (x[j]-x[i])*(z[k]-z[i]); 37 | double zn = (x[j]-x[i])*(y[k]-y[i]) - (x[k]-x[i])*(y[j]-y[i]); 38 | bool flag = zn < 0; 39 | for (int m = 0; flag && m < n; m++) 40 | flag = flag && ((x[m]-x[i])*xn + 41 | (y[m]-y[i])*yn + 42 | (z[m]-z[i])*zn <= 0); 43 | if (flag) ret.push_back(triple(i, j, k)); 44 | } 45 | } 46 | } 47 | return ret; 48 | } 49 | 50 | int main() 51 | { 52 | T xs[]={0, 0, 1, 0.9}; 53 | T ys[]={0, 1, 0, 0.9}; 54 | vector x(&xs[0], &xs[4]), y(&ys[0], &ys[4]); 55 | vector tri = delaunayTriangulation(x, y); 56 | 57 | //expected: 0 1 3 58 | // 0 3 2 59 | 60 | int i; 61 | for(i = 0; i < tri.size(); i++) 62 | printf("%d %d %d\n", tri[i].i, tri[i].j, tri[i].k); 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /geometry/ternary_search.cpp: -------------------------------------------------------------------------------- 1 | //Ternary Search - O(log(n)) 2 | //Max version, for minimum version just change signals 3 | 4 | ll ternary_search(ll l, ll r){ 5 | while(r - l > 3) { 6 | ll m1 = (l+r)/2; 7 | ll m2 = (l+r)/2 + 1; 8 | ll f1 = f(m1), f2 = f(m2); 9 | //if(f1 > f2) l = m1; 10 | if (f1 < f2) l = m1; 11 | else r = m2; 12 | } 13 | ll ans = 0; 14 | for(int i = l; i <= r; i++){ 15 | ll tmp = f(i); 16 | //ans = min(ans, tmp); 17 | ans = max(ans, tmp); 18 | } 19 | return ans; 20 | } 21 | 22 | //Faster version - 300 iteratons up to 1e-6 precision 23 | double ternary_search(double l, double r, int No = 300){ 24 | // for(int i = 0; i < No; i++){ 25 | while(r - l > EPS){ 26 | double m1 = l + (r - l) / 3; 27 | double m2 = r - (r - l) / 3; 28 | // if (f(m1) > f(m2)) 29 | if (f(m1) < f(m2)) 30 | l = m1; 31 | else 32 | r = m2; 33 | } 34 | return f(l); 35 | } -------------------------------------------------------------------------------- /graphs/2_sat_kosaraju.cpp: -------------------------------------------------------------------------------- 1 | /*********************************************************************************************** 2 | * 2-SAT (TELL WHETHER A SERIES OF STATEMENTS CAN OR CANNOT BE FEASIBLE AT THE SAME TIME) * * 3 | * Time complexity: O(V+E) * 4 | * Usage: n -> number of variables, 1-indexed * 5 | * p = v(i) -> picks the "true" state for variable i * 6 | * p = nv(i) -> picks the "false" state for variable i, i.e. ~i * 7 | * add(p, q) -> add clause (p v q) (which also means ~p => q, which also means ~q => p) * 8 | * run2sat() -> true if possible, false if impossible * 9 | * val[i] -> tells if i has to be true or false for that solution * 10 | ***********************************************************************************************/ 11 | 12 | int n, vis[2*N], ord[2*N], ordn, cnt, cmp[2*N], val[N]; 13 | vector adj[2*N], adjt[2*N]; 14 | 15 | // for a variable u with idx i 16 | // u is 2*i and !u is 2*i+1 17 | // (a v b) == !a -> b ^ !b -> a 18 | 19 | int v(int x) { return 2*x; } 20 | int nv(int x) { return 2*x+1; } 21 | 22 | // add clause (a v b) 23 | void add(int a, int b){ 24 | adj[a^1].push_back(b); 25 | adj[b^1].push_back(a); 26 | adjt[b].push_back(a^1); 27 | adjt[a].push_back(b^1); 28 | } 29 | 30 | void dfs(int x){ 31 | vis[x] = 1; 32 | for(auto v : adj[x]) if(!vis[v]) dfs(v); 33 | ord[ordn++] = x; 34 | } 35 | 36 | void dfst(int x){ 37 | cmp[x] = cnt, vis[x] = 0; 38 | for(auto v : adjt[x]) if(vis[v]) dfst(v); 39 | } 40 | 41 | bool run2sat(){ 42 | for(int i = 1; i <= n; i++) { 43 | if(!vis[v(i)]) dfs(v(i)); 44 | if(!vis[nv(i)]) dfs(nv(i)); 45 | } 46 | for(int i = ordn-1; i >= 0; i--) 47 | if(vis[ord[i]]) cnt++, dfst(ord[i]); 48 | for(int i = 1; i <= n; i ++){ 49 | if(cmp[v(i)] == cmp[nv(i)]) return false; 50 | val[i] = cmp[v(i)] > cmp[nv(i)]; 51 | } 52 | return true; 53 | } 54 | 55 | int main () { 56 | for (int i = 1; i <= n; i++) { 57 | if (val[i]); // i-th variable is true 58 | else // i-th variable is false 59 | } 60 | -------------------------------------------------------------------------------- /graphs/2_sat_tarjan.cpp: -------------------------------------------------------------------------------- 1 | // 2-SAT - O(V+E) 2 | // For each variable x, we create two nodes in the graph: u and !u 3 | // If the variable has index i, the index of u and !u are: 2*i and 2*i+1 4 | // Adds a statment u => v 5 | void add(int u, int v){ 6 | adj[u].pb(v); 7 | adj[v^1].pb(u^1); 8 | } 9 | 10 | //0-indexed variables; starts from var_0 and goes to var_n-1 11 | for(int i = 0; i < n; i++){ 12 | tarjan(2*i), tarjan(2*i + 1); 13 | //cmp is a tarjan variable that says the component from a certain node 14 | if(cmp[2*i] == cmp[2*i + 1]) //Invalid 15 | if(cmp[2*i] < cmp[2*i + 1]) //Var_i is true 16 | else //Var_i is false 17 | 18 | //its just a possible solution! 19 | } 20 | -------------------------------------------------------------------------------- /graphs/bellman_ford.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************** 2 | * BELLMAN-FORD ALGORITHM (SHORTEST PATH TO A VERTEX - WITH NEGATIVE COST) * 3 | * Time complexity: O(VE) * 4 | * Usage: dist[node] * 5 | * Notation: m: number of edges * 6 | * n: number of vertices * 7 | * (a, b, w): edge between a and b with weight w * 8 | * s: starting node * 9 | **********************************************************************************/ 10 | const int N = 1e4+10; // Maximum number of nodes 11 | vector adj[N], adjw[N]; 12 | int dist[N], v, w; 13 | 14 | memset(dist, 63, sizeof(dist)); 15 | dist[0] = 0; 16 | for (int i = 0; i < n-1; ++i) 17 | for (int u = 0; u < n; ++u) 18 | for (int j = 0; j < adj[u].size(); ++j) 19 | v = adj[u][j], w = adjw[u][j], 20 | dist[v] = min(dist[v], dist[u]+w); 21 | -------------------------------------------------------------------------------- /graphs/bfs.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************** 2 | * BFS (BREADTH-FIRST SEARCH) * 3 | * Time complexity: O(V+E) * 4 | * Usage: bfs(node) * 5 | * Notation: s: starting node * 6 | * adj[i]: adjacency list for node i * 7 | * vis[i]: visited state for node i (0 or 1) * 8 | **********************************************************************************/ 9 | 10 | const int N = 1e5+10; // Maximum number of nodes 11 | int dist[N], par[N]; 12 | vector adj[N]; 13 | queue q; 14 | 15 | void bfs (int s) { 16 | memset(dist, 63, sizeof(dist)); 17 | dist[s] = 0; 18 | q.push(s); 19 | 20 | while (!q.empty()) { 21 | int u = q.front(); q.pop(); 22 | for (auto v : adj[u]) if (dist[v] > dist[u] + 1) { 23 | par[v] = u; 24 | dist[v] = dist[u] + 1; 25 | q.push(v); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /graphs/block_cut.cpp: -------------------------------------------------------------------------------- 1 | // Tarjan for Block Cut Tree (Node Biconnected Componentes) - O(n + m) 2 | #define pb push_back 3 | #include 4 | using namespace std; 5 | 6 | const int N = 1e5+5; 7 | 8 | // Regular Tarjan stuff 9 | int n, num[N], low[N], cnt, ch[N], art[N]; 10 | vector adj[N], st; 11 | 12 | int lb[N]; // Last block that node is contained 13 | int bn; // Number of blocks 14 | vector blc[N]; // List of nodes from block 15 | 16 | void dfs(int u, int p) { 17 | num[u] = low[u] = ++cnt; 18 | ch[u] = adj[u].size(); 19 | st.pb(u); 20 | 21 | if (adj[u].size() == 1) blc[++bn].pb(u); 22 | 23 | for(int v : adj[u]) { 24 | if (!num[v]) { 25 | dfs(v, u), low[u] = min(low[u], low[v]); 26 | if (low[v] == num[u]) { 27 | if (p != -1 or ch[u] > 1) art[u] = 1; 28 | blc[++bn].pb(u); 29 | while(blc[bn].back() != v) 30 | blc[bn].pb(st.back()), st.pop_back(); 31 | } 32 | } 33 | else if (v != p) low[u] = min(low[u], num[v]), ch[v]--; 34 | } 35 | 36 | if (low[u] == num[u]) st.pop_back(); 37 | } 38 | 39 | // Nodes from 1 .. n are blocks 40 | // Nodes from n+1 .. 2*n are articulations 41 | vector bct[2*N]; // Adj list for Block Cut Tree 42 | 43 | void build_tree() { 44 | for(int u=1; u<=n; ++u) for(int v : adj[u]) if (num[u] > num[v]) { 45 | if (lb[u] == lb[v] or blc[lb[u]][0] == v) /* edge u-v belongs to block lb[u] */; 46 | else { /* edge u-v belongs to block cut tree */; 47 | int x = (art[u] ? u + n : lb[u]), y = (art[v] ? v + n : lb[v]); 48 | bct[x].pb(y), bct[y].pb(x); 49 | } 50 | } 51 | } 52 | 53 | void tarjan() { 54 | for(int u=1; u<=n; ++u) if (!num[u]) dfs(u, -1); 55 | for(int b=1; b<=bn; ++b) for(int u : blc[b]) lb[u] = b; 56 | build_tree(); 57 | } 58 | 59 | -------------------------------------------------------------------------------- /graphs/bridges_and_articulations.cpp: -------------------------------------------------------------------------------- 1 | // Articulation points and Bridges O(V+E) 2 | int par[N], art[N], low[N], num[N], ch[N], cnt; 3 | 4 | void articulation(int u) { 5 | low[u] = num[u] = ++cnt; 6 | for (int v : adj[u]) { 7 | if (!num[v]) { 8 | par[v] = u; ch[u]++; 9 | articulation(v); 10 | if (low[v] >= num[u]) art[u] = 1; 11 | if (low[v] > num[u]) { /* u-v bridge */ } 12 | low[u] = min(low[u], low[v]); 13 | } 14 | else if (v != par[u]) low[u] = min(low[u], num[v]); 15 | } 16 | } 17 | 18 | for (int i = 0; i < n; ++i) if (!num[i]) 19 | articulation(i), art[i] = ch[i]>1; 20 | -------------------------------------------------------------------------------- /graphs/dfs.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************** 2 | * DFS (DEPTH-FIRST SEARCH) * 3 | * Time complexity: O(V+E) * * 4 | * Notation: adj[x]: adjacency list for node x * 5 | * vis[i]: visited state for node i (0 or 1) * 6 | **********************************************************************************/ 7 | 8 | const int N = 1e5+10; 9 | int vis[N]; 10 | vector adj[N]; 11 | 12 | void dfs(int u) { 13 | vis[u] = 1; 14 | for (int v : adj[u]){ 15 | if (!vis[v]) { 16 | dfs(v); 17 | } 18 | } 19 | // vis[u] = 0; 20 | // Uncomment the line above if you need to 21 | // traverse only one path at a time (backtracking) 22 | } -------------------------------------------------------------------------------- /graphs/dijkstra.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************** 2 | * DIJKSTRA'S ALGORITHM (SHORTEST PATH TO A VERTEX) * 3 | * Time complexity: O((V+E)logE) * 4 | * Usage: dist[node] * 5 | * Notation: m: number of edges * 6 | * (a, b, w): edge between a and b with weight w * 7 | * s: starting node * 8 | * par[v]: parent node of u, used to rebuild the shortest path * 9 | **********************************************************************************/ 10 | 11 | vector adj[N], adjw[N]; 12 | int dist[N]; 13 | 14 | memset(dist, 63, sizeof(dist)); 15 | priority_queue pq; 16 | pq.push(mp(0,0)); 17 | 18 | while (!pq.empty()) { 19 | int u = pq.top().nd; 20 | int d = -pq.top().st; 21 | pq.pop(); 22 | 23 | if (d > dist[u]) continue; 24 | for (int i = 0; i < adj[u].size(); ++i) { 25 | int v = adj[u][i]; 26 | int w = adjw[u][i]; 27 | if (dist[u] + w < dist[v]) 28 | dist[v] = dist[u]+w, pq.push(mp(-dist[v], v)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /graphs/dominator_tree.cpp: -------------------------------------------------------------------------------- 1 | // a node u is said to be dominating node v if, from every path from the entry point to v you have to pass through u 2 | // so this code is able to find every dominator from a specific entry point (usually 1) 3 | // for directed graphs obviously 4 | 5 | const int N = 1e5 + 7; 6 | 7 | vector adj[N], radj[N], tree[N], bucket[N]; 8 | int sdom[N], par[N], dom[N], dsu[N], label[N], arr[N], rev[N], cnt; 9 | 10 | void dfs(int u) { 11 | cnt++; 12 | arr[u] = cnt; 13 | rev[cnt] = u; 14 | label[cnt] = cnt; 15 | sdom[cnt] = cnt; 16 | dsu[cnt] = cnt; 17 | for(auto e : adj[u]) { 18 | if(!arr[e]) { 19 | dfs(e); 20 | par[arr[e]] = arr[u]; 21 | } 22 | radj[arr[e]].push_back(arr[u]); 23 | } 24 | } 25 | 26 | int find(int u, int x = 0) { 27 | if(u == dsu[u]) { 28 | return (x ? -1 : u); 29 | } 30 | int v = find(dsu[u], x + 1); 31 | if(v == -1) { 32 | return u; 33 | } 34 | if(sdom[label[dsu[u]]] < sdom[label[u]]) { 35 | label[u] = label[dsu[u]]; 36 | } 37 | dsu[u] = v; 38 | return (x ? v : label[u]); 39 | } 40 | 41 | void unite(int u, int v) { 42 | dsu[v] = u; 43 | } 44 | 45 | // in main 46 | 47 | dfs(1); 48 | for(int i = cnt; i >= 1; i--) { 49 | for(auto e : radj[i]) { 50 | sdom[i] = min(sdom[i], sdom[find(e)]); 51 | } 52 | if(i > 1) { 53 | bucket[sdom[i]].push_back(i); 54 | } 55 | for(auto e : bucket[i]) { 56 | int v = find(e); 57 | if(sdom[e] == sdom[v]) { 58 | dom[e] = sdom[e]; 59 | } else { 60 | dom[e] = v; 61 | } 62 | } 63 | if(i > 1) { 64 | unite(par[i], i); 65 | } 66 | } 67 | for(int i = 2; i <= cnt; i++) { 68 | if(dom[i] != sdom[i]) { 69 | dom[i] = dom[dom[i]]; 70 | } 71 | tree[rev[i]].push_back(rev[dom[i]]); 72 | tree[rev[dom[i]]].push_back(rev[i]); 73 | } 74 | -------------------------------------------------------------------------------- /graphs/erdos_gallai.cpp: -------------------------------------------------------------------------------- 1 | // Erdos-Gallai - O(nlogn) 2 | // check if it's possible to create a simple graph (undirected edges) from 3 | // a sequence of vertice's degrees 4 | bool gallai(vector v) { 5 | vector sum; 6 | sum.resize(v.size()); 7 | 8 | sort(v.begin(), v.end(), greater()); 9 | sum[0] = v[0]; 10 | for (int i = 1; i < v.size(); i++) sum[i] = sum[i-1] + v[i]; 11 | if (sum.back() % 2) return 0; 12 | 13 | for (int k = 1; k < v.size(); k++) { 14 | int p = lower_bound(v.begin(), v.end(), k, greater()) - v.begin(); 15 | if (p < k) p = k; 16 | if (sum[k-1] > 1ll*k*(p-1) + sum.back() - sum[p-1]) return 0; 17 | } 18 | return 1; 19 | } 20 | 21 | -------------------------------------------------------------------------------- /graphs/eulerian_path.cpp: -------------------------------------------------------------------------------- 1 | vector ans, adj[N]; 2 | int in[N]; 3 | 4 | void dfs(int v){ 5 | while(adj[v].size()){ 6 | int x = adj[v].back(); 7 | adj[v].pop_back(); 8 | dfs(x); 9 | } 10 | ans.pb(v); 11 | } 12 | 13 | // Verify if there is an eulerian path or circuit 14 | vector v; 15 | for(int i = 0; i < n; i++) if(adj[i].size() != in[i]){ 16 | if(abs((int)adj[i].size() - in[i]) != 1) //-> There is no valid eulerian circuit/path 17 | v.pb(i); 18 | } 19 | 20 | if(v.size()){ 21 | if(v.size() != 2) //-> There is no valid eulerian path 22 | if(in[v[0]] > adj[v[0]].size()) swap(v[0], v[1]); 23 | if(in[v[0]] > adj[v[0]].size()) //-> There is no valid eulerian path 24 | adj[v[1]].pb(v[0]); // Turn the eulerian path into a eulerian circuit 25 | } 26 | 27 | dfs(0); 28 | for(int i = 0; i < cnt; i++) 29 | if(adj[i].size()) //-> There is no valid eulerian circuit/path in this case because the graph is not conected 30 | 31 | ans.pop_back(); // Since it's a curcuit, the first and the last are repeated 32 | reverse(ans.begin(), ans.end()); 33 | 34 | int bg = 0; // Is used to mark where the eulerian path begins 35 | if(v.size()){ 36 | for(int i = 0; i < ans.size(); i++) 37 | if(ans[i] == v[1] and ans[(i + 1)%ans.size()] == v[0]){ 38 | bg = i + 1; 39 | break; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /graphs/fast_kuhn.cpp: -------------------------------------------------------------------------------- 1 | const int N = 1e5+5; 2 | 3 | int x, marcB[N], matchB[N], matchA[N], ans, n, m, p; 4 | vector adj[N]; 5 | 6 | bool dfs(int v){ 7 | for(int i = 0; i < adj[v].size(); i++){ 8 | int viz = adj[v][i]; 9 | if(marcB[viz] == 1 ) continue; 10 | marcB[viz] = 1; 11 | 12 | if((matchB[viz] == -1) || dfs(matchB[viz])){ 13 | matchB[viz] = v; 14 | matchA[v] = viz; 15 | return true; 16 | } 17 | 18 | } 19 | return false; 20 | } 21 | 22 | int main(){ 23 | //... 24 | for(int i = 0; i<=n; i++) matchA[i] = -1; 25 | for(int j = 0; j<=m; j++) matchB[j] = -1; 26 | 27 | bool aux = true; 28 | while(aux){ 29 | for(int j=1; j<=m; j++) marcB[j] = 0; 30 | aux = false; 31 | for(int i=1; i<=n; i++){ 32 | if(matchA[i] != -1) continue; 33 | if(dfs(i)){ 34 | ans++; 35 | aux = true; 36 | } 37 | } 38 | } 39 | //... 40 | } 41 | -------------------------------------------------------------------------------- /graphs/find_cycle_3_4.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using lint = int64_t; 4 | 5 | constexpr int MOD = int(1e9) + 7; 6 | constexpr int INF = 0x3f3f3f3f; 7 | constexpr int NINF = 0xcfcfcfcf; 8 | constexpr lint LINF = 0x3f3f3f3f3f3f3f3f; 9 | 10 | #define endl '\n' 11 | 12 | const long double PI = acosl(-1.0); 13 | 14 | int cmp_double(double a, double b = 0, double eps = 1e-9) { 15 | return a + eps > b ? b + eps > a ? 0 : 1 : -1; 16 | } 17 | 18 | using namespace std; 19 | 20 | #define P 1000000007 21 | #define N 330000 22 | 23 | int n, m; 24 | vector go[N], lk[N]; 25 | int w[N], deg[N], pos[N], id[N]; 26 | 27 | bool circle3() { 28 | int ans = 0; 29 | for(int i = 1; i <= n; i++) w[i] = 0; 30 | for(int x = 1; x <= n; x++) { 31 | for(int y : lk[x]) w[y] = 1; 32 | for(int y : lk[x]) for(int z:lk[y]) if(w[z]) { 33 | ans=(ans+go[x].size()+go[y].size()+go[z].size() - 6); 34 | if(ans) return true; 35 | } 36 | for(int y:lk[x]) w[y] = 0; 37 | } 38 | return false; 39 | } 40 | 41 | bool circle4() { 42 | for(int i = 1; i <= n; i++) w[i] = 0; 43 | int ans = 0; 44 | for(int x = 1; x <= n; x++) { 45 | for(int y:go[x]) for(int z:lk[y]) if(pos[z] > pos[x]) { 46 | ans = (ans+w[z]); 47 | w[z]++; 48 | if(ans) return true; 49 | } 50 | for(int y:go[x]) for(int z : lk[y]) w[z] = 0; 51 | } 52 | return false; 53 | } 54 | 55 | inline bool cmp(const int &x, const int &y) { 56 | return deg[x] < deg[y]; 57 | } 58 | 59 | int main() { 60 | cin.tie(nullptr)->sync_with_stdio(false); 61 | cin >> n >> m; 62 | 63 | int x, y; 64 | for(int i = 0; i < n; i++) { 65 | cin >> x >> y; 66 | } 67 | 68 | for(int i = 1; i <= n; i++) { 69 | deg[i] = 0, go[i].clear(), lk[i].clear(); 70 | } 71 | while (m--){ 72 | int a, b; 73 | cin >> a >> b; 74 | deg[a]++, deg[b]++; 75 | go[a].push_back(b); 76 | go[b].push_back(a); 77 | } 78 | 79 | for(int i = 1; i <= n; i++) id[i]= i; 80 | sort(id+1, id+1+n, cmp); 81 | for(int i = 1; i<= n; i++) pos[id[i]]=i; 82 | for(int x = 1; x<= n; x++) { 83 | for(int y:go[x]) { 84 | if(pos[y]>pos[x]) lk[x].push_back(y); 85 | } 86 | }; 87 | 88 | if(circle3()) { 89 | cout << "3" << endl; 90 | return 0; 91 | }; 92 | 93 | if(circle4()) { 94 | cout << "4" << endl; 95 | return 0; 96 | }; 97 | 98 | cout << "5" << endl; 99 | return 0; 100 | } -------------------------------------------------------------------------------- /graphs/floyd_warshall.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************** 2 | * FLOYD-WARSHALL ALGORITHM (SHORTEST PATH TO ANY VERTEX) * 3 | * Time complexity: O(V^3) * 4 | * Usage: dist[from][to] * 5 | * Notation: m: number of edges * 6 | * n: number of vertices * 7 | * (a, b, w): edge between a and b with weight w * 8 | **********************************************************************************/ 9 | 10 | int adj[N][N]; // no-edge = INF 11 | 12 | for (int k = 0; k < n; ++k) 13 | for (int i = 0; i < n; ++i) 14 | for (int j = 0; j < n; ++j) 15 | adj[i][j] = min(adj[i][j], adj[i][k]+adj[k][j]); 16 | -------------------------------------------------------------------------------- /graphs/hungarian.cpp: -------------------------------------------------------------------------------- 1 | // Hungarian - O(m*n^2) 2 | // Assignment Problem 3 | 4 | int n, m; 5 | int pu[N], pv[N], cost[N][M]; 6 | int pairV[N], way[M], minv[M], used[M]; 7 | 8 | void hungarian() { 9 | for(int i = 1, j0 = 0; i <= n; i++) { 10 | pairV[0] = i; 11 | memset(minv, 63, sizeof minv); 12 | memset(used, 0, sizeof used); 13 | do { 14 | used[j0] = 1; 15 | int i0 = pairV[j0], delta = INF, j1; 16 | for(int j = 1; j <= m; j++) { 17 | if(used[j]) continue; 18 | int cur = cost[i0][j] - pu[i0] - pv[j]; 19 | if(cur < minv[j]) minv[j] = cur, way[j] = j0; 20 | if(minv[j] < delta) delta = minv[j], j1 = j; 21 | } 22 | 23 | for(int j = 0; j <= m; j++) { 24 | if(used[j]) pu[pairV[j]] += delta, pv[j] -= delta; 25 | else minv[j] -= delta; 26 | } 27 | j0 = j1; 28 | } while(pairV[j0]); 29 | 30 | do { 31 | int j1 = way[j0]; 32 | pairV[j0] = pairV[j1]; 33 | j0 = j1; 34 | } while(j0); 35 | } 36 | } 37 | 38 | // in main 39 | // for(int j = 1; j <= m; j++) 40 | // if(pairV[j]) ans += cost[pairV[j]][j]; 41 | // 42 | -------------------------------------------------------------------------------- /graphs/hungarian_navarro.cpp: -------------------------------------------------------------------------------- 1 | // Hungarian - O(n^2 * m) 2 | template 3 | struct Hungarian { 4 | bool swap_coord = false; 5 | int lines, cols; 6 | T ans; 7 | 8 | vector pairV, way; 9 | vector used; 10 | vector pu, pv, minv; 11 | vector> cost; 12 | 13 | Hungarian(int _n, int _m) { 14 | if (_n > _m) { 15 | swap(_n, _m); 16 | swap_coord = true; 17 | } 18 | 19 | lines = _n + 1, cols = _m + 1; 20 | 21 | clear(); 22 | cost.resize(lines); 23 | for (auto& line : cost) line.assign(cols, 0); 24 | } 25 | 26 | void clear() { 27 | pairV.assign(cols, 0); 28 | way.assign(cols, 0); 29 | pv.assign(cols, 0); 30 | pu.assign(lines, 0); 31 | } 32 | 33 | void update(int i, int j, T val) { 34 | if (is_zero_indexed) i++, j++; 35 | if (is_max) val = -val; 36 | if (swap_coord) swap(i, j); 37 | 38 | assert(i < lines); 39 | assert(j < cols); 40 | 41 | cost[i][j] = val; 42 | } 43 | 44 | T run() { 45 | T _INF = numeric_limits::max(); 46 | for (int i = 1, j0 = 0; i < lines; i++) { 47 | pairV[0] = i; 48 | minv.assign(cols, _INF); 49 | used.assign(cols, 0); 50 | do { 51 | used[j0] = 1; 52 | int i0 = pairV[j0], j1; 53 | T delta = _INF; 54 | for (int j = 1; j < cols; j++) { 55 | if (used[j]) continue; 56 | T cur = cost[i0][j] - pu[i0] - pv[j]; 57 | if (cur < minv[j]) minv[j] = cur, way[j] = j0; 58 | if (minv[j] < delta) delta = minv[j], j1 = j; 59 | } 60 | 61 | for (int j = 0; j < cols; j++) { 62 | if (used[j]) pu[pairV[j]] += delta, pv[j] -= delta; 63 | else minv[j] -= delta; 64 | } 65 | j0 = j1; 66 | } while (pairV[j0]); 67 | 68 | do { 69 | int j1 = way[j0]; 70 | pairV[j0] = pairV[j1]; 71 | j0 = j1; 72 | } while (j0); 73 | } 74 | 75 | ans = 0; 76 | for (int j = 1; j < cols; j++) if (pairV[j]) ans += cost[pairV[j]][j]; 77 | 78 | if (is_max) ans = -ans; 79 | if (is_zero_indexed) { 80 | for (int j = 0; j + 1 < cols; j++) pairV[j] = pairV[j + 1], pairV[j]--; 81 | pairV[cols - 1] = -1; 82 | } 83 | if (swap_coord) { 84 | vector pairV_sub(lines, 0); 85 | for (int j = 0; j < cols; j++) if (pairV[j] >= 0) pairV_sub[pairV[j]] = j; 86 | swap(pairV, pairV_sub); 87 | } 88 | 89 | return ans; 90 | } 91 | }; 92 | 93 | template 94 | struct HungarianMult : public Hungarian { 95 | using super = Hungarian; 96 | 97 | HungarianMult(int _n, int _m) : super(_n, _m) {} 98 | 99 | void update(int i, int j, long double x) { 100 | super::update(i, j, log2(x)); 101 | } 102 | }; -------------------------------------------------------------------------------- /graphs/kahn.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************** 2 | * KAHN'S ALGORITHM (TOPOLOGICAL SORTING) * * 3 | * Time complexity: O(V+E) * 4 | * Notation: adj[i]: adjacency matrix for node i * 5 | * n: number of vertices * 6 | * e: number of edges * 7 | * a, b: edge between a and b * 8 | * inc: number of incoming arcs/edges * 9 | * q: queue with the independent vertices * 10 | * tsort: final topo sort, i.e. possible order to traverse graph * 11 | **********************************************************************************/ 12 | 13 | 14 | vector adj[N]; 15 | int inc[N]; // number of incoming arcs/edges 16 | 17 | // undirected graph: inc[v] <= 1 18 | // directed graph: inc[v] == 0 19 | 20 | queue q; 21 | for (int i = 1; i <= n; ++i) if (inc[i] <= 1) q.push(i); 22 | 23 | while (!q.empty()) { 24 | int u = q.front(); q.pop(); 25 | for (int v : adj[u]) 26 | if (inc[v] > 1 and --inc[v] <= 1) 27 | q.push(v); 28 | } 29 | -------------------------------------------------------------------------------- /graphs/kosaraju.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************** 2 | * KOSARAJU'S ALGORITHM (GET EVERY STRONGLY CONNECTED COMPONENTS (SCC)) * 3 | * Description: Given a directed graph, the algorithm generates a list of every * 4 | * strongly connected components. A SCC is a set of points in which you can reach * 5 | * every point regardless of where you start from. For instance, cycles can be * 6 | * a SCC themselves or part of a greater SCC. * 7 | * This algorithm starts with a DFS and generates an array called "ord" which * 8 | * stores vertices according to the finish times (i.e. when it reaches "return"). * 9 | * Then, it makes a reversed DFS according to "ord" list. The set of points * 10 | * visited by the reversed DFS defines a new SCC. * 11 | * One of the uses of getting all SCC is that you can generate a new DAG (Directed * 12 | * Acyclic Graph), easier to work with, in which each SCC being a "supernode" of * 13 | * the DAG. * 14 | * Time complexity: O(V+E) * 15 | * Notation: adj[i]: adjacency list for node i * 16 | * adjt[i]: reversed adjacency list for node i * 17 | * ord: array of vertices according to their finish time * 18 | * ordn: ord counter * 19 | * scc[i]: supernode assigned to i * 20 | * scc_cnt: amount of supernodes in the graph * 21 | **********************************************************************************/ 22 | const int N = 2e5 + 5; 23 | 24 | vector adj[N], adjt[N]; 25 | int n, ordn, scc_cnt, vis[N], ord[N], scc[N]; 26 | 27 | //Directed Version 28 | void dfs(int u) { 29 | vis[u] = 1; 30 | for (auto v : adj[u]) if (!vis[v]) dfs(v); 31 | ord[ordn++] = u; 32 | } 33 | 34 | void dfst(int u) { 35 | scc[u] = scc_cnt, vis[u] = 0; 36 | for (auto v : adjt[u]) if (vis[v]) dfst(v); 37 | } 38 | 39 | // add edge: u -> v 40 | void add_edge(int u, int v){ 41 | adj[u].push_back(v); 42 | adjt[v].push_back(u); 43 | } 44 | 45 | //Undirected version: 46 | /* 47 | int par[N]; 48 | 49 | void dfs(int u) { 50 | vis[u] = 1; 51 | for (auto v : adj[u]) if(!vis[v]) par[v] = u, dfs(v); 52 | ord[ordn++] = u; 53 | } 54 | 55 | void dfst(int u) { 56 | scc[u] = scc_cnt, vis[u] = 0; 57 | for (auto v : adj[u]) if(vis[v] and u != par[v]) dfst(v); 58 | } 59 | 60 | // add edge: u -> v 61 | void add_edge(int u, int v){ 62 | adj[u].push_back(v); 63 | adj[v].push_back(u); 64 | } 65 | 66 | */ 67 | 68 | // run kosaraju 69 | void kosaraju(){ 70 | for (int i = 1; i <= n; ++i) if (!vis[i]) dfs(i); 71 | for (int i = ordn - 1; i >= 0; --i) if (vis[ord[i]]) scc_cnt++, dfst(ord[i]); 72 | } 73 | -------------------------------------------------------------------------------- /graphs/kruskal.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************** 2 | * KRUSKAL'S ALGORITHM (MINIMAL SPANNING TREE - INCREASING EDGE SIZE) * 3 | * Time complexity: O(ElogE) * 4 | * Usage: cost, sz[find(node)] * 5 | * Notation: cost: sum of all edges which belong to such MST * 6 | * sz: vector of subsets sizes, i.e. size of the subset a node is in * 7 | **********************************************************************************/ 8 | 9 | // + Union-find 10 | 11 | int cost = 0; 12 | vector >> edges; //mp(dist, mp(node1, node2)) 13 | 14 | int main () { 15 | // ... 16 | sort(edges.begin(), edges.end()); 17 | for (auto e : edges) 18 | if (find(e.nd.st) != find(e.nd.nd)) 19 | unite(e.nd.st, e.nd.nd), cost += e.st; 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /graphs/kuhn.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************** 2 | * KUHN'S ALGORITHM (FIND GREATEST NUMBER OF MATCHINGS - BIPARTITE GRAPH) * 3 | * Time complexity: O(VE) * 4 | * Notation: ans: number of matchings * 5 | * b[j]: matching edge b[j] <-> j * 6 | * adj[i]: adjacency list for node i * 7 | * vis: visited nodes * 8 | * x: counter to help reuse vis list * 9 | **********************************************************************************/ 10 | 11 | // TIP: If too slow, shuffle nodes and try again. 12 | int x, vis[N], b[N], ans; 13 | 14 | bool match(int u) { 15 | if (vis[u] == x) return 0; 16 | vis[u] = x; 17 | for (int v : adj[u]) 18 | if (!b[v] or match(b[v])) return b[v]=u; 19 | return 0; 20 | } 21 | 22 | for (int i = 1; i <= n; ++i) ++x, ans += match(i); 23 | 24 | // Maximum Independent Set on bipartite graph 25 | MIS + MCBM = V 26 | 27 | // Minimum Vertex Cover on bipartite graph 28 | MVC = MCBM 29 | -------------------------------------------------------------------------------- /graphs/lca.cpp: -------------------------------------------------------------------------------- 1 | // Lowest Common Ancestor 2 | const int N = 1e6, M = 25; 3 | int anc[M][N], h[N], rt; 4 | 5 | // TODO: Calculate h[u] and set anc[0][u] = parent of node u for each u 6 | 7 | // build (sparse table) 8 | anc[0][rt] = rt; // set parent of the root to itself 9 | for (int i = 1; i < M; ++i) 10 | for (int j = 1; j <= n; ++j) 11 | anc[i][j] = anc[i-1][anc[i-1][j]]; 12 | 13 | // query 14 | int lca(int u, int v) { 15 | if (h[u] < h[v]) swap(u, v); 16 | for (int i = M-1; i >= 0; --i) if (h[u]-(1<= h[v]) 17 | u = anc[i][u]; 18 | 19 | if (u == v) return u; 20 | 21 | for (int i = M-1; i >= 0; --i) if (anc[i][u] != anc[i][v]) 22 | u = anc[i][u], v = anc[i][v]; 23 | return anc[0][u]; 24 | } 25 | -------------------------------------------------------------------------------- /graphs/max_weight_lca.cpp: -------------------------------------------------------------------------------- 1 | // Using LCA to find max edge weight between (u, v) 2 | 3 | const int N = 1e5+5; // Max number of vertices 4 | const int K = 20; // Each 1e3 requires ~ 10 K 5 | const int M = K+5; 6 | int n; // Number of vertices 7 | vector adj[N]; 8 | int vis[N], h[N], anc[N][M], mx[N][M]; 9 | 10 | void dfs (int u) { 11 | vis[u] = 1; 12 | for (auto p : adj[u]) { 13 | int v = p.st; 14 | int w = p.nd; 15 | if (!vis[v]) { 16 | h[v] = h[u]+1; 17 | anc[v][0] = u; 18 | mx[v][0] = w; 19 | dfs(v); 20 | } 21 | } 22 | } 23 | 24 | void build () { 25 | // cl(mn, 63) -- Don't forget to initialize with INF if min edge! 26 | anc[1][0] = 1; 27 | dfs(1); 28 | for (int j = 1; j <= K; j++) for (int i = 1; i <= n; i++) { 29 | anc[i][j] = anc[anc[i][j-1]][j-1]; 30 | mx[i][j] = max(mx[i][j-1], mx[anc[i][j-1]][j-1]); 31 | } 32 | } 33 | 34 | int mxedge (int u, int v) { 35 | int ans = 0; 36 | 37 | if (h[u] < h[v]) swap(u, v); 38 | for (int j = K; j >= 0; j--) if (h[anc[u][j]] >= h[v]) { 39 | ans = max(ans, mx[u][j]); 40 | u = anc[u][j]; 41 | } 42 | if (u == v) return ans; 43 | for (int j = K; j >= 0; j--) if (anc[u][j] != anc[v][j]) { 44 | ans = max(ans, mx[u][j]); 45 | ans = max(ans, mx[v][j]); 46 | u = anc[u][j]; 47 | v = anc[v][j]; 48 | } 49 | return max({ans, mx[u][0], mx[v][0]}); 50 | } -------------------------------------------------------------------------------- /graphs/min_cost_max_flow.cpp: -------------------------------------------------------------------------------- 1 | // USE INF = 1e9! 2 | 3 | /********************************************************************************** 4 | * MIN COST MAX FLOW (MINIMUM COST TO ACHIEVE MAXIMUM FLOW) * 5 | * Description: Given a graph which represents a flow network where every edge has * 6 | * a capacity and a cost per unit, find the minimum cost to establish the maximum * 7 | * possible flow from s to t. * 8 | * Note: When adding edge (a, b), it is a directed edge! * 9 | * Usage: min_cost_max_flow() * 10 | * add_edge(from, to, cost, capacity) * 11 | * Notation: flw: max flow * 12 | * cst: min cost to achieve flw * 13 | * Testcase: * 14 | * add_edge(src, 1, 0, 1); add_edge(1, snk, 0, 1); add_edge(2, 3, 1, INF); * 15 | * add_edge(src, 2, 0, 1); add_edge(2, snk, 0, 1); add_edge(3, 4, 1, INF); * 16 | * add_edge(src, 2, 0, 1); add_edge(3, snk, 0, 1); * 17 | * add_edge(src, 2, 0, 1); add_edge(4, snk, 0, 1); => flw = 4, cst = 3 * 18 | **********************************************************************************/ 19 | 20 | // w: weight or cost, c : capacity 21 | struct edge {int v, f, w, c; }; 22 | 23 | int n, flw_lmt=INF, src, snk, flw, cst, p[N], d[N], et[N]; 24 | vector e; 25 | vector g[N]; 26 | 27 | void add_edge(int u, int v, int w, int c) { 28 | int k = e.size(); 29 | g[u].push_back(k); 30 | g[v].push_back(k+1); 31 | e.push_back({ v, 0, w, c }); 32 | e.push_back({ u, 0, -w, 0 }); 33 | } 34 | 35 | void clear() { 36 | flw_lmt = INF; 37 | for(int i=0; i<=n; ++i) g[i].clear(); 38 | e.clear(); 39 | } 40 | 41 | void min_cost_max_flow() { 42 | flw = 0, cst = 0; 43 | while (flw < flw_lmt) { 44 | memset(et, 0, (n+1) * sizeof(int)); 45 | memset(d, 63, (n+1) * sizeof(int)); 46 | deque q; 47 | q.push_back(src), d[src] = 0; 48 | 49 | while (!q.empty()) { 50 | int u = q.front(); q.pop_front(); 51 | et[u] = 2; 52 | 53 | for(int i : g[u]) { 54 | edge &dir = e[i]; 55 | int v = dir.v; 56 | if (dir.f < dir.c and d[u] + dir.w < d[v]) { 57 | d[v] = d[u] + dir.w; 58 | if (et[v] == 0) q.push_back(v); 59 | else if (et[v] == 2) q.push_front(v); 60 | et[v] = 1; 61 | p[v] = i; 62 | } 63 | } 64 | } 65 | 66 | if (d[snk] > INF) break; 67 | 68 | int inc = flw_lmt - flw; 69 | for (int u=snk; u != src; u = e[p[u]^1].v) { 70 | edge &dir = e[p[u]]; 71 | inc = min(inc, dir.c - dir.f); 72 | } 73 | 74 | for (int u=snk; u != src; u = e[p[u]^1].v) { 75 | edge &dir = e[p[u]], &rev = e[p[u]^1]; 76 | dir.f += inc; 77 | rev.f -= inc; 78 | cst += inc * dir.w; 79 | } 80 | 81 | if (!inc) break; 82 | flw += inc; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /graphs/prim.cpp: -------------------------------------------------------------------------------- 1 | // Prim - MST O(ElogE) 2 | vi adj[N], adjw[N]; 3 | int vis[N]; 4 | 5 | priority_queue pq; 6 | pq.push(mp(0, 0)); 7 | 8 | while (!pq.empty()) { 9 | int u = pq.top().nd; 10 | pq.pop(); 11 | if (vis[u]) continue; 12 | vis[u]=1; 13 | for (int i = 0; i < adj[u].size(); ++i) { 14 | int v = adj[u][i]; 15 | int w = adjw[u][i]; 16 | if (!vis[v]) pq.push(mp(-w, v)); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /graphs/small_to_large.cpp: -------------------------------------------------------------------------------- 1 | // Imagine you have a tree with colored vertices, and you want to do some type of query on every subtree about the colors inside 2 | // complexity: O(nlogn) 3 | 4 | vector adj[N], vec[N]; 5 | int sz[N], color[N], cnt[N]; 6 | 7 | void dfs_size(int v = 1, int p = 0) { 8 | sz[v] = 1; 9 | for (auto u : adj[v]) { 10 | if (u != p) { 11 | dfs_size(u, v); 12 | sz[v] += sz[u]; 13 | } 14 | } 15 | } 16 | 17 | void dfs(int v = 1, int p = 0, bool keep = false) { 18 | int Max = -1, bigchild = -1; 19 | for (auto u : adj[v]) { 20 | if (u != p && Max < sz[u]) { 21 | Max = sz[u]; 22 | bigchild = u; 23 | } 24 | } 25 | for (auto u : adj[v]) { 26 | if (u != p && u != bigchild) { 27 | dfs(u, v, 0); 28 | } 29 | } 30 | if (bigchild != -1) { 31 | dfs(bigchild, v, 1); 32 | swap(vec[v], vec[bigchild]); 33 | } 34 | vec[v].push_back(v); 35 | cnt[color[v]]++; 36 | for (auto u : adj[v]) { 37 | if (u != p && u != bigchild) { 38 | for (auto x : vec[u]) { 39 | cnt[color[x]]++; 40 | vec[v].push_back(x); 41 | } 42 | } 43 | } 44 | // now here you can do what the query wants 45 | // there are cnt[c] vertex in subtree v color with c 46 | if (keep == 0) { 47 | for (auto u : vec[v]) { 48 | cnt[color[u]]--; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /graphs/spfa.cpp: -------------------------------------------------------------------------------- 1 | // Shortest Path Faster Algoritm O(VE) 2 | int dist[N], inq[N]; 3 | 4 | cl(dist,63); 5 | queue q; 6 | q.push(0); dist[0] = 0; inq[0] = 1; 7 | 8 | while (!q.empty()) { 9 | int u = q.front(); q.pop(); inq[u]=0; 10 | for (int i = 0; i < adj[u].size(); ++i) { 11 | int v = adj[u][i], w = adjw[u][i]; 12 | if (dist[v] > dist[u] + w) { 13 | dist[v] = dist[u] + w; 14 | if (!inq[v]) q.push(v), inq[v] = 1; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /graphs/stable_marriage.cpp: -------------------------------------------------------------------------------- 1 | std::vector> stableMarriage(std::vector> first, std::vector> second, std::vector cap) { 2 | assert(cap.size() == second.size()); 3 | int n = (int) first.size(), m = (int) second.size(); 4 | // init 5 | // if O(N * M) first in memory, use table 6 | std::map, int> prio; 7 | std::vector>> current(m); 8 | for(int i = 0; i < n; i++) { 9 | std::reverse(first[i].begin(), first[i].end()); 10 | } 11 | for(int i = 0; i < m; i++) { 12 | for(int j = 0; j < (int) second[i].size(); j++) { 13 | prio[{second[i][j], i}] = j; 14 | } 15 | } 16 | // solve 17 | for(int i = 0; i < n; i++) { 18 | int on = i; 19 | while(!first[on].empty()) { 20 | int to = first[on].back(); 21 | first[on].pop_back(); 22 | if(cap[to]) { 23 | cap[to]--; 24 | assert(prio.count({on, to})); 25 | current[to].insert({prio[{on, to}], on}); 26 | break; 27 | } 28 | assert(!current[to].empty()); 29 | auto it = current[to].end(); 30 | it--; 31 | if(it->first > prio[{on, to}]) { 32 | int nxt = it->second; 33 | current[to].erase(it); 34 | current[to].insert({prio[{on, to}], on}); 35 | on = nxt; 36 | } 37 | } 38 | } 39 | // return 40 | std::vector> ans(m); 41 | for(int i = 0; i < m; i++) { 42 | for(auto it : current[i]) { 43 | ans[i].push_back(it.second); 44 | } 45 | } 46 | return ans; 47 | } -------------------------------------------------------------------------------- /graphs/stanford_stoer_wagner.cpp: -------------------------------------------------------------------------------- 1 | // a is a N*N matrix storing the graph we use; a[i][j]=a[j][i] 2 | memset(use,0,sizeof(use)); 3 | ans=maxlongint; 4 | for (int i=1;imaxc)) maxc=reach[k],maxk=k; 20 | c2=maxk,visit[maxk]=1; 21 | for (int k=1;k<=N;k++) 22 | if (visit[k]==0) reach[k]+=a[maxk][k],last[k]=maxk; 23 | } 24 | c1=last[c2]; 25 | sum=0; 26 | for (int j=1;j<=N;j++) 27 | if (use[j]==0) sum+=a[j][c2]; 28 | ans=min(ans,sum); 29 | use[c2]=1; 30 | for (int j=1;j<=N;j++) 31 | if ((c1!=j)&&(use[j]==0)) {a[j][c1]+=a[j][c2];a[c1][j]=a[j][c1];} 32 | } 33 | 34 | -------------------------------------------------------------------------------- /graphs/tarjan.cpp: -------------------------------------------------------------------------------- 1 | // Tarjan for SCC and Edge Biconnected Componentes - O(n + m) 2 | vector adj[N]; 3 | stack st; 4 | bool inSt[N]; 5 | 6 | int id[N], cmp[N]; 7 | int cnt, cmpCnt; 8 | 9 | void clear(){ 10 | memset(id, 0, sizeof id); 11 | cnt = cmpCnt = 0; 12 | } 13 | 14 | int tarjan(int n){ 15 | int low; 16 | id[n] = low = ++cnt; 17 | st.push(n), inSt[n] = true; 18 | 19 | for(auto x : adj[n]){ 20 | if(id[x] and inSt[x]) low = min(low, id[x]); 21 | else if(!id[x]) { 22 | int lowx = tarjan(x); 23 | if(inSt[x]) 24 | low = min(low, lowx); 25 | } 26 | } 27 | 28 | if(low == id[n]){ 29 | while(st.size()){ 30 | int x = st.top(); 31 | inSt[x] = false; 32 | cmp[x] = cmpCnt; 33 | 34 | st.pop(); 35 | if(x == n) break; 36 | } 37 | cmpCnt++; 38 | } 39 | return low; 40 | } 41 | -------------------------------------------------------------------------------- /graphs/zero_one_bfs.cpp: -------------------------------------------------------------------------------- 1 | // 0-1 BFS - O(V+E) 2 | 3 | const int N = 1e5 + 5; 4 | 5 | int dist[N]; 6 | vector adj[N]; 7 | deque dq; 8 | 9 | void zero_one_bfs (int x){ 10 | cl(dist, 63); 11 | dist[x] = 0; 12 | dq.push_back({x, 0}); 13 | while(!dq.empty()){ 14 | int u = dq.front().st; 15 | int ud = dq.front().nd; 16 | dq.pop_front(); 17 | if(dist[u] < ud) continue; 18 | for(auto x : adj[u]){ 19 | int v = x.st; 20 | int w = x.nd; 21 | if(dist[u] + w < dist[v]){ 22 | dist[v] = dist[u] + w; 23 | if(w) dq.push_back({v, dist[v]}); 24 | else dq.push_front({v, dist[v]}); 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /math/advanced.cpp: -------------------------------------------------------------------------------- 1 | /* Line integral = integral(sqrt(1 + (dy/dx)^2)) dx */ 2 | 3 | /* Multiplicative Inverse over MOD for all 1..N - 1 < MOD in O(N) 4 | Only works for prime MOD. If all 1..MOD - 1 needed, use N = MOD */ 5 | ll inv[N]; 6 | inv[1] = 1; 7 | for(int i = 2; i < N; ++i) 8 | inv[i] = MOD - (MOD / i) * inv[MOD % i] % MOD; 9 | 10 | /* Catalan 11 | f(n) = sum(f(i) * f(n - i - 1)), i in [0, n - 1] = (2n)! / ((n+1)! * n!) = ... 12 | If you have any function f(n) (there are many) that follows this sequence (0-indexed): 13 | 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440 14 | than it's the Catalan function */ 15 | ll cat[N]; 16 | cat[0] = 1; 17 | for(int i = 1; i + 1 < N; i++) // needs inv[i + 1] till inv[N - 1] 18 | cat[i] = 2ll * (2ll * i - 1) * inv[i + 1] % MOD * cat[i - 1] % MOD; 19 | 20 | /* Floor(n / i), i = [1, n], has <= 2 * sqrt(n) diff values. 21 | Proof: i = [1, sqrt(n)] has sqrt(n) diff values. 22 | For i = [sqrt(n), n] we have that 1 <= n / i <= sqrt(n) 23 | and thus has <= sqrt(n) diff values. 24 | */ 25 | /* l = first number that has floor(N / l) = x 26 | r = last number that has floor(N / r) = x 27 | N / r >= floor(N / l) 28 | r <= N / floor(N / l)*/ 29 | for(int l = 1, r; l <= n; l = r + 1){ 30 | r = n / (n / l); 31 | // floor(n / i) has the same value for l <= i <= r 32 | } 33 | 34 | /* Recurrence using matriz 35 | h[i + 2] = a1 * h[i + 1] + a0 * h[i] 36 | [h[i] h[i-1]] = [h[1] h[0]] * [a1 1] ^ (i - 1) 37 | [a0 0] */ 38 | 39 | /* Fibonacci in O(log(N)) with memoization 40 | f(0) = f(1) = 1 41 | f(2*k) = f(k)^2 + f(k - 1)^2 42 | f(2*k + 1) = f(k)*[f(k) + 2*f(k - 1)] */ 43 | 44 | /* Wilson's Theorem Extension 45 | B = b1 * b2 * ... * bm (mod n) = +-1, all bi <= n such that gcd(bi, n) = 1 46 | if(n <= 4 or n = (odd prime)^k or n = 2 * (odd prime)^k) B = -1; for any k 47 | else B = 1; */ 48 | 49 | /* Stirling numbers of the second kind 50 | S(n, k) = Number of ways to split n numbers into k non-empty sets 51 | S(n, 1) = S(n, n) = 1 52 | S(n, k) = k * S(n - 1, k) + S(n - 1, k - 1) 53 | Sr(n, k) = S(n, k) with at least r numbers in each set 54 | Sr(n, k) = k * Sr(n - 1, k) + (n - 1) * Sr(n - r, k - 1) 55 | (r - 1) 56 | S(n - d + 1, k - d + 1) = S(n, k) where if indexes i, j belong to the same set, then |i - j| >= d */ 57 | 58 | /* Burnside's Lemma 59 | |Classes| = 1 / |G| * sum(K ^ C(g)) for each g in G 60 | G = Different permutations possible 61 | C(g) = Number of cycles on the permutation g 62 | K = Number of states for each element 63 | 64 | Different ways to paint a necklace with N beads and K colors: 65 | G = {(1, 2, ... N), (2, 3, ... N, 1), ... (N, 1, ... N - 1)} 66 | gi = (i, i + 1, ... i + N), (taking mod N to get it right) i = 1 ... N 67 | i -> 2i -> 3i ..., Cycles in gi all have size n / gcd(i, n), so C(gi) = gcd(i, n) 68 | Ans = 1 / N * sum(K ^ gcd(i, n)), i = 1 ... N 69 | (For the brave, you can get to Ans = 1 / N * sum(euler_phi(N / d) * K ^ d), d | N) */ 70 | 71 | /* Mobius Inversion 72 | Sum of gcd(i, j), 1 <= i, j <= N? 73 | sum(k->N) k * sum(i->N) sum(j->N) [gcd(i, j) == k], i = a * k, j = b * k 74 | = sum(k->N) k * sum(a->N/k) sum(b->N/k) [gcd(a, b) == 1] 75 | = sum(k->N) k * sum(a->N/k) sum(b->N/k) sum(d->N/k) [d | a] * [d | b] * mi(d) 76 | = sum(k->N) k * sum(d->N/k) mi(d) * floor(N / kd)^2, l = kd, l <= N, k | l, d = l / k 77 | = sum(l->N) floor(N / l)^2 * sum(k|l) k * mi(l / k) 78 | If f(n) = sum(x|n)(g(x) * h(x)) with g(x) and h(x) multiplicative, than f(n) is multiplicative 79 | Hence, g(l) = sum(k|l) k * mi(l / k) is multiplicative 80 | = sum(l->N) floor(N / l)^2 * g(l) */ 81 | 82 | /* Frobenius / Chicken McNugget 83 | n, m given, gcd(n, m) = 1, we want to know if it's possible to create N = a * n + b * m 84 | N, a, b >= 0 85 | The greatest number NOT possible is n * m - n - m 86 | We can NOT create (n - 1) * (m - 1) / 2 numbers */ 87 | -------------------------------------------------------------------------------- /math/basics.cpp: -------------------------------------------------------------------------------- 1 | // Greatest Common Divisor & Lowest Common Multiple 2 | ll gcd(ll a, ll b) { return b ? gcd(b, a%b) : a; } 3 | ll lcm(ll a, ll b) { return a/gcd(a, b)*b; } 4 | 5 | // Multiply caring overflow 6 | ll mulmod(ll a, ll b, ll m = MOD) { 7 | ll r=0; 8 | for (a %= m; b; b>>=1, a=(a*2)%m) if (b&1) r=(r+a)%m; 9 | return r; 10 | } 11 | 12 | // Another option for mulmod is using long double 13 | ull mulmod(ull a, ull b, ull m = MOD) { 14 | ull q = (ld) a * (ld) b / (ld) m; 15 | ull r = a * b - q * m; 16 | return (r + m) % m; 17 | } 18 | 19 | // Fast exponential 20 | ll fexp(ll a, ll b, ll m = MOD) { 21 | ll r=1; 22 | for (a %= m; b; b>>=1, a=(a*a)%m) if (b&1) r=(r*a)%m; 23 | return r; 24 | } 25 | -------------------------------------------------------------------------------- /math/discrete_log.cpp: -------------------------------------------------------------------------------- 1 | // O(sqrt(m)) 2 | // Solve c * a^x = b mod(m) for integer x >= 0. 3 | // Return the smallest x possible, or -1 if there is no solution 4 | // If all solutions needed, solve c * a^x = b mod(m) and (a*b) * a^y = b mod(m) 5 | // x + k * (y + 1) for k >= 0 are all solutions 6 | // Works for any integer values of c, a, b and positive m 7 | 8 | // Corner Cases: 9 | // 0^x = 1 mod(m) returns x = 0, so you may want to change it to -1 10 | // You also may want to change for 0^x = 0 mod(1) to return x = 1 instead 11 | // We leave it like it is because you might be actually checking for m^x = 0^x mod(m) 12 | // which would have x = 0 as the actual solution. 13 | ll discrete_log(ll c, ll a, ll b, ll m){ 14 | c = ((c % m) + m) % m, a = ((a % m) + m) % m, b = ((b % m) + m) % m; 15 | if(c == b) 16 | return 0; 17 | 18 | ll g = __gcd(a, m); 19 | if(b % g) return -1; 20 | 21 | if(g > 1){ 22 | ll r = discrete_log(c * a / g, a, b / g, m / g); 23 | return r + (r >= 0); 24 | } 25 | 26 | unordered_map babystep; 27 | ll n = 1, an = a % m; 28 | 29 | // set n to the ceil of sqrt(m): 30 | while(n * n < m) n++, an = (an * a) % m; 31 | 32 | // babysteps: 33 | ll bstep = b; 34 | for(ll i = 0; i <= n; i++){ 35 | babystep[bstep] = i; 36 | bstep = (bstep * a) % m; 37 | } 38 | 39 | // giantsteps: 40 | ll gstep = c * an % m; 41 | for(ll i = 1; i <= n; i++){ 42 | if(babystep.find(gstep) != babystep.end()) 43 | return n * i - babystep[gstep]; 44 | gstep = (gstep * an) % m; 45 | } 46 | return -1; 47 | } 48 | -------------------------------------------------------------------------------- /math/euler_phi.cpp: -------------------------------------------------------------------------------- 1 | // Euler phi (totient) 2 | int ind = 0, pf = primes[0], ans = n; 3 | while (1ll*pf*pf <= n) { 4 | if (n%pf==0) ans -= ans/pf; 5 | while (n%pf==0) n /= pf; 6 | pf = primes[++ind]; 7 | } 8 | if (n != 1) ans -= ans/n; 9 | 10 | // IME2014 11 | int phi[N]; 12 | void totient() { 13 | for (int i = 1; i < N; ++i) phi[i]=i; 14 | for (int i = 2; i < N; i+=2) phi[i]>>=1; 15 | for (int j = 3; j < N; j+=2) if (phi[j]==j) { 16 | phi[j]--; 17 | for (int i = 2*j; i < N; i+=j) phi[i]=phi[i]/j*(j-1); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /math/extended_euclid.cpp: -------------------------------------------------------------------------------- 1 | // Extended Euclid: 2 | void euclid(ll a, ll b, ll &x, ll &y) { 3 | if (b) euclid(b, a%b, y, x), y -= x*(a/b); 4 | else x = 1, y = 0; 5 | } 6 | 7 | // find (x, y) such that a*x + b*y = c or return false if it's not possible 8 | // [x + k*b/gcd(a, b), y - k*a/gcd(a, b)] are also solutions 9 | bool diof(ll a, ll b, ll c, ll &x, ll &y){ 10 | euclid(abs(a), abs(b), x, y); 11 | ll g = abs(__gcd(a, b)); 12 | if(c % g) return false; 13 | x *= c / g; 14 | y *= c / g; 15 | if(a < 0) x = -x; 16 | if(b < 0) y = -y; 17 | return true; 18 | } 19 | 20 | // auxiliar to find_all_solutions 21 | void shift_solution (ll &x, ll &y, ll a, ll b, ll cnt) { 22 | x += cnt * b; 23 | y -= cnt * a; 24 | } 25 | 26 | // Find the amount of solutions of 27 | // ax + by = c 28 | // in given intervals for x and y 29 | ll find_all_solutions (ll a, ll b, ll c, ll minx, ll maxx, ll miny, ll maxy) { 30 | ll x, y, g = __gcd(a, b); 31 | if(!diof(a, b, c, x, y)) return 0; 32 | a /= g; b /= g; 33 | 34 | int sign_a = a>0 ? +1 : -1; 35 | int sign_b = b>0 ? +1 : -1; 36 | 37 | shift_solution (x, y, a, b, (minx - x) / b); 38 | if (x < minx) 39 | shift_solution (x, y, a, b, sign_b); 40 | if (x > maxx) 41 | return 0; 42 | int lx1 = x; 43 | 44 | shift_solution (x, y, a, b, (maxx - x) / b); 45 | if (x > maxx) 46 | shift_solution (x, y, a, b, -sign_b); 47 | int rx1 = x; 48 | 49 | shift_solution (x, y, a, b, - (miny - y) / a); 50 | if (y < miny) 51 | shift_solution (x, y, a, b, -sign_a); 52 | if (y > maxy) 53 | return 0; 54 | int lx2 = x; 55 | 56 | shift_solution (x, y, a, b, - (maxy - y) / a); 57 | if (y > maxy) 58 | shift_solution (x, y, a, b, sign_a); 59 | int rx2 = x; 60 | 61 | if (lx2 > rx2) 62 | swap (lx2, rx2); 63 | int lx = max (lx1, lx2); 64 | int rx = min (rx1, rx2); 65 | 66 | if (lx > rx) return 0; 67 | return (rx - lx) / abs(b) + 1; 68 | } 69 | 70 | bool crt_auxiliar(ll a, ll b, ll m1, ll m2, ll &ans){ 71 | ll x, y; 72 | if(!diof(m1, m2, b - a, x, y)) return false; 73 | ll lcm = m1 / __gcd(m1, m2) * m2; 74 | ans = ((a + x % (lcm / m1) * m1) % lcm + lcm) % lcm; 75 | return true; 76 | } 77 | 78 | // find ans such that ans = a[i] mod b[i] for all 0 <= i < n or return false if not possible 79 | // ans + k * lcm(b[i]) are also solutions 80 | bool crt(int n, ll a[], ll b[], ll &ans){ 81 | if(!b[0]) return false; 82 | ans = a[0] % b[0]; 83 | ll l = b[0]; 84 | for(int i = 1; i < n; i++){ 85 | if(!b[i]) return false; 86 | if(!crt_auxiliar(ans, a[i] % b[i], l, b[i], ans)) return false; 87 | l *= (b[i] / __gcd(b[i], l)); 88 | } 89 | return true; 90 | } 91 | -------------------------------------------------------------------------------- /math/fft.cpp: -------------------------------------------------------------------------------- 1 | // Fast Fourier Transform - O(nlogn) 2 | 3 | /* 4 | // Use struct instead. Performance will be way better! 5 | typedef complex T; 6 | T a[N], b[N]; 7 | */ 8 | 9 | struct T { 10 | ld x, y; 11 | T() : x(0), y(0) {} 12 | T(ld a, ld b=0) : x(a), y(b) {} 13 | 14 | T operator/=(ld k) { x/=k; y/=k; return (*this); } 15 | T operator*(T a) const { return T(x*a.x - y*a.y, x*a.y + y*a.x); } 16 | T operator+(T a) const { return T(x+a.x, y+a.y); } 17 | T operator-(T a) const { return T(x-a.x, y-a.y); } 18 | } a[N], b[N]; 19 | 20 | // a: vector containing polynomial 21 | // n: power of two greater or equal product size 22 | /* 23 | // Use iterative version! 24 | void fft_recursive(T* a, int n, int s) { 25 | if (n == 1) return; 26 | T tmp[n]; 27 | for (int i = 0; i < n/2; ++i) 28 | tmp[i] = a[2*i], tmp[i+n/2] = a[2*i+1]; 29 | 30 | fft_recursive(&tmp[0], n/2, s); 31 | fft_recursive(&tmp[n/2], n/2, s); 32 | 33 | T wn = T(cos(s*2*PI/n), sin(s*2*PI/n)), w(1,0); 34 | for (int i = 0; i < n/2; i++, w=w*wn) 35 | a[i] = tmp[i] + w*tmp[i+n/2], 36 | a[i+n/2] = tmp[i] - w*tmp[i+n/2]; 37 | } 38 | */ 39 | 40 | void fft(T* a, int n, int s) { 41 | for (int i=0, j=0; ij) swap(a[i], a[j]); 43 | for (int l=n/2; (j^=l) < l; l>>=1); 44 | } 45 | 46 | for(int i = 1; (1<> 1; 49 | T wn = T(cos(s*2*PI/M), sin(s*2*PI/M)); 50 | for(int j = 0; j < n; j += M) { 51 | T w = T(1, 0); 52 | for(int l = j; l < K + j; ++l){ 53 | T t = w*a[l + K]; 54 | a[l + K] = a[l]-t; 55 | a[l] = a[l] + t; 56 | w = wn*w; 57 | } 58 | } 59 | } 60 | } 61 | 62 | // assert n is a power of two greater of equal product size 63 | // n = na + nb; while (n&(n-1)) n++; 64 | void multiply(T* a, T* b, int n) { 65 | fft(a,n,1); 66 | fft(b,n,1); 67 | for (int i = 0; i < n; i++) a[i] = a[i]*b[i]; 68 | fft(a,n,-1); 69 | for (int i = 0; i < n; i++) a[i] /= n; 70 | } 71 | 72 | // Convert to integers after multiplying: 73 | // (int)(a[i].x + 0.5); 74 | -------------------------------------------------------------------------------- /math/fwht.cpp: -------------------------------------------------------------------------------- 1 | template 2 | std::vector FWHT(std::vector a, const bool inv = false) { 3 | int n = (int) a.size(); 4 | for(int len = 1; len < n; len += len) { 5 | for(int i = 0; i < n; i += 2 * len) { 6 | for(int j = 0; j < len; j++) { 7 | auto u = a[i + j], v = a[i + j + len]; 8 | if(ch == '^') { 9 | a[i + j] = u + v; 10 | a[i + j + len] = u - v; 11 | } 12 | if(ch == '|') { 13 | if(!inv) { 14 | a[i + j + len] += a[i + j]; 15 | } else { 16 | a[i + j + len] -= a[i + j]; 17 | } 18 | } 19 | if(ch == '&') { 20 | if(!inv) { 21 | a[i + j] += a[i + j + len]; 22 | } else { 23 | a[i + j] -= a[i + j + len]; 24 | } 25 | } 26 | } 27 | } 28 | } 29 | if(ch == '^' && inv) { 30 | for(int i = 0; i < n; i++) { 31 | a[i] = a[i] / n; 32 | } 33 | } 34 | return a; 35 | } -------------------------------------------------------------------------------- /math/gauss_elim.cpp: -------------------------------------------------------------------------------- 1 | //Gaussian Elimination 2 | //double A[N][M+1], X[M] 3 | 4 | // if n < m, there's no solution 5 | // column m holds the right side of the equation 6 | // X holds the solutions 7 | 8 | for(int j=0; jabs(A[l][j])) 12 | l=i; 13 | if(abs(A[i][j]) < EPS) continue; 14 | for(int k = 0; k < m+1; k++) { //Swap lines 15 | swap(A[l][k],A[j][k]); 16 | } 17 | for(int i = j+1; i < n; i++) { //eliminate column 18 | double t=A[i][j]/A[j][j]; 19 | for(int k = j; k < m+1; k++) 20 | A[i][k]-=t*A[j][k]; 21 | } 22 | } 23 | 24 | for(int i = m-1; i >= 0; i--) { //solve triangular system 25 | for(int j = m-1; j > i; j--) 26 | A[i][m] -= A[i][j]*X[j]; 27 | X[i]=A[i][m]/A[i][i]; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /math/gauss_elim_ext.cpp: -------------------------------------------------------------------------------- 1 | // Gauss-Jordan Elimination with Scaled Partial Pivoting 2 | // Extended to Calculate Inverses - O(n^3) 3 | // To get more precision choose m[j][i] as pivot the element such that m[j][i] / mx[j] is maximized. 4 | // mx[j] is the element with biggest absolute value of row j. 5 | 6 | ld C[N][M]; // N = 1000, M = 2*N+1; 7 | int row, col; 8 | 9 | bool elim() { 10 | for(int i=0; i abs(C[p][i])) p = j; 13 | for(int j=i; j=0; --i) for(int j=i-1; j>=0; --j) { 28 | ld c = -C[j][i]; 29 | for(int k=i; k= 0; i--){ 19 | for(int j = l; j < n; j++) 20 | if(eq[j][i]){ // pivot 21 | swap(eq[l], eq[j]); 22 | swap(r[l], r[j]); 23 | } 24 | if(l == n || !eq[l][i]) 25 | continue; 26 | lid[l] = i + 1; 27 | for(int j = l + 1; j < n; j++){ // eliminate column 28 | if(!eq[j][i]) 29 | continue; 30 | for(int k = 0; k <= i; k++) 31 | eq[j][k] ^= eq[l][k]; 32 | r[j] ^= r[l]; 33 | } 34 | l++; 35 | } 36 | for(int i = n - 1; i >= 0; i--){ // solve triangular matrix 37 | for(int j = 0; j < lid[i + 1]; j++) 38 | r[i] ^= (eq[i][j] && ans[j]); 39 | // for lexicographically least just delete the for bellow 40 | for(int j = lid[i + 1]; j + 1 < lid[i]; j++){ 41 | ans[j] = true; 42 | r[i] ^= eq[i][j]; 43 | } 44 | if(lid[i]) 45 | ans[lid[i] - 1] = r[i]; 46 | else if(r[i]) 47 | return false; 48 | } 49 | return true; 50 | } 51 | -------------------------------------------------------------------------------- /math/gss.cpp: -------------------------------------------------------------------------------- 1 | double gss(double l, double r) { 2 | double m1 = r-(r-l)/gr, m2 = l+(r-l)/gr; 3 | double f1 = f(m1), f2 = f(m2); 4 | while(fabs(l-r)>EPS) { 5 | if(f1>f2) l=m1, f1=f2, m1=m2, m2=l+(r-l)/gr, f2=f(m2); 6 | else r=m2, f2=f1, m2=m1, m1=r-(r-l)/gr, f1=f(m1); 7 | } 8 | return l; 9 | } 10 | -------------------------------------------------------------------------------- /math/josephus.cpp: -------------------------------------------------------------------------------- 1 | // UFMG 2 | /* Josephus Problem - It returns the position to be, in order to not die. O(n)*/ 3 | /* With k=2, for instance, the game begins with 2 being killed and then n+2, n+4, ... */ 4 | ll josephus(ll n, ll k) { 5 | if(n==1) return 1; 6 | else return (josephus(n-1, k)+k-1)%n+1; 7 | } 8 | 9 | /* Another Way to compute the last position to be killed - O(d * log n) */ 10 | ll josephus(ll n, ll d) { 11 | ll K = 1; 12 | while (K <= (d - 1)*n) K = (d * K + d - 2) / (d - 1); 13 | return d * n + 1 - K; 14 | } 15 | -------------------------------------------------------------------------------- /math/lagrange.cpp: -------------------------------------------------------------------------------- 1 | class LagrangePoly { 2 | public: 3 | LagrangePoly(std::vector _a) { 4 | //f(i) = _a[i] 5 | //interpola o vetor em um polinomio de grau y.size() - 1 6 | y = _a; 7 | den.resize(y.size()); 8 | int n = (int) y.size(); 9 | for(int i = 0; i < n; i++) { 10 | y[i] = (y[i] % MOD + MOD) % MOD; 11 | den[i] = ifat[n - i - 1] * ifat[i] % MOD; 12 | if((n - i - 1) % 2 == 1) { 13 | den[i] = (MOD - den[i]) % MOD; 14 | } 15 | } 16 | } 17 | 18 | long long getVal(long long x) { 19 | int n = (int) y.size(); 20 | x %= MOD; 21 | if(x < n) { 22 | //return y[(int) x]; 23 | } 24 | std::vector l, r; 25 | l.resize(n); 26 | l[0] = 1; 27 | for(int i = 1; i < n; i++) { 28 | l[i] = l[i - 1] * (x - (i - 1) + MOD) % MOD; 29 | } 30 | r.resize(n); 31 | r[n - 1] = 1; 32 | for(int i = n - 2; i >= 0; i--) { 33 | r[i] = r[i + 1] * (x - (i + 1) + MOD) % MOD; 34 | } 35 | long long ans = 0; 36 | for(int i = 0; i < n; i++) { 37 | long long coef = l[i] * r[i] % MOD; 38 | ans = (ans + coef * y[i] % MOD * den[i]) % MOD; 39 | } 40 | return ans; 41 | } 42 | 43 | private: 44 | std::vector y, den; 45 | }; 46 | 47 | int main(){ 48 | fat[0] = ifat[0] = 1; 49 | for(int i = 1; i < ms; i++) { 50 | fat[i] = fat[i - 1] * i % MOD; 51 | ifat[i] = fexp(fat[i], MOD - 2); 52 | } 53 | // Codeforces 622F 54 | int x, k; 55 | std::cin >> x >> k; 56 | std::vector a; 57 | a.push_back(0); 58 | for(long long i = 1; i <= k + 1; i++) { 59 | a.push_back((a.back() + fexp(i, k)) % MOD); 60 | } 61 | LagrangePoly f(a); 62 | std::cout << f.getVal(x) << '\n'; 63 | } -------------------------------------------------------------------------------- /math/matrix.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This code assumes you are multiplying two matrices that can be multiplied: (A nxp * B pxm) 3 | Matrix fexp assumes square matrices 4 | */ 5 | 6 | const int MOD = 1e9 + 7; 7 | typedef long long ll; 8 | typedef long long type; 9 | 10 | struct matrix{ 11 | //matrix n x m 12 | vector> a; 13 | int n, m; 14 | matrix() = default; 15 | 16 | matrix(int _n, int _m) : n(_n), m(_m){ 17 | a.resize(n, vector(m)); 18 | } 19 | 20 | matrix operator *(matrix other){ 21 | matrix result(this->n, other.m); 22 | for(int i = 0; i < result.n; i++){ 23 | for(int j = 0; j < result.m; j++){ 24 | for(int k = 0; k < this->m; k++){ 25 | result.a[i][j] = (result.a[i][j] + a[i][k] * other.a[k][j]); 26 | //result.a[i][j] = (result.a[i][j] + (a[i][k] * other.a[k][j]) % MOD) % MOD; 27 | } 28 | } 29 | } 30 | return result; 31 | } 32 | }; 33 | 34 | matrix identity(int n){ 35 | matrix id(n, n); 36 | for(int i = 0; i < n; i++) id.a[i][i] = 1; 37 | return id; 38 | } 39 | 40 | matrix fexp(matrix b, ll e){ 41 | matrix ans = identity(b.n); 42 | while(e){ 43 | if(e & 1) ans = (ans * b); 44 | b = b * b; 45 | e >>= 1; 46 | } 47 | return ans; 48 | } -------------------------------------------------------------------------------- /math/mobius.cpp: -------------------------------------------------------------------------------- 1 | // 1 if n == 1 2 | // 0 if exists x | n%(x^2) == 0 3 | // else (-1)^k, k = #(p) | p is prime and n%p == 0 4 | 5 | //Calculate Mobius for all integers using sieve 6 | //O(n*log(log(n))) 7 | void mobius() { 8 | for(int i = 1; i < N; i++) mob[i] = 1; 9 | 10 | for(ll i = 2; i < N; i++) if(!sieve[i]){ 11 | for(ll j = i; j < N; j += i) sieve[j] = i, mob[j] *= -1; 12 | for(ll j = i*i; j < N; j += i*i) mob[j] = 0; 13 | } 14 | } 15 | 16 | /* 17 | //Calculate Mobius for 1 integer 18 | //O(sqrt(n)) 19 | int mobius(int n){ 20 | if(n == 1) return 1; 21 | int p = 0; 22 | for(int i = 2; i*i <= n; i++) 23 | if(n%i == 0){ 24 | n /= i; 25 | p++; 26 | if(n%i == 0) return 0; 27 | } 28 | if(n > 1) p++; 29 | return p&1 ? -1 : 1; 30 | } 31 | */ 32 | -------------------------------------------------------------------------------- /math/mobius_inversion.cpp: -------------------------------------------------------------------------------- 1 | // multiplicative function calculator 2 | // euler_phi and mobius are multiplicative 3 | // if another f[N] needed just remove comments 4 | // O(N) 5 | 6 | bool p[N]; 7 | vector primes; 8 | ll g[N]; 9 | // ll f[N]; 10 | 11 | void mfc(){ 12 | // if g(1) != 1 than it's not multiplicative 13 | g[1] = 1; 14 | // f[1] = 1; 15 | primes.clear(); 16 | primes.reserve(N / 10); 17 | for(ll i = 2; i < N; i++){ 18 | if(!p[i]){ 19 | primes.push_back(i); 20 | for(ll j = i; j < N; j *= i){ 21 | g[j] = // g(p^k) you found 22 | // f[j] = f(p^k) you found 23 | p[j] = (j != i); 24 | } 25 | } 26 | for(ll j : primes){ 27 | if(i * j >= N || i % j == 0) 28 | break; 29 | for(ll k = j; i * k < N; k *= j){ 30 | g[i * k] = g[i] * g[k]; 31 | // f[i * k] = f[i] * f[k]; 32 | p[i * k] = true; 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /math/ntt.cpp: -------------------------------------------------------------------------------- 1 | namespace ntt { 2 | long long w[N], k, nrev, fact[N], ifact[N]; 3 | void f(int n) { 4 | fact[0] = 1; 5 | for(int i = 1; i <= n; i++) { 6 | fact[i] = (fact[i - 1] * i) % mod; 7 | } 8 | ifact[n] = binexp(fact[n], mod - 2); 9 | for(int i = n - 1; i >= 0; i--) { 10 | ifact[i] = (ifact[i + 1] * (i + 1)) % mod; 11 | } 12 | } 13 | void init(int n, int root) { 14 | w[0] = 1; 15 | k = binexp(root, (mod - 1) / n); 16 | nrev = binexp(n, mod - 2); 17 | for(int i = 1; i <= n; i++) { 18 | w[i] = (w[i - 1] * k) % mod; 19 | } 20 | } 21 | inline void ntt(vector &a, int n, bool inv = false) { 22 | a.resize(n); 23 | for(int i = 0, j = 0; i < n; i++) { 24 | if(i > j) swap(a[i], a[j]); 25 | for(int l = n / 2; (j ^= l) < l; l >>= 1); 26 | } 27 | for(int i = 2; i <= n; i <<= 1) { 28 | for(int j = 0; j < n; j += i) { 29 | for(int l = 0; l < i / 2; l++) { 30 | int x = j + l, y = j + l + (i / 2), z = (n / i) * l; 31 | long long tmp = (a[y] * w[(inv ? (n - z) : z)]) % mod; 32 | a[y] = (a[x] - tmp + mod) % mod; 33 | a[x] = (a[j + l] + tmp) % mod; 34 | } 35 | } 36 | } 37 | if(inv) { 38 | for(int i = 0; i < n; i++) { 39 | a[i] = (a[i] * nrev) % mod; 40 | } 41 | } 42 | } 43 | // use search() from PrimitiveRoot.cpp if MOD isn't 998244353 44 | vector multiply(vector& a, vector& b, int root = 3) { 45 | int n = a.size() + b.size() - 1; 46 | while(n & (n - 1)) n++; 47 | a.resize(n); 48 | b.resize(n); 49 | init(n, root); 50 | ntt(a, n); 51 | ntt(b, n); 52 | vector ans(n); 53 | for(int i = 0; i < n; i++) { 54 | ans[i] = (a[i] * b[i]) % mod; 55 | } 56 | ntt(ans, n, true); 57 | return ans; 58 | } 59 | vector poly_shift(vector& a, int shift) { 60 | int n = a.size() - 1; 61 | f(n); 62 | vector x(n + 1), y(n + 1); 63 | long long cur = 1; 64 | for(int i = 0; i <= n; i++) { 65 | x[i] = cur * ifact[i] % mod; 66 | cur = (cur * shift) % mod; 67 | y[i] = a[n - i] * fact[n - i] % mod; 68 | } 69 | vector tmp = multiply(x, y), res(n + 1); 70 | for(int i = 0; i <= n; i++) { 71 | res[i] = tmp[n - i] * ifact[i] % mod; 72 | } 73 | return res; 74 | } 75 | } -------------------------------------------------------------------------------- /math/pollard_rho.cpp: -------------------------------------------------------------------------------- 1 | // factor(N, v) to get N factorized in vector v 2 | // O(N ^ (1 / 4)) on average 3 | // Miller-Rabin - Primarily Test O(|base|*(logn)^2) 4 | ll addmod(ll a, ll b, ll m){ 5 | if(a >= m - b) return a + b - m; 6 | return a + b; 7 | } 8 | 9 | ll mulmod(ll a, ll b, ll m){ 10 | ll ans = 0; 11 | while(b){ 12 | if(b & 1) ans = addmod(ans, a, m); 13 | a = addmod(a, a, m); 14 | b >>= 1; 15 | } 16 | return ans; 17 | } 18 | 19 | ll fexp(ll a, ll b, ll n){ 20 | ll r = 1; 21 | while(b){ 22 | if(b & 1) r = mulmod(r, a, n); 23 | a = mulmod(a, a, n); 24 | b >>= 1; 25 | } 26 | return r; 27 | } 28 | 29 | bool miller(ll a, ll n){ 30 | if (a >= n) return true; 31 | ll s = 0, d = n - 1; 32 | while(d % 2 == 0) d >>= 1, s++; 33 | ll x = fexp(a, d, n); 34 | if (x == 1 || x == n - 1) return true; 35 | for (int r = 0; r < s; r++, x = mulmod(x,x,n)){ 36 | if (x == 1) return false; 37 | if (x == n - 1) return true; 38 | } 39 | return false; 40 | } 41 | 42 | bool isprime(ll n){ 43 | if(n == 1) return false; 44 | int base[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}; 45 | for (int i = 0; i < 12; ++i) if (!miller(base[i], n)) return false; 46 | return true; 47 | } 48 | 49 | ll pollard(ll n){ 50 | ll x, y, d, c = 1; 51 | if (n % 2 == 0) return 2; 52 | while(true){ 53 | y = x = 2; 54 | while(true){ 55 | x = addmod(mulmod(x,x,n), c, n); 56 | y = addmod(mulmod(y,y,n), c, n); 57 | y = addmod(mulmod(y,y,n), c, n); 58 | if (x == y) break; 59 | d = __gcd(abs(x-y), n); 60 | if (d > 1) return d; 61 | } 62 | c++; 63 | } 64 | } 65 | 66 | vector factor(ll n){ 67 | if (n == 1 || isprime(n)) return {n}; 68 | ll f = pollard(n); 69 | vector l = factor(f), r = factor(n / f); 70 | l.insert(l.end(), r.begin(), r.end()); 71 | sort(l.begin(), l.end()); 72 | return l; 73 | } 74 | 75 | //n < 2,047 base = {2}; 76 | //n < 9,080,191 base = {31, 73}; 77 | //n < 2,152,302,898,747 base = {2, 3, 5, 7, 11}; 78 | //n < 318,665,857,834,031,151,167,461 base = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}; 79 | //n < 3,317,044,064,679,887,385,961,981 base = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41}; 80 | -------------------------------------------------------------------------------- /math/pollard_rho_optimization.cpp: -------------------------------------------------------------------------------- 1 | // We recomend you to use pollard-rho.cpp! I've never needed this code, but here it is. 2 | // This uses Brent's algorithm for cycle detection 3 | // 4 | std::mt19937 rng((int) std::chrono::steady_clock::now().time_since_epoch().count()); 5 | 6 | ull func(ull x, ull n, ull c) { return (mulmod(x, x, n) + c) % n; // f(x) = (x^2 + c) % n; } 7 | 8 | ull pollard(ull n) { 9 | // Finds a positive divisor of n 10 | ull x, y, d, c; 11 | ull pot, lam; 12 | if(n % 2 == 0) return 2; 13 | if(isprime(n)) return n; 14 | 15 | while(1) { 16 | y = x = 2; d = 1; 17 | pot = lam = 1; 18 | while(1) { 19 | c = rng() % n; 20 | if(c != 0 and (c+2)%n != 0) break; 21 | } 22 | while(1) { 23 | if(pot == lam) { 24 | x = y; 25 | pot <<= 1; 26 | lam = 0; 27 | } 28 | y = func(y, n, c); 29 | lam++; 30 | d = gcd(x >= y ? x-y : y-x, n); 31 | if (d > 1) { 32 | if(d == n) break; 33 | else return d; 34 | } 35 | } 36 | } 37 | } 38 | 39 | void fator(ull n, vector &v) { 40 | // prime factorization of n, put into a vector v. 41 | // 42 | // for each prime factor of n, it is repeated the amount of times 43 | // that it divides n 44 | // 45 | // ex : n == 120, v = {2, 2, 2, 3, 5}; 46 | // 47 | // 48 | if(isprime(n)) { v.pb(n); return; } 49 | vector w, t; w.pb(n); t.pb(1); 50 | 51 | while(!w.empty()) { 52 | ull bck = w.back(); 53 | ull div = pollard(bck); 54 | 55 | if(div == w.back()) { 56 | int amt = 0; 57 | for(int i=0; i < (int) w.size(); i++) { 58 | int cur = 0; 59 | while(w[i] % div == 0) { 60 | w[i] /= div; 61 | cur++; 62 | } 63 | amt += cur * t[i]; 64 | if(w[i] == 1) { 65 | swap(w[i], w.back()); 66 | swap(t[i], t.back()); 67 | w.pop_back(); 68 | t.pop_back(); 69 | } 70 | } 71 | while(amt--) v.pb(div); 72 | } 73 | else { 74 | int amt = 0; 75 | while(w.back() % div == 0) { 76 | w.back() /= div; 77 | amt++; 78 | } 79 | amt *= t.back(); 80 | if(w.back() == 1) { 81 | w.pop_back(); 82 | t.pop_back(); 83 | } 84 | 85 | w.pb(div); 86 | t.pb(amt); 87 | } 88 | } 89 | 90 | // the divisors will not be sorted, so you need to sort it afterwards 91 | sort(v.begin(), v.end()); 92 | } 93 | -------------------------------------------------------------------------------- /math/prime_factors.cpp: -------------------------------------------------------------------------------- 1 | // Prime factors (up to 9*10^13. For greater see Pollard Rho) 2 | vi factors; 3 | int ind=0, pf = primes[0]; 4 | while (pf*pf <= n) { 5 | while (n%pf == 0) n /= pf, factors.pb(pf); 6 | pf = primes[++ind]; 7 | } 8 | if (n != 1) factors.pb(n); 9 | -------------------------------------------------------------------------------- /math/primitive_root.cpp: -------------------------------------------------------------------------------- 1 | // Finds a primitive root modulo p 2 | // To make it works for any value of p, we must add calculation of phi(p) 3 | // n is 1, 2, 4 or p^k or 2*p^k (p odd in both cases) 4 | ll root(ll p) { 5 | ll n = p-1; 6 | vector fact; 7 | 8 | for (int i=2; i*i<=n; ++i) if (n % i == 0) { 9 | fact.push_back (i); 10 | while (n % i == 0) n /= i; 11 | } 12 | 13 | if (n > 1) fact.push_back (n); 14 | 15 | for (int res=2; res<=p; ++res) { 16 | bool ok = true; 17 | for (size_t i=0; i= 0 6 | // 7 | // INPUT: A -- an m x n matrix 8 | // b -- an m-dimensional vector 9 | // c -- an n-dimensional vector 10 | // x -- a vector where the optimal solution will be stored 11 | // 12 | // OUTPUT: value of the optimal solution (infinity if unbounded 13 | // above, nan if infeasible) 14 | // 15 | // To use this code, create an LPSolver object with A, b, and c as 16 | // arguments. Then, call Solve(x). 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | using namespace std; 25 | typedef long double DOUBLE; 26 | typedef vector VD; 27 | typedef vector VVD; 28 | typedef vector VI; 29 | const DOUBLE EPS = 1e-9; 30 | 31 | struct LPSolver { 32 | int m, n; 33 | VI B, N; 34 | VVD D; 35 | 36 | LPSolver(const VVD &A, const VD &b, const VD &c) : 37 | m(b.size()), n(c.size()), N(n + 1), B(m), D(m + 2, VD(n + 2)) { 38 | for (int i = 0; i < m; i++) for (int j = 0; j < n; j++) D[i][j] = A[i][j]; 39 | for (int i = 0; i < m; i++) { B[i] = n + i; D[i][n] = -1; D[i][n + 1] = b[i]; } 40 | for (int j = 0; j < n; j++) { N[j] = j; D[m][j] = -c[j]; } 41 | N[n] = -1; D[m + 1][n] = 1; 42 | } 43 | 44 | void Pivot(int r, int s) { 45 | for (int i = 0; i < m + 2; i++) if (i != r) 46 | for (int j = 0; j < n + 2; j++) if (j != s) 47 | D[i][j] -= D[r][j] * D[i][s] / D[r][s]; 48 | for (int j = 0; j < n + 2; j++) if (j != s) D[r][j] /= D[r][s]; 49 | for (int i = 0; i < m + 2; i++) if (i != r) D[i][s] /= -D[r][s]; 50 | D[r][s] = 1.0 / D[r][s]; 51 | swap(B[r], N[s]); 52 | } 53 | 54 | bool Simplex(int phase) { 55 | int x = phase == 1 ? m + 1 : m; 56 | while (true) { 57 | int s = -1; 58 | for (int j = 0; j <= n; j++) { 59 | if (phase == 2 && N[j] == -1) continue; 60 | if (s == -1 || D[x][j] < D[x][s] || D[x][j] == D[x][s] && N[j] < N[s]) s = j; 61 | } 62 | if (D[x][s] > -EPS) return true; 63 | int r = -1; 64 | for (int i = 0; i < m; i++) { 65 | if (D[i][s] < EPS) continue; 66 | if (r == -1 || D[i][n + 1] / D[i][s] < D[r][n + 1] / D[r][s] || 67 | (D[i][n + 1] / D[i][s]) == (D[r][n + 1] / D[r][s]) && B[i] < B[r]) r = i; 68 | } 69 | if (r == -1) return false; 70 | Pivot(r, s); 71 | } 72 | } 73 | 74 | DOUBLE Solve(VD &x) { 75 | int r = 0; 76 | for (int i = 1; i < m; i++) if (D[i][n + 1] < D[r][n + 1]) r = i; 77 | if (D[r][n + 1] < -EPS) { 78 | Pivot(r, n); 79 | if (!Simplex(1) || D[m + 1][n + 1] < -EPS) return -numeric_limits::infinity(); 80 | for (int i = 0; i < m; i++) if (B[i] == -1) { 81 | int s = -1; 82 | for (int j = 0; j <= n; j++) 83 | if (s == -1 || D[i][j] < D[i][s] || D[i][j] == D[i][s] && N[j] < N[s]) s = j; 84 | Pivot(i, s); 85 | } 86 | } 87 | if (!Simplex(2)) return numeric_limits::infinity(); 88 | x = VD(n); 89 | for (int i = 0; i < m; i++) if (B[i] < n) x[B[i]] = D[i][n + 1]; 90 | return D[m][n + 1]; 91 | } 92 | }; 93 | 94 | int main() { 95 | 96 | const int m = 4; 97 | const int n = 3; 98 | DOUBLE _A[m][n] = { 99 | { 6, -1, 0 }, 100 | { -1, -5, 0 }, 101 | { 1, 5, 1 }, 102 | { -1, -5, -1 } 103 | }; 104 | DOUBLE _b[m] = { 10, -4, 5, -5 }; 105 | DOUBLE _c[n] = { 1, -1, 0 }; 106 | 107 | VVD A(m); 108 | VD b(_b, _b + m); 109 | VD c(_c, _c + n); 110 | for (int i = 0; i < m; i++) A[i] = VD(_A[i], _A[i] + n); 111 | 112 | LPSolver solver(A, b, c); 113 | VD x; 114 | DOUBLE value = solver.Solve(x); 115 | 116 | cerr << "VALUE: " << value << endl; // VALUE: 1.29032 117 | cerr << "SOLUTION:"; // SOLUTION: 1.74194 0.451613 1 118 | for (size_t i = 0; i < x.size(); i++) cerr << " " << x[i]; 119 | cerr << endl; 120 | return 0; 121 | } 122 | -------------------------------------------------------------------------------- /mathextra.tex: -------------------------------------------------------------------------------- 1 | \section{Math Extra} 2 | \subsection{Combinatorial formulas} 3 | 4 | $\sum_{k=0}^{n}k^{2}=n(n+1)(2n+1)/6$\\ 5 | $\sum_{k=0}^{n}k^{3}=n^{2}(n+1)^{2}/4$\\ 6 | $\sum_{k=0}^{n}k^{4}=(6n^{5}+15n^{4}+10n^{3}-n)/30$\\ 7 | $\sum_{k=0}^{n}k^{5}=(2n^{6}+6n^{5}+5n^{4}-n^{2})/12$\\ 8 | $\sum_{k=0}^{n}x^{k}=(x^{n+1}-1)/(x-1)$\\ 9 | $\sum_{k=0}^{n}kx^{k}=(x-(n+1)x^{n+1}+nx^{n+2})/(x-1)^{2}$\\ 10 | ${n \choose k}=\frac{n!}{(n-k)!k!}$\\ 11 | ${n \choose k}={n-1 \choose k}+{n-1 \choose k-1}$\\ 12 | ${n \choose k}=\frac{n}{n-k}{n-1 \choose k}$\\ 13 | ${n \choose k}=\frac{n-k+1}{k}{n \choose k-1}$\\ 14 | ${n+1 \choose k}=\frac{n+1}{n-k+1}{n \choose k}$\\ 15 | ${n \choose k+1}=\frac{n-k}{k+1}{n \choose k}$\\ 16 | $\sum_{k=1}^{n}k\tbinom{n}{k}=n2^{n-1}$\\ 17 | $\sum_{k=1}^{n}k^{2}\tbinom{n}{k}=(n+n^{2})2^{n-2}$\\ 18 | ${m+n \choose r}=\sum_{k=0}^{r}{m \choose k}{n \choose r-k}$\\ 19 | ${n \choose k}=\prod_{i=1}^{k}\frac{n-k+i}{i}$\\ 20 | 21 | \subsection{Number theory identities} 22 | \textbf{Lucas' Theorem:} For non-negative integers $m$ and $n$ and a prime $p$, 23 | 24 | $$\binom{m}{n}\equiv\prod_{i=0}^k\binom{m_i}{n_i}\pmod p,$$ 25 | where 26 | $$m=m_kp^k+m_{k-1}p^{k-1}+\cdots +m_1p+m_0$$ 27 | is the base $p$ representation of $m$, and similarly for $n$. 28 | 29 | \subsection{Stirling Numbers of the second kind} 30 | Number of ways to partition a set of $n$ numbers into $k$ non-empty subsets. 31 | 32 | $${n \brace k}=\frac{1}{k!}\sum_{j=0}^{k}(-1)^{(k-j)}{k \choose j}j^n$$ 33 | 34 | Recurrence relation: 35 | 36 | $${0 \brace 0}=1$$ 37 | $${n \brace 0}={0 \brace n}=1$$ 38 | $${n+1 \brace k}=k{n \brace k}+{n \brace k-1}$$ 39 | 40 | 41 | \subsection{Burnside's Lemma} 42 | Let $G$ be a finite group that acts on a set $X$. For each $g$ in $G$ let $X^g$ denote the set of elements in $X$ that are fixed by $g$, which means $X^g=\{x\in X| g(x)=x\}$. Burnside's lemma assers the following formula for the number of orbits, denoted $|X/G|$: 43 | \begin{align*} 44 | |X/G|=\frac{1}{|G|} \sum_{g\in G} |X^g| 45 | \end{align*} 46 | 47 | \subsection{Numerical integration} 48 | RK4: to integrate $\dot{y} = f(t, y)$ with $y_0 = y(t_0)$, compute 49 | \begin{align*} 50 | k_1 &= f(t_n, y_n) \\ 51 | k_2 &= f(t_n + \frac h 2, y_n + \frac h 2 k_1) \\ 52 | k_3 &= f(t_n + \frac h 2, y_n + \frac h 2 k_2) \\ 53 | k_4 &= f(t_n + h, y_n + h k_3) \\ 54 | y_{n+1} &= y_n + \frac h 6 (k_1 + 2k_2 + 2k_3 + k_4) 55 | \end{align*} 56 | -------------------------------------------------------------------------------- /misc/bitset.cpp: -------------------------------------------------------------------------------- 1 | //Goes through the subsets of a set x : 2 | int b = 0; 3 | do { 4 | // process subset b 5 | } while (b=(b-x)&x); 6 | -------------------------------------------------------------------------------- /misc/builtin.cpp: -------------------------------------------------------------------------------- 1 | __builtin_ctz(x) // trailing zeroes 2 | __builtin_clz(x) // leading zeroes 3 | __builtin_popcount(x) // # bits set 4 | __builtin_ffs(x) // index(LSB) + 1 [0 if x==0] 5 | 6 | // Add ll to the end for long long [__builtin_clzll(x)] 7 | -------------------------------------------------------------------------------- /misc/date.cpp: -------------------------------------------------------------------------------- 1 | struct Date { 2 | int d, m, y; 3 | static int mnt[], mntsum[]; 4 | 5 | Date() : d(1), m(1), y(1) {} 6 | Date(int d, int m, int y) : d(d), m(m), y(y) {} 7 | Date(int days) : d(1), m(1), y(1) { advance(days); } 8 | 9 | bool bissexto() { return (y%4 == 0 and y%100) or (y%400 == 0); } 10 | 11 | int mdays() { return mnt[m] + (m == 2)*bissexto(); } 12 | int ydays() { return 365+bissexto(); } 13 | 14 | int msum() { return mntsum[m-1] + (m > 2)*bissexto(); } 15 | int ysum() { return 365*(y-1) + (y-1)/4 - (y-1)/100 + (y-1)/400; } 16 | 17 | int count() { return (d-1) + msum() + ysum(); } 18 | 19 | int day() { 20 | int x = y - (m<3); 21 | return (x + x/4 - x/100 + x/400 + mntsum[m-1] + d + 6)%7; 22 | } 23 | 24 | void advance(int days) { 25 | days += count(); 26 | d = m = 1, y = 1 + days/366; 27 | days -= count(); 28 | while(days >= ydays()) days -= ydays(), y++; 29 | while(days >= mdays()) days -= mdays(), m++; 30 | d += days; 31 | } 32 | }; 33 | 34 | int Date::mnt[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 35 | int Date::mntsum[13] = {}; 36 | for(int i=1; i<13; ++i) Date::mntsum[i] = Date::mntsum[i-1] + Date::mnt[i]; 37 | -------------------------------------------------------------------------------- /misc/ita_paren2polish.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | /* 7 | * Parenthetic to polish expression conversion 8 | */ 9 | 10 | inline bool isOp(char c) { 11 | return c=='+' || c=='-' || c=='*' || c=='/' || c=='^'; 12 | } 13 | 14 | inline bool isCarac(char c) { 15 | return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9'); 16 | } 17 | 18 | int paren2polish(char* paren, char* polish) { 19 | map prec; 20 | prec['('] = 0; 21 | prec['+'] = prec['-'] = 1; 22 | prec['*'] = prec['/'] = 2; 23 | prec['^'] = 3; 24 | int len = 0; 25 | stack op; 26 | for (int i = 0; paren[i]; i++) { 27 | if (isOp(paren[i])) { 28 | while (!op.empty() && prec[op.top()] >= prec[paren[i]]) { 29 | polish[len++] = op.top(); op.pop(); 30 | } 31 | op.push(paren[i]); 32 | } 33 | else if (paren[i]=='(') op.push('('); 34 | else if (paren[i]==')') { 35 | for (; op.top()!='('; op.pop()) 36 | polish[len++] = op.top(); 37 | op.pop(); 38 | } 39 | else if (isCarac(paren[i])) 40 | polish[len++] = paren[i]; 41 | } 42 | for(; !op.empty(); op.pop()) 43 | polish[len++] = op.top(); 44 | polish[len] = 0; 45 | return len; 46 | } 47 | 48 | /* 49 | * TEST MATRIX 50 | */ 51 | 52 | int main() { 53 | int N, len; 54 | char polish[400], paren[400]; 55 | scanf("%d", &N); 56 | for (int j=0; j v, ans; 5 | 6 | void mergesort(int l, int r, vector &v){ 7 | if(l == r) return; 8 | int mid = (l+r)/2; 9 | mergesort(l, mid, v), mergesort(mid+1, r, v); 10 | int i = l, j = mid + 1, k = l; 11 | while(i <= mid or j <= r){ 12 | if(i <= mid and (j > r or v[i] <= v[j])) ans[k++] = v[i++]; 13 | else ans[k++] = v[j++], inv += j-k; 14 | } 15 | for(int i = l; i <= r; i++) v[i] = ans[i]; 16 | } 17 | 18 | //in main 19 | ans.resize(v.size()); 20 | -------------------------------------------------------------------------------- /misc/modular_int.cpp: -------------------------------------------------------------------------------- 1 | // Struct to do basic modular arithmetic 2 | 3 | template 4 | struct Modular { 5 | int v; 6 | 7 | static int minv(int a, int m) { 8 | a %= m; 9 | assert(a); 10 | return a == 1 ? 1 : int(m - ll(minv(m, a)) * ll(m) / a); 11 | } 12 | 13 | Modular(ll _v = 0) : v(int(_v % MOD)) { 14 | if (v < 0) v += MOD; 15 | } 16 | 17 | bool operator==(const Modular& b) const { return v == b.v; } 18 | bool operator!=(const Modular& b) const { return v != b.v; } 19 | 20 | friend Modular inv(const Modular& b) { return Modular(minv(b.v, MOD)); } 21 | 22 | friend ostream& operator<<(ostream& os, const Modular& b) { return os << b.v; } 23 | friend istream& operator>>(istream& is, Modular& b) { 24 | ll _v; 25 | is >> _v; 26 | b = Modular(_v); 27 | return is; 28 | } 29 | 30 | Modular operator+(const Modular& b) const { 31 | Modular ans; 32 | ans.v = v >= MOD - b.v ? v + b.v - MOD : v + b.v; 33 | return ans; 34 | } 35 | 36 | Modular operator-(const Modular& b) const { 37 | Modular ans; 38 | ans.v = v < b.v ? v - b.v + MOD : v - b.v; 39 | return ans; 40 | } 41 | 42 | Modular operator*(const Modular& b) const { 43 | Modular ans; 44 | ans.v = int(ll(v) * ll(b.v) % MOD); 45 | return ans; 46 | } 47 | 48 | Modular operator/(const Modular& b) const { 49 | return (*this) * inv(b); 50 | } 51 | 52 | Modular& operator+=(const Modular& b) { return *this = *this + b; } 53 | Modular& operator-=(const Modular& b) { return *this = *this - b; } 54 | Modular& operator*=(const Modular& b) { return *this = *this * b; } 55 | Modular& operator/=(const Modular& b) { return *this = *this / b; } 56 | }; 57 | 58 | using Mint = Modular; 59 | -------------------------------------------------------------------------------- /misc/parallel_bin_search.cpp: -------------------------------------------------------------------------------- 1 | // Parallel Binary Search - O(nlog n * cost to update data structure + qlog n * cost for binary search condition) 2 | 3 | struct Query { int i, ans; /*+ query related info*/ }; 4 | vector req; 5 | 6 | void pbs(vector& qs, int l /* = min value*/, int r /* = max value*/) { 7 | if (qs.empty()) return; 8 | 9 | if (l == r) { 10 | for (auto& q : qs) req[q.i].ans = l; 11 | return; 12 | } 13 | 14 | int mid = (l + r) / 2; 15 | // mid = (l + r + 1) / 2 if different from simple upper/lower bound 16 | 17 | for (int i = l; i <= mid; i++) { 18 | // add value to data structure 19 | } 20 | 21 | vector vl, vr; 22 | for (auto& q : qs) { 23 | if (/* cond */) vl.push_back(q); 24 | else vr.push_back(q); 25 | } 26 | 27 | pbs(vr, mid + 1, r); 28 | 29 | for (int i = l; i <= mid; i++) { 30 | // remove value from data structure 31 | } 32 | 33 | pbs(vl, l, mid); 34 | } 35 | -------------------------------------------------------------------------------- /misc/prime_numbers.txt: -------------------------------------------------------------------------------- 1 | 2 3 5 7 11 13 17 19 23 29 2 | 31 37 41 43 47 53 59 61 67 71 3 | 73 79 83 89 97 101 103 107 109 113 4 | 127 131 137 139 149 151 157 163 167 173 5 | 179 181 191 193 197 199 211 223 227 229 6 | 233 239 241 251 257 263 269 271 277 281 7 | 283 293 307 311 313 317 331 337 347 349 8 | 353 359 367 373 379 383 389 397 401 409 9 | 419 421 431 433 439 443 449 457 461 463 10 | 467 479 487 491 499 503 509 521 523 541 11 | 547 557 563 569 571 577 587 593 599 601 12 | 607 613 617 619 631 641 643 647 653 659 13 | 661 673 677 683 691 701 709 719 727 733 14 | 739 743 751 757 761 769 773 787 797 809 15 | 811 821 823 827 829 839 853 857 859 863 16 | 877 881 883 887 907 911 919 929 937 941 17 | 947 953 967 971 977 983 991 997 1009 1013 18 | 1019 1021 1031 1033 1039 1049 1051 1061 1063 1069 19 | 1087 1091 1093 1097 1103 1109 1117 1123 1129 1151 20 | 1153 1163 1171 1181 1187 1193 1201 1213 1217 1223 21 | 1229 1231 1237 1249 1259 1277 1279 1283 1289 1291 22 | 1297 1301 1303 1307 1319 1321 1327 1361 1367 1373 23 | 1381 1399 1409 1423 1427 1429 1433 1439 1447 1451 24 | 1453 1459 1471 1481 1483 1487 1489 1493 1499 1511 25 | 1523 1531 1543 1549 1553 1559 1567 1571 1579 1583 26 | 1597 1601 1607 1609 1613 1619 1621 1627 1637 1657 27 | 1663 1667 1669 1693 1697 1699 1709 1721 1723 1733 28 | 1741 1747 1753 1759 1777 1783 1787 1789 1801 1811 29 | 1823 1831 1847 1861 1867 1871 1873 1877 1879 1889 30 | 1901 1907 1913 1931 1933 1949 1951 1973 1979 1987 31 | 32 | 970'997 971'483 921'281'269 999'279'733 33 | 1'000'000'009 1'000'000'021 1'000'000'409 1'005'012'527 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /misc/python.py: -------------------------------------------------------------------------------- 1 | # reopen 2 | import sys 3 | sys.stdout = open('out','w') 4 | sys.stdin = open('in' ,'r') 5 | 6 | //Dummy example 7 | R = lambda: map(int, input().split()) 8 | n, k = R(), 9 | v, t = [], [0]*n 10 | for p, c, i in sorted(zip(R(), R(), range(n))): 11 | t[i] = sum(v)+c 12 | v += [c] 13 | v = sorted(v)[::-1] 14 | if len(v) > k: 15 | v.pop() 16 | print(' '.join(map(str, t))) 17 | -------------------------------------------------------------------------------- /misc/sqrt_decomposition.cpp: -------------------------------------------------------------------------------- 1 | // Square Root Decomposition (Mo's Algorithm) - O(n^(3/2)) 2 | const int N = 1e5+1, SQ = 500; 3 | int n, m, v[N]; 4 | 5 | void add(int p) { /* add value to aggregated data structure */ } 6 | void rem(int p) { /* remove value from aggregated data structure */ } 7 | 8 | struct query { int i, l, r, ans; } qs[N]; 9 | 10 | bool c1(query a, query b) { 11 | if(a.l/SQ != b.l/SQ) return a.l < b.l; 12 | return a.l/SQ&1 ? a.r > b.r : a.r < b.r; 13 | } 14 | 15 | bool c2(query a, query b) { return a.i < b.i; } 16 | 17 | /* inside main */ 18 | int l = 0, r = -1; 19 | sort(qs, qs+m, c1); 20 | for (int i = 0; i < m; ++i) { 21 | query &q = qs[i]; 22 | while (r < q.r) add(v[++r]); 23 | while (r > q.r) rem(v[r--]); 24 | while (l < q.l) rem(v[l++]); 25 | while (l > q.l) add(v[--l]); 26 | 27 | q.ans = /* calculate answer */; 28 | } 29 | 30 | sort(qs, qs+m, c2); // sort to original order 31 | -------------------------------------------------------------------------------- /misc/stanford_latlong.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Converts from rectangular coordinates to latitude/longitude and vice 3 | versa. Uses degrees (not radians). 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | struct ll 12 | { 13 | double r, lat, lon; 14 | }; 15 | 16 | struct rect 17 | { 18 | double x, y, z; 19 | }; 20 | 21 | ll convert(rect& P) 22 | { 23 | ll Q; 24 | Q.r = sqrt(P.x*P.x+P.y*P.y+P.z*P.z); 25 | Q.lat = 180/M_PI*asin(P.z/Q.r); 26 | Q.lon = 180/M_PI*acos(P.x/sqrt(P.x*P.x+P.y*P.y)); 27 | 28 | return Q; 29 | } 30 | 31 | rect convert(ll& Q) 32 | { 33 | rect P; 34 | P.x = Q.r*cos(Q.lon*M_PI/180)*cos(Q.lat*M_PI/180); 35 | P.y = Q.r*sin(Q.lon*M_PI/180)*cos(Q.lat*M_PI/180); 36 | P.z = Q.r*sin(Q.lat*M_PI/180); 37 | 38 | return P; 39 | } 40 | 41 | int main() 42 | { 43 | rect A; 44 | ll B; 45 | 46 | A.x = -1.0; A.y = 2.0; A.z = -3.0; 47 | 48 | B = convert(A); 49 | cout << B.r << " " << B.lat << " " << B.lon << endl; 50 | 51 | A = convert(B); 52 | cout << A.x << " " << A.y << " " << A.z << endl; 53 | } 54 | -------------------------------------------------------------------------------- /misc/week_day.cpp: -------------------------------------------------------------------------------- 1 | int v[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 }; 2 | int day(int d, int m, int y) { 3 | y -= m<3; 4 | return (y + y/4 - y/100 + y/400 + v[m-1] + d)%7; 5 | } 6 | -------------------------------------------------------------------------------- /notebook.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imeplusplus/icpc-notebook/d6db5cb0e077ed674fd16828f3c1e452a222d103/notebook.pdf -------------------------------------------------------------------------------- /notebook.tex: -------------------------------------------------------------------------------- 1 | \documentclass[a4paper,10pt]{article} 2 | \usepackage[left=0.4in,right=0.4in,top=0.7in,bottom=0.4in]{geometry} 3 | \usepackage{hyperref} 4 | \usepackage{fancyhdr} 5 | \usepackage{listings} 6 | \usepackage{xcolor} 7 | \usepackage{tocloft} 8 | \usepackage{pdflscape} 9 | \usepackage{multicol} 10 | \usepackage{tabularx} 11 | \usepackage{mathtools} 12 | 13 | \renewcommand*{\ttdefault}{pcr} 14 | \renewcommand\cftsecfont{\fontsize{8}{9}\bfseries} 15 | \renewcommand\cftsecpagefont{\fontsize{8}{9}\mdseries} 16 | \renewcommand\cftsubsecfont{\fontsize{5}{6}\mdseries} 17 | \renewcommand\cftsubsecpagefont{\fontsize{5}{6}\mdseries} 18 | \renewcommand\cftsecafterpnum{\vspace{-1ex}} 19 | \renewcommand\cftsubsecafterpnum{\vspace{-1ex}} 20 | 21 | \lstdefinestyle{shared}{ 22 | belowcaptionskip=1\baselineskip, 23 | breaklines=true, 24 | xleftmargin=\parindent, 25 | showstringspaces=false, 26 | basicstyle=\fontsize{6}{6}\ttfamily, 27 | } 28 | \lstdefinestyle{cpp}{ 29 | style=shared, 30 | language=C++, 31 | keywordstyle=\bfseries\color{green!40!black}, 32 | commentstyle=\itshape\color{red!80!black}, 33 | identifierstyle=\color{blue}, 34 | stringstyle=\color{purple!40!black}, 35 | } 36 | \lstdefinestyle{java}{ 37 | style=shared, 38 | language=Java, 39 | keywordstyle=\bfseries\color{green!40!black}, 40 | commentstyle=\itshape\color{purple!40!black}, 41 | identifierstyle=\color{blue}, 42 | stringstyle=\color{orange}, 43 | } 44 | \lstdefinestyle{py}{ 45 | style=shared, 46 | language=Python, 47 | keywordstyle=\bfseries\color{green!40!black}, 48 | commentstyle=\itshape\color{purple!40!black}, 49 | identifierstyle=\color{blue}, 50 | stringstyle=\color{orange}, 51 | } 52 | \lstdefinestyle{txt}{ 53 | style=shared, 54 | } 55 | \lstset{escapechar=@} 56 | 57 | \pagestyle{fancy} 58 | \fancyhead[L]{IME++} 59 | \fancyhead[R]{\thepage} 60 | \fancyfoot[C]{} 61 | 62 | \fancypagestyle{plain} 63 | { 64 | \fancyhead[L]{IME++} 65 | \fancyhead[R]{\thepage} 66 | \fancyfoot[C]{} 67 | } 68 | 69 | \title{\vspace{-4ex}\Large{IME++ ACM-ICPC Team Notebook}} 70 | \author{} 71 | \date{} 72 | 73 | \setlength{\columnseprule}{0.5pt} 74 | \def\columnseprulecolor{\color{black}} 75 | 76 | \begin{document} 77 | \begin{landscape} 78 | \begin{multicols}{3} 79 | 80 | \maketitle 81 | \vspace{-13ex} 82 | \tableofcontents 83 | \pagestyle{fancy} 84 | 85 | \input contents.tex 86 | \input mathextra.tex 87 | 88 | \end{multicols} 89 | 90 | \input solutionpage.tex 91 | 92 | \end{landscape} 93 | 94 | \end{document} 95 | -------------------------------------------------------------------------------- /solutionpage.tex: -------------------------------------------------------------------------------- 1 | \newpage 2 | \onecolumn 3 | \begin{table}[ht] 4 | \centering 5 | \resizebox{\textwidth}{!}{ 6 | \begin{tabularx}{\textwidth}{|c|c|c|c|X|c|c|} 7 | \hline 8 | & S & R & X & Assunto & Descricao & Diff\\ 9 | \hline 10 | & & & & & &\\ 11 | A & & & & & &\\ 12 | & & & & & &\\ 13 | \hline 14 | & & & & & &\\ 15 | B & & & & & &\\ 16 | & & & & & &\\ 17 | \hline 18 | & & & & & &\\ 19 | C & & & & & &\\ 20 | & & & & & &\\ 21 | \hline 22 | & & & & & &\\ 23 | D & & & & & &\\ 24 | & & & & & &\\ 25 | \hline 26 | & & & & & &\\ 27 | E & & & & & &\\ 28 | & & & & & &\\ 29 | \hline 30 | & & & & & &\\ 31 | F & & & & & &\\ 32 | & & & & & &\\ 33 | \hline 34 | & & & & & &\\ 35 | G & & & & & &\\ 36 | & & & & & &\\ 37 | \hline 38 | & & & & & &\\ 39 | H & & & & & &\\ 40 | & & & & & &\\ 41 | \hline 42 | & & & & & &\\ 43 | I & & & & & &\\ 44 | & & & & & &\\ 45 | \hline 46 | & & & & & &\\ 47 | J & & & & & &\\ 48 | & & & & & &\\ 49 | \hline 50 | & & & & & &\\ 51 | K & & & & & &\\ 52 | & & & & & &\\ 53 | \hline 54 | & & & & & &\\ 55 | L & & & & & &\\ 56 | & & & & & &\\ 57 | \hline 58 | \end{tabularx}} 59 | \end{table} 60 | -------------------------------------------------------------------------------- /strings/aho_corasick.cpp: -------------------------------------------------------------------------------- 1 | // Aho-Corasick 2 | 3 | // Build: O(sum size of patterns) 4 | // Find total number of matches: O(size of input string) 5 | // Find number of matches for each pattern: O(num of patterns + size of input string) 6 | 7 | // ids start from 0 by default! 8 | 9 | template 10 | struct Aho { 11 | struct Node { 12 | int p, char_p, link = -1, str_idx = -1, nxt[ALPHA_SIZE]; 13 | bool has_end = false; 14 | Node(int _p = -1, int _char_p = -1) : p(_p), char_p(_char_p) { 15 | fill(nxt, nxt + ALPHA_SIZE, -1); 16 | } 17 | }; 18 | 19 | vector nodes = { Node() }; 20 | int ans, cnt = 0; 21 | bool build_done = false; 22 | vector> rep; 23 | vector ord, occur, occur_aux; 24 | 25 | // change this if different alphabet 26 | int remap(char c) { 27 | if (islower(c)) return c - 'a'; 28 | if (isalpha(c)) return c - 'A' + 26; 29 | return c - '0' + 52; 30 | } 31 | 32 | void add(string &p, int id = -1) { 33 | int u = 0; 34 | if (id == -1) id = cnt++; 35 | 36 | for (char ch : p) { 37 | int c = remap(ch); 38 | if (nodes[u].nxt[c] == -1) { 39 | nodes[u].nxt[c] = (int)nodes.size(); 40 | nodes.push_back(Node(u, c)); 41 | } 42 | 43 | u = nodes[u].nxt[c]; 44 | } 45 | 46 | if (nodes[u].str_idx != -1) rep.push_back({ id, nodes[u].str_idx }); 47 | else nodes[u].str_idx = id; 48 | nodes[u].has_end = true; 49 | } 50 | 51 | void build() { 52 | build_done = true; 53 | queue q; 54 | 55 | for (int i = 0; i < ALPHA_SIZE; i++) { 56 | if (nodes[0].nxt[i] != -1) q.push(nodes[0].nxt[i]); 57 | else nodes[0].nxt[i] = 0; 58 | } 59 | 60 | while(q.size()) { 61 | int u = q.front(); 62 | ord.push_back(u); 63 | q.pop(); 64 | 65 | int j = nodes[nodes[u].p].link; 66 | if (j == -1) nodes[u].link = 0; 67 | else nodes[u].link = nodes[j].nxt[nodes[u].char_p]; 68 | 69 | nodes[u].has_end |= nodes[nodes[u].link].has_end; 70 | 71 | for (int i = 0; i < ALPHA_SIZE; i++) { 72 | if (nodes[u].nxt[i] != -1) q.push(nodes[u].nxt[i]); 73 | else nodes[u].nxt[i] = nodes[nodes[u].link].nxt[i]; 74 | } 75 | } 76 | } 77 | 78 | int match(string &s) { 79 | if (!cnt) return 0; 80 | if (!build_done) build(); 81 | 82 | ans = 0; 83 | occur = vector(cnt); 84 | occur_aux = vector(nodes.size()); 85 | 86 | int u = 0; 87 | for (char ch : s) { 88 | int c = remap(ch); 89 | u = nodes[u].nxt[c]; 90 | occur_aux[u]++; 91 | } 92 | 93 | for (int i = (int)ord.size() - 1; i >= 0; i--) { 94 | int v = ord[i]; 95 | int fv = nodes[v].link; 96 | occur_aux[fv] += occur_aux[v]; 97 | if (nodes[v].str_idx != -1) { 98 | occur[nodes[v].str_idx] = occur_aux[v]; 99 | ans += occur_aux[v]; 100 | } 101 | } 102 | 103 | for (pair x : rep) occur[x.first] = occur[x.second]; 104 | return ans; 105 | } 106 | }; 107 | -------------------------------------------------------------------------------- /strings/aho_emaxx.cpp: -------------------------------------------------------------------------------- 1 | // Aho Corasick - 2 | // Multiple string matching 3 | 4 | #include 5 | using namespace std; 6 | 7 | int remap(char c) { 8 | if (islower(c)) return c - 'a'; 9 | return c - 'A' + 26; 10 | } 11 | 12 | const int K = 52; 13 | 14 | struct Aho { 15 | struct Node { 16 | int nxt[K]; 17 | int par = -1; 18 | int link = -1; 19 | int go[K]; 20 | bitset<1005> ids; 21 | char pch; 22 | 23 | Node(int p = -1, char ch = '$') : par { p }, pch { ch } { 24 | fill(begin(nxt), end(nxt), -1); 25 | fill(begin(go), end(go), -1); 26 | } 27 | }; 28 | 29 | vector nodes; 30 | 31 | Aho() : nodes (1) {} 32 | 33 | void add_string(const string& s, int id) { 34 | int u = 0; 35 | for (char ch : s) { 36 | int c = remap(ch); 37 | if (nodes[u].nxt[c] == -1) { 38 | nodes[u].nxt[c] = nodes.size(); 39 | nodes.emplace_back(u, ch); 40 | } 41 | 42 | u = nodes[u].nxt[c]; 43 | } 44 | 45 | nodes[u].ids.set(id); 46 | } 47 | 48 | int get_link(int u) { 49 | if (nodes[u].link == -1) { 50 | if (u == 0 or nodes[u].par == 0) nodes[u].link = 0; 51 | else nodes[u].link = go(get_link(nodes[u].par), nodes[u].pch); 52 | } 53 | return nodes[u].link; 54 | } 55 | 56 | int go(int u, char ch) { 57 | int c = remap(ch); 58 | if (nodes[u].go[c] == -1) { 59 | if (nodes[u].nxt[c] != -1) nodes[u].go[c] = nodes[u].nxt[c]; 60 | else nodes[u].go[c] = (u == 0) ? 0 : go(get_link(u), ch); 61 | nodes[u].ids |= nodes[nodes[u].go[c]].ids; 62 | } 63 | return nodes[u].go[c]; 64 | } 65 | 66 | bitset<1005> run(const string& s) { 67 | bitset<1005> bs; 68 | int u = 0; 69 | for (char ch : s) { 70 | int c = remap(ch); 71 | if (go(u, ch) == -1) assert(0); 72 | bs |= nodes[u].ids; 73 | u = nodes[u].nxt[c]; 74 | if (u == -1) u = 0; 75 | } 76 | bs |= nodes[u].ids; 77 | return bs; 78 | } 79 | }; 80 | -------------------------------------------------------------------------------- /strings/booths_algorithm.cpp: -------------------------------------------------------------------------------- 1 | // Booth's Algorithm - Find the lexicographically least rotation of a string in O(n) 2 | 3 | string least_rotation(string s) { 4 | s += s; 5 | vector f((int)s.size(), -1); 6 | int k = 0; 7 | for (int j = 1; j < (int)s.size(); j++) { 8 | int i = f[j - k - 1]; 9 | while (i != -1 and s[j] != s[k + i + 1]) { 10 | if (s[j] < s[k + i + 1]) k = j - i - 1; 11 | i = f[i]; 12 | } 13 | 14 | if (s[j] != s[k + i + 1]) { 15 | if (s[j] < s[k]) k = j; 16 | f[j - k] = -1; 17 | } else f[j - k] = i + 1; 18 | } 19 | 20 | return s.substr(k, (int)s.size() / 2); 21 | } 22 | -------------------------------------------------------------------------------- /strings/eertree.cpp: -------------------------------------------------------------------------------- 1 | // creates an automaton with the suffix links being the largest suffix palindrome of the current string, all on O(nlogalpha) 2 | 3 | const int N = 1e6 + 7, alph = 26; 4 | 5 | char s[N]; 6 | int len[N], link[N], to[alph][N], prv[N]; 7 | int n, last, sz; 8 | long long ans; 9 | 10 | void init() { 11 | s[n++] = -1; 12 | link[0] = 1; 13 | len[1] = -1; 14 | sz = 2; 15 | } 16 | 17 | int get_link(int v) { 18 | while(s[n - len[v] - 2] != s[n - 1]) v = link[v]; 19 | return v; 20 | } 21 | 22 | void add_letter(char c) { 23 | s[n++] = c; 24 | last = get_link(last); 25 | if(!to[c - 'a'][last]) { 26 | len[sz] = len[last] + 2; 27 | link[sz] = to[c - 'a'][get_link(link[last])]; 28 | to[c - 'a'][last] = sz++; 29 | } 30 | last = to[c - 'a'][last]; 31 | } 32 | -------------------------------------------------------------------------------- /strings/kmp.cpp: -------------------------------------------------------------------------------- 1 | // Knuth-Morris-Pratt - String Matching O(n+m) 2 | char s[N], p[N]; 3 | int b[N], n, m; // n = strlen(s), m = strlen(p); 4 | 5 | void kmppre() { 6 | b[0] = -1; 7 | for (int i = 0, j = -1; i < m; b[++i] = ++j) 8 | while (j >= 0 and p[i] != p[j]) 9 | j = b[j]; 10 | } 11 | 12 | void kmp() { 13 | for (int i = 0, j = 0; i < n;) { 14 | while (j >= 0 and s[i] != p[j]) j=b[j]; 15 | i++, j++; 16 | if (j == m) { 17 | // match position i-j 18 | j = b[j]; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /strings/kmp_automaton.cpp: -------------------------------------------------------------------------------- 1 | // KMP Automaton - 2 | 3 | // max size pattern 4 | const int N = 1e5 + 5; 5 | 6 | int cnt, nxt[N+1][26]; 7 | 8 | void prekmp(string &p) { 9 | nxt[0][p[0] - 'a'] = 1; 10 | for(int i = 1, j = 0; i <= p.size(); i++) { 11 | for(int c = 0; c < 26; c++) nxt[i][c] = nxt[j][c]; 12 | if(i == p.size()) continue; 13 | nxt[i][p[i] - 'a'] = i+1; 14 | j = nxt[j][p[i] - 'a']; 15 | } 16 | } 17 | 18 | void kmp(string &s, string &p) { 19 | for(int i = 0, j = 0; i < s.size(); i++) { 20 | j = nxt[j][s[i] - 'a']; 21 | if(j == p.size()) cnt++; //match i - j + 1 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /strings/manacher.cpp: -------------------------------------------------------------------------------- 1 | // Manacher (Longest Palindromic String) - O(n) 2 | int lps[2*N+5]; 3 | char s[N]; 4 | 5 | int manacher() { 6 | int n = strlen(s); 7 | 8 | string p (2*n+3, '#'); 9 | p[0] = '^'; 10 | for (int i = 0; i < n; i++) p[2*(i+1)] = s[i]; 11 | p[2*n+2] = '$'; 12 | 13 | int k = 0, r = 0, m = 0; 14 | int l = p.length(); 15 | for (int i = 1; i < l; i++) { 16 | int o = 2*k - i; 17 | lps[i] = (r > i) ? min(r-i, lps[o]) : 0; 18 | while (p[i + 1 + lps[i]] == p[i - 1 - lps[i]]) lps[i]++; 19 | if (i + lps[i] > r) k = i, r = i + lps[i]; 20 | m = max(m, lps[i]); 21 | } 22 | return m; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /strings/manacher_2.cpp: -------------------------------------------------------------------------------- 1 | // Mancher O(n) 2 | 3 | vector d1, d2; 4 | 5 | // d1 -> odd : size = 2 * d1[i] - 1, palindrome from i - d1[i] + 1 to i + d1[i] - 1 6 | // d2 -> even : size = 2 * d2[i], palindrome from i - d2[i] to i + d2[i] - 1 7 | 8 | void manacher(string &s) { 9 | int n = s.size(); 10 | d1.resize(n), d2.resize(n); 11 | for(int i = 0, l1 = 0, l2 = 0, r1 = -1, r2 = -1; i < n; i++) { 12 | if(i <= r1) { 13 | d1[i] = min(d1[r1 + l1 - i], r1 - i + 1); 14 | } 15 | if(i <= r2) { 16 | d2[i] = min(d2[r2 + l2 - i + 1], r2 - i + 1); 17 | } 18 | while(i - d1[i] >= 0 and i + d1[i] < n and s[i - d1[i]] == s[i + d1[i]]) { 19 | d1[i]++; 20 | } 21 | while(i - d2[i] - 1 >= 0 and i + d2[i] < n and s[i - d2[i] - 1] == s[i + d2[i]]) { 22 | d2[i]++; 23 | } 24 | if(i + d1[i] - 1 > r1) { 25 | l1 = i - d1[i] + 1; 26 | r1 = i + d1[i] - 1; 27 | } 28 | if(i + d2[i] - 1 > r2) { 29 | l2 = i - d2[i]; 30 | r2 = i + d2[i] - 1; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /strings/rabin_karp.cpp: -------------------------------------------------------------------------------- 1 | // Rabin-Karp - String Matching + Hashing O(n+m) 2 | const int B = 31; 3 | char s[N], p[N]; 4 | int n, m; // n = strlen(s), m = strlen(p) 5 | 6 | void rabin() { 7 | if (n0 and s[pi[i]]!=s[i]) 7 | pi[i]=pi[pi[i]]; 8 | if(s[pi[i]]==s[i-1]) 9 | pi[i]++; 10 | } 11 | } 12 | 13 | int main() { 14 | //... 15 | //Initialize prefix function 16 | char p[N]; //Pattern 17 | int len = strlen(p); //Pattern size 18 | int pi[N]; //Prefix function 19 | p_f(p, pi); 20 | 21 | // Create KMP automaton 22 | int A[N][128]; //A[i][j]: from state i (size of largest suffix of text which is prefix of pattern), append character j -> new state A[i][j] 23 | for( char c : ALPHABET ) 24 | A[0][c] = (p[0] == c); 25 | for( int i = 1; p[i]; i++ ) { 26 | for( char c : ALPHABET ) { 27 | if(c==p[i]) 28 | A[i][c]=i+1; //match 29 | else 30 | A[i][c]=A[pi[i]][c]; //try second largest suffix 31 | } 32 | } 33 | 34 | //Create KMP "string appending" automaton 35 | // g_n = g_(n-1) + char(n) + g_(n-1) 36 | // g_0 = "", g_1 = "a", g_2 = "aba", g_3 = "abacaba", ... 37 | int F[M][N]; //F[i][j]: from state j (size of largest suffix of text which is prefix of pattern), append string g_i -> new state F[i][j] 38 | for(int i = 0; i < m; i++) { 39 | for(int j = 0; j <= len; j++) { 40 | if(i==0) 41 | F[i][j] = j; //append empty string 42 | else { 43 | int x = F[i-1][j]; //append g_(i-1) 44 | x = A[x][j]; //append character j 45 | x = F[i-1][x]; //append g_(i-1) 46 | F[i][j] = x; 47 | } 48 | } 49 | } 50 | 51 | //Create number of matches matrix 52 | int K[M][N]; //K[i][j]: from state j (size of largest suffix of text which is prefix of pattern), append string g_i -> K[i][j] matches 53 | for(int i = 0; i < m; i++) { 54 | for(int j = 0; j <= len; j++) { 55 | if(i==0) 56 | K[i][j] = (j==len); //append empty string 57 | else { 58 | int x = F[i-1][j]; //append g_(i-1) 59 | x = A[x][j]; //append character j 60 | 61 | K[i][j] = K[i-1][j] /*append g_(i-1)*/ + (x==len) /*append character j*/ + K[i-1][x]; /*append g_(i-1)*/ 62 | } 63 | } 64 | } 65 | //number of matches in g_k 66 | int answer = K[0][k]; 67 | //... 68 | } 69 | 70 | -------------------------------------------------------------------------------- /strings/string_hashing.cpp: -------------------------------------------------------------------------------- 1 | // String Hashing 2 | // Rabin Karp - O(n + m) 3 | 4 | // max size txt + 1 5 | const int N = 1e6 + 5; 6 | 7 | // lowercase letters p = 31 (remember to do s[i] - 'a' + 1) 8 | // uppercase and lowercase letters p = 53 (remember to do s[i] - 'a' + 1) 9 | // any character p = 313 10 | 11 | const int MOD = 1e9+9; 12 | ull h[N], p[N]; 13 | ull pr = 313; 14 | 15 | int cnt; 16 | 17 | 18 | void build(string &s) { 19 | p[0] = 1, p[1] = pr; 20 | for(int i = 1; i <= s.size(); i++) { 21 | h[i] = ((p[1]*h[i-1]) % MOD + s[i-1]) % MOD; 22 | p[i] = (p[1]*p[i-1]) % MOD; 23 | } 24 | } 25 | 26 | // 1-indexed 27 | ull fhash(int l, int r) { 28 | return (h[r] - ((h[l-1]*p[r-l+1]) % MOD) + MOD) % MOD; 29 | } 30 | 31 | ull shash(string &pt) { 32 | ull h = 0; 33 | for(int i = 0; i < pt.size(); i++) 34 | h = ((h*pr) % MOD + pt[i]) % MOD; 35 | return h; 36 | } 37 | 38 | void rabin_karp(string &s, string &pt) { 39 | build(s); 40 | ull hp = shash(pt); 41 | for(int i = 0, m = pt.size(); i + m <= s.size(); i++) { 42 | if(fhash(i+1, i+m) == hp) { 43 | // match at i 44 | cnt++; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /strings/string_multihashing.cpp: -------------------------------------------------------------------------------- 1 | // String Hashing 2 | // Rabin Karp - O(n + m) 3 | template 4 | struct Hash { 5 | int hs[N]; 6 | static vector mods; 7 | 8 | static int add(int a, int b, int mod) { return a >= mod - b ? a + b - mod : a + b; } 9 | static int sub(int a, int b, int mod) { return a - b < 0 ? a - b + mod : a - b; } 10 | static int mul(int a, int b, int mod) { return 1ll * a * b % mod; } 11 | 12 | Hash(int x = 0) { fill(hs, hs + N, x); } 13 | 14 | bool operator<(const Hash& b) const { 15 | for (int i = 0; i < N; i++) { 16 | if (hs[i] < b.hs[i]) return true; 17 | if (hs[i] > b.hs[i]) return false; 18 | } 19 | return false; 20 | } 21 | 22 | Hash operator+(const Hash& b) const { 23 | Hash ans; 24 | for (int i = 0; i < N; i++) ans.hs[i] = add(hs[i], b.hs[i], mods[i]); 25 | return ans; 26 | } 27 | 28 | Hash operator-(const Hash& b) const { 29 | Hash ans; 30 | for (int i = 0; i < N; i++) ans.hs[i] = sub(hs[i], b.hs[i], mods[i]); 31 | return ans; 32 | } 33 | 34 | Hash operator*(const Hash& b) const { 35 | Hash ans; 36 | for (int i = 0; i < N; i++) ans.hs[i] = mul(hs[i], b.hs[i], mods[i]); 37 | return ans; 38 | } 39 | 40 | Hash operator+(int b) const { 41 | Hash ans; 42 | for (int i = 0; i < N; i++) ans.hs[i] = add(hs[i], b, mods[i]); 43 | return ans; 44 | } 45 | 46 | Hash operator*(int b) const { 47 | Hash ans; 48 | for (int i = 0; i < N; i++) ans.hs[i] = mul(hs[i], b, mods[i]); 49 | return ans; 50 | } 51 | 52 | friend Hash operator*(int a, const Hash& b) { 53 | Hash ans; 54 | for (int i = 0; i < N; i++) ans.hs[i] = mul(b.hs[i], a, b.mods[i]); 55 | return ans; 56 | } 57 | 58 | friend ostream& operator<<(ostream& os, const Hash& b) { 59 | for (int i = 0; i < N; i++) os << b.hs[i] << " \n"[i == N - 1]; 60 | return os; 61 | } 62 | }; 63 | 64 | template vector Hash::mods = { (int) 1e9 + 9, (int) 1e9 + 33, (int) 1e9 + 87 }; 65 | 66 | // In case you need to generate the MODs, uncomment this: 67 | // Obs: you may need this on your template 68 | // mt19937_64 llrand((int) chrono::steady_clock::now().time_since_epoch().count()); 69 | // In main: gen<>(); 70 | /* 71 | template vector Hash::mods; 72 | template 73 | void gen() { 74 | while (Hash::mods.size() < N) { 75 | int mod; 76 | bool is_prime; 77 | do { 78 | mod = (int) 1e8 + (int) (llrand() % (int) 9e8); 79 | is_prime = true; 80 | for (int i = 2; i * i <= mod; i++) { 81 | if (mod % i == 0) { 82 | is_prime = false; 83 | break; 84 | } 85 | } 86 | } while (!is_prime); 87 | Hash::mods.push_back(mod); 88 | } 89 | } 90 | */ 91 | 92 | template 93 | struct PolyHash { 94 | vector> h, p; 95 | 96 | PolyHash(string& s, int pr = 313) { 97 | int sz = (int)s.size(); 98 | p.resize(sz + 1); 99 | h.resize(sz + 1); 100 | 101 | p[0] = 1, h[0] = s[0]; 102 | for (int i = 1; i < sz; i++) { 103 | h[i] = pr * h[i - 1] + s[i]; 104 | p[i] = pr * p[i - 1]; 105 | } 106 | } 107 | 108 | Hash fhash(int l, int r) { 109 | if (!l) return h[r]; 110 | return h[r] - h[l - 1] * p[r - l + 1]; 111 | } 112 | 113 | static Hash shash(string& s, int pr = 313) { 114 | Hash ans; 115 | for (int i = 0; i < (int)s.size(); i++) ans = pr * ans + s[i]; 116 | return ans; 117 | } 118 | 119 | friend int rabin_karp(string& s, string& pt) { 120 | PolyHash hs = PolyHash(s); 121 | Hash hp = hs.shash(pt); 122 | int cnt = 0; 123 | for (int i = 0, m = (int)pt.size(); i + m <= (int)s.size(); i++) { 124 | if (hs.fhash(i, i + m - 1) == hp) { 125 | // match at i 126 | cnt++; 127 | } 128 | } 129 | 130 | return cnt; 131 | } 132 | }; 133 | -------------------------------------------------------------------------------- /strings/suffix_array.cpp: -------------------------------------------------------------------------------- 1 | // Suffix Array O(nlogn) 2 | // s.push('$'); 3 | vector suffix_array(string &s){ 4 | int n = s.size(), alph = 256; 5 | vector cnt(max(n, alph)), p(n), c(n); 6 | 7 | for(auto c : s) cnt[c]++; 8 | for(int i = 1; i < alph; i++) cnt[i] += cnt[i - 1]; 9 | for(int i = 0; i < n; i++) p[--cnt[s[i]]] = i; 10 | for(int i = 1; i < n; i++) 11 | c[p[i]] = c[p[i - 1]] + (s[p[i]] != s[p[i - 1]]); 12 | 13 | vector c2(n), p2(n); 14 | 15 | for(int k = 0; (1 << k) < n; k++){ 16 | int classes = c[p[n - 1]] + 1; 17 | fill(cnt.begin(), cnt.begin() + classes, 0); 18 | 19 | for(int i = 0; i < n; i++) p2[i] = (p[i] - (1 << k) + n)%n; 20 | for(int i = 0; i < n; i++) cnt[c[i]]++; 21 | for(int i = 1; i < classes; i++) cnt[i] += cnt[i - 1]; 22 | for(int i = n - 1; i >= 0; i--) p[--cnt[c[p2[i]]]] = p2[i]; 23 | 24 | c2[p[0]] = 0; 25 | for(int i = 1; i < n; i++){ 26 | pair b1 = {c[p[i]], c[(p[i] + (1 << k))%n]}; 27 | pair b2 = {c[p[i - 1]], c[(p[i - 1] + (1 << k))%n]}; 28 | c2[p[i]] = c2[p[i - 1]] + (b1 != b2); 29 | } 30 | 31 | c.swap(c2); 32 | } 33 | return p; 34 | } 35 | 36 | // Longest Common Prefix with SA O(n) 37 | vector lcp(string &s, vector &p){ 38 | int n = s.size(); 39 | vector ans(n - 1), pi(n); 40 | for(int i = 0; i < n; i++) pi[p[i]] = i; 41 | 42 | int lst = 0; 43 | for(int i = 0; i < n - 1; i++){ 44 | if(pi[i] == n - 1) continue; 45 | while(s[i + lst] == s[p[pi[i] + 1] + lst]) lst++; 46 | 47 | ans[pi[i]] = lst; 48 | lst = max(0, lst - 1); 49 | } 50 | 51 | return ans; 52 | } 53 | 54 | // Longest Repeated Substring O(n) 55 | int lrs = 0; 56 | for (int i = 0; i < n; ++i) lrs = max(lrs, lcp[i]); 57 | 58 | // Longest Common Substring O(n) 59 | // m = strlen(s); 60 | // strcat(s, "$"); strcat(s, p); strcat(s, "#"); 61 | // n = strlen(s); 62 | int lcs = 0; 63 | for (int i = 1; i < n; ++i) if ((sa[i] < m) != (sa[i-1] < m)) 64 | lcs = max(lcs, lcp[i]); 65 | 66 | // To calc LCS for multiple texts use a slide window with minqueue 67 | // The numver of different substrings of a string is n*(n + 1)/2 - sum(lcs[i]) 68 | -------------------------------------------------------------------------------- /strings/suffix_automaton.cpp: -------------------------------------------------------------------------------- 1 | // Suffix Automaton Construction - O(n) 2 | 3 | const int N = 1e6+1, K = 26; 4 | int sl[2*N], len[2*N], sz, last; 5 | ll cnt[2*N]; 6 | map adj[2*N]; 7 | 8 | void add(int c) { 9 | int u = sz++; 10 | len[u] = len[last] + 1; 11 | cnt[u] = 1; 12 | 13 | int p = last; 14 | while(p != -1 and !adj[p][c]) 15 | adj[p][c] = u, p = sl[p]; 16 | 17 | if (p == -1) sl[u] = 0; 18 | else { 19 | int q = adj[p][c]; 20 | if (len[p] + 1 == len[q]) sl[u] = q; 21 | else { 22 | int r = sz++; 23 | len[r] = len[p] + 1; 24 | sl[r] = sl[q]; 25 | adj[r] = adj[q]; 26 | while(p != -1 and adj[p][c] == q) 27 | adj[p][c] = r, p = sl[p]; 28 | sl[q] = sl[u] = r; 29 | } 30 | } 31 | 32 | last = u; 33 | } 34 | 35 | void clear() { 36 | for(int i=0; i<=sz; ++i) adj[i].clear(); 37 | last = 0; 38 | sz = 1; 39 | sl[0] = -1; 40 | } 41 | 42 | void build(char *s) { 43 | clear(); 44 | for(int i=0; s[i]; ++i) add(s[i]); 45 | } 46 | 47 | // Pattern matching - O(|p|) 48 | bool check(char *p) { 49 | int u = 0, ok = 1; 50 | for(int i=0; p[i]; ++i) { 51 | u = adj[u][p[i]]; 52 | if (!u) ok = 0; 53 | } 54 | return ok; 55 | } 56 | 57 | // Substring count - O(|p|) 58 | ll d[2*N]; 59 | 60 | void substr_cnt(int u) { 61 | d[u] = 1; 62 | for(auto p : adj[u]) { 63 | int v = p.second; 64 | if (!d[v]) substr_cnt(v); 65 | d[u] += d[v]; 66 | } 67 | } 68 | 69 | ll substr_cnt() { 70 | memset(d, 0, sizeof d); 71 | substr_cnt(0); 72 | return d[0] - 1; 73 | } 74 | 75 | // k-th Substring - O(|s|) 76 | // Just find the k-th path in the automaton. 77 | // Can be done with the value d calculated in previous problem. 78 | 79 | // Smallest cyclic shift - O(|s|) 80 | // Build the automaton for string s + s. And adapt previous dp 81 | // to only count paths with size |s|. 82 | 83 | 84 | // Number of occurences - O(|p|) 85 | vector t[2*N]; 86 | 87 | void occur_count(int u) { 88 | for(int v : t[u]) occur_count(v), cnt[u] += cnt[v]; 89 | } 90 | 91 | void build_tree() { 92 | for(int i=1; i<=sz; ++i) 93 | t[sl[i]].push_back(i); 94 | occur_count(0); 95 | } 96 | 97 | ll occur_count(char *p) { 98 | // Call build tree once per automaton 99 | int u = 0; 100 | for(int i=0; p[i]; ++i) { 101 | u = adj[u][p[i]]; 102 | if (!u) break; 103 | } 104 | return !u ? 0 : cnt[u]; 105 | } 106 | 107 | // First occurence - (|p|) 108 | // Store the first position of occurence fp. 109 | // Add the the code to add function: 110 | // fp[u] = len[u] - 1; 111 | // fp[r] = fp[q]; 112 | 113 | // To answer a query, just output fp[u] - strlen(p) + 1 114 | // where u is the state corresponding to string p 115 | 116 | // All occurences - O(|p| + |ans|) 117 | // All the occurences can reach the first occurence via suffix links. 118 | // So every state that contains a occreunce is reacheable by the 119 | // first occurence state in the suffix link tree. Just do a DFS in this 120 | // tree, starting from the first occurence. 121 | // OBS: cloned nodes will output same answer twice. 122 | 123 | 124 | // Smallest substring not contained in the string - O(|s| * K) 125 | // Just do a dynamic programming: 126 | // d[u] = 1 // if d does not have 1 transition 127 | // d[u] = 1 + min d[v] // otherwise 128 | 129 | 130 | // LCS of 2 Strings - O(|s| + |t|) 131 | // Build automaton of s and traverse the automaton wih string t 132 | // mantaining the current state and the current lenght. 133 | // When we have a transition: update state, increase lenght by one. 134 | // If we don't update state by suffix link and the new lenght will 135 | // should be reduced (if bigger) to the new state length. 136 | // Answer will be the maximum length of the whole traversal. 137 | 138 | // LCS of n Strings - O(n*|s|*K) 139 | // Create a new string S = s_1 + d1 + ... + s_n + d_n, 140 | // where d_i are delimiters that are unique (d_i != d_j). 141 | // For each state use DP + bitmask to calculate if it can 142 | // reach a d_i transition without going through other d_j. 143 | // The answer will be the biggest len[u] that can reach all 144 | // d_i's. 145 | -------------------------------------------------------------------------------- /strings/suffix_tree.cpp: -------------------------------------------------------------------------------- 1 | // Suffix Tree 2 | // Build: O(|s|) 3 | // Match: O(|p|) 4 | 5 | template 6 | struct SuffixTree { 7 | struct Node { 8 | int p, link = -1, l, r, nch = 0; 9 | vector nxt; 10 | Node(int _l = 0, int _r = -1, int _p = -1) : p(_p), l(_l), r(_r), nxt(ALPHA_SIZE, -1) {} 11 | 12 | int len() { return r - l + 1; } 13 | int next(char ch) { return nxt[remap(ch)]; } 14 | 15 | // change this if different alphabet 16 | int remap(char c) { 17 | if (islower(c)) return c - 'a'; 18 | if (isalpha(c)) return c - 'A' + 26; 19 | return c - '0' + 52; 20 | } 21 | 22 | void setEdge(char ch, int nx) { 23 | int c = remap(ch); 24 | if (nxt[c] != -1 and nx == -1) nch--; 25 | else if (nxt[c] == -1 and nx != -1) nch++; 26 | nxt[c] = nx; 27 | } 28 | }; 29 | 30 | string s; 31 | long long num_diff_substr = 0; 32 | vector nodes; 33 | queue leaves; 34 | pair st = { 0, 0 }; 35 | int ls = 0, rs = -1, n; 36 | 37 | int size() { return rs - ls + 1; } 38 | 39 | SuffixTree(string &_s) { 40 | s = _s; 41 | // Add this if you want every suffix to be a node 42 | // s += '$'; 43 | n = (int)s.size(); 44 | nodes.reserve(2 * n + 1); 45 | nodes.push_back(Node()); 46 | //for (int i = 0; i < n; i++) extend(); 47 | } 48 | 49 | pair walk(pair _st, int l, int r) { 50 | int u = _st.first; 51 | int d = _st.second; 52 | 53 | while (l <= r) { 54 | if (d == nodes[u].len()) { 55 | u = nodes[u].next(s[l]), d = 0; 56 | if (u == -1) return { u, d }; 57 | } else { 58 | if (s[nodes[u].l + d] != s[l]) return { -1, -1 }; 59 | if (r - l + 1 + d < nodes[u].len()) return { u, r - l + 1 + d }; 60 | l += nodes[u].len() - d; 61 | d = nodes[u].len(); 62 | } 63 | } 64 | 65 | return { u, d }; 66 | } 67 | 68 | int split(pair _st) { 69 | int u = _st.first; 70 | int d = _st.second; 71 | 72 | if (d == nodes[u].len()) return u; 73 | if (!d) return nodes[u].p; 74 | 75 | Node& nu = nodes[u]; 76 | int mid = (int)nodes.size(); 77 | nodes.push_back(Node(nu.l, nu.l + d - 1, nu.p)); 78 | nodes[nu.p].setEdge(s[nu.l], mid); 79 | nodes[mid].setEdge(s[nu.l + d], u); 80 | nu.p = mid; 81 | nu.l += d; 82 | return mid; 83 | } 84 | 85 | int getLink(int u) { 86 | if (nodes[u].link != -1) return nodes[u].link; 87 | if (nodes[u].p == -1) return 0; 88 | int to = getLink(nodes[u].p); 89 | pair nst = { to, nodes[to].len() }; 90 | return nodes[u].link = split(walk(nst, nodes[u].l + (nodes[u].p == 0), nodes[u].r)); 91 | } 92 | 93 | bool match(string &p) { 94 | int u = 0, d = 0; 95 | for (char ch : p) { 96 | if (d == min(nodes[u].r, rs) - nodes[u].l + 1) { 97 | u = nodes[u].next(ch), d = 1; 98 | if (u == -1) return false; 99 | } else { 100 | if (ch != s[nodes[u].l + d]) return false; 101 | d++; 102 | } 103 | } 104 | return true; 105 | } 106 | 107 | void extend() { 108 | int mid; 109 | assert(rs != n - 1); 110 | rs++; 111 | num_diff_substr += (int)leaves.size(); 112 | do { 113 | pair nst = walk(st, rs, rs); 114 | if (nst.first != -1) { st = nst; return; } 115 | mid = split(st); 116 | int leaf = (int)nodes.size(); 117 | num_diff_substr++; 118 | leaves.push(leaf); 119 | nodes.push_back(Node(rs, n - 1, mid)); 120 | nodes[mid].setEdge(s[rs], leaf); 121 | int to = getLink(mid); 122 | st = { to, nodes[to].len() }; 123 | } while (mid); 124 | } 125 | 126 | void pop() { 127 | assert(ls <= rs); 128 | ls++; 129 | int leaf = leaves.front(); 130 | leaves.pop(); 131 | Node* nlf = &nodes[leaf]; 132 | while (!nlf->nch) { 133 | if (st.first != leaf) { 134 | nodes[nlf->p].setEdge(s[nlf->l], -1); 135 | num_diff_substr -= min(nlf->r, rs) - nlf->l + 1; 136 | leaf = nlf->p; 137 | nlf = &nodes[leaf]; 138 | } else { 139 | if (st.second != min(nlf->r, rs) - nlf->l + 1) { 140 | int mid = split(st); 141 | st.first = mid; 142 | num_diff_substr -= min(nlf->r, rs) - nlf->l + 1; 143 | nodes[mid].setEdge(s[nlf->l], -1); 144 | *nlf = nodes[mid]; 145 | nodes[nlf->p].setEdge(s[nlf->l], leaf); 146 | nodes.pop_back(); 147 | } 148 | break; 149 | } 150 | } 151 | 152 | if (leaf and !nlf->nch) { 153 | leaves.push(leaf); 154 | int to = getLink(nlf->p); 155 | pair nst = { to, nodes[to].len() }; 156 | st = walk(nst, nlf->l + (nlf->p == 0), nlf->r); 157 | nlf->l = rs - nlf->len() + 1; 158 | nlf->r = n - 1; 159 | } 160 | } 161 | }; 162 | -------------------------------------------------------------------------------- /strings/z_function.cpp: -------------------------------------------------------------------------------- 1 | // Z-Function - O(n) 2 | 3 | vector zfunction(const string& s){ 4 | vector z (s.size()); 5 | for (int i = 1, l = 0, r = 0, n = s.size(); i < n; i++){ 6 | if (i <= r) z[i] = min(z[i-l], r - i + 1); 7 | while (i + z[i] < n and s[z[i]] == s[z[i] + i]) z[i]++; 8 | if (i + z[i] - 1 > r) l = i, r = i + z[i] - 1; 9 | } 10 | return z; 11 | } 12 | -------------------------------------------------------------------------------- /template.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #define st first 5 | #define nd second 6 | #define mp make_pair 7 | #define cl(x, v) memset((x), (v), sizeof(x)) 8 | #define gcd(x,y) __gcd((x),(y)) 9 | 10 | #ifndef ONLINE_JUDGE 11 | #define db(x) cerr << #x << " == " << x << endl 12 | #define dbs(x) cerr << x << endl 13 | #define _ << ", " << 14 | #else 15 | #define db(x) ((void)0) 16 | #define dbs(x) ((void)0) 17 | #endif 18 | 19 | typedef long long ll; 20 | typedef long double ld; 21 | 22 | typedef pair pii; 23 | typedef pair piii; 24 | typedef pair pll; 25 | typedef pair plll; 26 | 27 | const ld EPS = 1e-9, PI = acos(-1.); 28 | const ll LINF = 0x3f3f3f3f3f3f3f3f; 29 | const int INF = 0x3f3f3f3f, MOD = 1e9+7;; 30 | const int N = 1e5+5; 31 | 32 | int main() { 33 | ios_base::sync_with_stdio(false); 34 | cin.tie(NULL); 35 | //freopen("in", "r", stdin); 36 | //freopen("out", "w", stdout); 37 | return 0; 38 | } -------------------------------------------------------------------------------- /tests/data-structures/bit.test.cpp: -------------------------------------------------------------------------------- 1 | // @problem_url: https://www.spoj.com/problems/FENTREE/ 2 | #include 3 | 4 | using namespace std; 5 | typedef long long ll; 6 | 7 | const int N = 2e6; 8 | 9 | // @include: data-structures/bit.cpp 10 | 11 | int main() { 12 | int n; 13 | cin >> n; 14 | 15 | for (int i = 1; i <= n; i++) { 16 | int x; 17 | cin >> x; 18 | add(i, x); 19 | } 20 | 21 | int q; 22 | cin >> q; 23 | 24 | for (int i = 0; i < q; i++) { 25 | char c; 26 | int a, b; 27 | 28 | cin >> c >> a >> b; 29 | 30 | if (c == 'q') { 31 | cout << query(b) - query(a - 1) << '\n'; 32 | } 33 | else { 34 | add(a, b); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /tests/data-structures/dsu.test.cpp: -------------------------------------------------------------------------------- 1 | // @problem_url: https://www.spoj.com/problems/FRNDCIRC/ 2 | #include 3 | using namespace std; 4 | 5 | const int N = 2e5; 6 | 7 | // @include: data-structures/dsu.cpp 8 | 9 | int main() { 10 | int t; 11 | cin >> t; 12 | 13 | while (t--) { 14 | for (int i = 0; i < 1e5; i++) { 15 | par[i] = i; 16 | sz[i] = 1; 17 | } 18 | 19 | map id; 20 | 21 | int n; 22 | cin >> n; 23 | 24 | for (int i = 0; i < n; i++) { 25 | string a, b; 26 | cin >> a >> b; 27 | 28 | if (id.count(a) == 0) { 29 | id[a] = id.size(); 30 | } 31 | 32 | if (id.count(b) == 0) { 33 | id[b] = id.size(); 34 | } 35 | 36 | unite(id[a], id[b]); 37 | 38 | cout << sz[find(id[a])] << '\n'; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/dynamic-programming/lis.test.cpp: -------------------------------------------------------------------------------- 1 | // @problem_url: https://codeforces.com/problemset/problem/340/D 2 | #include 3 | using namespace std; 4 | 5 | const int N = 2e5; 6 | 7 | int main() { 8 | int dp[N], v[N], n, lis; 9 | 10 | cin >> n; 11 | for (int i = 0; i < n; i++) 12 | cin >> v[i]; 13 | 14 | // @include: dynamic-programming/lis.cpp 15 | 16 | cout << lis << endl; 17 | } 18 | -------------------------------------------------------------------------------- /tests/graphs/hungarian-navarro.test1.cpp: -------------------------------------------------------------------------------- 1 | // @problem_url: https://codeforces.com/group/kZPk3ZTzR5/contest/102346/problem/G 2 | #include 3 | using namespace std; 4 | 5 | // @include: graphs/hungarian-navarro.cpp 6 | 7 | int n, m; 8 | long double x; 9 | 10 | int main() { 11 | ios_base::sync_with_stdio(0), cin.tie(0); 12 | cin >> n; 13 | auto h = HungarianMult (n, n); 14 | 15 | for (int i = 0; i < n; i++) { 16 | for (int j = 0; j < n; j++) { 17 | cin >> x; 18 | h.update(i, j, x); 19 | } 20 | } 21 | 22 | h.run(); 23 | for (int i = 0; i < n; i++) cout << h.pairV[i] + 1 << " \n"[i == n - 1]; 24 | } -------------------------------------------------------------------------------- /tests/graphs/hungarian-navarro.test2.cpp: -------------------------------------------------------------------------------- 1 | // @problem_url: https://codeforces.com/gym/101635/problem/G 2 | #include 3 | using namespace std; 4 | 5 | // @include: graphs/hungarian-navarro.cpp 6 | 7 | const int N = 2e3 + 5; 8 | 9 | int n, m; 10 | pair b[N], c[N], rest; 11 | 12 | int main(){ 13 | ios_base::sync_with_stdio(0), cin.tie(0); 14 | cin >> n >> m; 15 | for (int i = 0; i < n; i++) cin >> b[i].first >> b[i].second; 16 | for (int i = 0; i < m; i++) cin >> c[i].first >> c[i].second; 17 | cin >> rest.first >> rest.second; 18 | 19 | auto h = Hungarian (n + m - 1, n); 20 | 21 | int ans = 0; 22 | for (int i = 0; i < n; i++) ans += abs(rest.first - b[i].first) + abs(rest.second - b[i].second); 23 | 24 | for (int i = 0; i < n; i++) { 25 | for (int j = 0; j < n + m - 1; j++) { 26 | if (j < m) h.update(j, i, abs(b[i].first - c[j].first) + abs(b[i].second - c[j].second)); 27 | else h.update(j, i, abs(rest.first - b[i].first) + abs(rest.second - b[i].second)); 28 | } 29 | } 30 | 31 | cout << (ans + h.run()) << "\n"; 32 | 33 | return 0; 34 | } -------------------------------------------------------------------------------- /tests/math/fft.test.cpp: -------------------------------------------------------------------------------- 1 | // @problem_url: https://www.spoj.com/problems/MUL/ 2 | #include 3 | 4 | using namespace std; 5 | typedef long double ld; 6 | const ld PI = acos(-1); 7 | 8 | const int N = 2e5; 9 | 10 | // @include: math/fft.cpp 11 | 12 | int main() { 13 | int n; 14 | cin >> n; 15 | 16 | while (n--) { 17 | string a, b; 18 | cin >> a >> b; 19 | 20 | int size = a.size() + b.size(); 21 | while (size - (size & -size) != 0) size -= size & -size; 22 | size *= 2; 23 | 24 | vector va(size); 25 | vector vb(size); 26 | 27 | for (int i = 0; i < a.size(); i++) va[a.size() - i - 1].x = a[i] - '0'; 28 | for (int i = 0; i < b.size(); i++) vb[b.size() - i - 1].x = b[i] - '0'; 29 | 30 | multiply(&va[0], &vb[0], size); 31 | 32 | string answer; 33 | int goes = 0; 34 | 35 | for (auto c : va) { 36 | int x = c.x + 0.5 + goes; 37 | 38 | goes = 0; 39 | if (x > 9) { 40 | goes = x / 10; 41 | x = x % 10; 42 | } 43 | 44 | answer.push_back(x + '0'); 45 | } 46 | answer.push_back(goes + '0'); 47 | 48 | while (answer.back() == '0') answer.pop_back(); 49 | if (answer.empty()) answer.push_back('0'); 50 | reverse(answer.begin(), answer.end()); 51 | 52 | cout << answer << endl; 53 | } 54 | } -------------------------------------------------------------------------------- /tests/strings/z.test.cpp: -------------------------------------------------------------------------------- 1 | // @problem_url: https://www.spoj.com/problems/NAJPF/ 2 | #include 3 | using namespace std; 4 | 5 | // @include: strings/z.cpp 6 | 7 | int main() { 8 | int t; 9 | cin >> t; 10 | while (t--) { 11 | string s, p; 12 | cin >> s >> p; 13 | 14 | int p_size = p.size(); 15 | p.push_back('#'); 16 | p.append(s); 17 | 18 | auto z = zfunction(p); 19 | 20 | vector match; 21 | for (int i = p_size + 1; i < p.size(); i++) { 22 | if (z[i] == p_size) match.push_back(i - p_size); 23 | } 24 | 25 | if (match.empty()) { 26 | cout << "Not Found\n\n"; 27 | continue; 28 | } 29 | 30 | cout << match.size() << '\n'; 31 | 32 | for (auto x : match) cout << x << " "; 33 | cout << "\n\n"; 34 | } 35 | } -------------------------------------------------------------------------------- /vimrc: -------------------------------------------------------------------------------- 1 | syntax on 2 | set et ts=2 sw=0 sts=-1 ai nu hls cindent 3 | nnoremap ; : 4 | vnoremap ; : 5 | noremap 15gj 6 | noremap 15gk 7 | nnoremap i 8 | inoremap ,. 9 | vnoremap ,. 10 | nnoremap ,. 11 | --------------------------------------------------------------------------------