├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── bashrc ├── code ├── bit.cpp ├── bit_library.cpp ├── contra_ataque_ramsay.cpp ├── ed │ ├── LineContainer.cpp │ ├── bit2D.cpp │ ├── cht.cpp │ ├── cht_simple.cpp │ ├── eertree.cpp │ ├── hash_table.cpp │ ├── hld.cpp │ ├── lichao.cpp │ ├── merge_sort_tree.cpp │ ├── minq.cpp │ ├── order_set.cpp │ ├── segtree.cpp │ ├── segtree_rec.cpp │ ├── sparse_table.cpp │ ├── suffix_tree.cpp │ ├── treap.cpp │ └── wavelet_tree.cpp ├── fft.cpp ├── fft_tourist.cpp ├── gauss.cpp ├── gauss_xor.cpp ├── geometry │ ├── 2D.cpp │ ├── circle_line_intersection.cpp │ ├── convexhull.cpp │ ├── detect_halfplane.cpp │ ├── halfplane.cpp │ ├── in_poly.cpp │ ├── in_poly2.cpp │ ├── mink.cpp │ ├── near.cpp │ └── tangents.cpp ├── graph │ ├── bipartite_matching.cpp │ ├── blossom.cpp │ ├── centroid_decomp.cpp │ ├── circulation.cpp │ ├── dinic.cpp │ ├── dominator_tree.cpp │ ├── hungarian_mcm.cpp │ ├── kosaraju.cpp │ ├── maxcliq.cpp │ ├── mcmf.cpp │ ├── mcmf_dfs.cpp │ ├── mcmf_dijkstra.cpp │ ├── pushrelabel.cpp │ ├── stl.cpp │ ├── tarjan.cpp │ └── weight_blossom.cpp ├── math │ ├── crt.cpp │ ├── det.cpp │ ├── diophantine.cpp │ ├── division_trick.cpp │ ├── euclides.cpp │ ├── fast_mul_mod.cpp │ ├── inv.cpp │ ├── karatsuba.cpp │ ├── matrix.cpp │ ├── matrix_simple.cpp │ ├── miller_rabin.cpp │ ├── mobius.cpp │ ├── mod.cpp │ ├── mod_arithmetic.cpp │ ├── pollard_rho.cpp │ ├── primitive_root.cpp │ ├── simplex.cpp │ ├── simpson.cpp │ └── tot.cpp ├── matroid.cpp ├── misc │ ├── ColorUpdate.cpp │ ├── bigint.cpp │ ├── bipar.cpp │ ├── bitset.cpp │ ├── buffered_reader.cpp │ ├── burn.cpp │ ├── edge_coloring.cpp │ ├── factmod.cpp │ ├── fast_mod.cpp │ ├── fastio.cpp │ ├── hilbert_order.cpp │ ├── klondike.cpp │ ├── knapsack_bounded_cost.cpp │ ├── lca.cpp │ ├── lis.cpp │ ├── rand.cpp │ ├── recursive_lambda.cpp │ ├── slope.cpp │ ├── submasks.cpp │ └── sum_mod.cpp ├── ntt.cpp ├── string │ ├── adamant_suffix_tree.cpp │ ├── aho_corasick.cpp │ ├── all_palindrome.cpp │ ├── min_rot.cpp │ ├── pf.cpp │ ├── suffix_array.cpp │ ├── suffix_automaton.cpp │ └── z_algo.cpp └── template.cpp ├── notebook.pdf ├── notebook.tex ├── scripts └── unused_files.sh └── vimrc /.gitignore: -------------------------------------------------------------------------------- 1 | *.out 2 | in 3 | *.swp 4 | 5 | ## Core latex/pdflatex auxiliary files: 6 | *.aux 7 | *.lof 8 | *.log 9 | *.lot 10 | *.fls 11 | *.out 12 | *.toc 13 | *.fmt 14 | *.fot 15 | *.cb 16 | *.cb2 17 | .*.lb 18 | 19 | ## Intermediate documents: 20 | *.dvi 21 | *.xdv 22 | *-converted-to.* 23 | # these rules might exclude image files for figures etc. 24 | # *.ps 25 | # *.eps 26 | # *.pdf 27 | 28 | ## Generated if empty string is given at "Please type another file name for output:" 29 | .pdf 30 | 31 | ## Bibliography auxiliary files (bibtex/biblatex/biber): 32 | *.bbl 33 | *.bcf 34 | *.blg 35 | *-blx.aux 36 | *-blx.bib 37 | *.run.xml 38 | 39 | ## Build tool auxiliary files: 40 | *.fdb_latexmk 41 | *.synctex 42 | *.synctex(busy) 43 | *.synctex.gz 44 | *.synctex.gz(busy) 45 | *.pdfsync 46 | 47 | ## Auxiliary and intermediate files from other packages: 48 | # algorithms 49 | *.alg 50 | *.loa 51 | 52 | # achemso 53 | acs-*.bib 54 | 55 | # amsthm 56 | *.thm 57 | 58 | # beamer 59 | *.nav 60 | *.pre 61 | *.snm 62 | *.vrb 63 | 64 | # changes 65 | *.soc 66 | 67 | # cprotect 68 | *.cpt 69 | 70 | # elsarticle (documentclass of Elsevier journals) 71 | *.spl 72 | 73 | # endnotes 74 | *.ent 75 | 76 | # fixme 77 | *.lox 78 | 79 | # feynmf/feynmp 80 | *.mf 81 | *.mp 82 | *.t[1-9] 83 | *.t[1-9][0-9] 84 | *.tfm 85 | 86 | #(r)(e)ledmac/(r)(e)ledpar 87 | *.end 88 | *.?end 89 | *.[1-9] 90 | *.[1-9][0-9] 91 | *.[1-9][0-9][0-9] 92 | *.[1-9]R 93 | *.[1-9][0-9]R 94 | *.[1-9][0-9][0-9]R 95 | *.eledsec[1-9] 96 | *.eledsec[1-9]R 97 | *.eledsec[1-9][0-9] 98 | *.eledsec[1-9][0-9]R 99 | *.eledsec[1-9][0-9][0-9] 100 | *.eledsec[1-9][0-9][0-9]R 101 | 102 | # glossaries 103 | *.acn 104 | *.acr 105 | *.glg 106 | *.glo 107 | *.gls 108 | *.glsdefs 109 | 110 | # gnuplottex 111 | *-gnuplottex-* 112 | 113 | # gregoriotex 114 | *.gaux 115 | *.gtex 116 | 117 | # htlatex 118 | *.4ct 119 | *.4tc 120 | *.idv 121 | *.lg 122 | *.trc 123 | *.xref 124 | 125 | # hyperref 126 | *.brf 127 | 128 | # knitr 129 | *-concordance.tex 130 | # TODO Comment the next line if you want to keep your tikz graphics files 131 | *.tikz 132 | *-tikzDictionary 133 | 134 | # listings 135 | *.lol 136 | 137 | # makeidx 138 | *.idx 139 | *.ilg 140 | *.ind 141 | *.ist 142 | 143 | # minitoc 144 | *.maf 145 | *.mlf 146 | *.mlt 147 | *.mtc[0-9]* 148 | *.slf[0-9]* 149 | *.slt[0-9]* 150 | *.stc[0-9]* 151 | 152 | # minted 153 | _minted* 154 | *.pyg 155 | 156 | # morewrites 157 | *.mw 158 | 159 | # nomencl 160 | *.nlg 161 | *.nlo 162 | *.nls 163 | 164 | # pax 165 | *.pax 166 | 167 | # pdfpcnotes 168 | *.pdfpc 169 | 170 | # sagetex 171 | *.sagetex.sage 172 | *.sagetex.py 173 | *.sagetex.scmd 174 | 175 | # scrwfile 176 | *.wrt 177 | 178 | # sympy 179 | *.sout 180 | *.sympy 181 | sympy-plots-for-*.tex/ 182 | 183 | # pdfcomment 184 | *.upa 185 | *.upb 186 | 187 | # pythontex 188 | *.pytxcode 189 | pythontex-files-*/ 190 | 191 | # thmtools 192 | *.loe 193 | 194 | # TikZ & PGF 195 | *.dpth 196 | *.md5 197 | *.auxlock 198 | 199 | # todonotes 200 | *.tdo 201 | 202 | # easy-todo 203 | *.lod 204 | 205 | # xmpincl 206 | *.xmpi 207 | 208 | # xindy 209 | *.xdy 210 | 211 | # xypic precompiled matrices 212 | *.xyc 213 | 214 | # endfloat 215 | *.ttt 216 | *.fff 217 | 218 | # Latexian 219 | TSWLatexianTemp* 220 | 221 | ## Editors: 222 | # WinEdt 223 | *.bak 224 | *.sav 225 | 226 | # Texpad 227 | .texpadtmp 228 | 229 | # Kile 230 | *.backup 231 | 232 | # KBibTeX 233 | *~[0-9]* 234 | 235 | # auto folder when using emacs and auctex 236 | ./auto/* 237 | *.el 238 | 239 | # expex forward references with \gathertags 240 | *-tags.tex 241 | 242 | # standalone packages 243 | *.sta 244 | 245 | # generated if using elsarticle.cls 246 | *.spl 247 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 José Marcos da Silva Leite 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 | show_unused_files: 2 | @./scripts/unused_files.sh 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # icpc-notebook -------------------------------------------------------------------------------- /bashrc: -------------------------------------------------------------------------------- 1 | alias comp='g++ -std=c++17 -Wshadow -Wall -Wextra -Wformat=2 -Wconversion -fsanitize=address,undefined -fno-sanitize-recover -Wfatal-errors' 2 | 3 | -------------------------------------------------------------------------------- /code/bit.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* bit diferente -> range minimum query*/ 3 | 4 | struct ft_diff { 5 | int n; 6 | vector ft, ft_inv; 7 | vector vet; 8 | 9 | ft_diff(int size) : n(size), ft(n, 0), ft_inv(n, 0), vet(n, 0){ 10 | for (int i = 1; i < n; i++) ft[i] = ft_inv[i] = i; 11 | } 12 | int min_id(int a, int b) const { 13 | return vet[a] < vet[b] ? a : b; 14 | } 15 | int min_id_ft(int a, int b) const { 16 | return vet[a] < vet[ft[b]] ? a : b; 17 | } 18 | int min_id_inv(int a, int b) const { 19 | return vet[a] < vet[ft_inv[b]] ? a : b; 20 | } 21 | int query_rmq (int a, int b) const{ 22 | int i, mini = a; 23 | //bit invertida 24 | for (i = a; i <= b; i += (i & -i)) 25 | if (i + (i & -i) <= b) 26 | mini = min_id(mini, ft_inv[i]); 27 | else mini = min_id(min, i); 28 | //bit normal 29 | for (i = b; i >= a; i -= (i & -i)) 30 | if (i - (i & -i) >= a) 31 | mini = min_id(mini, ft[i]); 32 | return mini; 33 | } 34 | 35 | void upd (int a, int v) { 36 | put_value(a, v); 37 | update_rmq(a, v); 38 | } 39 | 40 | void put_value (int a, int v) { 41 | vet[a] = v; 42 | } 43 | void update_rmq (int a, int v) { 44 | int mini_l = a, mini_r = a; 45 | for (int i = a; i < n; i += (i & -i)) { 46 | if (ft[i] != a) ft[i] = min_id(a, ft[i]); 47 | else { 48 | ft[i] = vet[mini_l] < vet[mini_r] ? 49 | min_id(mini_l, a) : mini(mini_r, a); 50 | if (i >= a + 1) 51 | mini_r = min_id_inv(mini_r, i); 52 | if (i - (i & -i) + 1 <= a - 1) 53 | mini_l = min_id_ft(mini_l, i - (i & -i) + 1); 54 | } 55 | } 56 | mini_l = a, mini_r = a; 57 | //bit invertida 58 | for (int i = a; i; i -= (i & -i)) { 59 | if (ft_inv[i] != a) ft_inv[i] = min_id(a, ft_inv[i]); 60 | else { 61 | ft_inv[i] = vet[mini_l] < vet[mini_r] ? 62 | min_id(mini_l, a) : min_id(mini_r, a); 63 | if (i + (i & -i) - 1 >= a + 1) 64 | mini_r = min_id_inv(mini_r, i + (i & -i) - 1); 65 | if (i <= a - 1) 66 | mini_l = min_id_ft(mini_l, i); 67 | } 68 | } 69 | } 70 | 71 | }; 72 | 73 | -------------------------------------------------------------------------------- /code/bit_library.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | #define MAXN 100000 7 | //int vet[MAXN]; 8 | //int ft[MAXN]; 9 | //int ft_inv[MAXN]; 10 | 11 | /* bit normal -> cumulative frequency */ 12 | 13 | class ft_normal { 14 | public: 15 | 16 | vector ft; 17 | int n; 18 | 19 | ft_normal (int size) : n(size), ft(n, 0){} 20 | int query_cf(int a) const{ int resp = 0; 21 | for (int i = a; i; i -= (i & -i)) resp += ft[i]; 22 | return resp; } 23 | int update_cf (int a, int v) { 24 | for (int i = a; i < n; i += (i & -i)) ft[i] += v; 25 | return 0; } 26 | 27 | }; 28 | 29 | 30 | class ft_invert { 31 | public: 32 | 33 | vector ft_inv; 34 | int n; 35 | 36 | ft_invert (int size) : n(size), ft_inv(n, 0){} 37 | int query_cf_inv(int a) const{ int resp = 0; 38 | for (int i = a; i < n; i += (i & -i)) resp += ft_inv[i]; 39 | return resp; } 40 | int update_cf_inv (int a, int v) { 41 | for (int i = a; i; i -= (i & -i)) ft_inv[i] += v; 42 | return 0; } 43 | }; 44 | 45 | /* bit diferente -> range minimum query*/ 46 | 47 | class ft_diff { 48 | public: 49 | int n; 50 | vector ft; 51 | vector ft_inv; 52 | vector vet; 53 | 54 | ft_diff(int size) : n(size), ft(n, 0), ft_inv(n, 0), vet(n, 0){ 55 | for (int i = 1; i < n; i++) ft[i] = ft_inv[i] = i; } 56 | int query_rmq (int a, int b) const{ 57 | int i, mini = a; 58 | //bit normal 59 | for (i = a; i <= b; i += (i & -i)) 60 | if (i + (i & -i) <= b) mini = vet[mini] < vet[ft_inv[i]] ? mini : ft_inv[i]; 61 | else mini = vet[mini] < vet[i] ? mini : i; 62 | //bit invertida 63 | for (i = b; i >= a; i -= (i & -i)) 64 | if (i - (i & -i) >= a) mini = vet[mini] < vet[ft[i]] ? mini : ft[i]; 65 | return mini; 66 | } 67 | 68 | int upd (int a, int v) { 69 | put_value(a, v); 70 | update_rmq(a, v); 71 | return 0; 72 | } 73 | 74 | int put_value (int a, int v) { 75 | vet[a] = v; 76 | return 0; 77 | } 78 | int update_rmq (int a, int v) const{ 79 | //printf("UPDATE %d %d\n", a, v); 80 | int mini_l = a, mini_r = a; 81 | //bit normal 82 | for (int i = a; i < n; i += (i & -i)) { 83 | if (ft[i] != a) ft[i] = v < vet[ft[i]] ? a : ft[i]; 84 | else { 85 | //if (i < 10) { 86 | //printf("\tnormal\n"); 87 | // printf("(%d, %d)\n", i - (i & -i) + 1, i); 88 | // printf("%d\n", ft[i]); 89 | // if (i >= a + 1) 90 | // printf("R %d\n", query_rmq(a + 1, i)); 91 | // if (i - (i & -i) + 1 <= a - 1) 92 | // printf("L %d\n", query_rmq(i - (i & -i) + 1, a - 1)); 93 | // } 94 | //int mini_ll = vet[mini_l] < vet[i - (i & -i) + 1] ? mini_l : i - (i & -i) + 1; 95 | //int mini_rr = vet[mini_r] < vet[i] ? mini_r : i; 96 | 97 | ft[i] = vet[mini_l] < vet[mini_r] ? (vet[mini_l] < v ? mini_l : a) : (vet[mini_r] < v ? mini_r : a); 98 | // if (i < 10) { 99 | // printf("%d\n", ft[i]); 100 | // printf("\tfim\n"); 101 | // } 102 | if (i >= a + 1) 103 | mini_r = vet[mini_r] < vet[ft_inv[i]] ? mini_r : i; 104 | if (i - (i & -i) + 1 <= a - 1) 105 | mini_l = vet[mini_l] < vet[ft[i - (i & -i) + 1]] ? mini_l : i - (i & -i) + 1; 106 | } 107 | } 108 | mini_l = a, mini_r = a; 109 | //bit invertida 110 | for (int i = a; i; i -= (i & -i)) { 111 | // if (i < 10) { 112 | // printf("\tinvertido\n"); 113 | // printf("(%d, %d)\n", i, i + (i & -i) - 1); 114 | // printf("%d\n", ft_inv[i]); 115 | // if (i + (i & -i) - 1 >= a + 1) 116 | // printf("R %d\n", query_rmq(a + 1, i + (i & -i) - 1 >= a + 1)); 117 | // if (i <= a - 1) 118 | // printf("L %d\n", query_rmq(i, a - 1)); 119 | // } 120 | if (ft_inv[i] != a) ft_inv[i] = v < vet[ft_inv[i]] ? a : ft_inv[i]; 121 | // if (i < 10) { 122 | // printf("%d\n", ft[i]); 123 | // printf("\tfim\n"); 124 | // } 125 | else { 126 | //int mini_ll = vet[mini_l] < vet[i - (i & -i) + 1] ? mini_l : i - (i & -i) + 1; 127 | //int mini_rr = vet[mini_r] < vet[i] ? mini_r : i; 128 | 129 | ft_inv[i] = vet[mini_l] < vet[mini_r] ? (vet[mini_l] < v ? mini_l : a) : (vet[mini_r] < v ? mini_r : a); 130 | if (i + (i & -i) - 1 >= a + 1) 131 | mini_r = vet[mini_r] < vet[ft_inv[i + (i & -i) - 1]] ? mini_r : (i + (i & -i) - 1); 132 | if (i <= a - 1) 133 | mini_l = vet[mini_l] < vet[ft[i]] ? mini_l : i; 134 | } 135 | } 136 | return 0; 137 | } 138 | 139 | }; 140 | 141 | int main () { 142 | 143 | ft_diff ft(100000); 144 | 145 | ft.upd(1, 2); 146 | //vet[1] = 2; ft.update_rmq(1, 2); 147 | ft.upd(2, -1); 148 | //vet[2] = -1; ft.update_rmq(2, -1); 149 | ft.upd(3, 1); 150 | //vet[3] = 1; ft.update_rmq(3, 1); 151 | ft.upd(4, 7); 152 | //vet[4] = 7; ft.update_rmq(4, 7); 153 | ft.upd(5, -50); 154 | //vet[5] = -50; ft.update_rmq(5, -50); 155 | ft.upd(6, 2); 156 | //vet[6] = 2; ft.update_rmq(6, 2); 157 | ft.upd(7, 3); 158 | //vet[7] = 3; ft.update_rmq(7, 3); 159 | 160 | printf("%d\n", ft.query_rmq(1, 7)); 161 | printf("%d\n", ft.query_rmq(6, 7)); 162 | printf("%d\n", ft.query_rmq(5, 5)); 163 | printf("%d\n", ft.query_rmq(1, 3)); 164 | printf("%d\n", ft.query_rmq(3, 4)); 165 | printf("%d\n", ft.query_rmq(1, 4)); 166 | 167 | printf("\n"); 168 | ft.upd(5, 5); 169 | //vet[5] = 5; ft.update_rmq(5, 5); 170 | ft.upd(3, 10); 171 | //vet[3] = 10; ft.update_rmq(3, 10); 172 | 173 | printf("%d\n", ft.query_rmq(1, 7)); 174 | printf("%d\n", ft.query_rmq(6, 7)); 175 | printf("%d\n", ft.query_rmq(5, 5)); 176 | printf("%d\n", ft.query_rmq(1, 3)); 177 | printf("%d\n", ft.query_rmq(3, 4)); 178 | printf("%d\n", ft.query_rmq(1, 4)); 179 | 180 | printf("\n"); 181 | ft.upd(1, -100); 182 | //vet[1] = -100; ft.update_rmq(1, -100); 183 | 184 | printf("%d\n", ft.query_rmq(1, 7)); 185 | printf("%d\n", ft.query_rmq(6, 7)); 186 | printf("%d\n", ft.query_rmq(5, 5)); 187 | printf("%d\n", ft.query_rmq(1, 3)); 188 | printf("%d\n", ft.query_rmq(3, 4)); 189 | printf("%d\n", ft.query_rmq(1, 4)); 190 | } 191 | -------------------------------------------------------------------------------- /code/contra_ataque_ramsay.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define LADO 800 8 | #define SEG_LADO 1400000 9 | 10 | using namespace std; 11 | 12 | class Sgtree{ 13 | private: 14 | int arv[SEG_LADO]; 15 | public: 16 | int query(int L, int R, int D, int U, int l, int r, int d, int u, int p); 17 | void update(int L, int R, int D, int U, int pos_x, int pos_y, int num, int p); 18 | Sgtree(){memset(arv, 0, SEG_LADO<<2);}; 19 | }tipo_segtree; 20 | 21 | 22 | typedef struct _sold{ 23 | int x,y; 24 | bool pai; 25 | }tipo_soldado; 26 | 27 | 28 | int Sgtree::query(int L, int R, int D, int U, int l, int r, int d, int u, int p) { 29 | if(r < L || l > R || d > U || u < D) 30 | return 0; 31 | if(L >= l && R <= r && U <= u && D >= d){ 32 | return arv[p]; 33 | } 34 | int tmp1, tmp2, tmp3, tmp4; 35 | tmp1 = query(L, (L+R)>>1, D, (U+D)>>1, l, r, d, u, (p<<2)+1); 36 | tmp2 = query(L, (L+R)>>1, ((U+D)>>1) + 1, U, l, r, d, u, (p<<2)+2); 37 | tmp3 = query(((L+R)>>1) + 1, R, D, (U+D)>>1, l, r, d, u, (p<<2)+3); 38 | tmp4 = query(((L+R)>>1) + 1, R, ((U+D)>>1) + 1, U, l, r, d, u, (p<<2)+4); 39 | 40 | tmp1 = max(tmp1, tmp2); 41 | tmp1 = max(tmp1, tmp3); 42 | return max(tmp1, tmp4); 43 | } 44 | 45 | void Sgtree::update(int L, int R, int D, int U, int pos_x, int pos_y, int num, int p){ 46 | if(L == R && U == D){ 47 | arv[p] = num; 48 | } 49 | else{ 50 | if(pos_x <= (L+R)>>1){ 51 | if(pos_y <= (U+D)>>1) 52 | update(L, (L+R)>>1, D, (U+D)>>1, pos_x, pos_y, num, (p<<2)+1); 53 | else 54 | update(L, (L+R)>>1, ((U+D)>>1) + 1, U, pos_x, pos_y, num, (p<<2)+2); 55 | } 56 | else{ 57 | if(pos_y <= (U+D)>>1) 58 | update(((L+R)>>1) + 1, R, D, (U+D)>>1, pos_x, pos_y, num, (p<<2)+3); 59 | else 60 | update(((L+R)>>1) + 1, R, ((U+D)>>1) + 1, U, pos_x, pos_y, num, (p<<2)+4); 61 | } 62 | int tmp1, tmp2; 63 | tmp1 = max(arv[(p<<2)+1], arv[(p<<2)+2]); 64 | tmp2 = max(arv[(p<<2)+3], arv[(p<<2)+4]); 65 | arv[p] = max(tmp1, tmp2); 66 | } 67 | 68 | } 69 | 70 | vector G[50001]; 71 | Sgtree *tree; 72 | tipo_soldado soldado[50001]; 73 | bool is_root[50001]; 74 | int ans = 1; 75 | void dfs(int no){ 76 | int tmp = tree->query(0, LADO, 0, LADO, 0 ,soldado[no].x-1, 0, soldado[no].y-1, 0); 77 | tmp++; 78 | tree->update(0, LADO, 0, LADO, soldado[no].x, soldado[no].y, tmp, 0); 79 | 80 | ans = max(ans, tmp); 81 | for(int j : G[no]) 82 | dfs(j); 83 | tree->update(0, LADO, 0, LADO, soldado[no].x, soldado[no].y, 0, 0); 84 | } 85 | 86 | 87 | int main() { 88 | int N, M, i, j, no_pai, no_filho; 89 | tree = new Sgtree(); 90 | 91 | scanf("%d %d", &N, &M); 92 | for(i = 1; i <= N; i++){ 93 | scanf("%d", &soldado[i].x); 94 | scanf("%d", &soldado[i].y); 95 | soldado[i].x += 400; 96 | soldado[i].y += 400; 97 | } 98 | 99 | for(i = 1; i <= N; i++) is_root[i] = 1; 100 | for(i = 1; i <= M; i++){ 101 | scanf("%d %d", &no_filho, &no_pai); 102 | G[no_pai].push_back(no_filho); 103 | is_root[no_filho] = 0; 104 | } 105 | 106 | for(i = 1; i <= N; i++){ 107 | if(!is_root[i]) continue; 108 | if(!G[i].empty()) 109 | dfs(i); 110 | } 111 | 112 | printf("%d\n", ans); 113 | return 0; 114 | } 115 | -------------------------------------------------------------------------------- /code/ed/LineContainer.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm 3 | * source: https://github.com/kth-competitive-programming/kactl/blob/master/content/data-structures/LineContainer.h 4 | * License: CC0 5 | */ 6 | 7 | struct Line { 8 | mutable ll m, b, p; 9 | bool operator<(const Line& o) const { return m < o.m; } 10 | bool operator<(ll x) const { return p < x; } 11 | }; 12 | 13 | struct LineContainer : multiset> { // CPP14 only 14 | // (for doubles, use inf = 1/.0, div(a,b) = a/b) 15 | const ll inf = LLONG_MAX; 16 | ll div(ll a, ll b) { // floored division 17 | return a / b - ((a ^ b) < 0 && a % b); } 18 | bool isect(iterator x, iterator y) { 19 | if (y == end()) { x->p = inf; return false; } 20 | if (x->m == y->m) x->p = x->b > y->b ? inf : -inf; 21 | else x->p = div(y->b - x->b, x->m - y->m); 22 | return x->p >= y->p; 23 | } 24 | void add(ll m, ll b) { 25 | auto z = insert({m, b, 0}), y = z++, x = y; 26 | while (isect(y, z)) z = erase(z); 27 | if (x != begin() && isect(--x, y)) isect(x, y = erase(y)); 28 | while ((y = x) != begin() && (--x)->p >= y->p) 29 | isect(x, erase(y)); 30 | } 31 | ll query(ll x) { 32 | assert(!empty()); 33 | auto l = *lower_bound(x); 34 | return l.m * x + l.b; 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /code/ed/bit2D.cpp: -------------------------------------------------------------------------------- 1 | vector go[N]; 2 | vector ft[N]; 3 | 4 | void prec_add(int x, int y) { 5 | for(; x < N; x += x & -x) { 6 | go[x].push_back(y); 7 | } 8 | } 9 | void init() { 10 | for(int i = 1; i < N; i++) { 11 | sort(go[i].begin(), go[i].end()); 12 | ft[i].assign(go[i].size() + 1, 0); 13 | } 14 | } 15 | void add(int x, int y, int val) { 16 | for(; x < N; x += x & -x) { 17 | int id = int(upper_bound(go[x].begin(), go[x].end(), y) - go[x].begin()); 18 | for(; id < (int)ft[x].size(); id += id & -id) 19 | ft[x][id] += val; 20 | } 21 | } 22 | int sum(int x, int y) { 23 | int ans = 0; 24 | for(; x > 0; x -= x & -x) { 25 | int id = int(upper_bound(go[x].begin(), go[x].end(), y) - go[x].begin()); 26 | for(; id > 0; id -= id & -id) 27 | ans += ft[x][id]; 28 | } 29 | return ans; 30 | } 31 | -------------------------------------------------------------------------------- /code/ed/cht.cpp: -------------------------------------------------------------------------------- 1 | const ll is_query = -(1LL<<62); 2 | struct Line{ 3 | ll m, b; 4 | mutable function succ; 5 | bool operator<(const Line& rhs) const{ 6 | if(rhs.b != is_query) return m < rhs.m; 7 | const Line* s = succ(); 8 | if(!s) return 0; 9 | ll x = rhs.m; 10 | return b - s->b < (s->m - m) * x; 11 | } 12 | }; 13 | struct Cht : public multiset{ // maintain max 14 | bool bad(iterator y){ 15 | auto z = next(y); 16 | if(y == begin()){ 17 | if(z == end()) return 0; 18 | return y->m == z->m && y->b <= z->b; 19 | } 20 | auto x = prev(y); 21 | if(z == end()) return y->m == x->m && y->b <= x->b; 22 | return (long double)(x->b - y->b)*(z->m - y->m) >= (long double)(y->b - z->b)*(y->m - x->m); 23 | } 24 | void insert_line(ll m, ll b){ 25 | auto y = insert({ m, b }); 26 | y->succ = [=]{ return next(y) == end() ? 0 : &*next(y); }; 27 | if(bad(y)){ erase(y); return; } 28 | while(next(y) != end() && bad(next(y))) erase(next(y)); 29 | while(y != begin() && bad(prev(y))) erase(prev(y)); 30 | } 31 | ll eval(ll x){ 32 | auto l = *lower_bound((Line) { x, is_query }); 33 | return l.m * x + l.b; 34 | } 35 | }; 36 | 37 | -------------------------------------------------------------------------------- /code/ed/cht_simple.cpp: -------------------------------------------------------------------------------- 1 | struct Line{ 2 | ll m, b; 3 | inline ll eval(ll x) const{ 4 | return x * m + b; 5 | } 6 | }; 7 | 8 | // min => cht.back().m >= L.m 9 | // max => cht.back().m <= L.m 10 | void push_line(vector &cht, Line L){ 11 | while((int)cht.size() >= 2){ 12 | int sz = (int)cht.size(); 13 | if((long double)(L.b-cht[sz-1].b)*(cht[sz-2].m-L.m) 14 | <= (long double)(L.b-cht[sz-2].b)*(cht[sz-1].m-L.m)){ 15 | cht.pop_back(); 16 | } 17 | else break; 18 | } 19 | cht.push_back(L); 20 | } 21 | 22 | // x increasing; pos = 0 in first call 23 | ll linear_search(const vector &cht,ll x,int &pos){ 24 | while(pos+1 < (int)cht.size()){ 25 | /*>>*/ if(cht[pos].eval(x) >= cht[pos+1].eval(x)) pos++; 26 | else break; 27 | } 28 | return cht[pos].eval(x); 29 | } 30 | 31 | ll binary_search(const vector &cht, ll x){ 32 | int L = 0, R = (int)cht.size()-2; 33 | int bans = (int)cht.size()-1; 34 | while(L <= R){ 35 | int mid = (L+R)/2; 36 | if(cht[mid].eval(x) >= cht[mid+1].eval(x)) // <<< 37 | L = mid + 1; 38 | else bans = mid, R = mid - 1; 39 | } 40 | return cht[bans].eval(x); 41 | } 42 | 43 | -------------------------------------------------------------------------------- /code/ed/eertree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | const int maxn = 3e5 + 1, sigma = 26; 6 | int len[maxn], link[maxn], to[maxn][sigma]; 7 | int slink[maxn], diff[maxn], series_ans[maxn]; 8 | int sz, last, n; 9 | char s[maxn]; 10 | 11 | void init() 12 | { 13 | s[n++] = -1; 14 | link[0] = 1; 15 | len[1] = -1; 16 | sz = 2; 17 | } 18 | 19 | int get_link(int v) 20 | { 21 | while(s[n - len[v] - 2] != s[n - 1]) v = link[v]; 22 | return v; 23 | } 24 | 25 | void add_letter(char c) 26 | { 27 | s[n++] = c -= 'a'; 28 | last = get_link(last); 29 | if(!to[last][c]) 30 | { 31 | len[sz] = len[last] + 2; 32 | link[sz] = to[get_link(link[last])][c]; 33 | diff[sz] = len[sz] - len[link[sz]]; 34 | if(diff[sz] == diff[link[sz]]) 35 | slink[sz] = slink[link[sz]]; 36 | else 37 | slink[sz] = link[sz]; 38 | to[last][c] = sz++; 39 | } 40 | last = to[last][c]; 41 | } 42 | 43 | int main() 44 | { 45 | ios::sync_with_stdio(0); 46 | cin.tie(0); 47 | init(); 48 | string s; 49 | cin >> s; 50 | int n = s.size(); 51 | int ans[n + 1]; 52 | memset(ans, 63, sizeof(ans)); 53 | ans[0] = 0; 54 | for(int i = 1; i <= n; i++) 55 | { 56 | add_letter(s[i - 1]); 57 | for(int v = last; len[v] > 0; v = slink[v]) 58 | { 59 | series_ans[v] = ans[i - (len[slink[v]] + diff[v])]; 60 | if(diff[v] == diff[link[v]]) 61 | series_ans[v] = min(series_ans[v], series_ans[link[v]]); 62 | ans[i] = min(ans[i], series_ans[v] + 1); 63 | } 64 | cout << ans[i] << "\n"; 65 | } 66 | return 0; 67 | } 68 | 69 | -------------------------------------------------------------------------------- /code/ed/hash_table.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace __gnu_pbds; 3 | 4 | struct custom_hash { 5 | static uint64_t splitmix64(uint64_t x) { 6 | // http://xorshift.di.unimi.it/splitmix64.c 7 | x += 0x9e3779b97f4a7c15; 8 | x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9; 9 | x = (x ^ (x >> 27)) * 0x94d049bb133111eb; 10 | return x ^ (x >> 31); 11 | } 12 | 13 | size_t operator()(uint64_t x) const { 14 | static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count(); 15 | return splitmix64(x + FIXED_RANDOM); 16 | } 17 | }; 18 | 19 | gp_hash_table table; 20 | unordered_map uhash; 21 | uhash.reserve(1 << 15); 22 | uhash.max_load_factor(0.25); 23 | -------------------------------------------------------------------------------- /code/ed/hld.cpp: -------------------------------------------------------------------------------- 1 | void dfs_sz(int u){ 2 | sz[u] = 1; 3 | for(auto &v : g[u]) if(v == p[u]){ 4 | swap(v, g[u].back()); g[u].pop_back(); 5 | break; 6 | } 7 | for(auto &v : g[u]){ 8 | p[v] = u; dfs_sz(v); sz[u] += sz[v]; 9 | if(sz[v] > sz[ g[u][0] ]) 10 | swap(v, g[u][0]); 11 | } 12 | } 13 | // nxt[u] = start of path with u 14 | // set nxt[root] = root beforehand 15 | void dfs_hld(int u){ 16 | in[u] = t++; 17 | rin[in[u]] = u; 18 | for(auto v : g[u]){ 19 | nxt[v] = (v == g[u][0] ? nxt[u] : v); dfs_hld(v); 20 | } 21 | out[u] = t; 22 | } 23 | // subtree of u => [ in[u], out[u] ) 24 | // path from nxt[u] to u => [ in[ nxt[u] ], in[u] ] 25 | -------------------------------------------------------------------------------- /code/ed/lichao.cpp: -------------------------------------------------------------------------------- 1 | void add_line(line nw, int v = 1, int l = 0, int r = maxn) { // [l, r) 2 | int m = (l + r) / 2; 3 | bool lef = nw.eval(l) < st[v].eval(l); 4 | bool mid = nw.eval(m) < st[v].eval(m); 5 | if(mid) swap(st[v], nw); 6 | if(r - l == 1) { 7 | return; 8 | } else if(lef != mid) { 9 | add_line(nw, 2 * v, l, m); 10 | } else { 11 | add_line(nw, 2 * v + 1, m, r); 12 | } 13 | } 14 | 15 | int get(int x, int v = 1, int l = 0, int r = maxn) { 16 | int m = (l + r) / 2; 17 | if(r - l == 1) { 18 | return st[v].eval(x); 19 | } else if(x < m) { 20 | return min(st[v].eval(x), get(x, 2*v, l, m)); 21 | } else { 22 | return min(st[v].eval(x), get(x, 2*v+1, m, r)); 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /code/ed/merge_sort_tree.cpp: -------------------------------------------------------------------------------- 1 | struct MergeTree{ 2 | int n; 3 | vector> st; 4 | 5 | void build(int p, int L, int R, const int v[]){ 6 | if(L == R){ 7 | st[p].push_back(v[L]); 8 | return; 9 | } 10 | int mid = (L+R)/2; 11 | build(2*p, L, mid, v); 12 | build(2*p+1, mid+1, R, v); 13 | st[p].resize(R-L+1); 14 | merge(st[2*p].begin(), st[2*p].end(), 15 | st[2*p+1].begin(), st[2*p+1].end(), 16 | st[p].begin()); 17 | } 18 | 19 | int query(int p, int L, int R, int i, int j, int x) const{ 20 | if(L > j || R < i) return 0; 21 | if(L >= i && R <= j){ 22 | int id = lower_bound(st[p].begin(), st[p].end(), x) - st[p].begin(); 23 | return int(st[p].size()) - id; 24 | } 25 | int mid = (L+R)/2; 26 | return query(2*p, L, mid, i, j, x) + 27 | query(2*p+1, mid+1, R, i, j, x); 28 | } 29 | 30 | public: 31 | MergeTree(int sz, const int v[]): n(sz), st(4*sz){ 32 | build(1, 1, n, v); 33 | } 34 | 35 | //number of elements >= x on segment [i, j] 36 | int query(int i, int j, int x) const{ 37 | if(i > j) swap(i, j); 38 | return query(1, 1, n, i, j, x); 39 | } 40 | }; 41 | 42 | -------------------------------------------------------------------------------- /code/ed/minq.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class minQ{ 3 | deque > p; 4 | T delta; 5 | int sz; 6 | public: 7 | minQ() : delta(0), sz(0) {} 8 | inline int size() const{ return sz; } 9 | inline void add(T x){ delta += x; } 10 | inline void push(T x, int id){ 11 | x -= delta, sz++; 12 | int t = 1; 13 | while(p.size() > 0 && get<0>(p.back()) >= x) 14 | t += get<1>(p.back()), p.pop_back(); 15 | p.emplace_back(x, t, id); 16 | } 17 | inline void pop(){ 18 | get<1>(p.front())--, sz--; 19 | if(!get<1>(p.front())) p.pop_front(); 20 | } 21 | T getmin() const{ return get<0>(p.front())+delta; } 22 | int getid() const{ return get<2>(p.front()); } 23 | }; 24 | -------------------------------------------------------------------------------- /code/ed/order_set.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | using namespace __gnu_pbds; // or pb_ds; 7 | 8 | template 9 | using oset = tree, rb_tree_tag, tree_order_statistics_node_update>; 10 | // find_by_order / order_of_key 11 | 12 | -------------------------------------------------------------------------------- /code/ed/segtree.cpp: -------------------------------------------------------------------------------- 1 | T query(int l, int r){ // [l, r] 2 | T rl, rr; 3 | for(l += n, r += n+1; l < r; l >>= 1, r >>= 1){ 4 | if(l & 1) rl = merge(rl, st[l++]); 5 | if(r & 1) rr = merge(st[--r], rr); 6 | } 7 | return merge(rl, rr); 8 | } 9 | 10 | // initially save v[i] in st[n+i] for all i in [0, n) 11 | void build(){ 12 | for(int p = n-1; p > 0; p--) 13 | st[p] = merge(st[2*p], st[2*p+1]); 14 | } 15 | 16 | void update(int p, T val){ 17 | st[p += n] = val; 18 | while(p >>= 1) st[p] = merge(st[2*p], st[2*p+1]); 19 | } 20 | 21 | -------------------------------------------------------------------------------- /code/ed/segtree_rec.cpp: -------------------------------------------------------------------------------- 1 | class SegTree{ 2 | vi st; 3 | vi lazy; 4 | int size; 5 | 6 | int el_neutro = -oo; 7 | 8 | inline int f(int a, int b){ 9 | return max(a,b); 10 | } 11 | inline int left(int i) {return 2 * i + 1;}; 12 | inline int right(int i) {return 2 * i + 2;}; 13 | void build(int sti, int stl, int str, vi& nums) { 14 | if(stl == str) { 15 | st[sti] = nums[stl]; 16 | return; 17 | } 18 | int mid = (stl + str) / 2; 19 | build(left(sti), stl, mid, nums); 20 | build(right(sti), mid + 1, str, nums); 21 | st[sti] = f(st[left(sti)], st[right(sti)]); 22 | } 23 | 24 | void propagate(int sti, int stl, int str){ 25 | if(lazy[sti]){ 26 | st[sti] += lazy[sti]; 27 | if(stl != str) 28 | { 29 | lazy[left(sti)] += lazy[sti]; 30 | lazy[right(sti)] += lazy[sti]; 31 | } 32 | lazy[sti] = 0; 33 | } 34 | } 35 | int query(int sti, int stl, int str, int l, int r){ 36 | propagate(sti, stl, str); 37 | 38 | if(str < l || r < stl) 39 | return el_neutro; 40 | 41 | 42 | if(stl >= l and str <= r) 43 | return st[sti]; 44 | 45 | int mid = (str+stl)/2; 46 | 47 | return f(query(left(sti),stl,mid,l,r),query(right(sti),mid+1,str,l,r)); 48 | } 49 | void update_range(int sti, int stl, int str, int l,int r, int amm){ 50 | propagate(sti, stl, str); 51 | if(stl >= l and str <= r){ 52 | lazy[sti] = amm; 53 | propagate(sti, stl, str); 54 | return; 55 | } 56 | if(stl > r or str < l) 57 | return; 58 | int mid = (stl + str)/2; 59 | update_range(left(sti),stl,mid,l,r,amm); 60 | update_range(right(sti),mid+1,str,l,r,amm); 61 | st[sti] = f(st[left(sti)],st[right(sti)]); 62 | } 63 | void update(int sti, int stl, int str, int i, int amm){ 64 | propagate(sti, stl, str); 65 | if(stl == i and str == i){ 66 | st[sti] = amm; 67 | return; 68 | } 69 | if(stl > i or str < i) 70 | return; 71 | int mid = (stl + str)/2; 72 | update(left(sti),stl,mid,i,amm); 73 | update(right(sti),mid+1,str,i,amm); 74 | st[sti] = f(st[left(sti)],st[right(sti)]); 75 | } 76 | public: 77 | SegTree(vi& v) : st(4*v.size(),0), lazy(4*v.size(),0) {size = v.size(); build(0,0,size - 1, v);} 78 | SegTree(int n) : st(4*n,0), lazy(4*n,0){size = n;} 79 | int query(int l, int r){return query(0,0,size-1,l,r);} 80 | void update_range(int l, int r, int amm){update_range(0,0,size-1,l,r,amm);} 81 | void update(int i, int amm){update(0,0,size-1,i,amm);} 82 | }; 83 | -------------------------------------------------------------------------------- /code/ed/sparse_table.cpp: -------------------------------------------------------------------------------- 1 | int fn(int i, int j){ 2 | if(j == 0) return v[i]; 3 | if(~dn[i][j]) return dn[i][j]; 4 | return dn[i][j] = min(fn(i, j-1), fn(i + (1 << (j-1)), j-1)); 5 | } 6 | 7 | int getmn(int l, int r){ // [l, r] 8 | int lz = lg(r - l + 1); 9 | return min(fn(l, lz), fn(r - (1 << lz) + 1, lz)); 10 | } 11 | -------------------------------------------------------------------------------- /code/ed/suffix_tree.cpp: -------------------------------------------------------------------------------- 1 | namespace sf { 2 | // const int NS = ; const int N = * 2; 3 | int cn, cd, ns, en = 1, lst; 4 | string S[NS]; int si = -1; 5 | vector sufn[N]; // sufn[si][i] no do sufixo S[si][i...] 6 | struct node { 7 | int l, r, si, p, suf; 8 | map adj; 9 | node() : l(0), r(-1), suf(0), p(0) {} 10 | node(int L, int R, int S, int P) : l(L), r(R), si(S), p(P) {} 11 | inline int len() { return r - l + 1; } 12 | inline int operator[](int i) { return S[si][l + i]; } 13 | inline int& operator()(char c) { return adj[c]; } 14 | } t[N]; 15 | inline int new_node(int L, int R, int S, int P) { t[en] = node(L, R, S, P); return en++; } 16 | void add_string(string s) { 17 | s += '$'; S[++si] = s; sufn[si].resize(s.size() + 1); cn = cd = 0; 18 | int i = 0; const int n = s.size(); 19 | for(int j = 0; j < n; j++) 20 | for(; i <= j; i++) { 21 | if(cd == t[cn].len() && t[cn](s[j])) { cn = t[cn](s[j]); cd = 0; } 22 | if(cd < t[cn].len() && t[cn][cd] == s[j]) { 23 | cd++; 24 | if(j < s.size() - 1) break; 25 | else { 26 | if(i) t[lst].suf = cn; 27 | for(; i <= j; i++) { sufn[si][i] = cn; cn = t[cn].suf; } 28 | } 29 | } else if(cd == t[cn].len()) { 30 | sufn[si][i] = en; 31 | if(i) t[lst].suf = en; lst = en; 32 | t[cn](s[j]) = new_node(j, n - 1, si, cn); 33 | cn = t[cn].suf; cd = t[cn].len(); 34 | } else { 35 | int mid = new_node(t[cn].l, t[cn].l + cd - 1, t[cn].si, t[cn].p); 36 | t[t[cn].p](t[cn][0]) = mid; 37 | if(ns) t[ns].suf = mid; 38 | if(i) t[lst].suf = en; lst = en; 39 | sufn[si][i] = en; 40 | t[mid](s[j]) = new_node(j, n - 1, si, mid); 41 | t[mid](t[cn][cd]) = cn; 42 | t[cn].p = mid; t[cn].l += cd; cn = t[mid].p; 43 | int g = cn? j - cd : i + 1; cn = t[cn].suf; 44 | while(g < j && g + t[t[cn](S[si][g])].len() <= j) { 45 | cn = t[cn](S[si][g]); g += t[cn].len(); 46 | } 47 | if(g == j) { ns = 0; t[mid].suf = cn; cd = t[cn].len(); } 48 | else { ns = mid; cn = t[cn](S[si][g]); cd = j - g; } 49 | } 50 | } 51 | } 52 | }; 53 | -------------------------------------------------------------------------------- /code/ed/treap.cpp: -------------------------------------------------------------------------------- 1 | // source: https://github.com/victorsenam/caderno/blob/master/code/treap.cpp 2 | //const int N = ; typedef int num; 3 | num X[N]; int en = 1, Y[N], sz[N], L[N], R[N]; 4 | void calc (int u) { // update node given children info 5 | if(!u) return; 6 | sz[u] = sz[L[u]] + 1 + sz[R[u]]; 7 | // code here, no recursion 8 | } 9 | void unlaze (int u) { 10 | if(!u) return; 11 | // code here, no recursion 12 | } 13 | void split_val(int u, num x, int &l, int &r) { // l gets <= x, r gets > x 14 | unlaze(u); if(!u) return (void) (l = r = 0); 15 | if(X[u] <= x) { split_val(R[u], x, l, r); R[u] = l; l = u; } 16 | else { split_val(L[u], x, l, r); L[u] = r; r = u; } 17 | calc(u); 18 | } 19 | void split_sz(int u, int s, int &l, int &r) { // l gets first s, r gets remaining 20 | unlaze(u); if(!u) return (void) (l = r = 0); 21 | if(sz[L[u]] < s) { split_sz(R[u], s - sz[L[u]] - 1, l, r); R[u] = l; l = u; } 22 | else { split_sz(L[u], s, l, r); L[u] = r; r = u; } 23 | calc(u); 24 | } 25 | int merge(int l, int r) { // els on l <= els on r 26 | unlaze(l); unlaze(r); if(!l || !r) return l + r; int u; 27 | if(Y[l] > Y[r]) { R[l] = merge(R[l], r); u = l; } 28 | else { L[r] = merge(l, L[r]); u = r; } 29 | calc(u); return u; 30 | } 31 | void init(int n=N-1) { // XXX call before using other funcs 32 | for(int i = en = 1; i <= n; i++) { Y[i] = i; sz[i] = 1; L[i] = R[i] = 0; } 33 | random_shuffle(Y + 1, Y + n + 1); 34 | } 35 | void insert(int &u, int it){ 36 | unlaze(u); 37 | if(!u) u = it; 38 | else if(Y[it] > Y[u]) split_val(u, X[it], L[it], R[it]), u = it; 39 | else insert(X[it] < X[u] ? L[u] : R[u], it); 40 | calc(u); 41 | } 42 | void erase(int &u, num key){ 43 | unlaze(u); 44 | if(!u) return; 45 | if(X[u] == key) u = merge(L[u], R[u]); 46 | else erase(key < X[u] ? L[u] : R[u], key); 47 | calc(u); 48 | } 49 | int create_node(num key){ 50 | X[en] = key; 51 | sz[en] = 1; 52 | L[en] = R[en] = 0; 53 | return en++; 54 | } 55 | int query(int u, int l, int r){//0 index 56 | unlaze(u); 57 | if(u! or r < 0 or l >= sz[u]) return identity_element; 58 | if(l <= 0 and r >= sz[u] - 1) return subt_data[u]; 59 | int ans = query(L[u], l, r); 60 | if(l <= sz[ L[u] ] and sz[ L[u] ] <= r) 61 | ans = max(ans, st[u]); 62 | ans = max(ans, query(R[u], l-sz[L[u]]-1, r-sz[L[u]]-1)); 63 | return ans; 64 | } 65 | -------------------------------------------------------------------------------- /code/ed/wavelet_tree.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class wavelet { // 1-based!! 3 | T L, R; 4 | vector l; 5 | vector sum; // << 6 | wavelet *lef, *rig; 7 | 8 | int r(int i) const{ return i - l[i]; } 9 | 10 | public: 11 | template 12 | wavelet(ITER bg, ITER en) { // it changes the argument array 13 | lef = rig = nullptr; 14 | L = *bg, R = *bg; 15 | 16 | for(auto it = bg; it != en; it++) 17 | L = min(L, *it), R = max(R, *it); 18 | if(L == R) return; 19 | 20 | T mid = L + (R - L)/2; 21 | l.reserve(std::distance(bg, en) + 1); 22 | sum.reserve(std::distance(bg, en) + 1); 23 | l.push_back(0), sum.push_back(0); 24 | for(auto it = bg; it != en; it++) 25 | l.push_back(l.back() + (*it <= mid)), 26 | sum.push_back(sum.back() + *it); 27 | 28 | auto tmp = stable_partition(bg, en, [mid](T x){ 29 | return x <= mid; 30 | }); 31 | 32 | if(bg != tmp) lef = new wavelet(bg, tmp); 33 | if(tmp != en) rig = new wavelet(tmp, en); 34 | } 35 | ~wavelet(){ 36 | delete lef; 37 | delete rig; 38 | } 39 | // 1 index, first is 1st 40 | T kth(int i, int j, int k) const{ 41 | if(L >= R) return L; 42 | int c = l[j] - l[i-1]; 43 | if(c >= k) return lef->kth(l[i-1]+1, l[j], k); 44 | else return rig->kth(r(i-1)+1, r(j), k - c); 45 | } 46 | // # elements > x on [i, j] 47 | int cnt(int i, int j, T x) const{ 48 | if(L > x) return j - i + 1; 49 | if(R <= x || L == R) return 0; 50 | int ans = 0; 51 | if(lef) ans += lef->cnt(l[i-1]+1, l[j], x); 52 | if(rig) ans += rig->cnt(r(i-1)+1, r(j), x); 53 | return ans; 54 | } 55 | // sum of elements <= k on [i, j] 56 | T sumk(int i, int j, T k){ 57 | if(L == R) return R <= k ? L * (j - i + 1) : 0; 58 | if(R <= k) return sum[j] - sum[i-1]; 59 | int ans = 0; 60 | if(lef) ans += lef->sumk(l[i-1]+1, l[j], k); 61 | if(rig) ans += rig->sumk(r(i-1)+1, r(j), k); 62 | return ans; 63 | } 64 | // swap (i, i+1) just need to update "array" l[i] 65 | }; 66 | -------------------------------------------------------------------------------- /code/fft.cpp: -------------------------------------------------------------------------------- 1 | void fft(vector &a, bool inv){ 2 | int n = (int)a.size(); 3 | 4 | for(int i = 1, j = 0; i < n; i++){ 5 | int bit = n >> 1; 6 | for(; j >= bit; bit >>= 1) j -= bit; 7 | j += bit; 8 | if(i < j) swap(a[i], a[j]); 9 | } 10 | 11 | for(int sz = 2; sz <= n; sz <<= 1) { 12 | double ang = 2 * PI / sz * (inv ? -1 : 1); 13 | base wlen(cos(ang), sin(ang)); 14 | for(int i = 0; i < n; i += sz){ 15 | base w(1, 0); 16 | for(int j = 0; j < sz / 2; j++){ 17 | base u = a[i+j], v = a[i+j + sz/2] * w; 18 | a[i+j] = u + v; 19 | a[i+j+sz/2] = u - v; 20 | w *= wlen; 21 | } 22 | } 23 | } 24 | if(inv) for(int i = 0; i < n; i++) a[i] /= 1.0 * n; 25 | } 26 | -------------------------------------------------------------------------------- /code/fft_tourist.cpp: -------------------------------------------------------------------------------- 1 | namespace fft { 2 | typedef double dbl; 3 | 4 | struct num { 5 | dbl x, y; 6 | num() { x = y = 0; } 7 | num(dbl x, dbl y) : x(x), y(y) {} 8 | }; 9 | 10 | inline num operator+(num a, num b) { return num(a.x + b.x, a.y + b.y); } 11 | inline num operator-(num a, num b) { return num(a.x - b.x, a.y - b.y); } 12 | inline num operator*(num a, num b) { return num(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x); } 13 | inline num conj(num a) { return num(a.x, -a.y); } 14 | 15 | int base = 1; 16 | vector roots = {{0, 0}, {1, 0}}; 17 | vector rev = {0, 1}; 18 | 19 | const dbl PI = acosl(-1.0); 20 | 21 | void ensure_base(int nbase) { 22 | if(nbase <= base) return; 23 | 24 | rev.resize(1 << nbase); 25 | for(int i = 0; i < (1 << nbase); i++) { 26 | rev[i] = (rev[i >> 1] >> 1) + ((i & 1) << (nbase - 1)); 27 | } 28 | roots.resize(1 << nbase); 29 | 30 | while(base < nbase) { 31 | dbl angle = 2*PI / (1 << (base + 1)); 32 | for(int i = 1 << (base - 1); i < (1 << base); i++) { 33 | roots[i << 1] = roots[i]; 34 | dbl angle_i = angle * (2 * i + 1 - (1 << base)); 35 | roots[(i << 1) + 1] = num(cos(angle_i), sin(angle_i)); 36 | } 37 | base++; 38 | } 39 | } 40 | 41 | void fft(vector &a, int n = -1) { 42 | if(n == -1) { 43 | n = a.size(); 44 | } 45 | assert((n & (n-1)) == 0); 46 | int zeros = __builtin_ctz(n); 47 | ensure_base(zeros); 48 | int shift = base - zeros; 49 | for(int i = 0; i < n; i++) { 50 | if(i < (rev[i] >> shift)) { 51 | swap(a[i], a[rev[i] >> shift]); 52 | } 53 | } 54 | for(int k = 1; k < n; k <<= 1) { 55 | for(int i = 0; i < n; i += 2 * k) { 56 | for(int j = 0; j < k; j++) { 57 | num z = a[i+j+k] * roots[j+k]; 58 | a[i+j+k] = a[i+j] - z; 59 | a[i+j] = a[i+j] + z; 60 | } 61 | } 62 | } 63 | } 64 | 65 | vector fa, fb; 66 | vector multiply(vector &a, vector &b) { 67 | int need = a.size() + b.size() - 1; 68 | int nbase = 0; 69 | while((1 << nbase) < need) nbase++; 70 | ensure_base(nbase); 71 | int sz = 1 << nbase; 72 | if(sz > (int) fa.size()) { 73 | fa.resize(sz); 74 | } 75 | for(int i = 0; i < sz; i++) { 76 | int x = (i < (int) a.size() ? a[i] : 0); 77 | int y = (i < (int) b.size() ? b[i] : 0); 78 | fa[i] = num(x, y); 79 | } 80 | fft(fa, sz); 81 | num r(0, -0.25 / sz); 82 | for(int i = 0; i <= (sz >> 1); i++) { 83 | int j = (sz - i) & (sz - 1); 84 | num z = (fa[j] * fa[j] - conj(fa[i] * fa[i])) * r; 85 | if(i != j) { 86 | fa[j] = (fa[i] * fa[i] - conj(fa[j] * fa[j])) * r; 87 | } 88 | fa[i] = z; 89 | } 90 | fft(fa, sz); 91 | vector res(need); 92 | for(int i = 0; i < need; i++) { 93 | res[i] = fa[i].x + 0.5; 94 | } 95 | return res; 96 | } 97 | 98 | vector multiply_mod(vector &a, vector &b, int m, int eq = 0) { 99 | int need = a.size() + b.size() - 1; 100 | int nbase = 0; 101 | while ((1 << nbase) < need) nbase++; 102 | ensure_base(nbase); 103 | int sz = 1 << nbase; 104 | if (sz > (int) fa.size()) { 105 | fa.resize(sz); 106 | } 107 | for (int i = 0; i < (int) a.size(); i++) { 108 | int x = (a[i] % m + m) % m; 109 | fa[i] = num(x & ((1 << 15) - 1), x >> 15); 110 | } 111 | fill(fa.begin() + a.size(), fa.begin() + sz, num {0, 0}); 112 | fft(fa, sz); 113 | if (sz > (int) fb.size()) { 114 | fb.resize(sz); 115 | } 116 | if (eq) { 117 | copy(fa.begin(), fa.begin() + sz, fb.begin()); 118 | } else { 119 | for (int i = 0; i < (int) b.size(); i++) { 120 | int x = (b[i] % m + m) % m; 121 | fb[i] = num(x & ((1 << 15) - 1), x >> 15); 122 | } 123 | fill(fb.begin() + b.size(), fb.begin() + sz, num {0, 0}); 124 | fft(fb, sz); 125 | } 126 | dbl ratio = 0.25 / sz; 127 | num r2(0, -1); 128 | num r3(ratio, 0); 129 | num r4(0, -ratio); 130 | num r5(0, 1); 131 | for (int i = 0; i <= (sz >> 1); i++) { 132 | int j = (sz - i) & (sz - 1); 133 | num a1 = (fa[i] + conj(fa[j])); 134 | num a2 = (fa[i] - conj(fa[j])) * r2; 135 | num b1 = (fb[i] + conj(fb[j])) * r3; 136 | num b2 = (fb[i] - conj(fb[j])) * r4; 137 | if (i != j) { 138 | num c1 = (fa[j] + conj(fa[i])); 139 | num c2 = (fa[j] - conj(fa[i])) * r2; 140 | num d1 = (fb[j] + conj(fb[i])) * r3; 141 | num d2 = (fb[j] - conj(fb[i])) * r4; 142 | fa[i] = c1 * d1 + c2 * d2 * r5; 143 | fb[i] = c1 * d2 + c2 * d1; 144 | } 145 | fa[j] = a1 * b1 + a2 * b2 * r5; 146 | fb[j] = a1 * b2 + a2 * b1; 147 | } 148 | fft(fa, sz); 149 | fft(fb, sz); 150 | vector res(need); 151 | for (int i = 0; i < need; i++) { 152 | long long aa = fa[i].x + 0.5; 153 | long long bb = fb[i].x + 0.5; 154 | long long cc = fa[i].y + 0.5; 155 | res[i] = (aa + ((bb % m) << 15) + ((cc % m) << 30)) % m; 156 | } 157 | return res; 158 | } 159 | 160 | vector square_mod(vector &a, int m) { 161 | return multiply_mod(a, a, m, 1); 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /code/gauss.cpp: -------------------------------------------------------------------------------- 1 | // Solves systems of linear equations. 2 | // To use, build a matrix of coefficients and call run(mat, R, C). If the i-th variable is free, row[i] will be -1, otherwise it's value will be ans[i]. 3 | 4 | namespace Gauss { 5 | const int MAXC = 1001; 6 | int row[MAXC]; 7 | double ans[MAXC]; 8 | 9 | void run(double mat[][MAXC], int R, int C) { 10 | REP(i, C) row[i] = -1; 11 | 12 | int r = 0; 13 | REP(c, C) { 14 | int k = r; 15 | FOR(i, r, R) if(fabs(mat[i][c]) > fabs(mat[k][c])) k = i; 16 | if(fabs(mat[k][c]) < eps) continue; 17 | 18 | REP(j, C+1) swap(mat[r][j], mat[k][j]); 19 | REP(i, R) if (i != r) { 20 | double w = mat[i][c] / mat[r][c]; 21 | REP(j, C+1) mat[i][j] -= mat[r][j] * w; 22 | } 23 | row[c] = r++; 24 | } 25 | 26 | REP(i, C) { 27 | int r = row[i]; 28 | ans[i] = r == -1 ? 0 : mat[r][C] / mat[r][i]; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /code/gauss_xor.cpp: -------------------------------------------------------------------------------- 1 | const ll MAX = 1e9; 2 | const int LOG_MAX = 64 - __builtin_clzll((ll)MAX); 3 | 4 | struct Gauss { 5 | array vet; 6 | int size; 7 | Gauss() : size(0) { 8 | fill(vet.begin(), vet.end(), 0); 9 | } 10 | Gauss(vector vals) : size(0) { 11 | fill(vet.begin(), vet.end(), 0); 12 | for(ll val : vals) add(val); 13 | } 14 | bool add(ll val) { 15 | for(int i = 0; i < LOG_MAX; i++) if(val & (1LL << i)) { 16 | if(vet[i] == 0) { 17 | vet[i] = val; 18 | size++; 19 | return true; 20 | } 21 | val ^= vet[i]; 22 | } 23 | return false; 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /code/geometry/2D.cpp: -------------------------------------------------------------------------------- 1 | typedef double cod; 2 | double eps = 1e-7; 3 | bool eq(cod a, cod b){ return abs(a - b) <= eps; } 4 | 5 | struct vec{ 6 | cod x, y; int id; 7 | vec(cod a = 0, cod b = 0) : x(a), y(b) {} 8 | vec operator+(const vec &o) const{ 9 | return {x + o.x, y + o.y}; 10 | } 11 | vec operator-(const vec &o) const{ 12 | return {x - o.x, y - o.y}; 13 | } 14 | vec operator*(cod t) const{ 15 | return {x * t, y * t}; 16 | } 17 | vec operator/(cod t) const{ 18 | return {x / t, y / t}; 19 | } 20 | cod operator*(const vec &o) const{ // cos 21 | return x * o.x + y * o.y; 22 | } 23 | cod operator^(const vec &o) const{ // sin 24 | return x * o.y - y * o.x; 25 | } 26 | bool operator==(const vec &o) const{ 27 | return eq(x, o.x) && eq(y, o.y); 28 | } 29 | bool operator<(const vec &o) const{ 30 | if(!eq(x, o.x)) return x < o.x; 31 | return y < o.y; 32 | } 33 | cod cross(const vec &a, const vec &b) const{ 34 | return (a-(*this)) ^ (b-(*this)); 35 | } 36 | int ccw(const vec &a, const vec &b) const{ 37 | cod tmp = cross(a, b); 38 | return (tmp > eps) - (tmp < -eps); 39 | } 40 | cod dot(const vec &a, const vec &b) const{ 41 | return (a-(*this)) * (b-(*this)); 42 | } 43 | cod len() const{ 44 | return sqrt(x * x + y * y); // < 45 | } 46 | double angle(const vec &a, const vec &b) const{ 47 | return atan2(cross(a, b), dot(a, b)); 48 | } 49 | double tan(const vec &a, const vec &b) const{ 50 | return cross(a, b) / dot(a, b); 51 | } 52 | vec unit() const{ 53 | return operator/(len()); 54 | } 55 | int quad() const{ 56 | if(x > 0 && y >=0) return 0; 57 | if(x <=0 && y > 0) return 1; 58 | if(x < 0 && y <=0) return 2; 59 | return 3; 60 | } 61 | bool comp(const vec &a, const vec &b) const{ 62 | return (a - *this).comp(b - *this); 63 | } 64 | bool comp(vec b){ 65 | if(quad() != b.quad()) return quad() < b.quad(); 66 | if(!eq(operator^(b), 0)) return operator^(b) > 0; 67 | return (*this) * (*this) < b * b; 68 | } 69 | template 70 | void sort_by_angle(T first, T last) const{ 71 | std::sort(first, last, [=](const vec &a, const vec &b){ 72 | return comp(a, b); 73 | }); 74 | } 75 | vec rot90() const{ return {-y, x}; } 76 | vec rot(double a) const{ 77 | return {cos(a)*x -sin(a)*y, sin(a)*x +cos(a)*y}; 78 | } 79 | vec proj(const vec &b) const{ // proj of *this onto b 80 | cod k = operator*(b) / (b * b); 81 | return b * k; 82 | } 83 | // proj of (*this) onto the plane orthogonal to b 84 | vec rejection(vec b) const{ 85 | return (*this) - proj(b); 86 | } 87 | }; 88 | 89 | struct line{ 90 | cod a, b, c; vec n; 91 | line(vec q, vec w){ // q.cross(w, (x, y)) = 0 92 | a = -(w.y-q.y); 93 | b = w.x-q.x; 94 | c = -(a * q.x + b * q.y); 95 | n = {a, b}; 96 | } 97 | cod dist(const vec &o) const{ 98 | return abs(eval(o)) / n.len(); 99 | } 100 | bool contains(const vec &o) const{ 101 | return eq(a * o.x + b * o.y + c, 0); 102 | } 103 | cod dist(const line &o) const{ 104 | if(!parallel(o)) return 0; 105 | if(!eq(o.a * b, o.b * a)) return 0; 106 | if(!eq(a, 0)) 107 | return abs(c - o.c * a / o.a) / n.len(); 108 | if(!eq(b, 0)) 109 | return abs(c - o.c * b / o.b) / n.len(); 110 | return abs(c - o.c); 111 | } 112 | bool parallel(const line &o) const{ 113 | return eq(n ^ o.n, 0); 114 | } 115 | bool operator==(const line &o) const{ 116 | if(!eq(a*o.b, b*o.a)) return false; 117 | if(!eq(a*o.c, c*o.a)) return false; 118 | if(!eq(c*o.b, b*o.c)) return false; 119 | return true; 120 | } 121 | bool intersect(const line &o) const{ 122 | return !parallel(o) || *this == o; 123 | } 124 | vec inter(const line &o) const{ 125 | if(parallel(o)){ 126 | if(*this == o){ } 127 | else{ /* dont intersect */ } 128 | } 129 | 130 | auto tmp = n ^ o.n; 131 | return {(o.c*b -c*o.b)/tmp, (o.a*c -a*o.c)/tmp}; 132 | } 133 | vec at_x(cod x) const{ 134 | return {x, (-c-a*x)/b}; 135 | } 136 | vec at_y(cod y) const{ 137 | return {(-c-b*y)/a, y}; 138 | } 139 | cod eval(const vec &o) const{ 140 | return a * o.x + b * o.y + c; 141 | } 142 | }; 143 | 144 | struct segment{ 145 | vec p, q; 146 | segment(vec a = vec(), vec b = vec()): p(a), q(b) {} 147 | bool onstrip(const vec &o) const{ // onstrip strip 148 | return p.dot(o, q) >= -eps && q.dot(o, p) >= -eps; 149 | } 150 | cod len() const{ 151 | return (p-q).len(); 152 | } 153 | cod dist(const vec &o) const{ 154 | if(onstrip(o)) return line(p, q).dist(o); 155 | return min((o-q).len(), (o-p).len()); 156 | } 157 | bool contains(const vec &o) const{ 158 | return eq(p.cross(q, o), 0) && onstrip(o); 159 | } 160 | bool intersect(const segment &o) const{ 161 | if(contains(o.p)) return true; 162 | if(contains(o.q)) return true; 163 | if(o.contains(q)) return true; 164 | if(o.contains(p)) return true; 165 | return p.ccw(q, o.p) * p.ccw(q, o.q) == -1 166 | && o.p.ccw(o.q, q) * o.p.ccw(o.q, p) == -1; 167 | } 168 | bool intersect(const line &o) const{ 169 | return o.eval(p) * o.eval(q) <= 0; 170 | } 171 | cod dist(const segment &o) const{ 172 | if(line(p, q).parallel(line(o.p, o.q))){ 173 | if(onstrip(o.p) || onstrip(o.q) 174 | || o.onstrip(p) || o.onstrip(q)) 175 | return line(p, q).dist(line(o.p, o.q)); 176 | } 177 | else if(intersect(o)) return 0; 178 | return min(min(dist(o.p), dist(o.q)), 179 | min(o.dist(p), o.dist(q))); 180 | } 181 | cod dist(const line &o) const{ 182 | if(line(p, q).parallel(o)) 183 | return line(p, q).dist(o); 184 | else if(intersect(o)) return 0; 185 | return min(o.dist(p), o.dist(q)); 186 | } 187 | }; 188 | 189 | struct hray{ 190 | vec p, q; 191 | hray(vec a = vec(), vec b = vec()): p(a), q(b){} 192 | bool onstrip(const vec &o) const{ // onstrip strip 193 | return p.dot(q, o) >= -eps; 194 | } 195 | cod dist(const vec &o) const{ 196 | if(onstrip(o)) return line(p, q).dist(o); 197 | return (o-p).len(); 198 | } 199 | bool intersect(const segment &o) const{ 200 | if(!o.intersect(line(p,q))) return false; 201 | if(line(o.p, o.q).parallel(line(p,q))) 202 | return contains(o.p) || contains(o.q); 203 | return contains(line(p,q).inter(line(o.p,o.q))); 204 | } 205 | bool contains(const vec &o) const{ 206 | return eq(line(p, q).eval(o), 0) && onstrip(o); 207 | } 208 | cod dist(const segment &o) const{ 209 | if(line(p, q).parallel(line(o.p, o.q))){ 210 | if(onstrip(o.p) || onstrip(o.q)) 211 | return line(p, q).dist(line(o.p, o.q)); 212 | return o.dist(p); 213 | } 214 | else if(intersect(o)) return 0; 215 | return min(min(dist(o.p), dist(o.q)), 216 | o.dist(p)); 217 | } 218 | bool intersect(const hray &o) const{ 219 | if(!line(p, q).parallel(line(o.p, o.q))) 220 | return false; 221 | auto pt = line(p, q).inter(line(o.p, o.q)); 222 | return contains(pt) && o.contains(pt); // << 223 | } 224 | bool intersect(const line &o) const{ 225 | if(line(p, q).parallel(o)) return line(p, q)== o; 226 | if(o.contains(p) || o.contains(q)) return true; 227 | return (o.eval(p) >= -eps)^(o.eval(p) v) { 271 | random_shuffle(v.begin(), v.end()); 272 | circle ans; 273 | int n = (int)v.size(); 274 | for(int i = 0; i < n; i++) if(!ans.inside(v[i])) { 275 | ans = circle(v[i]); 276 | for(int j = 0; j < i; j++) if(!ans.inside(v[j])){ 277 | ans = circle(v[i], v[j]); 278 | for(int k=0; k r*r*(a*a+b*b)+EPS) 6 | puts("no points"); 7 | else if(abs(c*c - r*r*(a*a+b*b)) < EPS){ 8 | puts("1 point"); 9 | cout << x0 << ' ' << y0 << '\n'; 10 | } 11 | else { 12 | double d = r*r - c*c/(a*a+b*b); 13 | double mult = sqrt (d / (a*a+b*b)); 14 | double ax, ay, bx, by; 15 | ax = x0 + b * mult; 16 | bx = x0 - b * mult; 17 | ay = y0 - a * mult; 18 | by = y0 + a * mult; 19 | puts ("2 points"); 20 | cout< monotone_chain_ch(vector P){ 2 | sort(P.begin(), P.end()); 3 | 4 | vector L, U; 5 | for(auto p : P){ 6 | // BE CAREFUL WITH OVERFLOW! 7 | // MAX VALUE (2*A)^2, where 0 <= abs(p.x), abs(p.y) <= A 8 | while(L.size() >= 2 && L[L.size() - 2].cross(L.back(), p) <= 0) 9 | L.pop_back(); 10 | 11 | L.push_back(p); 12 | } 13 | 14 | reverse(P.begin(), P.end()); 15 | for(auto p : P){ 16 | while(U.size() >= 2 && U[U.size() - 2].cross(U.back(), p) <= 0) 17 | U.pop_back(); 18 | 19 | U.push_back(p); 20 | } 21 | 22 | L.pop_back(), U.pop_back(); 23 | 24 | L.reserve(L.size() + U.size()); 25 | L.insert(L.end(), U.begin(), U.end()); 26 | 27 | return L; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /code/geometry/detect_halfplane.cpp: -------------------------------------------------------------------------------- 1 | // abs(point a) = absolute value of a 2 | // ccw(a, b, c) = a.ccw(b, c) 3 | pair half_inter(vector > &vet){ 4 | random_shuffle(all(vet)); 5 | point p; 6 | rep(i,0,sz(vet)) if(ccw(vet[i].x,vet[i].y,p) != 1){ 7 | point dir = (vet[i].y - vet[i].x) / abs(vet[i].y - vet[i].x); 8 | point l = vet[i].x - dir*1e15; 9 | point r = vet[i].x + dir*1e15; 10 | if(r < l) swap(l, r); 11 | rep(j, 0, i){ 12 | if(ccw(point(), vet[i].x-vet[i].y, vet[j].x-vet[j].y) == 0){ 13 | if(ccw(vet[j].x, vet[j].y, p) == 1) 14 | continue; 15 | return mp(false, point()); 16 | } 17 | if(ccw(vet[j].x, vet[j].y, l) != 1) 18 | l = max(l, line_intersect(vet[i].x,vet[i].y,vet[j].x,vet[j].y)); 19 | if(ccw(vet[j].x, vet[j].y, r) != 1) 20 | r = min(r, line_intersect(vet[i].x,vet[i].y,vet[j].x,vet[j].y)); 21 | if(!(l < r)) return mp(false, point()); 22 | } 23 | p = r; 24 | } 25 | return mp(true, p); 26 | } 27 | -------------------------------------------------------------------------------- /code/geometry/halfplane.cpp: -------------------------------------------------------------------------------- 1 | const double eps = 1e-8; 2 | typedef pair pi; 3 | bool z(long double x){ return fabs(x) < eps; } 4 | struct line{ 5 | long double a, b, c; 6 | bool operator<(const line &l)const{ 7 | bool flag1 = pi(a, b) > pi(0, 0); 8 | bool flag2 = pi(l.a, l.b) > pi(0, 0); 9 | if(flag1 != flag2) return flag1 > flag2; 10 | long double t = ccw(pi(0, 0), pi(a, b), pi(l.a, l.b)); 11 | return z(t) ? c * hypot(l.a, l.b) < l.c * hypot(a, b) : t > 0; 12 | } 13 | pi slope(){ return pi(a, b); } 14 | }; 15 | pi cross(line a, line b){ 16 | long double det = a.a * b.b - b.a * a.b; 17 | return pi((a.c * b.b - a.b * b.c) / det, (a.a * b.c - a.c * b.a) / det); 18 | } 19 | bool bad(line a, line b, line c){ 20 | if(ccw(pi(0, 0), a.slope(), b.slope()) <= 0) return false; 21 | pi crs = cross(a, b); 22 | return crs.first * c.a + crs.second * c.b >= c.c; 23 | } 24 | bool solve(vector v, vector &solution){ // ax + by <= c; 25 | sort(v.begin(), v.end()); 26 | deque dq; 27 | for(auto &i : v){ 28 | if(!dq.empty() && z(ccw(pi(0, 0), dq.back().slope(), i.slope()))) continue; 29 | while(dq.size() >= 2 && bad(dq[dq.size()-2], dq.back(), i)) dq.pop_back(); 30 | while(dq.size() >= 2 && bad(i, dq[0], dq[1])) dq.pop_front(); 31 | dq.push_back(i); 32 | } 33 | while(dq.size() > 2 && bad(dq[dq.size()-2], dq.back(), dq[0])) dq.pop_back(); 34 | while(dq.size() > 2 && bad(dq.back(), dq[0], dq[1])) dq.pop_front(); 35 | vector tmp; 36 | for(int i=0; i &vet, vec p){ 2 | auto it = lower_bound(vet.begin(), vet.end(), p); 3 | if(it == vet.end()) return false; 4 | if(it == vet.begin()) return *it == p; 5 | return prev(it)->cross(*it, p) <= 0; 6 | } 7 | 8 | bool above(const vector &vet, vec p){ 9 | auto it = lower_bound(vet.begin(), vet.end(), p); 10 | if(it == vet.end()) return false; 11 | if(it == vet.begin()) return *it == p; 12 | return prev(it)->cross(*it, p) >= 0; 13 | } 14 | 15 | // lowerhull, upperhull and point, borders included 16 | bool inside_poly(const vector &lo, const vector &hi, vec p){ 17 | return below(hi, p) && above(lo, p); 18 | } 19 | -------------------------------------------------------------------------------- /code/geometry/in_poly2.cpp: -------------------------------------------------------------------------------- 1 | // borders included 2 | // must not have 3 colinear consecutive points 3 | bool inside_poly(const vector &v, vec p){ 4 | if(v[0].ccw(v[1], p) < 0) return false; 5 | if(v[0].ccw(v.back(), p) > 0) return 0; 6 | if(v[0].ccw(v.back(), p) == 0) 7 | return v[0].dot(p, v.back()) >= 0 8 | && v.back().dot(p, v[0]) >= 0; 9 | 10 | int L = 1, R = (int)v.size() - 1, ans = 1; 11 | 12 | while(L <= R){ 13 | int mid = (L+R)/2; 14 | if(v[0].ccw(v[mid], p) >= 0) ans = mid, L = mid+1; 15 | else R = mid-1; 16 | } 17 | 18 | return v[ans].ccw(v[(ans+1)%v.size()], p) >= 0; 19 | } 20 | -------------------------------------------------------------------------------- /code/geometry/mink.cpp: -------------------------------------------------------------------------------- 1 | vector mk(const vector&a,const vector&b){ 2 | int i = 0, j = 0; 3 | for(int k = 0; k < (int)a.size(); k++)if(a[k] c; 9 | c.reserve(a.size() + b.size()); 10 | for(int k = 0; k < int(a.size()+b.size()); k++){ 11 | vec pt{a[i] + b[j]}; 12 | if((int)c.size() >= 2 13 | && c[c.size()-2].ccw(c.back(), pt) == 0) 14 | c.pop_back(); 15 | c.push_back(pt); 16 | int q = i+1, w = j+1; 17 | if(q == int(a.size())) q = 0; 18 | if(w == int(b.size())) w = 0; 19 | if(c.back().ccw(a[i]+b[w], a[q]+b[j]) < 0) i = q; 20 | else j = w; 21 | } 22 | c.shrink_to_fit(); 23 | 24 | return c; 25 | } 26 | -------------------------------------------------------------------------------- /code/geometry/near.cpp: -------------------------------------------------------------------------------- 1 | struct pt { 2 | int x, y, id; 3 | }; 4 | 5 | inline bool cmp_x (const pt & a, const pt & b) { 6 | return a.x < b.x || a.x == b.x && a.y < b.y; 7 | } 8 | 9 | inline bool cmp_y (const pt & a, const pt & b) { 10 | return a.y < b.y; 11 | } 12 | 13 | pt a[MAXN]; 14 | 15 | double mindist; 16 | int ansa, ansb; 17 | 18 | inline void upd_ans (const pt & a, const pt & b) { 19 | double dist = sqrt ((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) + .0); 20 | if (dist < mindist) 21 | mindist = dist, ansa = a.id, ansb = b.id; 22 | } 23 | 24 | void rec (int l, int r) { 25 | if (r - l <= 3) { 26 | for (int i=l; i<=r; ++i) 27 | for (int j=i+1; j<=r; ++j) 28 | upd_ans (a[i], a[j]); 29 | sort (a+l, a+r+1, &cmp_y); 30 | return; 31 | } 32 | 33 | int m = (l + r) >> 1; 34 | int midx = a[m].x; 35 | rec (l, m), rec (m+1, r); 36 | static pt t[MAXN]; 37 | merge (a+l, a+m+1, a+m+1, a+r+1, t, &cmp_y); 38 | copy (t, t+r-l+1, a+l); 39 | 40 | int tsz = 0; 41 | for (int i=l; i<=r; ++i) 42 | if (abs (a[i].x - midx) < mindist) { 43 | for (int j=tsz-1; j>=0 && a[i].y - t[j].y < mindist; --j) 44 | upd_ans (a[i], t[j]); 45 | t[tsz++] = a[i]; 46 | } 47 | } 48 | 49 | sort (a, a+n, &cmp_x); 50 | mindist = 1E20; 51 | rec (0, n-1); -------------------------------------------------------------------------------- /code/geometry/tangents.cpp: -------------------------------------------------------------------------------- 1 | // solve first for same circle(and infinitely many tangents) 2 | // Find up to four tangents of two circles 3 | void tangents(pt c, double r1, double r2, vector & ans){ 4 | double r = r2 - r1; 5 | double z = c.x * c.x + c.y * c.y; 6 | double d = z - r * r; 7 | if(d < -EPS) return; 8 | d = sqrt(abs(d)); 9 | line l; 10 | l.a = (c.x * r + c.y * d) / z; 11 | l.b = (c.y * r - c.x * d) / z; 12 | l.c = r1; 13 | ans.push_back (l); 14 | } 15 | 16 | vector tangents(circle a, circle b){ 17 | vector ans; 18 | pt aux = a.center - b.center; 19 | for(int i = -1; i <= 1; i += 2) 20 | for(int j = -1; j <= 1; j += 2) 21 | tangents(aux, a.r * i, b.r * j, ans); 22 | for(size_t i = 0; i < ans.size(); ++i) 23 | ans[i].c -= ans[i].a * a.x + ans[i].b * a.y; 24 | return ans; 25 | } 26 | -------------------------------------------------------------------------------- /code/graph/bipartite_matching.cpp: -------------------------------------------------------------------------------- 1 | // O(V * E) 2 | int match[N]; 3 | int vis[N], pass; 4 | vector g[N]; 5 | 6 | bool dfs(int u) { 7 | vis[u] = pass; 8 | 9 | for(int v : g[u]) if(vis[v] != pass) { 10 | vis[v] = pass; 11 | if(match[v] == -1 or dfs(match[v])) { 12 | match[v] = u; 13 | match[u] = v; 14 | return true; 15 | } 16 | } 17 | return false; 18 | } 19 | 20 | int max_maching() { 21 | memset(match, -1, sizeof match); 22 | int max_matching_size = 0; 23 | for(int u : vertices_on_side_A) { 24 | pass++; 25 | if(dfs(i)) max_matching_size++; 26 | } 27 | return max_matching_size; 28 | } 29 | -------------------------------------------------------------------------------- /code/graph/blossom.cpp: -------------------------------------------------------------------------------- 1 | const int MAXN = 2020 + 1; 2 | // 1-based Vertex index 3 | int vis[MAXN], par[MAXN], orig[MAXN], match[MAXN], aux[MAXN], t, N; 4 | vector conn[MAXN]; 5 | queue Q; 6 | void addEdge(int u, int v) { 7 | conn[u].push_back(v); conn[v].push_back(u); 8 | } 9 | void init(int n) { 10 | N = n; t = 0; 11 | for(int i=0; i<=n; ++i) 12 | conn[i].clear(), match[i] = aux[i] = par[i] = 0; 13 | } 14 | void augment(int u, int v) { 15 | int pv = v, nv; 16 | do { 17 | pv = par[v]; nv = match[pv]; 18 | match[v] = pv; match[pv] = v; 19 | v = nv; 20 | } while(u != pv); 21 | } 22 | int lca(int v, int w) { 23 | ++t; 24 | while(true) { 25 | if(v) { 26 | if(aux[v] == t) return v; aux[v] = t; 27 | v = orig[par[match[v]]]; 28 | } 29 | swap(v, w); 30 | } 31 | } 32 | void blossom(int v, int w, int a) { 33 | while(orig[v] != a) { 34 | par[v] = w; w = match[v]; 35 | if(vis[w] == 1) Q.push(w), vis[w] = 0; 36 | orig[v] = orig[w] = a; v = par[w]; 37 | } 38 | } 39 | bool bfs(int u) { 40 | fill(vis+1, vis+1+N, -1); iota(orig + 1, orig + N + 1, 1); 41 | Q = queue(); Q.push(u); vis[u] = 0; 42 | while(!Q.empty()) { 43 | int v = Q.front(); Q.pop(); 44 | for(int x: conn[v]) { 45 | if(vis[x] == -1) { 46 | par[x] = v; vis[x] = 1; 47 | if(!match[x]) return augment(u, x), true; 48 | Q.push(match[x]); vis[match[x]] = 0; 49 | } 50 | else if(vis[x] == 0 && orig[v] != orig[x]) { 51 | int a = lca(orig[v], orig[x]); 52 | blossom(x, v, a); blossom(v, x, a); 53 | } 54 | } 55 | } 56 | return false; 57 | } 58 | int Match() { 59 | int ans = 0; 60 | // find random matching (not necessary, constant improvement) 61 | vector V(N-1); iota(V.begin(), V.end(), 1); 62 | shuffle(V.begin(), V.end(), mt19937(0x94949)); 63 | for(auto x: V) if(!match[x]){ 64 | for(auto y: conn[x]) if(!match[y]) { 65 | match[x] = y, match[y] = x; 66 | ++ans; break; 67 | } 68 | } 69 | for(int i=1; i<=N; ++i) if(!match[i] && bfs(i)) ++ans; 70 | return ans; 71 | } 72 | -------------------------------------------------------------------------------- /code/graph/centroid_decomp.cpp: -------------------------------------------------------------------------------- 1 | void decomp(int v, int p){ 2 | int treesize = calc_sz(v, v); 3 | if(treesize < k) return; 4 | int cent = centroid(v, v, treesize); 5 | erased[cent] = 1; 6 | 7 | for(int i = 1; i <= treesize; i++) dist[i] = 1e18; 8 | 9 | for(pair x : G[cent]) if(!erased[x.ff]){ 10 | procurar_ans(x.ff, cent, 1, x.ss); // linear 11 | atualiza_dist(x.ff, cent, 1, x.ss); // linear 12 | } 13 | 14 | for(pair x : G[cent]) if(!erased[x.ff]) 15 | decomp(x.ff, cent); 16 | } 17 | 18 | -------------------------------------------------------------------------------- /code/graph/circulation.cpp: -------------------------------------------------------------------------------- 1 | // Circulation 2 | // 3 | // Given a directed weighted graph, computes the minimum cost to run the maximum 4 | // amount of circulation flow through the graph. 5 | // 6 | // Configure: MAXV 7 | // Configure: MAXE (at least 2 * calls_to_edge) 8 | // 9 | // Functions: 10 | // - init(n) initializes the algorithm with the given number of nodes 11 | // - edge(x, y, c, w) adds an edge x->y with capacity c and weight w 12 | // - run() runs the algorithm and returns total cost 13 | // 14 | // Time complexity: No idea, but it should be fast enough to solve any problem 15 | // where V and E are up to around 1000. 16 | // 17 | // Constants to configure: 18 | // - MAXV is the maximum number of vertices 19 | // - MAXE is the maximum number of edges (i.e. twice the calls to function edge) 20 | 21 | namespace Circu { 22 | const int MAXV = 1000100; 23 | const int MAXE = 1000100; 24 | 25 | int V, E; 26 | int how[MAXV], good[MAXV], bio[MAXV], cookie = 1; llint dist[MAXV]; 27 | int from[MAXE], to[MAXE]; llint cap[MAXE], cost[MAXE]; 28 | 29 | void init(int n) { V = n; E = 0; } 30 | 31 | void edge(int x, int y, llint c, llint w) { 32 | from[E] = x; to[E] = y; cap[E] = c; cost[E] = +w; ++E; 33 | from[E] = y; to[E] = x; cap[E] = 0; cost[E] = -w; ++E; 34 | } 35 | 36 | void reset() { 37 | REP(i, V) dist[i] = 0; 38 | REP(i, V) how[i] = -1; 39 | } 40 | 41 | bool relax() { 42 | bool ret = false; 43 | REP(e, E) if (cap[e]) { 44 | int x = from[e]; 45 | int y = to[e]; 46 | 47 | if (dist[x] + cost[e] < dist[y]) { 48 | dist[y] = dist[x] + cost[e]; 49 | how[y] = e; 50 | ret = true; 51 | } 52 | } 53 | return ret; 54 | } 55 | 56 | llint cycle(int s, bool flip = false) { 57 | int x = s; 58 | llint c = cap[how[x]]; 59 | do { 60 | int e = how[x]; 61 | c = min(c, cap[e]); 62 | x = from[e]; 63 | } while (x != s); 64 | 65 | llint sum = 0; 66 | do { 67 | int e = how[x]; 68 | if (flip) { 69 | cap[e] -= c; 70 | cap[e^1] += c; 71 | } 72 | sum += cost[e] * c; 73 | x = from[e]; 74 | } while (x != s); 75 | return sum; 76 | } 77 | 78 | llint push(int x) { 79 | for (++cookie; bio[x] != cookie; x = from[how[x]]) { 80 | if (!good[x] || how[x] == -1 || cap[how[x]] == 0) return 0; 81 | bio[x] = cookie; 82 | good[x] = false; 83 | } 84 | return cycle(x) >= 0 ? 0 : cycle(x, true); 85 | } 86 | 87 | llint run() { 88 | reset(); 89 | llint ret = 0; 90 | REP(step, 2*V) { 91 | if (step == V) reset(); 92 | if (!relax()) continue; 93 | 94 | REP(i, V) good[i] = true; 95 | REP(i, V) if (llint w = push(i)) ret += w, step = 0; 96 | } 97 | return ret; 98 | } 99 | } -------------------------------------------------------------------------------- /code/graph/dinic.cpp: -------------------------------------------------------------------------------- 1 | const int N = 100005; 2 | const int E = 2000006; 3 | vector g[N]; 4 | int ne; 5 | struct Edge{ 6 | int from, to; ll flow, cap; 7 | } edge[E]; 8 | int lvl[N], vis[N], pass, start = N-2, target = N-1; 9 | int qu[N], qt, px[N]; 10 | 11 | ll run(int s, int sink, ll minE){ 12 | if(s == sink) return minE; 13 | 14 | ll ans = 0; 15 | 16 | for(; px[s] < (int)g[s].size(); px[s]++){ 17 | int e = g[s][ px[s] ]; 18 | auto &v = edge[e], &rev = edge[e^1]; 19 | if(lvl[v.to] != lvl[s]+1 || v.flow >= v.cap) 20 | continue; // v.cap - v.flow < lim 21 | ll tmp = run(v.to, sink,min(minE, v.cap-v.flow)); 22 | v.flow += tmp, rev.flow -= tmp; 23 | ans += tmp, minE -= tmp; 24 | if(minE == 0) break; 25 | } 26 | return ans; 27 | } 28 | bool bfs(int source, int sink){ 29 | qt = 0; 30 | qu[qt++] = source; 31 | lvl[source] = 1; 32 | vis[source] = ++pass; 33 | for(int i = 0; i < qt; i++){ 34 | int u = qu[i]; 35 | px[u] = 0; 36 | if(u == sink) return true; 37 | for(auto& ed : g[u]) { 38 | auto v = edge[ed]; 39 | if(v.flow >= v.cap || vis[v.to] == pass) 40 | continue; // v.cap - v.flow < lim 41 | vis[v.to] = pass; 42 | lvl[v.to] = lvl[u]+1; 43 | qu[qt++] = v.to; 44 | } 45 | } 46 | return false; 47 | } 48 | ll flow(int source = start, int sink = target){ 49 | ll ans = 0; 50 | //for(lim = (1LL << 62); lim >= 1; lim /= 2) 51 | while(bfs(source, sink)) 52 | ans += run(source, sink, oo); 53 | return ans; 54 | } 55 | void addEdge(int u, int v, ll c = 1, ll rc = 0){ 56 | edge[ne] = {u, v, 0, c}; 57 | g[u].push_back(ne++); 58 | edge[ne] = {v, u, 0, rc}; 59 | g[v].push_back(ne++); 60 | } 61 | void reset_flow(){ 62 | for(int i = 0; i < ne; i++) 63 | edge[i].flow = 0; 64 | } 65 | 66 | -------------------------------------------------------------------------------- /code/graph/dominator_tree.cpp: -------------------------------------------------------------------------------- 1 | vector g[N], gt[N], T[N]; 2 | vector S; 3 | int dsu[N], label[N]; 4 | int sdom[N], idom[N], dfs_time, id[N]; 5 | 6 | vector bucket[N]; 7 | vector down[N]; 8 | 9 | void prep(int u){ 10 | S.push_back(u); 11 | id[u] = ++dfs_time; 12 | label[u] = sdom[u] = dsu[u] = u; 13 | 14 | for(int v : g[u]){ 15 | if(!id[v]) 16 | prep(v), down[u].push_back(v); 17 | gt[v].push_back(u); 18 | } 19 | } 20 | 21 | int fnd(int u, int flag = 0){ 22 | if(u == dsu[u]) return u; 23 | int v = fnd(dsu[u], 1), b = label[ dsu[u] ]; 24 | if(id[ sdom[b] ] < id[ sdom[ label[u] ] ]) 25 | label[u] = b; 26 | dsu[u] = v; 27 | return flag ? v : label[u]; 28 | } 29 | 30 | void build_dominator_tree(int root, int sz){ 31 | // memset(id, 0, sizeof(int) * (sz + 1)); 32 | // for(int i = 0; i <= sz; i++) T[i].clear(); 33 | prep(root); 34 | reverse(S.begin(), S.end()); 35 | 36 | int w; 37 | for(int u : S){ 38 | for(int v : gt[u]){ 39 | w = fnd(v); 40 | if(id[ sdom[w] ] < id[ sdom[u] ]) 41 | sdom[u] = sdom[w]; 42 | } 43 | gt[u].clear(); 44 | 45 | if(u != root) bucket[ sdom[u] ].push_back(u); 46 | 47 | for(int v : bucket[u]){ 48 | w = fnd(v); 49 | if(sdom[w] == sdom[v]) idom[v] = sdom[v]; 50 | else idom[v] = w; 51 | } 52 | bucket[u].clear(); 53 | 54 | for(int v : down[u]) dsu[v] = u; 55 | down[u].clear(); 56 | } 57 | 58 | reverse(S.begin(), S.end()); 59 | for(int u : S) if(u != root){ 60 | if(idom[u] != sdom[u]) idom[u] = idom[ idom[u] ]; 61 | T[ idom[u] ].push_back(u); 62 | } 63 | S.clear(); 64 | } 65 | -------------------------------------------------------------------------------- /code/graph/hungarian_mcm.cpp: -------------------------------------------------------------------------------- 1 | // Min cost matching 2 | // O(n^2 * m) 3 | // n == nro de linhas 4 | // m == nro de colunas 5 | // n <= m | flow == n 6 | // a[i][j] = custo pra conectar i a j 7 | vector u(n + 1), v(m + 1), p(m + 1), way(m + 1); 8 | for(int i = 1; i <= n; ++i){ 9 | p[0] = i; 10 | int j0 = 0; 11 | vector minv(m + 1 , oo); 12 | vector used(m + 1 , false); 13 | do{ 14 | used[j0] = true; 15 | int i0 = p[j0] , delta = oo, j1; 16 | for(int j = 1; j <= m; ++j) 17 | if(! used[j]){ 18 | int cur = a[i0][j] - u[i0] - v[j]; 19 | if(cur < minv[j]) 20 | minv[j] = cur, way[j] = j0; 21 | if(minv[j] < delta) 22 | delta = minv[j] , j1 = j; 23 | } 24 | for(int j = 0; j <= m; ++j) 25 | if(used[j]) 26 | u[p[j]] += delta, v[j] -= delta; 27 | else 28 | minv[j] -= delta; 29 | j0 = j1; 30 | }while(p[j0] != 0); 31 | 32 | do{ 33 | int j1 = way[j0]; 34 | p[j0] = p[j1]; 35 | j0 = j1; 36 | }while(j0); 37 | } 38 | 39 | // match[i] = coluna escolhida para linha i 40 | vector match(n + 1); 41 | for(int j = 1; j <= m; ++j) 42 | match[p[j]] = j; 43 | 44 | int cost = -v[0]; 45 | -------------------------------------------------------------------------------- /code/graph/kosaraju.cpp: -------------------------------------------------------------------------------- 1 | vector g[N], gt[N], S; int vis[N], cor[N]; 2 | void dfs(int u){ 3 | vis[u] = 1; for(int v : g[u]) if(!vis[v]) dfs(v); 4 | S.push_back(u); 5 | } 6 | void dfst(int u, int e){ 7 | cor[u] = e; 8 | for(int v : gt[u]) if(!cor[v]) dfst(v, e); 9 | } 10 | void kosaraju(){ 11 | for(int i = 1; i <= n; i++) if(!vis[i]) dfs(i); 12 | for(int i = 1; i <= n; i++) for(int j : g[i]) 13 | gt[j].push_back(i); 14 | int e = 0; reverse(S.begin(), S.end()); 15 | for(int u : S) if(!cor[u]) dfst(u, ++e); 16 | } 17 | -------------------------------------------------------------------------------- /code/graph/maxcliq.cpp: -------------------------------------------------------------------------------- 1 | long long adj[N], dp[N]; 2 | 3 | for(int i = 0; i < n; i++){ 4 | for(int j = 0; j < n; j++){ 5 | int x; 6 | scanf("%d",&x); 7 | if(x || i == j) 8 | adj[i] |= 1LL << j; 9 | } 10 | } 11 | 12 | int resto = n - n/2; 13 | int C = n/2; 14 | for(int i = 1; i < (1 << resto); i++){ 15 | int x = i; 16 | for(int j = 0; j < resto; j++) 17 | if(i & (1 << j)) 18 | x &= adj[j + C] >> C; 19 | if(x == i){ 20 | dp[i] = __builtin_popcount(i); 21 | } 22 | } 23 | 24 | for(int i = 1; i < (1 << resto); i++) 25 | for(int j = 0; j < resto; j++) 26 | if(i & (1 << j)) 27 | dp[i] = max(dp[i], dp[i ^ (1 << j)]); 28 | 29 | int maxCliq = 0; 30 | for(int i = 0; i < (1 << C); i++){ 31 | int x = i, y = (1 << resto) - 1; 32 | for(int j = 0; j < C; j++) 33 | if(i & (1 << j)) 34 | x &= adj[j] & ((1 << C) - 1), y &= adj[j] >> C; 35 | if(x != i) continue; 36 | maxCliq = max(maxCliq, __builtin_popcount(i) + dp[y]); 37 | } 38 | -------------------------------------------------------------------------------- /code/graph/mcmf.cpp: -------------------------------------------------------------------------------- 1 | const ll oo = 1e18; 2 | const int N = 422, E = 2 * 10006; 3 | 4 | vector g[N]; 5 | int ne; 6 | struct Edge{ 7 | int from, to; ll cap, cost; 8 | } edge[E]; 9 | int start = N-1, target = N-2, p[N]; int inqueue[N]; 10 | ll d[N]; 11 | ll pot[N]; 12 | bool dijkstra(int source, int sink) { 13 | for(int i = 0; i < N; i++) d[i] = oo; 14 | d[source] = 0; 15 | priority_queue> q; 16 | q.emplace(0, source); 17 | ll dt; int u; 18 | while(!q.empty()) { 19 | tie(dt, u) = q.top(); q.pop(); dt = -dt; 20 | if(dt > d[u]) continue; 21 | if(u == sink) return true; 22 | for(int e : g[u]) { 23 | auto v = edge[e]; 24 | const ll cand = d[u] + v.cost + pot[u] - pot[v.to]; 25 | if(v.cap > 0 and cand < d[v.to]) { 26 | p[v.to] = e; 27 | d[v.to] = cand; 28 | q.emplace(-d[v.to], v.to); 29 | } 30 | } 31 | } 32 | return d[sink] < oo; 33 | } 34 | 35 | // 36 | pair mincost(int source = start, int sink = target){ 37 | ll ans = 0, mf = 0; 38 | while(dijkstra(source, sink)){ 39 | ll f = oo; 40 | for(int u = sink; u != source; u = edge[ p[u] ].from) 41 | f = min(f, edge[ p[u] ].cap); 42 | mf += f; 43 | ans += f * (d[sink] - pot[source] + pot[sink]); 44 | for(int u = sink; u != source; u = edge[ p[u] ].from){ 45 | edge[ p[u] ].cap -= f; 46 | edge[ p[u] ^ 1 ].cap += f; 47 | } 48 | for(int i = 0; i < N; i++) pot[i] = min(oo, pot[i] + d[i]); 49 | } 50 | return {mf, ans}; 51 | } 52 | void addEdge(int u, int v, ll c, ll cost){ 53 | assert(cost >= 0); 54 | edge[ne] = {u, v, c, cost}; 55 | g[u].push_back(ne++); 56 | edge[ne] = {v, u, 0,-cost}; 57 | g[v].push_back(ne++); 58 | } 59 | 60 | -------------------------------------------------------------------------------- /code/graph/mcmf_dfs.cpp: -------------------------------------------------------------------------------- 1 | // Min-cost max-flow (uses DFS) 2 | // 3 | // Given a directed weighted graph, source, and sink, computes the minimum cost 4 | // of the maximum flow from source to sink. 5 | // This version uses DFS to find shortest paths and gives good performance on 6 | // very "shallow" graphs: graphs which have very short paths between source 7 | // and sink (e.g. at most 10 edges). 8 | // In such cases this algorithm can be orders of magnitude faster than the 9 | // Dijkstra version. 10 | // 11 | // To use, call init(n), then add edges using edge(x, y, c, w), and finally 12 | // call run(src, sink). 13 | // 14 | // Functions: 15 | // - init(n) initializes the algorithm with the given number of nodes 16 | // - edge(x, y, c, w) adds an edge x->y with capacity c and weight w 17 | // - run(src, sink) runs the algorithm and returns {total_cost, total_flow} 18 | // 19 | // Time complexity: O(V * E^3) 20 | // 21 | // Constants to configure: 22 | // - MAXV is the maximum number of vertices 23 | // - MAXE is the maximum number of edges (i.e. twice the calls to function edge) 24 | // - oo is the "infinity" value 25 | 26 | namespace Mcmf { 27 | const int MAXV = 1000100; 28 | const int MAXE = 1000100; 29 | const llint oo = 1e18; 30 | 31 | int V, E; 32 | int last[MAXV], curr[MAXV], bio[MAXV]; llint pi[MAXV]; 33 | int next[MAXE], adj[MAXE]; llint cap[MAXE], cost[MAXE]; 34 | 35 | void init(int n) { 36 | V = n; 37 | E = 0; 38 | REP(i, V) last[i] = -1; 39 | REP(i, V) pi[i] = 0; 40 | } 41 | 42 | void edge(int x, int y, llint c, llint w) { 43 | adj[E] = y; cap[E] = c; cost[E] = +w; next[E] = last[x]; last[x] = E++; 44 | adj[E] = x; cap[E] = 0; cost[E] = -w; next[E] = last[y]; last[y] = E++; 45 | } 46 | 47 | llint push(int x, int sink, llint flow) { 48 | if (x == sink) return flow; 49 | if (bio[x]) return 0; 50 | bio[x] = true; 51 | 52 | for (int &e = curr[x]; e != -1; e = next[e]) { 53 | int y = adj[e]; 54 | 55 | if (cap[e] && pi[x] == pi[y] + cost[e]) 56 | if (llint f = push(y, sink, min(flow, cap[e]))) 57 | return cap[e] -= f, cap[e^1] += f, f; 58 | } 59 | return 0; 60 | } 61 | 62 | pair run(int src, int sink) { 63 | llint total = 0; 64 | llint flow = 0; 65 | pi[src] = oo; 66 | 67 | for (;;) { 68 | REP(i, V) bio[i] = false; 69 | REP(i, V) curr[i] = last[i]; 70 | 71 | while (llint f = push(src, sink, oo)) { 72 | total += pi[src] * f; 73 | flow += f; 74 | REP(i, V) bio[i] = false; 75 | } 76 | 77 | llint inc = oo; 78 | REP(x, V) if (bio[x]) { 79 | for (int e = last[x]; e != -1; e = next[e]) { 80 | int y = adj[e]; 81 | if (cap[e] && !bio[y]) inc = min(inc, pi[y] + cost[e] - pi[x]); 82 | } 83 | } 84 | if (inc == oo) break; 85 | 86 | REP(i, V) if (bio[i]) pi[i] += inc; 87 | } 88 | return {total, flow}; 89 | } 90 | } -------------------------------------------------------------------------------- /code/graph/mcmf_dijkstra.cpp: -------------------------------------------------------------------------------- 1 | // Min-cost max-flow (uses Dijkstra's algorithm) 2 | // 3 | // Given a directed weighted graph, source, and sink, computes the minimum cost 4 | // of the maximum flow from source to sink. 5 | // This version uses Dijkstra's algorithm and gives good performance on all 6 | // kinds of graphs. 7 | // 8 | // To use, call init(n), then add edges using edge(x, y, c, w), and finally 9 | // call run(src, sink). 10 | // 11 | // Functions: 12 | // - init(n) initializes the algorithm with the given number of nodes 13 | // - edge(x, y, c, w) adds an edge x->y with capacity c and weight w 14 | // - run(src, sink) runs the algorithm and returns {total_cost, total_flow} 15 | // 16 | // Time complexity: O(V * E^2 log E) 17 | // 18 | // Constants to configure: 19 | // - MAXV is the maximum number of vertices 20 | // - MAXE is the maximum number of edges (i.e. twice the calls to function edge) 21 | // - oo is the "infinity" value 22 | 23 | namespace Mcmf { 24 | const int MAXV = 1000100; 25 | const int MAXE = 1000100; 26 | const llint oo = 1e18; 27 | 28 | int V, E; 29 | int last[MAXV], how[MAXV]; llint dist[MAXV]; 30 | int next[MAXE], from[MAXE], adj[MAXE]; llint cap[MAXE], cost[MAXE]; 31 | 32 | struct cmpf { 33 | bool operator () (int a, int b) { 34 | if (dist[a] != dist[b]) return dist[a] < dist[b]; 35 | return a < b; 36 | } 37 | }; 38 | set S; 39 | 40 | void init(int n) { 41 | V = n; 42 | E = 0; 43 | REP(i, V) last[i] = -1; 44 | } 45 | 46 | void edge(int x, int y, llint c, llint w) { 47 | from[E] = x; adj[E] = y; cap[E] = c; cost[E] = +w; next[E] = last[x]; last[x] = E++; 48 | from[E] = y; adj[E] = x; cap[E] = 0; cost[E] = -w; next[E] = last[y]; last[y] = E++; 49 | } 50 | 51 | pair run(int src, int sink) { 52 | llint total = 0; 53 | llint flow = 0; 54 | 55 | for (;;) { 56 | REP(i, V) dist[i] = oo; 57 | dist[src] = 0; 58 | 59 | for (;;) { 60 | bool done = true; 61 | REP(x, V) for (int e = last[x]; e != -1; e = next[e]) { 62 | if (cap[e] == 0) continue; 63 | 64 | int y = adj[e]; 65 | llint val = dist[x] + cost[e]; 66 | 67 | if (val < dist[y]) { 68 | dist[y] = val; 69 | how[y] = e; 70 | done = false; 71 | } 72 | } 73 | if (done) break; 74 | } 75 | 76 | if (dist[sink] >= oo / 2) break; 77 | 78 | llint aug = cap[how[sink]]; 79 | for (int i = sink; i != src; i = from[how[i]]) 80 | aug = min(aug, cap[how[i]]); 81 | 82 | for (int i = sink; i != src; i = from[how[i]]) { 83 | cap[how[i]] -= aug; 84 | cap[how[i]^1] += aug; 85 | total += cost[how[i]] * aug; 86 | } 87 | flow += aug; 88 | } 89 | return {total, flow}; 90 | } 91 | } -------------------------------------------------------------------------------- /code/graph/pushrelabel.cpp: -------------------------------------------------------------------------------- 1 | // Push relabel in O(V^2 E^0.5) with gap heuristic 2 | // It's quite fast 3 | template 4 | struct PushRelabel { 5 | struct Edge { int to, rev; flow_t f, c; }; 6 | vector > g; 7 | vector ec; 8 | vector cur; 9 | vector > hs; 10 | vector H; 11 | PushRelabel(int n) : g(n), ec(n), cur(n), hs(2*n), H(n) {} 12 | void add_edge(int s, int t, flow_t cap, flow_t rcap=0) { 13 | if (s == t) return; 14 | Edge a = {t, (int)g[t].size(), 0, cap}; 15 | Edge b = {s, (int)g[s].size(), 0, rcap}; 16 | g[s].push_back(a); 17 | g[t].push_back(b); 18 | } 19 | void add_flow(Edge& e, flow_t f) { 20 | Edge &back = g[e.to][e.rev]; 21 | if (!ec[e.to] && f) 22 | hs[H[e.to]].push_back(e.to); 23 | e.f += f, ec[e.to] += f; 24 | back.f -= f, ec[back.to] -= f; 25 | } 26 | flow_t max_flow(int s, int t) { 27 | int v = g.size(); 28 | H[s] = v; ec[t] = 1; 29 | vector co(2 * v); 30 | co[0] = v-1; 31 | for(int i = 0; i < v; ++i) cur[i] = g[i].data(); 32 | for(auto &e : g[s]) add_flow(e, e.c); 33 | 34 | if(hs[0].size()) 35 | for (int hi = 0; hi >= 0;) { 36 | int u = hs[hi].back(); 37 | hs[hi].pop_back(); 38 | while (ec[u] > 0) // discharge u 39 | if (cur[u] == g[u].data() + g[u].size()) { 40 | H[u] = 1e9; 41 | for(auto &e:g[u]) 42 | if (e.c - e.f && H[u] > H[e.to]+1) 43 | H[u] = H[e.to]+1, cur[u] = &e; 44 | if (++co[H[u]], !--co[hi] && hi < v) 45 | for(int i = 0; i < v; ++i) 46 | if (hi < H[i] && H[i] < v){ 47 | --co[H[i]]; 48 | H[i] = v + 1; 49 | } 50 | hi = H[u]; 51 | } else if (cur[u]->c - cur[u]->f && H[u] == H[cur[u]->to]+1) 52 | add_flow(*cur[u], min(ec[u], cur[u]->c - cur[u]->f)); 53 | else ++cur[u]; 54 | while (hi >= 0 && hs[hi].empty()) --hi; 55 | } 56 | return -ec[s]; 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /code/graph/stl.cpp: -------------------------------------------------------------------------------- 1 | void cnt_sz(int u, int p = -1){ 2 | sz[u] = 1; 3 | for(int v : g[u]) if(v != p) 4 | cnt_sz(v, u), sz[u] += sz[v]; 5 | } 6 | void add(int u, int p, int big = -1){ 7 | // Update info about this vx in global answer 8 | for(int v : g[u]) if(v != p && v != big) 9 | add(v, u); 10 | } 11 | void dfs(int u, int p, int keep){ 12 | int big = -1, mmx = -1; 13 | for(int v : g[u]) if(v != p && sz[v] > mmx) 14 | mmx = sz[v], big = v; 15 | for(int v : g[u]) if(v != p && v != big) 16 | dfs(v, u, 0); 17 | if(big != -1) dfs(big, u, 1); 18 | add(u, p, big); 19 | for(auto x : q[u]){ 20 | // answer all queries for this vx 21 | } 22 | if(!keep){ /*Remove data from this subtree*/ } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /code/graph/tarjan.cpp: -------------------------------------------------------------------------------- 1 | int cnt = 0, root; 2 | void dfs(int u, int p = -1){ 3 | low[u] = num[u] = ++t; 4 | for(int v : g[u]){ 5 | if(!num[v]){ 6 | dfs(v, u); 7 | if(u == root) cnt++; 8 | if(low[v] >= num[u]) u PONTO DE ARTICULACAO; 9 | if(low[v] > num[u]) ARESTA u->v PONTE; 10 | low[u] = min(low[u], low[v]); 11 | } 12 | else if(v != p) low[u] = min(low[u], num[v]); 13 | } 14 | } 15 | 16 | root PONTO DE ARTICULACAO <=> cnt > 1 17 | 18 | void tarjanSCC(int u){ 19 | low[u] = num[u] = ++cnt; 20 | vis[u] = 1; 21 | S.push_back(u); 22 | for(int v : g[u]){ 23 | if(!num[v]) tarjanSCC(v); 24 | if(vis[v]) low[u] = min(low[u], low[v]); 25 | } 26 | if(low[u] == num[u]){ 27 | ssc[u] = ++ssc_cnt; int v; 28 | do{ 29 | v = S.back(); S.pop_back(); vis[v] = 0; 30 | ssc[v] = ssc_cnt; 31 | }while(u != v); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /code/graph/weight_blossom.cpp: -------------------------------------------------------------------------------- 1 | // N^3 (but fast in practice) 2 | static const int INF = INT_MAX; 3 | static const int N = 514; 4 | struct edge{ 5 | int u,v,w; edge(){} 6 | edge(int ui,int vi,int wi) 7 | :u(ui),v(vi),w(wi){} 8 | }; 9 | int n,n_x; 10 | edge g[N*2][N*2]; 11 | int lab[N*2]; 12 | int match[N*2],slack[N*2],st[N*2],pa[N*2]; 13 | int flo_from[N*2][N+1],S[N*2],vis[N*2]; 14 | vector flo[N*2]; 15 | queue q; 16 | int e_delta(const edge &e){ 17 | return lab[e.u]+lab[e.v]-g[e.u][e.v].w*2; 18 | } 19 | void update_slack(int u,int x){ 20 | if(!slack[x]||e_delta(g[u][x])0&&st[u]!=x&&S[st[u]]==0) 26 | update_slack(u,x); 27 | } 28 | void q_push(int x){ 29 | if(x<=n)q.push(x); 30 | else for(size_t i=0;in)for(size_t i=0;in_x)++n_x; 78 | lab[b]=0,S[b]=0; 79 | match[b]=match[lca]; 80 | flo[b].clear(); 81 | flo[b].push_back(lca); 82 | for(int x=u,y;x!=lca;x=st[pa[y]]) 83 | flo[b].push_back(x),flo[b].push_back(y=st[match[x]]),q_push(y); 84 | reverse(flo[b].begin()+1,flo[b].end()); 85 | for(int x=v,y;x!=lca;x=st[pa[y]]) 86 | flo[b].push_back(x),flo[b].push_back(y=st[match[x]]),q_push(y); 87 | set_st(b,b); 88 | for(int x=1;x<=n_x;++x)g[b][x].w=g[x][b].w=0; 89 | for(int x=1;x<=n;++x)flo_from[b][x]=0; 90 | for(size_t i=0;i(); 136 | for(int x=1;x<=n_x;++x) 137 | if(st[x]==x&&!match[x])pa[x]=0,S[x]=0,q_push(x); 138 | if(q.empty())return false; 139 | for(;;){ 140 | while(q.size()){ 141 | int u=q.front();q.pop(); 142 | if(S[st[u]]==1)continue; 143 | for(int v=1;v<=n;++v) 144 | if(g[u][v].w>0&&st[u]!=st[v]){ 145 | if(e_delta(g[u][v])==0){ 146 | if(on_found_edge(g[u][v]))return true; 147 | }else update_slack(u,st[v]); 148 | } 149 | } 150 | int d=INF; 151 | for(int b=n+1;b<=n_x;++b) 152 | if(st[b]==b&&S[b]==1)d=min(d,lab[b]/2); 153 | for(int x=1;x<=n_x;++x) 154 | if(st[x]==x&&slack[x]){ 155 | if(S[x]==-1)d=min(d,e_delta(g[slack[x]][x])); 156 | else if(S[x]==0)d=min(d,e_delta(g[slack[x]][x])/2); 157 | } 158 | for(int u=1;u<=n;++u){ 159 | if(S[st[u]]==0){ 160 | if(lab[u]<=d)return 0; 161 | lab[u]-=d; 162 | }else if(S[st[u]]==1)lab[u]+=d; 163 | } 164 | for(int b=n+1;b<=n_x;++b) 165 | if(st[b]==b){ 166 | if(S[st[b]]==0)lab[b]+=d*2; 167 | else if(S[st[b]]==1)lab[b]-=d*2; 168 | } 169 | q=queue(); 170 | for(int x=1;x<=n_x;++x) 171 | if(st[x]==x&&slack[x]&&st[slack[x]]!=x&&e_delta(g[slack[x]][x])==0) 172 | if(on_found_edge(g[slack[x]][x]))return true; 173 | for(int b=n+1;b<=n_x;++b) 174 | if(st[b]==b&&S[b]==1&&lab[b]==0)expand_blossom(b); 175 | } 176 | return false; 177 | } 178 | pair solve(){ 179 | memset(match+1,0,sizeof(int)*n); 180 | n_x=n; 181 | int n_matches=0; 182 | long long tot_weight=0; 183 | for(int u=0;u<=n;++u)st[u]=u,flo[u].clear(); 184 | int w_max=0; 185 | for(int u=1;u<=n;++u) 186 | for(int v=1;v<=n;++v){ 187 | flo_from[u][v]=(u==v?u:0); 188 | w_max=max(w_max,g[u][v].w); 189 | } 190 | for(int u=1;u<=n;++u)lab[u]=w_max; 191 | while(matching())++n_matches; 192 | for(int u=1;u<=n;++u) 193 | if(match[u]&&match[u]> &vet){ 3 | ll ans = 0, lcm = 1; 4 | ll a, b, g, x, y; 5 | for(const auto &p : vet) { 6 | tie(a, b) = p; 7 | tie(g, x, y) = gcd(lcm, b); 8 | if((a - ans) % g != 0) return -1; // no solution 9 | ans = ans + x * ((a - ans) / g) % (b / g) * lcm; 10 | lcm = lcm * (b / g); 11 | ans = (ans % lcm + lcm) % lcm; 12 | } 13 | return ans; 14 | } 15 | -------------------------------------------------------------------------------- /code/math/det.cpp: -------------------------------------------------------------------------------- 1 | int n; 2 | long double a[n][n]; 3 | 4 | long double gauss(){ 5 | long double det = 1; 6 | for(int i = 0; i < n; i++){ 7 | int q = i; 8 | for(int j = i+1; j < n; j++){ 9 | if(abs(a[j][i]) > abs(a[q][i])) 10 | q = j; 11 | } 12 | if(abs(a[q][i]) < EPS){ 13 | det = 0; 14 | break; 15 | } 16 | if(i != q){ 17 | for(int w = 0; w < n; w++) 18 | swap(a[i][w], a[q][w]); 19 | det = -det; 20 | } 21 | det *= a[i][i]; 22 | for(int j = i+1; j < n; j++) a[i][j] /= a[i][i]; 23 | 24 | for(int j = 0; j < n; j++) if(j != i){ 25 | if(abs(a[j][i]) > EPS) 26 | for(int k = i+1; k < n; k++) 27 | a[j][k] -= a[i][k] * a[j][i]; 28 | } 29 | } 30 | 31 | return det; 32 | } 33 | -------------------------------------------------------------------------------- /code/math/diophantine.cpp: -------------------------------------------------------------------------------- 1 | template 2 | T extgcd(T a, T b, T &x, T &y) { 3 | if (a == 0) { 4 | x = 0; 5 | y = 1; 6 | return b; 7 | } 8 | T p = b / a; 9 | T g = extgcd(b - p * a, a, y, x); 10 | x -= p * y; 11 | return g; 12 | } 13 | 14 | template 15 | bool diophantine(T a, T b, T c, T &x, T &y, T &g) { 16 | if (a == 0 && b == 0) { 17 | if (c == 0) { 18 | x = y = g = 0; 19 | return true; 20 | } 21 | return false; 22 | } 23 | if (a == 0) { 24 | if (c % b == 0) { 25 | x = 0; 26 | y = c / b; 27 | g = abs(b); 28 | return true; 29 | } 30 | return false; 31 | } 32 | if (b == 0) { 33 | if (c % a == 0) { 34 | x = c / a; 35 | y = 0; 36 | g = abs(a); 37 | return true; 38 | } 39 | return false; 40 | } 41 | g = extgcd(a, b, x, y); 42 | if (c % g != 0) { 43 | return false; 44 | } 45 | T dx = c / a; 46 | c -= dx * a; 47 | T dy = c / b; 48 | c -= dy * b; 49 | x = dx + mulmod(x, c / g, b); 50 | y = dy + mulmod(y, c / g, a); 51 | g = abs(g); 52 | return true; 53 | } 54 | 55 | -------------------------------------------------------------------------------- /code/math/division_trick.cpp: -------------------------------------------------------------------------------- 1 | for(int l = 1, r; l <= n; l = r + 1) { 2 | r = n / (n / l); 3 | // n / x yields the same value for l <= x <= r 4 | } 5 | for(int l, r = n; r > 0; r = l - 1) { 6 | int tmp = (n + r - 1) / r; 7 | l = (n + tmp - 1) / tmp; 8 | // (n+x-1) / x yields the same value for l <= x <= r 9 | } 10 | -------------------------------------------------------------------------------- /code/math/euclides.cpp: -------------------------------------------------------------------------------- 1 | // a*x + b*y = gcd(a, b), 2 | tuple gcd(int a, int b) { 3 | if(b == 0) return make_tuple(a, 1, 0); 4 | int q, w, e; 5 | tie(q, w, e) = gcd(b, a % b); 6 | return make_tuple(q, e, w - e * (a / b)); 7 | } 8 | -------------------------------------------------------------------------------- /code/math/fast_mul_mod.cpp: -------------------------------------------------------------------------------- 1 | ll mulmod(ll a, ll b, ll mod) { 2 | ll q = ll((long double)a * (long double)b / (long double)mod); 3 | ll r = (a * b - mod * q) % mod; 4 | if(r < 0) r += mod; 5 | return r; 6 | } 7 | -------------------------------------------------------------------------------- /code/math/inv.cpp: -------------------------------------------------------------------------------- 1 | inv[1] = 1; 2 | for(int i = 2; i < p; i++) 3 | inv[i] = (p - (p/i) * inv[p%i] % p) % p; 4 | 5 | -------------------------------------------------------------------------------- /code/math/karatsuba.cpp: -------------------------------------------------------------------------------- 1 | // source https://codeforces.com/blog/entry/74209 2 | 3 | #pragma GCC optimize("Ofast,unroll-loops") 4 | #pragma GCC target("avx,avx2,fma") 5 | namespace { 6 | template 7 | void mult(const T *__restrict a, const T *__restrict b, T *__restrict res) { 8 | if (n <= 64) { // if length is small then naive multiplication if faster 9 | for (int i = 0; i < n; i++) { 10 | for (int j = 0; j < n; j++) { 11 | res[i + j] += a[i] * b[j]; 12 | } 13 | } 14 | } else { 15 | const int mid = n / 2; 16 | alignas(64) T btmp[n], E[n] = {}; 17 | auto atmp = btmp + mid; 18 | for (int i = 0; i < mid; i++) { 19 | atmp[i] = a[i] + a[i + mid]; // atmp(x) - sum of two halfs a(x) 20 | btmp[i] = b[i] + b[i + mid]; // btmp(x) - sum of two halfs b(x) 21 | } 22 | mult(atmp, btmp, E); // Calculate E(x) = (alow(x) + ahigh(x)) * (blow(x) + bhigh(x)) 23 | mult(a + 0, b + 0, res); // Calculate rlow(x) = alow(x) * blow(x) 24 | mult(a + mid, b + mid, res + n); // Calculate rhigh(x) = ahigh(x) * bhigh(x) 25 | for (int i = 0; i < mid; i++) { // Then, calculate rmid(x) = E(x) - rlow(x) - rhigh(x) and write in memory 26 | const auto tmp = res[i + mid]; 27 | res[i + mid] += E[i] - res[i] - res[i + 2 * mid]; 28 | res[i + 2 * mid] += E[i + mid] - tmp - res[i + 3 * mid]; 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /code/math/matrix.cpp: -------------------------------------------------------------------------------- 1 | template > 2 | struct Matrix { 3 | T v[n][m]; 4 | 5 | Matrix(int d = 0) { 6 | for (int i = 0; i < n; i++) { 7 | for (int j = 0; j < m; j++) { 8 | v[i][j] = T(0); 9 | } 10 | if (i < m) { 11 | v[i][i] = T(d); 12 | } 13 | } 14 | } 15 | 16 | template 17 | Matrix operator*(Matrix &o) { 18 | Matrix ans; 19 | for (int i = 0; i < n; i++) { 20 | for (int j = 0; j < mm; j++) { 21 | for (int k = 0; k < m; k++) { 22 | ans.v[i][j] = ans.v[i][j] + v[i][k] * o.v[k][j]; 23 | } 24 | } 25 | } 26 | return ans; 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /code/math/matrix_simple.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct Matrix : std::array, _m> { // vector for dynamic size 3 | #define ma(i) this->operator[](i) 4 | #define mat this->_M_elems 5 | Matrix() { 6 | for(auto &row : *this) row.fill(0); 7 | } 8 | void identity() { 9 | for(auto &row : *this) row.fill(0); 10 | for(size_t i = 0; i < _n; i++) mat[i][i] = 1; 11 | } 12 | template 13 | Matrix operator*(const Matrix &o) const { 14 | Matrix ans; 15 | for(size_t i = 0; i < _n; i++) { 16 | for(size_t k = 0; k < _m; k++) { 17 | for(size_t j = 0; j < _p; j++) { 18 | ans[i][j] = ans[i][j] + mat[i][k] * o[k][j]; 19 | } 20 | } 21 | } 22 | return ans; 23 | } 24 | #undef mat 25 | #undef ma 26 | }; 27 | -------------------------------------------------------------------------------- /code/math/miller_rabin.cpp: -------------------------------------------------------------------------------- 1 | bool rabin(ll n){ 2 | if(n <= 1) return 0; 3 | if(n <= 3) return 1; 4 | ll s = 0, d = n - 1; 5 | while(d % 2 == 0) d /= 2, s++; 6 | for(int k = 0; k < 64; k++){ 7 | ll a = llrand(2, n-2); 8 | ll x = fexp(a, d, n); 9 | if(x != 1 && x != n-1){ 10 | for(int r = 1; r < s; r++){ 11 | x = mul(x, x, n); 12 | if(x == 1) return 0; 13 | if(x == n-1) break; 14 | } 15 | if(x != n-1) return 0; 16 | } 17 | } 18 | return 1; 19 | } 20 | 21 | -------------------------------------------------------------------------------- /code/math/mobius.cpp: -------------------------------------------------------------------------------- 1 | memset(mu, 0, sizeof mu); 2 | mu[1] = 1; 3 | for(int i = 1; i < N; i++) 4 | for(int j = i + i; j < N; j += i) 5 | mu[j] -= mu[i]; 6 | // g(n) = sum{f(d)} => f(n) = sum{mu(d)*g(n/d)} 7 | -------------------------------------------------------------------------------- /code/math/mod.cpp: -------------------------------------------------------------------------------- 1 | constexpr uint64_t mod = (1ull<<61) - 1; 2 | uint64_t modmul(uint64_t a, uint64_t b){ 3 | uint64_t l1 = (uint32_t)a, h1 = a>>32, l2 = (uint32_t)b, h2 = b>>32; 4 | uint64_t l = l1*l2, m = l1*h2 + l2*h1, h = h1*h2; 5 | uint64_t ret = (l&mod) + (l>>61) + (h << 3) + (m >> 29) + (m << 35 >> 3) + 1; 6 | ret = (ret & mod) + (ret>>61); 7 | ret = (ret & mod) + (ret>>61); 8 | return ret-1; 9 | } 10 | -------------------------------------------------------------------------------- /code/math/mod_arithmetic.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct modBase { 3 | modBase(int val = 0) : val(val) {} 4 | int val; 5 | 6 | modBase operator*(modBase o) { 7 | return (long long)val * o.val % mod; 8 | } 9 | modBase operator+(modBase o) { 10 | return val + o.val > mod ? val + o.val - mod : val + o.val; 11 | } 12 | }; 13 | 14 | template 15 | T fexp(T x, long long e) { 16 | T ans(1); 17 | for (; e > 0; e /= 2) { 18 | if (e & 1) ans = ans * x; 19 | x = x * x; 20 | } 21 | return ans; 22 | } 23 | -------------------------------------------------------------------------------- /code/math/pollard_rho.cpp: -------------------------------------------------------------------------------- 1 | ll rho(ll n){ 2 | if(n % 2 == 0) return 2; 3 | ll d, c, x, y, prod; 4 | do{ 5 | c = llrand(1, n - 1); 6 | x = llrand(1, n - 1); 7 | y = x; 8 | prod = 1; 9 | for(int i = 0; i < 40; i++) { 10 | x = add(mul(x, x, n), c, n); 11 | y = add(mul(y, y, n), c, n); 12 | y = add(mul(y, y, n), c, n); 13 | prod = mul(prod, abs(x - y), n) ?: prod; 14 | } 15 | d = __gcd(prod, n); 16 | } while(d == 1); 17 | return d; 18 | } 19 | 20 | ll pollard_rho(ll n){ 21 | ll x, c, y, d, k; 22 | int i; 23 | do{ 24 | i = 1; 25 | x = llrand(1, n-1), c = llrand(1, n-1); 26 | y = x, k = 4; 27 | do{ 28 | if(++i == k) y = x, k *= 2; 29 | x = add(mul(x, x, n), c, n); 30 | d = __gcd(abs(x - y), n); 31 | }while(d == 1); 32 | }while(d == n); 33 | return d; 34 | } 35 | void factorize(ll val, map &fac){ 36 | if(rabin(val)) fac[ val ]++; 37 | else{ 38 | ll d = pollard_rho(val); 39 | factorize(d, fac); 40 | factorize(val / d, fac); 41 | } 42 | } 43 | map factor(ll val){ 44 | map fac; 45 | if(val > 1) factorize(val, fac); 46 | return fac; 47 | } 48 | -------------------------------------------------------------------------------- /code/math/primitive_root.cpp: -------------------------------------------------------------------------------- 1 | // a primitive root modulo n is any number g such that any c coprime to n is congruent to a power of g modulo n. 2 | bool exists_root(ll n){ 3 | if(n == 1 || n == 2 || n == 4) return true; 4 | if(n % 2 == 0) n /= 2; 5 | if(n % 2 == 0) return false; 6 | // test if n is a power of only one prime 7 | for(ll i = 3; i * i <= n; i += 2) if(n % i == 0){ 8 | while(n % i == 0) n /= i; 9 | return n == 1; 10 | } 11 | return true; 12 | } 13 | ll primitive_root(ll n){ 14 | if(n == 1 || n == 2 || n == 4) return n - 1; 15 | if(not exists_root(n)) return -1; 16 | ll x = phi(n); 17 | auto pr = factorize(x); 18 | auto check = [x, n, pr](ll m){ 19 | for(ll p : pr) if(fexp(m, x / p, n) == 1) 20 | return false; 21 | return true; 22 | }; 23 | for(ll m = 2; ; m++) if(__gcd(m, n) == 1) 24 | if(check(m)) return m; 25 | } 26 | 27 | // Let's denote R(n) as the set of primitive roots modulo n, p is prime 28 | // g \in R(p) => (pow(g, p-1, p * p) == 1 ? g+p : g) \in R(pow(p, k)), for all k > 1 29 | // g in R(pow(p, k)) => (g % 2 == 1 ? g : g + pow(p, k)) \in R(2*pow(p, k)) 30 | 31 | -------------------------------------------------------------------------------- /code/math/simplex.cpp: -------------------------------------------------------------------------------- 1 | typedef long double dbl; 2 | const dbl eps = 1e-6; 3 | const int N = , M = ; 4 | 5 | mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); 6 | struct simplex { 7 | int X[N], Y[M]; 8 | dbl A[M][N], b[M], c[N]; 9 | dbl ans; 10 | int n, m; 11 | dbl sol[N]; 12 | 13 | void pivot(int x, int y){ 14 | swap(X[y], Y[x]); 15 | b[x] /= A[x][y]; 16 | for(int i = 0; i < n; i++) 17 | if(i != y) 18 | A[x][i] /= A[x][y]; 19 | A[x][y] = 1. / A[x][y]; 20 | for(int i = 0; i < m; i++) 21 | if(i != x && abs(A[i][y]) > eps) { 22 | b[i] -= A[i][y] * b[x]; 23 | for(int j = 0; j < n; j++) if(j != y) 24 | A[i][j] -= A[i][y] * A[x][j]; 25 | A[i][y] = -A[i][y] * A[x][y]; 26 | } 27 | ans += c[y] * b[x]; 28 | for(int i = 0; i < n; i++) 29 | if(i != y) 30 | c[i] -= c[y] * A[x][i]; 31 | c[y] = -c[y] * A[x][y]; 32 | } 33 | 34 | // maximiza sum(x[i] * c[i]) 35 | // sujeito a 36 | // sum(a[i][j] * x[j]) <= b[i] para 0 <= i < m (Ax <= b) 37 | // x[i] >= 0 para 0 <= i < n (x >= 0) 38 | // (n variaveis, m restricoes) 39 | // guarda a resposta em ans e retorna o valor otimo 40 | dbl solve(int _n, int _m) { 41 | this->n = _n; this->m = _m; 42 | 43 | for(int i = 1; i < m; i++){ 44 | int id = uniform_int_distribution(0, i)(rng); 45 | swap(b[i], b[id]); 46 | for(int j = 0; j < n; j++) 47 | swap(A[i][j], A[id][j]); 48 | } 49 | 50 | ans = 0.; 51 | for(int i = 0; i < n; i++) X[i] = i; 52 | for(int i = 0; i < m; i++) Y[i] = i + n; 53 | while(true) { 54 | int x = min_element(b, b + m) - b; 55 | if(b[x] >= -eps) 56 | break; 57 | int y = find_if(A[x], A[x] + n, [](dbl d) { return d < -eps; }) - A[x]; 58 | if(y == n) throw 1; // no solution 59 | pivot(x, y); 60 | } 61 | while(true) { 62 | int y = max_element(c, c + n) - c; 63 | if(c[y] <= eps) break; 64 | int x = -1; 65 | dbl mn = 1. / 0.; 66 | for(int i = 0; i < m; i++) 67 | if(A[i][y] > eps && b[i] / A[i][y] < mn) 68 | mn = b[i] / A[i][y], x = i; 69 | if(x == -1) throw 2; // unbounded 70 | pivot(x, y); 71 | } 72 | memset(sol, 0, sizeof(dbl) * n); 73 | for(int i = 0; i < m; i++) 74 | if(Y[i] < n) 75 | sol[Y[i]] = b[i]; 76 | return ans; 77 | } 78 | }; 79 | 80 | -------------------------------------------------------------------------------- /code/math/simpson.cpp: -------------------------------------------------------------------------------- 1 | inline double simpson(double fl,double fr,double fmid,double l,double r) { 2 | return (fl + fr + 4.0 * fmid) * (r - l) / 6.0; 3 | } 4 | double rsimpson(double slr,double fl,double fr,double fmid,double l,double r) { 5 | double mid = (l+r)*0.5; 6 | double fml = f((l+mid)*0.5), fmr = f((mid+r)*0.5); 7 | double slm = simpson(fl, fmid, fml, l, mid); 8 | double smr = simpson(fmid, fr, fmr, mid, r); 9 | if(fabs(slr-slm-smr) < eps and r - l < delta) return slr; 10 | return rsimpson(slm,fl,fmid,fml,l,mid) + rsimpson(smr,fmid,fr,fmr,mid,r); 11 | } 12 | double integrate(double l,double r) { 13 | double mid = (l+r)*0.5; 14 | double fl = f(l), fr = f(r), fmid = f(mid); 15 | return rsimpson(simpson(fl,fr,fmid,l,r),fl,fr,fmid,l,r); 16 | } 17 | -------------------------------------------------------------------------------- /code/math/tot.cpp: -------------------------------------------------------------------------------- 1 | ll totiente(ll n){ 2 | ll ans = n; 3 | for(ll i = 2; i*i <= n; i++){ 4 | if(n % i == 0){ 5 | ans = ans / i * (i - 1); 6 | while(n % i == 0) n /= i; 7 | } 8 | } 9 | 10 | if(n > 1) ans = ans / n * (n - 1); 11 | return ans; 12 | } 13 | -------------------------------------------------------------------------------- /code/matroid.cpp: -------------------------------------------------------------------------------- 1 | // Input two matroids (X, I_a) and (X, I_b) 2 | // output set I of maximum size, I \in I_a and I \in I_b 3 | set<> I; 4 | while(1){ 5 | for(e_i : X \ I) 6 | if(I + e_i \in I_a and I + e_i \in I_b) 7 | I = I + e_i; 8 | set<> A, T; queue<> Q; 9 | for(x : X) label[x] = MARK1; 10 | for(e_i : X \ I){ 11 | if(I + e_i \in I_a) 12 | Q.push(e_i), label[e_i] = MARK2; 13 | else{ 14 | for(x such that I - x + e_i \in I_a) 15 | A[x].push(e_i); 16 | } 17 | if(I + e_i \in I_b) 18 | T = T + {e_i} 19 | else{ 20 | for(x such that I - x + e_i \in I_b) 21 | A[e_i].push(x); 22 | } 23 | } 24 | if(T.empty()) break; 25 | bool found = false; 26 | while(!Q.empty() and !found){ 27 | auto e = Q.front(); Q.pop(); 28 | for(x : A[e]) if(label[x] == MARK1){ 29 | label[x] = e; Q.push(x); 30 | if(x \in T){ 31 | found = true; put = 1; 32 | while(label[x] != MARK2){ 33 | I = put ? (I + x) : (I - x); 34 | put = 1 - put; 35 | } 36 | I = I + x; 37 | break; 38 | } 39 | } 40 | } 41 | if(!found) break; 42 | } 43 | return I; 44 | -------------------------------------------------------------------------------- /code/misc/ColorUpdate.cpp: -------------------------------------------------------------------------------- 1 | // source: https://github.com/tfg50/Competitive-Programming/tree/master/Biblioteca/Data%20Structures 2 | 3 | #include 4 | #include 5 | 6 | template 7 | class ColorUpdate { 8 | public: 9 | struct Range { 10 | Range(int l = 0) { this->l = l; } 11 | Range(int l, int r, Info v) { 12 | this->l = l; 13 | this->r = r; 14 | this->v = v; 15 | } 16 | int l, r; 17 | Info v; 18 | 19 | bool operator < (const Range &b) const { return l < b.l; } 20 | }; 21 | 22 | std::vector upd(int l, int r, Info v) { 23 | std::vector ans; 24 | if(l >= r) return ans; 25 | auto it = ranges.lower_bound(l); 26 | if(it != ranges.begin()) { 27 | it--; 28 | if(it->r > l) { 29 | auto cur = *it; 30 | ranges.erase(it); 31 | ranges.insert(Range(cur.l, l, cur.v)); 32 | ranges.insert(Range(l, cur.r, cur.v)); 33 | } 34 | } 35 | it = ranges.lower_bound(r); 36 | if(it != ranges.begin()) { 37 | it--; 38 | if(it->r > r) { 39 | auto cur = *it; 40 | ranges.erase(it); 41 | ranges.insert(Range(cur.l, r, cur.v)); 42 | ranges.insert(Range(r, cur.r, cur.v)); 43 | } 44 | } 45 | for(it = ranges.lower_bound(l); it != ranges.end() && it->l < r; it++) { 46 | ans.push_back(*it); 47 | } 48 | ranges.erase(ranges.lower_bound(l), ranges.lower_bound(r)); 49 | ranges.insert(Range(l, r, v)); 50 | return ans; 51 | } 52 | private: 53 | std::set ranges; 54 | }; 55 | -------------------------------------------------------------------------------- /code/misc/bigint.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ############################################ 3 | ####################### THE BIG INT ########################## 4 | */ 5 | const int base = 1000000000; 6 | const int base_digits = 9; 7 | struct bigint { 8 | vector a; 9 | int sign; 10 | /**/ 11 | int size(){ 12 | if(a.empty())return 0; 13 | int ans=(a.size()-1)*base_digits; 14 | int ca=a.back(); 15 | while(ca) 16 | ans++,ca/=10; 17 | return ans; 18 | } 19 | bigint operator ^(const bigint &v){ 20 | bigint ans=1,a=*this,b=v; 21 | while(!b.isZero()){ 22 | if(b%2) 23 | ans*=a; 24 | a*=a,b/=2; 25 | } 26 | return ans; 27 | } 28 | string to_string(){ 29 | stringstream ss; 30 | ss << *this; 31 | string s; 32 | ss >> s; 33 | return s 34 | } 35 | int sumof(){ 36 | string s = to_string(); 37 | int ans = 0; 38 | for(auto c : s) ans += c - '0'; 39 | return ans; 40 | } 41 | /**/ 42 | bigint() : 43 | sign(1) { 44 | } 45 | 46 | bigint(long long v) { 47 | *this = v; 48 | } 49 | 50 | bigint(const string &s) { 51 | read(s); 52 | } 53 | 54 | void operator=(const bigint &v) { 55 | sign = v.sign; 56 | a = v.a; 57 | } 58 | 59 | void operator=(long long v) { 60 | sign = 1; 61 | a.clear(); 62 | if (v < 0) 63 | sign = -1, v = -v; 64 | for (; v > 0; v = v / base) 65 | a.push_back(v % base); 66 | } 67 | 68 | bigint operator+(const bigint &v) const { 69 | if (sign == v.sign) { 70 | bigint res = v; 71 | 72 | for (int i = 0, carry = 0; i < (int) max(a.size(), v.a.size()) || carry; ++i) { 73 | if (i == (int) res.a.size()) 74 | res.a.push_back(0); 75 | res.a[i] += carry + (i < (int) a.size() ? a[i] : 0); 76 | carry = res.a[i] >= base; 77 | if (carry) 78 | res.a[i] -= base; 79 | } 80 | return res; 81 | } 82 | return *this - (-v); 83 | } 84 | 85 | bigint operator-(const bigint &v) const { 86 | if (sign == v.sign) { 87 | if (abs() >= v.abs()) { 88 | bigint res = *this; 89 | for (int i = 0, carry = 0; i < (int) v.a.size() || carry; ++i) { 90 | res.a[i] -= carry + (i < (int) v.a.size() ? v.a[i] : 0); 91 | carry = res.a[i] < 0; 92 | if (carry) 93 | res.a[i] += base; 94 | } 95 | res.trim(); 96 | return res; 97 | } 98 | return -(v - *this); 99 | } 100 | return *this + (-v); 101 | } 102 | 103 | void operator*=(int v) { 104 | if (v < 0) 105 | sign = -sign, v = -v; 106 | for (int i = 0, carry = 0; i < (int) a.size() || carry; ++i) { 107 | if (i == (int) a.size()) 108 | a.push_back(0); 109 | long long cur = a[i] * (long long) v + carry; 110 | carry = (int) (cur / base); 111 | a[i] = (int) (cur % base); 112 | //asm("divl %%ecx" : "=a"(carry), "=d"(a[i]) : "A"(cur), "c"(base)); 113 | } 114 | trim(); 115 | } 116 | 117 | bigint operator*(int v) const { 118 | bigint res = *this; 119 | res *= v; 120 | return res; 121 | } 122 | 123 | void operator*=(long long v) { 124 | if (v < 0) 125 | sign = -sign, v = -v; 126 | for (int i = 0, carry = 0; i < (int) a.size() || carry; ++i) { 127 | if (i == (int) a.size()) 128 | a.push_back(0); 129 | long long cur = a[i] * (long long) v + carry; 130 | carry = (int) (cur / base); 131 | a[i] = (int) (cur % base); 132 | //asm("divl %%ecx" : "=a"(carry), "=d"(a[i]) : "A"(cur), "c"(base)); 133 | } 134 | trim(); 135 | } 136 | 137 | bigint operator*(long long v) const { 138 | bigint res = *this; 139 | res *= v; 140 | return res; 141 | } 142 | 143 | friend pair divmod(const bigint &a1, const bigint &b1) { 144 | int norm = base / (b1.a.back() + 1); 145 | bigint a = a1.abs() * norm; 146 | bigint b = b1.abs() * norm; 147 | bigint q, r; 148 | q.a.resize(a.a.size()); 149 | 150 | for (int i = a.a.size() - 1; i >= 0; i--) { 151 | r *= base; 152 | r += a.a[i]; 153 | int s1 = r.a.size() <= b.a.size() ? 0 : r.a[b.a.size()]; 154 | int s2 = r.a.size() <= b.a.size() - 1 ? 0 : r.a[b.a.size() - 1]; 155 | int d = ((long long) base * s1 + s2) / b.a.back(); 156 | r -= b * d; 157 | while (r < 0) 158 | r += b, --d; 159 | q.a[i] = d; 160 | } 161 | 162 | q.sign = a1.sign * b1.sign; 163 | r.sign = a1.sign; 164 | q.trim(); 165 | r.trim(); 166 | return make_pair(q, r / norm); 167 | } 168 | 169 | bigint operator/(const bigint &v) const { 170 | return divmod(*this, v).first; 171 | } 172 | 173 | bigint operator%(const bigint &v) const { 174 | return divmod(*this, v).second; 175 | } 176 | 177 | void operator/=(int v) { 178 | if (v < 0) 179 | sign = -sign, v = -v; 180 | for (int i = (int) a.size() - 1, rem = 0; i >= 0; --i) { 181 | long long cur = a[i] + rem * (long long) base; 182 | a[i] = (int) (cur / v); 183 | rem = (int) (cur % v); 184 | } 185 | trim(); 186 | } 187 | 188 | bigint operator/(int v) const { 189 | bigint res = *this; 190 | res /= v; 191 | return res; 192 | } 193 | 194 | int operator%(int v) const { 195 | if (v < 0) 196 | v = -v; 197 | int m = 0; 198 | for (int i = a.size() - 1; i >= 0; --i) 199 | m = (a[i] + m * (long long) base) % v; 200 | return m * sign; 201 | } 202 | 203 | void operator+=(const bigint &v) { 204 | *this = *this + v; 205 | } 206 | void operator-=(const bigint &v) { 207 | *this = *this - v; 208 | } 209 | void operator*=(const bigint &v) { 210 | *this = *this * v; 211 | } 212 | void operator/=(const bigint &v) { 213 | *this = *this / v; 214 | } 215 | 216 | bool operator<(const bigint &v) const { 217 | if (sign != v.sign) 218 | return sign < v.sign; 219 | if (a.size() != v.a.size()) 220 | return a.size() * sign < v.a.size() * v.sign; 221 | for (int i = a.size() - 1; i >= 0; i--) 222 | if (a[i] != v.a[i]) 223 | return a[i] * sign < v.a[i] * sign; 224 | return false; 225 | } 226 | 227 | bool operator>(const bigint &v) const { 228 | return v < *this; 229 | } 230 | bool operator<=(const bigint &v) const { 231 | return !(v < *this); 232 | } 233 | bool operator>=(const bigint &v) const { 234 | return !(*this < v); 235 | } 236 | bool operator==(const bigint &v) const { 237 | return !(*this < v) && !(v < *this); 238 | } 239 | bool operator!=(const bigint &v) const { 240 | return *this < v || v < *this; 241 | } 242 | 243 | void trim() { 244 | while (!a.empty() && !a.back()) 245 | a.pop_back(); 246 | if (a.empty()) 247 | sign = 1; 248 | } 249 | 250 | bool isZero() const { 251 | return a.empty() || (a.size() == 1 && !a[0]); 252 | } 253 | 254 | bigint operator-() const { 255 | bigint res = *this; 256 | res.sign = -sign; 257 | return res; 258 | } 259 | 260 | bigint abs() const { 261 | bigint res = *this; 262 | res.sign *= res.sign; 263 | return res; 264 | } 265 | 266 | long long longValue() const { 267 | long long res = 0; 268 | for (int i = a.size() - 1; i >= 0; i--) 269 | res = res * base + a[i]; 270 | return res * sign; 271 | } 272 | 273 | friend bigint gcd(const bigint &a, const bigint &b) { 274 | return b.isZero() ? a : gcd(b, a % b); 275 | } 276 | friend bigint lcm(const bigint &a, const bigint &b) { 277 | return a / gcd(a, b) * b; 278 | } 279 | 280 | void read(const string &s) { 281 | sign = 1; 282 | a.clear(); 283 | int pos = 0; 284 | while (pos < (int) s.size() && (s[pos] == '-' || s[pos] == '+')) { 285 | if (s[pos] == '-') 286 | sign = -sign; 287 | ++pos; 288 | } 289 | for (int i = s.size() - 1; i >= pos; i -= base_digits) { 290 | int x = 0; 291 | for (int j = max(pos, i - base_digits + 1); j <= i; j++) 292 | x = x * 10 + s[j] - '0'; 293 | a.push_back(x); 294 | } 295 | trim(); 296 | } 297 | 298 | friend istream& operator>>(istream &stream, bigint &v) { 299 | string s; 300 | stream >> s; 301 | v.read(s); 302 | return stream; 303 | } 304 | 305 | friend ostream& operator<<(ostream &stream, const bigint &v) { 306 | if (v.sign == -1) 307 | stream << '-'; 308 | stream << (v.a.empty() ? 0 : v.a.back()); 309 | for (int i = (int) v.a.size() - 2; i >= 0; --i) 310 | stream << setw(base_digits) << setfill('0') << v.a[i]; 311 | return stream; 312 | } 313 | 314 | static vector convert_base(const vector &a, int old_digits, int new_digits) { 315 | vector p(max(old_digits, new_digits) + 1); 316 | p[0] = 1; 317 | for (int i = 1; i < (int) p.size(); i++) 318 | p[i] = p[i - 1] * 10; 319 | vector res; 320 | long long cur = 0; 321 | int cur_digits = 0; 322 | for (int i = 0; i < (int) a.size(); i++) { 323 | cur += a[i] * p[cur_digits]; 324 | cur_digits += old_digits; 325 | while (cur_digits >= new_digits) { 326 | res.push_back(int(cur % p[new_digits])); 327 | cur /= p[new_digits]; 328 | cur_digits -= new_digits; 329 | } 330 | } 331 | res.push_back((int) cur); 332 | while (!res.empty() && !res.back()) 333 | res.pop_back(); 334 | return res; 335 | } 336 | 337 | typedef vector vll; 338 | 339 | static vll karatsubaMultiply(const vll &a, const vll &b) { 340 | int n = a.size(); 341 | vll res(n + n); 342 | if (n <= 32) { 343 | for (int i = 0; i < n; i++) 344 | for (int j = 0; j < n; j++) 345 | res[i + j] += a[i] * b[j]; 346 | return res; 347 | } 348 | 349 | int k = n >> 1; 350 | vll a1(a.begin(), a.begin() + k); 351 | vll a2(a.begin() + k, a.end()); 352 | vll b1(b.begin(), b.begin() + k); 353 | vll b2(b.begin() + k, b.end()); 354 | 355 | vll a1b1 = karatsubaMultiply(a1, b1); 356 | vll a2b2 = karatsubaMultiply(a2, b2); 357 | 358 | for (int i = 0; i < k; i++) 359 | a2[i] += a1[i]; 360 | for (int i = 0; i < k; i++) 361 | b2[i] += b1[i]; 362 | 363 | vll r = karatsubaMultiply(a2, b2); 364 | for (int i = 0; i < (int) a1b1.size(); i++) 365 | r[i] -= a1b1[i]; 366 | for (int i = 0; i < (int) a2b2.size(); i++) 367 | r[i] -= a2b2[i]; 368 | 369 | for (int i = 0; i < (int) r.size(); i++) 370 | res[i + k] += r[i]; 371 | for (int i = 0; i < (int) a1b1.size(); i++) 372 | res[i] += a1b1[i]; 373 | for (int i = 0; i < (int) a2b2.size(); i++) 374 | res[i + n] += a2b2[i]; 375 | return res; 376 | } 377 | 378 | bigint operator*(const bigint &v) const { 379 | vector a6 = convert_base(this->a, base_digits, 6); 380 | vector b6 = convert_base(v.a, base_digits, 6); 381 | vll a(a6.begin(), a6.end()); 382 | vll b(b6.begin(), b6.end()); 383 | while (a.size() < b.size()) 384 | a.push_back(0); 385 | while (b.size() < a.size()) 386 | b.push_back(0); 387 | while (a.size() & (a.size() - 1)) 388 | a.push_back(0), b.push_back(0); 389 | vll c = karatsubaMultiply(a, b); 390 | bigint res; 391 | res.sign = sign * v.sign; 392 | for (int i = 0, carry = 0; i < (int) c.size(); i++) { 393 | long long cur = c[i] + carry; 394 | res.a.push_back((int) (cur % 1000000)); 395 | carry = (int) (cur / 1000000); 396 | } 397 | res.a = convert_base(res.a, 6, base_digits); 398 | res.trim(); 399 | return res; 400 | } 401 | }; 402 | /* 403 | ####################### THE BIG INT ############### 404 | ########################################## 405 | */ 406 | -------------------------------------------------------------------------------- /code/misc/bipar.cpp: -------------------------------------------------------------------------------- 1 | struct DSU{ 2 | vector sz, p, change; 3 | vector> modifications; 4 | vector saves; 5 | bool bipartite; 6 | 7 | DSU(int n): sz(n+1, 1), p(n+1), change(n+1), bipartite(true){ 8 | iota(p.begin(), p.end(), 0); 9 | } 10 | 11 | void add_edge(int u, int v){ 12 | if(!bipartite) return; 13 | int must_change = get_colour(u) == get_colour(v); 14 | int a = rep(u), b = rep(v); 15 | if(sz[a] < sz[b]) swap(a, b); 16 | if(a != b){ 17 | p[b] = a; 18 | modifications.emplace_back(b, change[b], bipartite); 19 | change[b] ^= must_change; 20 | sz[a] += sz[b]; 21 | } 22 | else if(must_change){ 23 | modifications.emplace_back(0, change[0], bipartite); 24 | bipartite = false; 25 | } 26 | } 27 | 28 | int rep(int u){ 29 | return p[u] == u ? u : rep(p[u]); 30 | } 31 | 32 | int get_colour(int u){ 33 | if(p[u] == u) return change[u]; 34 | return change[u] ^ get_colour(p[u]); 35 | } 36 | 37 | void reset(){ 38 | modifications.clear(); 39 | saves.clear(); 40 | iota(p.begin(), p.end(), 0); 41 | fill(sz.begin(), sz.end(), 1); 42 | fill(change.begin(), change.end(), 0); 43 | bipartite = true; 44 | } 45 | 46 | void rollback(){ 47 | int u = get<0>(modifications.back()); 48 | tie(ignore, change[u], bipartite) = modifications.back(); 49 | sz[ p[u] ] -= sz[u]; 50 | p[u] = u; 51 | modifications.pop_back(); 52 | } 53 | 54 | void reload(){ 55 | while(modifications.size() > saves.back()) 56 | rollback(); 57 | saves.pop_back(); 58 | } 59 | 60 | void save(){ 61 | saves.push_back(modifications.size()); 62 | } 63 | }; 64 | -------------------------------------------------------------------------------- /code/misc/bitset.cpp: -------------------------------------------------------------------------------- 1 | #define private public 2 | #include 3 | #undef private 4 | #include 5 | 6 | using namespace std; 7 | 8 | #define tab _M_w 9 | using biti = typename remove_reference().tab[0])>::type; 10 | const int SIZE = 8 * sizeof(biti); 11 | const int LOG = __builtin_ctz(SIZE); 12 | 13 | template 14 | int find_prev(const bitset &x, int v) { 15 | int start = v >> LOG; 16 | int first_bits = v & (SIZE - 1); 17 | if(first_bits) { 18 | biti curr = x.tab[start]; 19 | curr = curr << (SIZE - first_bits) >> (SIZE - first_bits); 20 | if(curr) 21 | return start << LOG | (SIZE - __builtin_clzl(curr) - 1); 22 | } 23 | for(int i = start - 1; i >= 0; i--) { 24 | biti curr = x.tab[i]; 25 | if(curr) { 26 | return (i << LOG) | (SIZE - __builtin_clzl(curr) - 1); 27 | } 28 | } 29 | return -1; 30 | } 31 | 32 | // s._Find_first(); s._Find_next(k); find_prev(s, k+1); 33 | // _Unchecked_set/_Unchecked_reset/_Unchecked_flip 34 | -------------------------------------------------------------------------------- /code/misc/buffered_reader.cpp: -------------------------------------------------------------------------------- 1 | // source: https://github.com/ngthanhtrung23/ACM_Notebook_new/blob/master/buffered_reader.h 2 | int INP,AM,REACHEOF; 3 | #define BUFSIZE (1<<12) 4 | char BUF[BUFSIZE+1], *inp=BUF; 5 | #define GETCHAR(INP) { \ 6 | if(!*inp && !REACHEOF) { \ 7 | memset(BUF,0,sizeof BUF);\ 8 | int inpzzz = fread(BUF,1,BUFSIZE,stdin);\ 9 | if (inpzzz != BUFSIZE) REACHEOF = true;\ 10 | inp=BUF; \ 11 | } \ 12 | INP=*inp++; \ 13 | } 14 | #define DIG(a) (((a)>='0')&&((a)<='9')) 15 | #define GN(j) { \ 16 | AM=0;\ 17 | GETCHAR(INP); while(!DIG(INP) && INP!='-') GETCHAR(INP);\ 18 | if (INP=='-') {AM=1;GETCHAR(INP);} \ 19 | j=INP-'0'; GETCHAR(INP); \ 20 | while(DIG(INP)){j=10*j+(INP-'0');GETCHAR(INP);} \ 21 | if (AM) j=-j;\ 22 | } 23 | -------------------------------------------------------------------------------- /code/misc/burn.cpp: -------------------------------------------------------------------------------- 1 | // count the number of circular arrays of size m, with elements on range [1, c**(n*n)] 2 | int n, m, c; cin >> n >> m >> c; 3 | int x = f_exp(c, n * n); int ans = f_exp(x, m); 4 | for(int i = 1; i <= m; i++) if(m % i == 0) { 5 | int y = f_exp(x, i); 6 | for(int j = 1; j < i; j++) if(i % j == 0) 7 | y = sub(y, mult(j, dp[j])); 8 | dp[i] = mult(y, inv(i)); 9 | ans = sub(ans, mult(i - 1, dp[i])); 10 | } 11 | cout << ans << '\n'; 12 | -------------------------------------------------------------------------------- /code/misc/edge_coloring.cpp: -------------------------------------------------------------------------------- 1 | const int MX = 300; 2 | int C[MX][MX] = {}, G[MX][MX] = {}; 3 | 4 | void solve(vector &E, int N){ 5 | int X[MX] = {}, a, b; 6 | 7 | auto update = [&](int u){ for(X[u] = 1; C[u][X[u]]; X[u]++); }; 8 | auto color = [&](int u, int v, int c){ 9 | int p = G[u][v]; 10 | G[u][v] = G[v][u] = c; 11 | C[u][c] = v; C[v][c] = u; 12 | C[u][p] = C[v][p] = 0; 13 | if( p ) X[u] = X[v] = p; 14 | else update(u), update(v); 15 | return p; }; 16 | auto flip = [&](int u, int c1, int c2){ 17 | int p = C[u][c1], q = C[u][c2]; 18 | swap(C[u][c1], C[u][c2]); 19 | if( p ) G[u][p] = G[p][u] = c2; 20 | if( !C[u][c1] ) X[u] = c1; 21 | if( !C[u][c2] ) X[u] = c2; 22 | return p; }; 23 | 24 | for(int i = 1; i <= N; i++) X[i] = 1; 25 | for(int t = 0; t < E.size(); t++){ 26 | int u = E[t].first, v0 = E[t].second, v = v0, c0 = X[u], c = c0, d; 27 | vector L; 28 | int vst[MX] = {}; 29 | while(!G[u][v0]){ 30 | L.emplace_back(v, d = X[v]); 31 | if(!C[v][c]) for(a = (int)L.size()-1; a >= 0; a--) c = color(u, L[a].first, c); 32 | else if(!C[u][d])for(a=(int)L.size()-1;a>=0;a--)color(u,L[a].first,L[a].second); 33 | else if( vst[d] ) break; 34 | else vst[d] = 1, v = C[u][d]; 35 | } 36 | if( !G[u][v0] ){ 37 | for(;v; v = flip(v, c, d), swap(c, d)); 38 | if(C[u][c0]){ 39 | for(a = (int)L.size()-2; a >= 0 && L[a].second != c; a--); 40 | for(; a >= 0; a--) color(u, L[a].first, L[a].second); 41 | } else t--; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /code/misc/factmod.cpp: -------------------------------------------------------------------------------- 1 | // Compute (1*2*...*(p-1)*1*(p+1)*(p+2)*..*n) % p 2 | // in O(p*lg(n)) 3 | int factmod(int n, int p){ 4 | int ans = 1; 5 | while(n > 1){ 6 | for(int i = 2; i <= n % p; i++) 7 | ans = (ans * i) % p; 8 | n /= p; 9 | if(n % 2) ans = p - ans; 10 | } 11 | return ans % p; 12 | } 13 | int fac_pow(int n, int p){ 14 | int ans = 0; 15 | while(n) n /= p, ans += n; 16 | return ans; 17 | } 18 | int C(int n, int k, int p){ 19 | if(fac_pow(n, p) > fac_pow(n-k, p) + fac_pow(k, p)) 20 | return 0; 21 | int tmp = factmod(k, p) * factmod(n-k, p) % p; 22 | return (f_exp(tmp, p - 2, p) * factmod(n, p)) % p; 23 | } 24 | -------------------------------------------------------------------------------- /code/misc/fast_mod.cpp: -------------------------------------------------------------------------------- 1 | // source: https://github.com/koosaga/DeobureoMinkyuParty 2 | inline void fasterLLDivMod(unsigned long long x, unsigned y, unsigned &out_d, unsigned &out_m) { 3 | unsigned xh = (unsigned)(x >> 32), xl = (unsigned)x, d, m; 4 | #ifdef __GNUC__ 5 | asm( 6 | "divl %4 \n\t" 7 | : "=a" (d), "=d" (m) 8 | : "d" (xh), "a" (xl), "r" (y) 9 | ); 10 | #else 11 | __asm { 12 | mov edx, dword ptr[xh]; 13 | mov eax, dword ptr[xl]; 14 | div dword ptr[y]; 15 | mov dword ptr[d], eax; 16 | mov dword ptr[m], edx; 17 | }; 18 | #endif 19 | out_d = d; out_m = m; 20 | } 21 | inline unsigned mod(unsigned long long x, unsigned y) { 22 | unsigned dummy, r; 23 | fasterLLDivMod(x, y, dummy, r); 24 | return r; 25 | } 26 | -------------------------------------------------------------------------------- /code/misc/fastio.cpp: -------------------------------------------------------------------------------- 1 | #define pc(x) putchar_unlocked(x) 2 | #define gc(x) getchar_unlocked(x) 3 | 4 | inline void scan_int(int &x){ 5 | register int c = gc(); 6 | x = 0; 7 | int neg = 0; 8 | for(; ((c < '0' || c > '9') && c != '-'); c = gc()); 9 | if(c == '-'){ 10 | neg = 1; 11 | c = gc(); 12 | } 13 | for(; c >= '0' && c <= '9'; c = gc()) 14 | x = (x << 1) + (x << 3) + c - '0'; 15 | if(neg) x = -x; 16 | } 17 | 18 | inline void print_int(int n){ 19 | int rev = 0, count = 0, neg; 20 | if(n == 0){ 21 | pc('0'); 22 | return; 23 | } 24 | if(n < 0) n = -n, neg = 1; 25 | while(n % 10 == 0) count++, n /= 10; 26 | for(rev = 0; n != 0; n /= 10) 27 | rev = (rev << 3) + (rev << 1) + n % 10; 28 | if(neg) pc('-'); 29 | while(rev != 0) pc(rev % 10 + '0'), rev /= 10; 30 | while(count--) pc('0'); 31 | pc('\n'); 32 | } 33 | 34 | inline void print_string(char *str){ 35 | while(*str) pc(*str++); 36 | pc('\n'); 37 | } 38 | 39 | -------------------------------------------------------------------------------- /code/misc/hilbert_order.cpp: -------------------------------------------------------------------------------- 1 | // maybe use B = n / sqrt(q) 2 | inline int64_t hilbertOrder(int x, int y, int pow = 21, int rotate = 0) { 3 | if(pow == 0) return 0; 4 | int hpow = 1 << (pow-1); 5 | int seg = (x < hpow) ? ( 6 | (y < hpow) ? 0 : 3 7 | ) : ( 8 | (y < hpow) ? 1 : 2 9 | ); 10 | seg = (seg + rotate) & 3; 11 | const int rotateDelta[4] = {3, 0, 0, 1}; 12 | int nx = x & (x ^ hpow), ny = y & (y ^ hpow); 13 | int nrot = (rotate + rotateDelta[seg]) & 3; 14 | int64_t subSquareSize = int64_t(1) << (2*pow - 2); 15 | int64_t ans = seg * subSquareSize; 16 | int64_t add = hilbertOrder(nx, ny, pow-1, nrot); 17 | ans += (seg == 1 || seg == 2) ? add : (subSquareSize - add - 1); 18 | return ans; 19 | } 20 | -------------------------------------------------------------------------------- /code/misc/klondike.cpp: -------------------------------------------------------------------------------- 1 | // minimum number of moves to make 2 | // all elements equal 3 | // move: change a segment of equal value 4 | // elements to any value 5 | 6 | int v[305], dp[305][305], rec[305][305]; 7 | 8 | int f(int l, int r){ 9 | if(r == l) return 1; 10 | if(r < l) return 0; 11 | if(dp[l][r] != -1) return dp[l][r]; 12 | int ans = f(l+1, r) + 1; 13 | for(int i = l+1; i <= r; i++) 14 | if(v[i] == v[l]) 15 | ans = min(ans, f(l, i - 1) + f(i+1, r)); 16 | return dp[l][r] = ans; 17 | } 18 | -------------------------------------------------------------------------------- /code/misc/knapsack_bounded_cost.cpp: -------------------------------------------------------------------------------- 1 | // menor custo para conseguir peso ate M usando N tipos diferentes de elementos, sendo que o i-esimo elemento pode ser usado b[i] vezes, tem peso w[i] e custo c[i] 2 | // O(N * M) 3 | 4 | int b[N], w[N], c[N]; 5 | MinQueue Q[M] 6 | int d[M] //d[i] = custo minimo para conseguir peso i 7 | 8 | for(int i = 0; i <= M; i++) d[i] = i ? oo : 0; 9 | for(int i = 0; i < N; i++){ 10 | for(int j = 0; j < w[i]; j++) 11 | Q[j].clear(); 12 | for(int j = 0; j <= M; j++){ 13 | q = Q[j % w[i]]; 14 | if(q.size() >= q) q.pop(); 15 | q.add(c[i]); 16 | q.push(d[j]); 17 | d[j] = q.getmin(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /code/misc/lca.cpp: -------------------------------------------------------------------------------- 1 | int start[N], dfs_time; 2 | int tour[2*N], id[2*N]; 3 | 4 | void dfs(int u){ 5 | start[u] = dfs_time; 6 | id[dfs_time] = u; 7 | tour[dfs_time++] = start[u]; 8 | for(int v : g[u]){ 9 | dfs(v); 10 | id[dfs_time] = u; 11 | tour[dfs_time++] = start[u]; 12 | } 13 | } 14 | 15 | int LCA(int u, int v){ 16 | if(start[u] > start[v]) swap(u, v); 17 | return id[min(tour[k]for k in [start[u],start[v]])]; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /code/misc/lis.cpp: -------------------------------------------------------------------------------- 1 | multiset S; 2 | for(int i = 0; i < n; i++){ 3 | auto it = S.upper_bound(a[i]); // low for inc 4 | if(it != S.end()) S.erase(it); 5 | S.insert(a[i]); 6 | } 7 | ans = S.size(); 8 | -------------------------------------------------------------------------------- /code/misc/rand.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | cout << RAND_MAX << endl; 4 | mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); 5 | vector permutation(N); 6 | iota(permutation.begin(), permutation.end(), 0); 7 | shuffle(permutation.begin(), permutation.end(), rng); 8 | iota(permutation.begin(), permutation.end(), 0); 9 | for(int i = 1; i < N; i++){ 10 | swap(permutation[i], permutation[uniform_int_distribution(0, i)(rng)]); 11 | } 12 | -------------------------------------------------------------------------------- /code/misc/recursive_lambda.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class y_combinator_result { 3 | Fun fun_; 4 | public: 5 | template 6 | explicit y_combinator_result(T &&fun): fun_(std::forward(fun)) {} 7 | 8 | template 9 | decltype(auto) operator()(Args &&...args) { 10 | return fun_(std::ref(*this), std::forward(args)...); 11 | } 12 | }; 13 | 14 | template 15 | decltype(auto) y_combinator(Fun &&fun) { 16 | return y_combinator_result>(std::forward(fun)); 17 | } 18 | 19 | // auto gcd = y_combinator([](auto gcd, int a, int b) -> int { 20 | // return b == 0 ? a : gcd(b, a % b); 21 | // }); 22 | -------------------------------------------------------------------------------- /code/misc/slope.cpp: -------------------------------------------------------------------------------- 1 | ///By woqja125, contest: Codeforces Round #371 (Div. 1), problem: (C) Sonya and Problem Wihtout a Legend, Accepted, # 2 | int main() { 3 | int n, t; long long ans = 0; priority_queue Q; 4 | scanf("%d%d", &n, &t); Q.push(t); 5 | for(int i = 1; i < n; i++) { 6 | scanf("%d", &t); t -= i; Q.push(t); 7 | if(Q.top() > t) { 8 | ans += Q.top() - t; Q.pop(); Q.push(t); 9 | } 10 | } 11 | printf("%lld", ans); 12 | } 13 | -------------------------------------------------------------------------------- /code/misc/submasks.cpp: -------------------------------------------------------------------------------- 1 | // loop through all submask of a given bitmask 2 | // it does not include mask 0 3 | for(int sub = mask; sub; sub = (sub - 1) & mask){ 4 | 5 | } 6 | 7 | // loop through all supermasks of a given bitmask 8 | for(int super = mask; super < (1 << n); super = (super + 1) | mask) { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /code/misc/sum_mod.cpp: -------------------------------------------------------------------------------- 1 | //calcula (sum(0 <= i <= n) P(i)) % mod, 2 | //onde P(i) eh uma PA modular (com outro modulo) 3 | namespace sum_pa_mod{ 4 | ll calc(ll a, ll b, ll n, ll mod){ 5 | assert(a&&b); 6 | if(a >= b){ 7 | ll ret = ((n*(n+1)/2)%mod)*(a/b); 8 | if(a%b) ret = (ret + calc(a%b,b,n,mod))%mod; 9 | else ret = (ret+n+1)%mod; 10 | return ret; 11 | } 12 | return ((n+1)*(((n*a)/b+1)%mod) - calc(b,a,(n*a)/b,mod) + mod + n/b + 1)%mod; 13 | } 14 | 15 | //P(i) = a*i mod m 16 | ll solve(ll a, ll n, ll m, ll mod){ 17 | a = (a%m + m)%m; 18 | if(!a) return 0; 19 | ll ret = (n*(n+1)/2)%mod; 20 | ret = (ret*a)%mod; 21 | ll g = __gcd(a,m); 22 | ret -= m*(calc(a/g,m/g,n,mod)-n-1); 23 | return (ret%mod + mod)%mod; 24 | 25 | } 26 | //P(i) = a + r*i mod m 27 | ll solve(ll a, ll r, ll n, ll m, ll mod){ 28 | a = (a%m + m)%m; 29 | r = (r%m + m)%m; 30 | if(!r) return (a*(n+1))%mod; 31 | if(!a) return solve(r, n, m, mod); 32 | ll g, x, y; 33 | g = gcdExtended(r, m, x, y); 34 | x = (x%m + m)%m; 35 | ll d = a - (a/g)*g; 36 | a -= d; 37 | x = (x*(a/g))%m; 38 | return (solve(r, n+x, m, mod) - solve(r, x-1, m, mod) + mod + d*(n+1))%mod; 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /code/ntt.cpp: -------------------------------------------------------------------------------- 1 | const int mod = 7340033; 2 | const int root = 5; 3 | const int root_1 = 4404020; 4 | const int root_pw = 1<<20; 5 | 6 | void fft (vector & a, bool invert) { 7 | int n = (int) a.size(); 8 | 9 | for (int i=1, j=0; i> 1; 11 | for (; j>=bit; bit>>=1) 12 | j -= bit; 13 | j += bit; 14 | if (i < j) 15 | swap (a[i], a[j]); 16 | } 17 | 18 | for (int len=2; len<=n; len<<=1) { 19 | int wlen = invert ? root_1 : root; 20 | for (int i=len; i= 0 ? u-v : u-v+mod; 28 | w = int (w * 1ll * wlen % mod); 29 | } 30 | } 31 | } 32 | if (invert) { 33 | int nrev = reverse (n, mod); 34 | for (int i=0; i to[maxn]; 7 | int len[maxn], fpos[maxn], link[maxn]; 8 | int node, pos; 9 | int sz = 1, n = 0; 10 | 11 | int make_node(int _pos, int _len) { 12 | fpos[sz] = _pos; 13 | len[sz] = _len; 14 | return sz++; 15 | } 16 | void go_edge() { 17 | while (pos > len[to[node][s[n - pos]]]) { 18 | node = to[node][s[n - pos]]; 19 | pos -= len[node]; 20 | } 21 | } 22 | void add_letter(int c) { 23 | s[n++] = (char)c; 24 | pos++; 25 | int last = 0; 26 | while (pos > 0) { 27 | go_edge(); 28 | int edge = s[n - pos]; 29 | int &v = to[node][edge]; 30 | int t = s[fpos[v] + pos - 1]; 31 | if (v == 0) { 32 | v = make_node(n - pos, inf); 33 | link[last] = node; 34 | last = 0; 35 | } else if (t == c) { 36 | link[last] = node; 37 | return; 38 | } else { 39 | int u = make_node(fpos[v], pos - 1); 40 | to[u][c] = make_node(n - 1, inf); 41 | to[u][t] = v; 42 | fpos[v] += pos - 1; 43 | len[v] -= pos - 1; 44 | v = u; 45 | link[last] = u; 46 | last = u; 47 | } 48 | if (node == 0) 49 | pos--; 50 | else 51 | node = link[node]; 52 | } 53 | } 54 | void add_string(char *str) { 55 | for (int i = 0; str[i]; i++) add_letter(str[i]); 56 | add_letter('$'); 57 | } 58 | bool is_leaf(int u) { return len[u] > n; } 59 | int get_len(int u) { 60 | if (!u) return 0; 61 | if (is_leaf(u)) return n - fpos[u]; 62 | return len[u]; 63 | } 64 | int leafs[maxn]; 65 | int calc_leafs(int u = 0) { 66 | leafs[u] = is_leaf(u); 67 | for (const auto &c : to[u]) leafs[u] += calc_leafs(c.second); 68 | return leafs[u]; 69 | } 70 | }; // namespace sf 71 | 72 | int main() { sf::len[0] = sf::inf; } 73 | -------------------------------------------------------------------------------- /code/string/aho_corasick.cpp: -------------------------------------------------------------------------------- 1 | int to[N][A]; 2 | int ne = 2, fail[N], term[N]; 3 | void add_string(const char *str, int id){ 4 | int p = 1; 5 | for(int i = 0; str[i]; i++){ 6 | int ch = str[i] - 'a'; 7 | if(!to[p][ch]) to[p][ch] = ne++; 8 | p = to[p][ch]; 9 | } 10 | term[p]++; 11 | } 12 | void init(){ 13 | for(int i = 0; i < ne; i++) fail[i] = 1; 14 | queue q; q.push(1); 15 | int u, v; char c; 16 | while(!q.empty()){ 17 | u = q.front(); q.pop(); 18 | for(int i = 0; i < A; i++){ 19 | if(to[u][i]){ 20 | v = to[u][i]; q.push(v); 21 | if(u != 1){ 22 | fail[v] = to[ fail[u] ][i]; 23 | term[v] += term[ fail[v] ]; 24 | } 25 | } 26 | else if(u != 1) to[u][i] = to[ fail[u] ][i]; 27 | else to[u][i] = 1; 28 | } 29 | } 30 | } 31 | void clean() { 32 | memset(to, 0, ne * sizeof(to[0])); 33 | memset(fail, 0, ne * sizeof(fail[0])); 34 | memset(term, 0, ne * sizeof(term[0])); 35 | memset(to, 0, ne * sizeof(to[0])); 36 | ne = 2; 37 | } 38 | -------------------------------------------------------------------------------- /code/string/all_palindrome.cpp: -------------------------------------------------------------------------------- 1 | // rad[2 * i] = largest palindrome cetered at char i 2 | // rad[2 * i + 1] = largest palindrome cetered between chars i and i+i 3 | void manacher(char *s, int n, int *rad) { 4 | static char t[2*MAX]; 5 | int m = 2 * n - 1; 6 | 7 | for(int i = 0; i < m; i++) t[i] = -1; 8 | for(int i = 0; i < n; i++) t[2 * i] = s[i]; 9 | 10 | int x = 0; 11 | rad[0] = 0; // < 12 | for(int i = 1; i < m; i++) { 13 | int &r = rad[i] = 0; 14 | if(i <= x+rad[x]) r = min(rad[x+x-i],x+rad[x]-i); 15 | while(i - r - 1 >= 0 and i + r + 1 < m and 16 | t[i - r - 1] == t[i + r + 1]) ++r; 17 | if(i + r >= x + rad[x]) x = i; 18 | } 19 | 20 | for(int i = 0; i < m; i++) { 21 | if(i-rad[i] == 0 || i+rad[i] == m-1) ++rad[i]; 22 | } 23 | // for(int i = 0; i < m; i++) rad[i] /= 2; 24 | } 25 | -------------------------------------------------------------------------------- /code/string/min_rot.cpp: -------------------------------------------------------------------------------- 1 | int min_rotation(int *s, int N) { 2 | REP(i, N) s[N+i] = s[i]; 3 | 4 | int a = 0; 5 | REP(b, N) REP(i, N) { 6 | if (a+i == b || s[a+i] < s[b+i]) { b += max(0, i-1); break; } 7 | if (s[a+i] > s[b+i]) { a = b; break; } 8 | } 9 | return a; 10 | } 11 | -------------------------------------------------------------------------------- /code/string/pf.cpp: -------------------------------------------------------------------------------- 1 | vector preffix_function(const string &s){ 2 | int n = s.size(); vector b(n+1); 3 | b[0] = -1; int i = 0, j = -1; 4 | while(i < n){ 5 | while(j >= 0 && s[i] != s[j]) j = b[j]; 6 | b[++i] = ++j; 7 | } 8 | return b; 9 | } 10 | void kmp(const string &t, const string &p){ 11 | vector b = preffix_function(p); 12 | int n = t.size(), m = p.size(); 13 | int j = 0; 14 | for(int i = 0; i < n; i++){ 15 | while(j >= 0 && t[i] != p[j]) j = b[j]; 16 | j++; 17 | if(j == m){ 18 | //patern of p found on t 19 | j = b[j]; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /code/string/suffix_array.cpp: -------------------------------------------------------------------------------- 1 | int lcp[N], c[N]; 2 | 3 | // Caractere final da string '\0' esta sendo considerado parte da string s 4 | void build_sa(char s[], int n, int a[]){ 5 | const int A = 300; // Tamanho do alfabeto 6 | int c1[n], a1[n], h[n + A]; 7 | memset(h, 0, sizeof h); 8 | 9 | for(int i = 0; i < n; i++) { 10 | c[i] = s[i]; 11 | h[c[i] + 1]++; 12 | } 13 | 14 | partial_sum(h, h + A, h); 15 | for(int i = 0; i < n; i++) 16 | a[h[c[i]]++] = i; 17 | for(int i = 0; i < n; i++) 18 | h[c[i]]--; 19 | 20 | for(int L = 1; L < n; L <<= 1) { 21 | for(int i = 0; i < n; i++) { 22 | int j = (a[i] - L + n) % n; 23 | a1[h[c[j]]++] = j; 24 | } 25 | 26 | int cc = -1; 27 | for(int i = 0; i < n; i++) { 28 | if(i == 0 || c[a1[i]] != c[a1[i-1]] || c[(a1[i] + L) % n] != c[(a1[i-1] + L) % n]) 29 | h[++cc] = i; 30 | c1[a1[i]] = cc; 31 | } 32 | 33 | memcpy(a, a1, sizeof a1); 34 | memcpy(c, c1, sizeof c1); 35 | 36 | if(cc == n-1) break; 37 | } 38 | } 39 | 40 | void build_lcp(char s[], int n, int a[]){ // lcp[i] = lcp(s[:i], s[:i+1]) 41 | int k = 0; 42 | 43 | //memset(lcp, 0, sizeof lcp); 44 | for(int i = 0; i < n; i++){ 45 | if(c[i] == n-1) continue; 46 | int j = a[c[i]+1]; 47 | while(i+k < n && j+k < n && s[i+k] == s[j+k]) k++; 48 | lcp[c[i]] = k; 49 | if(k) k--; 50 | } 51 | } 52 | 53 | int comp_lcp(int i, int j){ 54 | if(i == j) return n - i; 55 | if(c[i] > c[j]) swap(i, j); 56 | return min(lcp[k] for k in [c[i], c[j]-1]); 57 | } -------------------------------------------------------------------------------- /code/string/suffix_automaton.cpp: -------------------------------------------------------------------------------- 1 | map to[2*N]; 2 | int link[2*N], len[2*N], last = 0, sz = 1; 3 | 4 | void add_letter(char c){ 5 | int p = last; 6 | last = sz++; 7 | len[last] = len[p] + 1; 8 | for(; !to[p][c]; p = link[p]) to[p][c] = last; 9 | if(to[p][c] == last){ 10 | link[last] = 0; 11 | return; 12 | } 13 | int u = to[p][c]; 14 | if(len[u] == len[p]+1){ 15 | link[last] = u; 16 | return; 17 | } 18 | int c1 = sz++; 19 | to[c1] = to[u]; 20 | link[c1] = link[u]; 21 | len[c1] = len[p]+1; 22 | link[last] = link[u] = c1; 23 | for(; to[p][c] == u; p = link[p]) to[p][c] = c1; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /code/string/z_algo.cpp: -------------------------------------------------------------------------------- 1 | vector z_algo(const string &s) { 2 | int n = s.size(), L = 0, R = 0; 3 | vector z(n, 0); 4 | for(int i = 1; i < n; i++){ 5 | if(i <= R) z[i] = min(z[i-L], R - i + 1); 6 | while(z[i]+i < n && s[ z[i]+i ] == s[ z[i] ]) 7 | z[i]++; 8 | if(i+z[i]-1 > R) L = i, R = i + z[i] - 1; 9 | } 10 | return z; 11 | } 12 | -------------------------------------------------------------------------------- /code/template.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define ff first 4 | #define ss second 5 | #define pb push_back 6 | 7 | using namespace std; 8 | using ll = long long; 9 | using ii = pair; 10 | 11 | const int N = 100005; 12 | 13 | int main() { 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /notebook.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joseleite19/icpc-notebook/18b9a6c8acbe485dfa19b1e5199d0e3a148097c6/notebook.pdf -------------------------------------------------------------------------------- /notebook.tex: -------------------------------------------------------------------------------- 1 | \documentclass[a4paper,10pt,oneside]{article} 2 | % \setcounter{secnumdepth}{-1} 3 | 4 | \usepackage{amsmath} 5 | \usepackage{amssymb} 6 | \usepackage{courier} 7 | \usepackage{graphicx} 8 | \usepackage{xcolor} 9 | \usepackage{color} 10 | \usepackage{pdflscape} 11 | \usepackage[utf8]{inputenc} 12 | \usepackage{listings} 13 | \usepackage[inline]{enumitem} 14 | \usepackage{verbatim} 15 | \usepackage{pxfonts} 16 | \usepackage{algorithm2e} 17 | \usepackage{algpseudocode} 18 | 19 | \usepackage[top=2cm, bottom=1.5cm, left=1cm, right=1cm]{geometry} 20 | \usepackage{multicol} 21 | \usepackage{fancyhdr} 22 | 23 | \pagestyle{fancy} 24 | 25 | \renewcommand{\sectionmark}[1]{\markboth{#1}{}} 26 | \renewcommand{\subsectionmark}[1]{\markright{#1}} 27 | 28 | \fancyhf{} 29 | \rhead{\leftmark, \thepage} 30 | 31 | \lhead{University of Brasilia} 32 | \cfoot{\thepage} 33 | 34 | \usepackage{titlesec} 35 | \titlespacing*{\section} 36 | {0pt}{2ex}{1ex} 37 | 38 | %\definecolor{dkgray}{rgb}{0.4,0.4,0.4} 39 | \definecolor{gray}{rgb}{0.6,0.6,0.6} 40 | \definecolor{dkgreen}{rgb}{0,0.6,0} 41 | %\definecolor{gray}{rgb}{0.5,0.5,0.5} 42 | \definecolor{mauve}{rgb}{0.58,0,0.82} 43 | 44 | \lstset{ 45 | language=c++, 46 | tabsize=4, 47 | aboveskip=.1em, 48 | belowskip=.1em, 49 | showstringspaces=false, 50 | basicstyle={\small\ttfamily}, 51 | columns=fullflexible, 52 | numberstyle=\tiny\color{gray}, 53 | % keywordstyle=\color{blue}, 54 | commentstyle=\color{dkgreen}, 55 | stringstyle=\color{mauve}, 56 | numbers=none, 57 | breaklines=true, 58 | breakindent=1.1em, 59 | breakatwhitespace=false, 60 | commentstyle=\color{gray}, 61 | } 62 | 63 | \newcommand\includes[2]{ 64 | \subsection{#1} 65 | \lstinputlisting{#2} 66 | } 67 | \newcommand\includess[2]{ 68 | \subsubsection{#1} 69 | \lstinputlisting{#2} 70 | } 71 | 72 | \setlength{\columnseprule}{1pt} 73 | 74 | \date{} 75 | \title{Rock Lee do Pagode Namora D+} 76 | %\title{ICPC Team Reference} 77 | \author{University of Brasilia} 78 | 79 | \begin{document} 80 | \maketitle 81 | \begin{multicols}{2} 82 | \tableofcontents 83 | % \newpage 84 | \thispagestyle{fancy} 85 | 86 | \lstinputlisting[language=bash]{vimrc} 87 | 88 | \lstinputlisting[language=bash]{bashrc} 89 | \includes{Template}{code/template.cpp} 90 | 91 | \section{Data Structures} 92 | \includes{Merge Sort Tree}{code/ed/merge_sort_tree.cpp} 93 | \includes{Fenwick Tree 2D}{code/ed/bit2D.cpp} 94 | \includes{Wavelet Tree}{code/ed/wavelet_tree.cpp} 95 | \includes{Order Set}{code/ed/order_set.cpp} 96 | \includes{Hash table}{code/ed/hash_table.cpp} 97 | \includes{Convex Hull Trick Simple}{code/ed/cht_simple.cpp} 98 | \includes{Convex Hull Trick}{code/ed/cht.cpp} 99 | \includes{Convex Hull Trick}{code/ed/LineContainer.cpp} 100 | \includes{Min queue}{code/ed/minq.cpp} 101 | \includes{Sparse Table}{code/ed/sparse_table.cpp} 102 | \includes{Treap}{code/ed/treap.cpp} 103 | \includes{ColorUpdate}{code/misc/ColorUpdate.cpp} 104 | \includes{Heavy Light Decomposition}{code/ed/hld.cpp} 105 | \includes{Iterative Segtree}{code/ed/segtree.cpp} 106 | \includes{Recursive Segtree + lazy}{code/ed/segtree_rec.cpp} 107 | \includes{LiChao's Segtree}{code/ed/lichao.cpp} 108 | \includes{Palindromic tree}{code/ed/eertree.cpp} 109 | 110 | \section{Math} 111 | \includes{Extended Euclidean Algorithm}{code/math/euclides.cpp} 112 | \includes{Chinese Remainder Theorem}{code/math/crt.cpp} 113 | \includes{Diophantine Solver}{code/math/diophantine.cpp} 114 | \includes{Preffix inverse}{code/math/inv.cpp} 115 | \includes{Pollard Rho}{code/math/pollard_rho.cpp} 116 | \includes{Miller Rabin}{code/math/miller_rabin.cpp} 117 | \includes{Totiente}{code/math/tot.cpp} 118 | \includes{Primitive root}{code/math/primitive_root.cpp} 119 | \includes{Mobius Function}{code/math/mobius.cpp} 120 | \includes{Mulmod TOP}{code/math/mod.cpp} 121 | \includes{Modular multiplication TOPPER}{code/math/fast_mul_mod.cpp} 122 | \includes{Division Trick}{code/math/division_trick.cpp} 123 | \includes{Matrix Determinant}{code/math/det.cpp} 124 | \includes{Simplex Method}{code/math/simplex.cpp} 125 | \includes{FFT}{code/fft.cpp} 126 | \includes{FFT Tourist}{code/fft_tourist.cpp} 127 | \includes{NTT}{code/ntt.cpp} 128 | \includes{Gauss}{code/gauss.cpp} 129 | \includes{Gauss Xor}{code/gauss_xor.cpp} 130 | \includes{Simpson}{code/math/simpson.cpp} 131 | \includes{Modular Arithmetic}{code/math/mod_arithmetic.cpp} 132 | \includes{Matrix}{code/math/matrix.cpp} 133 | 134 | \section{Graphs} 135 | \includes{Bipartite Matching}{code/graph/bipartite_matching.cpp} 136 | \includes{Dinic}{code/graph/dinic.cpp} 137 | \includes{Push relabel}{code/graph/pushrelabel.cpp} 138 | \includes{Min Cost Max Flow}{code/graph/mcmf.cpp} 139 | \includes{Blossom Algorithm for General Matching}{code/graph/blossom.cpp} 140 | \includes{Blossom Algorithm for Weighted General Matching}{code/graph/weight_blossom.cpp} 141 | \includes{Small to Large}{code/graph/stl.cpp} 142 | \includes{Centroid Decomposition}{code/graph/centroid_decomp.cpp} 143 | \includes{Kosaraju}{code/graph/kosaraju.cpp} 144 | \includes{Tarjan}{code/graph/tarjan.cpp} 145 | \includes{Max Clique}{code/graph/maxcliq.cpp} 146 | \includes{Dominator Tree}{code/graph/dominator_tree.cpp} 147 | \includes{Min Cost Matching}{code/graph/hungarian_mcm.cpp} 148 | 149 | \section{Strings} 150 | \includes{Aho Corasick}{code/string/aho_corasick.cpp} 151 | \includes{Suffix Array}{code/string/suffix_array.cpp} 152 | \includes{Adamant Suffix Tree}{code/string/adamant_suffix_tree.cpp} 153 | \includes{Z Algorithm}{code/string/z_algo.cpp} 154 | \includes{Prefix function/KMP}{code/string/pf.cpp} 155 | \includes{Min rotation}{code/string/min_rot.cpp} 156 | \includes{Manacher}{code/string/all_palindrome.cpp} 157 | \includes{Suffix Automaton}{code/string/suffix_automaton.cpp} 158 | \includes{Suffix Tree}{code/ed/suffix_tree.cpp} 159 | 160 | \section{Geometry} 161 | \includes{2D basics}{code/geometry/2D.cpp} 162 | \includes{Circle line intersection}{code/geometry/circle_line_intersection.cpp} 163 | \includes{Half plane intersection}{code/geometry/halfplane.cpp} 164 | \includes{Detect empty Half plane intersection}{code/geometry/detect_halfplane.cpp} 165 | 166 | \subsection{Circle Circle intersection} 167 | Assume that the first circle is centered at the origin and second at $(x2, y2)$. Find circle line intersection of first circle and line $Ax + By + C = 0$, where $A = -2x_2$, $B = -2y_2$, $C = x_2^2 + y_2^2 + r_1^2 - r_2^2$. 168 | 169 | Be aware of corner case with two circles centered at the same point. 170 | \includes{Tangents of two circles}{code/geometry/tangents.cpp} 171 | \includes{Convex Hull}{code/geometry/convexhull.cpp} 172 | \includes{Check point inside polygon}{code/geometry/in_poly.cpp} 173 | \includes{Check point inside polygon without lower/upper hull}{code/geometry/in_poly2.cpp} 174 | \includes{Minkowski sum}{code/geometry/mink.cpp} 175 | \subsection{Geo Notes} 176 | \subsubsection{Center of mass} 177 | \textbf{System of points(2D/3D):} Mass weighted average of points. \\ 178 | \textbf{Frame(2D/3D):} Get middle point of each segment solve as previously. \\ 179 | \textbf{Triangle:} Average of vertices. \\ 180 | \textbf{2D Polygon:} Compute \textbf{signed} area and center of mass of triangle $((0, 0), p_i, p_{i+1})$. Then solve as system of points.\\ 181 | \textbf{Polyhedron surface:} Solve each face as a 2D polygon(be aware of (0, 0)) then replace each face with its center of mass and solve as system of points. \\ 182 | \textbf{Tetrahedron(Triangular pyramid):} As triangles, its the average of points. \\ 183 | \textbf{Polyhedron:} Can be done as 2D polygon, but with tetrahedralization intead of triangulation. 184 | 185 | \subsubsection{Pick's Theorem} 186 | Given a polygon without self-intersections and all its vertices on integer coordinates in some 2D grid. Let $A$ be its area, $I$ the number of points with interger coordinates stricly inside the polygon and $B$ the number of points with interger coordinates in the border of the polygon. The following formula holds: $A = I + \frac{B}{2} - 1$. 187 | 188 | \section{Miscellaneous} 189 | \includes{LIS}{code/misc/lis.cpp} 190 | \includes{DSU rollback}{code/misc/bipar.cpp} 191 | \includes{Buildings}{code/misc/burn.cpp} 192 | \includes{Rand}{code/misc/rand.cpp} 193 | \includes{Klondike}{code/misc/klondike.cpp} 194 | \includes{Hilbert Order}{code/misc/hilbert_order.cpp} 195 | \includes{Modular Factorial}{code/misc/factmod.cpp} 196 | \includes{Enumeration all submasks of a bitmask}{code/misc/submasks.cpp} 197 | \includes{Slope Trick}{code/misc/slope.cpp} 198 | % \includes{Fast IO}{code/misc/fastio.cpp} 199 | % \includes{Big int}{code/misc/bigint.cpp} 200 | \includes{Knapsack Bounded with Cost}{code/misc/knapsack_bounded_cost.cpp} 201 | \includes{LCA \textless O(nlgn), O(1)\textgreater}{code/misc/lca.cpp} 202 | \includes{Buffered reader}{code/misc/buffered_reader.cpp} 203 | \includes{Modular summation}{code/misc/sum_mod.cpp} 204 | \includes{Edge coloring CPP}{code/misc/edge_coloring.cpp} 205 | 206 | \subsection{Burnside's Lemma} 207 | Let $(G, \oplus)$ be a finite group that acts on a set $X$. It should hold that $e_g*x=x$ and $g_1 *(g_2 * x) = (g_1 \oplus g_2) * x$, $\forall x \in X, g_1, g_2 \in G$. For each $g \in G$ let $X^g = \{x \in X \mid g*x = x \}$. The number of orbits its given by: 208 | 209 | $\mid X / G\mid~= \frac{1}{|G|} \sum_{g \in G}{|X^g|}$ 210 | 211 | \subsection{Wilson's Theorem} 212 | $(n-1)! = -1 \mod n \iff n\text{ is prime}$ 213 | 214 | \subsection{Fibonacci} 215 | \begin{itemize} 216 | \item $F_{n-1}F_{n+1} - F_n^2 = (-1)^n$ 217 | \item $F_{n+k} = F_kF_{n+1} + F_{k-1}F_n$ 218 | \item $GCD(F_n, F_m) = F_{GCD(n, m)}$ 219 | \item $F_n = \frac{(\frac{1+\sqrt{5}}{2})^n - (\frac{1-\sqrt{5}}{2})^n}{\sqrt{5}}$ 220 | \end{itemize} 221 | 222 | \subsection{Lucas's Theorem} 223 | For non-negative integers $m$ and $n$ and a prime $p$, the following congruence holds: 224 | 225 | $\displaystyle \binom{m}{n} \equiv \prod_{i = 0}^{k} \binom{m_i}{n_i} \pmod p$ 226 | 227 | where $m_i$ is the i-th digit of $m$ in base $p$. ${\displaystyle {\tbinom {a}{b}}=0}$ if $a < b$. 228 | 229 | \subsection{Kirchhoff's Theorem} 230 | Laplacian matrix is $L = D - A$, where $D$ is a diagonal matrix with vertex degrees on the diagonals and $A$ is adjacency matrix. 231 | 232 | The number of spanning trees is any cofactor of L. i-th cofactor is determinant of the matrix gotten by removing i-th row and column of L. 233 | 234 | \subsubsection{Multigraphs} 235 | In $D[i][i]$ all loops are excluded. $A[i][j]$ = number of edges from $i$ to $j$. 236 | 237 | \subsubsection{Directed multigraphs} 238 | $D[i][i]$ = indegree of i minus the number of loops at i. $A[i][j]$ = number of edges from $i$ to $j$. 239 | 240 | The number of oriented spanning trees rooted at a vertex i is the determinant of the matrix gotten by removing the ith row and column of L. 241 | 242 | \subsection{Matroid} 243 | Let $X$ set of objects, $I \subseteq 2^X$ set of independents sets such that: 244 | \begin{enumerate} 245 | \item $\emptyset \in I$ 246 | \item $A \in I, B \subseteq A \implies B \in I$ 247 | \item Exchange axiom, $A \in I, B \in I, |B| > |A| \implies \exists x \in B \setminus A : A \cup \{x\} \in I$ 248 | \item $A \subseteq X$ and $I$ and $I'$ are maximal independent subsets of A then $|I| = |I'|$ 249 | \end{enumerate} 250 | Then $(X, I)$ is a matroid. The combinatorial optimization problem associated with it is: Given a weight $w(e) \geq 0 ~\forall e \in X$, find an independet subset that has the largest possible total weight. 251 | 252 | \includess{Matroid intersection}{code/matroid.cpp} 253 | 254 | Where path(e) = [e] if label[e] = MARK2, path(label[e]) + [e] otherwise. 255 | 256 | \subsubsection{Matroid Union} 257 | Given $k$ matroids over the same set of objects $(X, I_1)$, $(X, I_2)$, \dots, $(X, I_k)$ find $A_1 \in I_1$, $A_2 \in I_2$, \dots, $A_k \in I_k$ such that $i \not= j, A_i \cap A_j = \emptyset$ and $|\bigcup\limits_{i=1}^{k} A_i|$ is maximum. Matroid union can be reduced to matroid intersection as follows. 258 | 259 | Let $X' = X \times \{1, 2, \dots, k\}$, ie, $k$ copies of each element of $X$ with different colors. $M1 = (X', Q)$ where $B \in Q \iff \forall ~1 \le i \le k, ~\{x\mid (x, i) \in B\} \in I_i$, ie, for each color, $B$ is independent. $M2 = (X', W)$ where $B \in W \iff i \not= j \implies \lnot((x, i) \in B \land (x, j) \in B)$, ie, each element is picked by at most one color. 260 | 261 | Intersection of $M1$ and $M2$ is the answer for the combinatorial problem of matroid union. 262 | 263 | \subsection{Notes} 264 | When we repeat something and each time we have probability $p$ to succeed then the expected number or tries is $\frac{1}{p}$, till we succeed. 265 | 266 | \textbf{Small to large} 267 | 268 | \textbf{Trick in statement} If $k$ sets are given you should note that the amount of different set sizes is $O(\sqrt{s})$ where $s$ is total size of those sets. And no more than $\sqrt{s}$ sets have size greater than $\sqrt{s}$. For example, a path to the root in Aho-Corasick through suffix links will have at most $O(\sqrt{s})$ vertices. 269 | 270 | \textbf{gcd on subsegment}, we have at most $\log(a_i)$ different values in $\{\gcd(a_j, a_{j+1}, ..., a_i)$ for $j < i\}$. 271 | 272 | \textbf{From static set to expandable}. To insert, create a new set with the new element. While there are two sets with same size, merge them. There will be at most $\log(n)$ disjoints sets. 273 | 274 | \textbf{Matrix exponentiation optimization}. Save binary power of $A_{nxn}$ and answer $q$ queries $b = A^mx$ in $O((n^3 + qn^2)log(m))$. 275 | 276 | \textbf{Ternary search on integers into binary search}, comparing f(mid) and f(mid+1), binary search on derivative 277 | 278 | \textbf{Dynamic offline set} For each element we will wind segment of time $[a, b]$ such that element is present in the set during this whole segment. Now we can come up with recursive procedure which handles $[l, r]$ time segment considering that all elements such that $[l, r] \subset [a, b]$ are already included into the set. Now, keeping this invariant we recursively go into $[l, m]$ and $[m+1, r]$ subsegments. Finally when we come into segment of length 1. 279 | 280 | $a > b \implies a \mod b < \frac{a}{2}$ 281 | 282 | \textbf{Convex Hull}. The expected number of points in the convex hull of a random set of points is $O(log(n))$. The number of points in a convex hull with points coordinates limited by $L$ is $O(L^{2/3})$. 283 | 284 | \textbf{Tree path query}. Sometimes the linear query is fast enough. Just do adamant's hld sorting subtrees by their size and remap vertices indexes. 285 | 286 | \textbf{Range query} offline can be solved by a sweep, ordering queries by R. 287 | 288 | Maximal number of divisors of any n-digit number. 7 4, 12, 32, 64, 128, 240, 448, 768, 1344, 2304, 4032, 6720, 10752, 17280, 26880, 41472, 64512, 103680, 161280, 245760, 368640, 552960, 860160, 1290240, 1966080, 2764800, 4128768, 6193152, 8957952, 13271040, 19660800, 28311552, 41287680, 59719680, 88473600, 127401984, 181665792, 264241152, 382205952, 530841600 289 | 290 | \end{multicols} 291 | 292 | 293 | \end{document} 294 | -------------------------------------------------------------------------------- /scripts/unused_files.sh: -------------------------------------------------------------------------------- 1 | all_files=$(find code -type f) 2 | used_files=$(grep -Fio "$all_files" notebook.tex) 3 | echo "$all_files" | grep -Fv "$used_files" 4 | 5 | -------------------------------------------------------------------------------- /vimrc: -------------------------------------------------------------------------------- 1 | set ts=4 sw=4 sta nu rnu sc stl+=%F cindent 2 | set bg=dark ruler timeoutlen=1000 3 | imap { {}O 4 | nmap 0V$%d 5 | nmap :m+1 6 | nmap :m-2 7 | nmap ggVG 8 | nmap :m-2 9 | nmap :m+1 10 | vmap "+y 11 | syntax on 12 | --------------------------------------------------------------------------------