├── .gitignore ├── README.md ├── code ├── data_structures │ ├── BIT_1D.cpp │ ├── BIT_2D.cpp │ ├── BIT_range_sum_and_range_update.cpp │ ├── DSU_with_partial_persistence.cpp │ ├── LiChao_tree.cpp │ ├── PBDS.cpp │ ├── Treap.cpp │ ├── TreeIsomorfismWithPolynomialHashing.cpp │ ├── centroid_decomposition.cpp │ ├── color_update.cpp │ ├── dynamic_segment_tree_with_lazy_propagation.cpp │ ├── dynamic_segment_tree_with_vector.cpp │ ├── heavy_light_decomposition.cpp │ ├── heavy_light_decomposition_path_and_subtree_queries.cpp │ ├── implicit_treap.cpp │ ├── max_queue.cpp │ ├── merge_sort_tree.cpp │ ├── merge_sort_tree_iterative.cpp │ ├── merge_sort_tree_range_order_statistics_queries.cpp │ ├── merge_sort_tree_with_set.cpp │ ├── ordered_set_With_BIT.cpp │ ├── persistent_segment_tree.cpp │ ├── persistent_segment_tree_without_vector.cpp │ ├── segment_tree_iterative.cpp │ ├── segment_tree_tree_2D.cpp │ ├── segment_tree_with_lazy_propagation.cpp │ ├── sparse_table_2D.cpp │ ├── sparse_table_RMQ.cpp │ ├── treeIsomorfismWithMap.cpp │ ├── two_stacks_trick.cpp │ └── wavelet_tree.cpp ├── dynamic_programming │ ├── Knapsack0-kSemValor.cpp │ ├── KnapsackWithCopies.cpp │ ├── KnapsackwithPDtopdown.cpp │ ├── coin_problem_topdown_dp.cpp │ ├── digit_DP_sum_of_digits_in_range.cpp │ ├── edit_distance_with_DP.cpp │ ├── kadane_2D.cpp │ ├── kadane_3D.cpp │ ├── knapsackErrichto.cpp │ ├── knapsack_with_copies_sqrtN_memory.cpp │ ├── knapsack_with_repetition_recurrence.cpp │ ├── knapsack_zero_one_without_value.cpp │ ├── longest_common_subsequece_and_edit_distance.cpp │ ├── longest_increasing_subsequence.cpp │ ├── subset_sum.cpp │ ├── traveling_salesman_problem_bottom_up_dp.cpp │ └── traveling_salesman_problem_topdown_dp.cpp ├── geometry │ ├── andrew_algorithm_convex_hull.cpp │ ├── build_two_lines_that_go_through_all_points_of_a_set.cpp │ ├── check_if_a_point_is_inside_a_convex_polygon.cpp │ ├── convex_hull_trick.cpp │ ├── distance_between_nearest_pair_of_points_2d.cpp │ ├── distance_between_nearest_pair_of_points_3d.cpp │ ├── dynamic_convex_hull_trick.cpp │ ├── enclosing_circle_R2.cpp │ ├── enclosing_circle_R3.cpp │ ├── geometry_stan.cpp │ ├── graham_scan.cpp │ ├── maximum_dot_product.cpp │ ├── radial_sort.cpp │ └── segment_intersection.cpp ├── graph │ ├── 2SAT.cpp │ ├── BFS_zero_one.cpp │ ├── MCE_MinimumEdgeCover.cpp │ ├── MPC_MinimumPathCover.cpp │ ├── MVC_MinimumVertexCover.cpp │ ├── binary_lifting.cpp │ ├── boruvka_MST.cpp │ ├── center_of_a_tree.cpp │ ├── diameter_and_center_of_a_tree.cpp │ ├── dijkstra.cpp │ ├── dinic.cpp │ ├── erdos_gallai_theorem.cpp │ ├── eulirian_path.cpp │ ├── floyd_sucessor_graph.cpp │ ├── ford_fulkerson.cpp │ ├── fully_dynamic_connectivity_check_if_two_vertices_are_in_the_same_component.cpp │ ├── fully_dynamic_connectivity_count_conected_components.cpp │ ├── hopcroft_karp.cpp │ ├── k_short_paths.cpp │ ├── knapsack_dijkstra.cpp │ ├── kuhn_MCBM.cpp │ ├── lca_with_square_root_decomposition.cpp │ ├── lca_with_tree_linearization_and_segment_tree.cpp │ ├── lca_with_tree_linearization_and_sparse_table.cpp │ ├── longest_and_shortest_path_in_DAG.cpp │ ├── maximum_clique.cpp │ ├── min_cost_max_flow.cpp │ ├── prim.cpp │ └── tree_isomorfism.cpp ├── math │ ├── Mod_Integer.cpp │ ├── baby_step_giant_step.cpp │ ├── catalan_numbers.cpp │ ├── chinese_remainder_theorem.cpp │ ├── conversion_base.cpp │ ├── counting_number_of_times_that_a_digit_appears_until_n.cpp │ ├── fast_fourier_transform.cpp │ ├── gaussian_elimination_for_max_subset_xor.cpp │ ├── karatsuba.cpp │ ├── matrix_exponentiation.cpp │ ├── miller_rabin.cpp │ ├── mobius.cpp │ ├── mod_gaussian_elimination.cpp │ ├── modular_arithmetic.cpp │ ├── mulmod_trick.cpp │ └── pollard_rho.cpp ├── miscellaneous │ ├── big_num_product.cpp │ ├── centroid_decomposition_closest_colored_vertex.cpp │ ├── count_divisors.cpp │ ├── count_sort.cpp │ ├── counting_different_elements_in_a_path_with_Mo.cpp │ ├── custom_hash_function_unordered_map_or_set.cpp │ ├── divide_conquer_optimization.cpp │ ├── fastIO.cpp │ ├── fence_problem_with_max_flow.cpp │ ├── gen_random_tree.cpp │ ├── histogram.cpp │ ├── inclusion_exclusion.cpp │ ├── index_compression.cpp │ ├── karp_rabin.cpp │ ├── knapsack_with_backtraking.cpp │ ├── knuth_optimization.cpp │ ├── lontest_substring_that_is_a_correct_bracket_sequence.cpp │ ├── maximum_subarray_xor.cpp │ ├── mo.cpp │ ├── odd_rectangles_area.cpp │ ├── quick_sort_and_Select.cpp │ ├── rectangles_union_area.cpp │ ├── small_to_large.cpp │ ├── square_root_decomposition.cpp │ └── string_matching_hash_sqrtdecomp.cpp ├── string │ ├── KMP.cpp │ ├── LIS_LDS.cpp │ ├── SA.cpp │ ├── Z_function.cpp │ ├── aho_corasick.cpp │ ├── dynamic_trie.cpp │ ├── longest_common_substring.cpp │ ├── manacher.cpp │ ├── string_hash.cpp │ ├── suffix_array.cpp │ ├── suffix_array_and_applications.cpp │ ├── trie.cpp │ ├── trie_static.cpp │ └── trie_with_vector.cpp └── useful_scripts │ ├── brute.cpp │ ├── gen.cpp │ ├── gen_tree.cpp │ ├── gen_tree2.cpp │ ├── makefile │ ├── sol.cpp │ ├── stress.sh │ ├── stress_test_animated.sh │ └── stress_with_checker.sh └── latex ├── GEMP-Notebook.pdf ├── extract.cpp ├── generate_pdf.py └── model └── notebook.tex /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | 3 | a.out -------------------------------------------------------------------------------- /code/data_structures/BIT_1D.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int aux, n, arr[1000], BIT[1000]; 5 | 6 | // construir uma BIT a partir de um array em O(N) 7 | void build() { 8 | for(int i = 1; i <= n; i++) { 9 | BIT[i] += arr[i]; 10 | if(i + (i & -i) <= n) 11 | BIT[i + (i & -i)] += BIT[i]; 12 | } 13 | } 14 | 15 | // construir o array que gera a BIT a partir de uma BIT em O(N) 16 | void buildArray() { 17 | for(int i = n; i >= 1; i--) 18 | if(i + (i & -i) <= n) 19 | BIT[i + (i & -i)] -= BIT[i]; 20 | } 21 | 22 | int sum(int x) { 23 | int s = 0; 24 | while(x) s += BIT[x], x -= x&-x; 25 | return s; 26 | } 27 | 28 | void update(int x, int value) { 29 | while(x <= n) BIT[x] += value, x += x&-x; 30 | } 31 | 32 | int main() { 33 | cin >> n; 34 | for(int i = 1; i <= n; i++) { 35 | cin >> aux; 36 | update(i, aux); 37 | } 38 | int a, b; 39 | cin >> a >> b; 40 | cout << sum(b)-sum(a-1) << '\n'; 41 | 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /code/data_structures/BIT_2D.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int MAX = 1e3; 4 | 5 | int n, aux, BIT[MAX][MAX]; 6 | 7 | void update(int x, int y, int value) 8 | { 9 | for(int i = x; i <= n; i += i&-i) 10 | for(int j = y; j <= n; j += j&-j) 11 | BIT[i][j] += value; 12 | } 13 | 14 | int query(int x, int y) 15 | { 16 | int sum = 0; 17 | for(int i = x; i > 0; i -= i&-i) 18 | for(int j = y; j > 0; j -= j&-j) 19 | sum += BIT[i][j]; 20 | return sum; 21 | } 22 | 23 | int queryInRectangle(int x1, int y1, int x2, int y2) 24 | { 25 | int sum = 0; 26 | sum += query(max(x1, x2), max(y1, y2)); 27 | sum -= query(max(x1, x2), min(y1, y2) - 1); 28 | sum -= query(min(x1, x2) - 1, max(y1, y2)); 29 | sum += query(min(x1, x2) - 1, min(y1, y2) - 1); 30 | return sum; 31 | } 32 | 33 | int main() 34 | { 35 | cin >> n; 36 | for(int i = 1; i <= n; i++) 37 | for(int j = 1; j <= n; j++) 38 | cin >> aux, update(i, j, aux); 39 | int x1, y1, x2, y2; 40 | while(cin >> x1 >> y1 >> x2 >> y2) 41 | cout << queryInRectangle(x1, y1, x2, y2) << '\n'; 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /code/data_structures/BIT_range_sum_and_range_update.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | const int MAX = 1e5; 3 | 4 | using namespace std; 5 | 6 | struct BIT { 7 | 8 | int N; 9 | int BIT1[MAX]; 10 | int BIT2[MAX]; 11 | 12 | BIT(int M) { 13 | N = M; 14 | } 15 | 16 | void add(int *b, int pos, int x) { 17 | while(pos <= N) b[pos] += x, pos += pos&-pos; 18 | } 19 | 20 | void range_add(int l, int r, int x) { 21 | add(BIT1, l, x); 22 | add(BIT1, r + 1, -x); 23 | add(BIT2, l, x * (l - 1)); 24 | add(BIT2, r + 1, -x * r); 25 | } 26 | 27 | int sum(int *b, int pos) { 28 | int s = 0; 29 | while(pos) s += b[pos], pos -= pos&-pos; 30 | return s; 31 | } 32 | 33 | int prefix_sum(int pos) { 34 | return sum(BIT1, pos) * pos - sum(BIT2, pos); 35 | } 36 | 37 | int range_sum(int l, int r) { 38 | return prefix_sum(r) - prefix_sum(l - 1); 39 | } 40 | }; 41 | 42 | int main() { 43 | 44 | int n, q; 45 | cin >> n >> q; 46 | 47 | BIT B(n); 48 | 49 | while(q--) { 50 | int o, l, r, x; 51 | cin >> o >> l >> r; 52 | if(o == 1) { 53 | cout << B.range_sum(l, r) << '\n'; 54 | } else { 55 | cin >> x; 56 | B.range_add(l, r, x); 57 | } 58 | } 59 | 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /code/data_structures/DSU_with_partial_persistence.cpp: -------------------------------------------------------------------------------- 1 | int n, pai[MAX], sz[MAX], his[MAX], tempo; 2 | 3 | void init() 4 | { 5 | tempo = 0; 6 | for(int i = 0; i < n; i++) 7 | pai[i] = i, sz[i] = 1, his[i] = 0; 8 | } 9 | 10 | int find(int x, int t) 11 | { 12 | if(pai[x] == x) return x; 13 | if(his[x] > t) return x; 14 | return find(pai[x], t); 15 | } 16 | 17 | void join(int u, int v) 18 | { 19 | tempo++; 20 | u = find(u, tempo); 21 | v = find(v, tempo); 22 | if(sz[u] > sz[v]) swap(u, v); 23 | pai[u] = v; 24 | his[u] = tempo; 25 | sz[v] += sz[u]; 26 | } 27 | -------------------------------------------------------------------------------- /code/data_structures/LiChao_tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define x real 4 | #define y imag 5 | typedef int ftype; 6 | typedef complex point; 7 | const int OO = 0x3f3f3f3f; 8 | const int maxn = 2e5; 9 | 10 | point line[4 * maxn]; 11 | 12 | void init() 13 | { 14 | for(int i = 0; i < 4 * maxn; i++) 15 | line[i] = point(0, OO); 16 | } 17 | 18 | ftype dot(point a, point b) 19 | { 20 | return (conj(a) * b).x(); 21 | } 22 | 23 | ftype f(point a, ftype x) 24 | { 25 | return dot(a, {x, 1}); 26 | } 27 | 28 | void add_line(point nw, int v = 1, int l = 0, int r = maxn) 29 | { 30 | int m = (l + r) / 2; 31 | bool lef = f(nw, l) < f(line[v], l); 32 | bool mid = f(nw, m) < f(line[v], m); 33 | if(mid) 34 | swap(line[v], nw); 35 | if(r - l == 1) 36 | return; 37 | else if(lef != mid) 38 | add_line(nw, 2 * v, l, m); 39 | else 40 | add_line(nw, 2 * v + 1, m, r); 41 | } 42 | 43 | int get(int x, int v = 1, int l = 0, int r = maxn) 44 | { 45 | int m = (l + r) / 2; 46 | if(r - l == 1) 47 | return f(line[v], x); 48 | else if(x < m) 49 | return min(f(line[v], x), get(x, 2 * v, l, m)); 50 | else 51 | return min(f(line[v], x), get(x, 2 * v + 1, m, r)); 52 | } 53 | 54 | int main() 55 | { 56 | init(); 57 | 58 | point a(2, 4); 59 | point b(1, 3); 60 | 61 | add_line(a); 62 | add_line(b); 63 | 64 | cout << get(2) << '\n'; 65 | 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /code/data_structures/PBDS.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | // Common file 3 | #include 4 | // Including tree_order_statistics_node_update 5 | #include 6 | using namespace std; 7 | using namespace __gnu_pbds; 8 | 9 | typedef tree, 10 | rb_tree_tag, tree_order_statistics_node_update> ordered_set; 11 | 12 | int main() 13 | { 14 | ordered_set X; 15 | X.insert(2); 16 | X.insert(13); 17 | X.insert(5); 18 | X.insert(2); 19 | cout << *X.find_by_order(0) << '\n'; 20 | cout << X.order_of_key(1) << '\n'; 21 | 22 | return 0; 23 | } 24 | 25 | 26 | /////////////////////////////////////////////////////// 27 | 28 | 29 | #include 30 | // Common file 31 | #include 32 | // Including tree_order_statistics_node_update 33 | #include 34 | using namespace std; 35 | using namespace __gnu_pbds; 36 | 37 | #define vi vector 38 | #define var pair 39 | #define ordered_multiset tree 40 | , rb_tree_tag, tree_order_statistics_node_update> 41 | 42 | int id = 0; map ids; 43 | 44 | void insere(ordered_multiset &s, int x) 45 | { 46 | s.insert({x, ++id}); 47 | ids[x].push_back(id); 48 | } 49 | 50 | void apaga(ordered_multiset &s, int x) 51 | { 52 | if(ids[x].empty()) return; 53 | s.erase({x, ids[x].back()}); 54 | ids[x].pop_back(); 55 | } 56 | 57 | int kth(ordered_multiset &s, int x) 58 | { 59 | return s.find_by_order(x)->first; 60 | } 61 | 62 | int smallerCount(ordered_multiset &s, int x) 63 | { 64 | return s.order_of_key({x, 0}); 65 | } 66 | 67 | int count(ordered_multiset &s, int x) 68 | { 69 | return smallerCount(s, x + 1) - smallerCount(s, x); 70 | } 71 | 72 | ordered_multiset::iterator find(ordered_multiset &s, int x) 73 | { 74 | if(ids[x].empty()) 75 | return s.end(); 76 | return s.find({x, ids[x].back()}); 77 | } 78 | 79 | int main() 80 | { 81 | ordered_multiset X; 82 | 83 | // usar funcoes ... 84 | 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /code/data_structures/TreeIsomorfismWithPolynomialHashing.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define ll long long 4 | const int MAX = 1e5 + 10; 5 | const ll A = 911382323; 6 | const ll B = 972663749; 7 | 8 | int n, ID, degree[MAX]; 9 | map formato; 10 | bool vis[MAX]; 11 | 12 | inline ll norm(ll a) 13 | { 14 | return a > B ? a = a % B : a; 15 | } 16 | 17 | inline ll add(ll a, ll b) 18 | { 19 | a = norm(a); b = norm(b); 20 | return norm(a + b); 21 | } 22 | 23 | inline ll prod(ll a, ll b) 24 | { 25 | a = norm(a); b = norm(b); 26 | return norm(a * b); 27 | } 28 | 29 | inline ll pol_hash(vector &v) 30 | { 31 | ll p = 1, ans = 0; 32 | for(ll &w : v) 33 | { 34 | ans = add(ans, prod(p, w)); 35 | p = prod(p, A); 36 | } 37 | return norm(ans); 38 | } 39 | 40 | ll dfs(int v, int p, vector> &G) 41 | { 42 | if((int)G[v].size() == 1) 43 | return 1; 44 | vector ids; 45 | for(int &u : G[v]) 46 | { 47 | if(u == p) continue; 48 | ll x = dfs(u, v, G); 49 | ids.push_back(x); 50 | } 51 | sort(ids.begin(), ids.end()); 52 | ll ph = pol_hash(ids); 53 | if(formato.count(ph) <= 0) formato[ph] = ++ID; 54 | return formato[ph]; 55 | } 56 | 57 | inline void findCenterAndComputeID(vector> &G, vector &val) 58 | { 59 | memset(vis, 0, sizeof(vis)); 60 | queue fila[2]; 61 | for(int i = 0; i < n; i++) 62 | if(degree[i] == 1) 63 | fila[0].push(i); 64 | int cnt = 0, turn = 0; 65 | while(cnt + 2 < n) 66 | { 67 | while(!fila[turn].empty()) 68 | { 69 | int u = fila[turn].front(); fila[turn].pop(); 70 | vis[u] = true; 71 | cnt++; 72 | for(int i = 0; i < G[u].size(); i++) 73 | if(!vis[G[u][i]]) 74 | { 75 | degree[G[u][i]]--; 76 | if(degree[G[u][i]] == 1) fila[1-turn].push(G[u][i]); 77 | } 78 | } 79 | turn ^= 1; 80 | } 81 | for(int i = 0; i < n; i++) 82 | { 83 | if(vis[i]) continue; 84 | val.push_back(dfs(i, -1, G)); 85 | } 86 | } 87 | 88 | int32_t main() 89 | { 90 | while(cin >> n) 91 | { 92 | formato.clear(); 93 | ID = 1; 94 | vector val[2]; 95 | for(int j = 0; j < 2; j++) 96 | { 97 | memset(degree, 0, sizeof(degree)); 98 | vector> G(n + 1); 99 | for(int i = 1; i < n; i++) 100 | { 101 | int u, v; 102 | scanf(" %d %d", &u, &v); u--; v--; 103 | G[u].push_back(v); 104 | G[v].push_back(u); 105 | degree[v]++; 106 | degree[u]++; 107 | } 108 | findCenterAndComputeID(G, val[j]); 109 | } 110 | bool fl = false; 111 | for(ll &v0 : val[0]) 112 | for(ll &v1 : val[1]) 113 | if(v0 == v1) 114 | fl = true; 115 | puts(fl ? "S" : "N"); 116 | } 117 | 118 | return 0; 119 | } 120 | -------------------------------------------------------------------------------- /code/data_structures/centroid_decomposition.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int MAX = 1e5; 4 | 5 | int n, m, Centroid_Tree[MAX], Size[MAX]; 6 | vector G[MAX], cTree[MAX]; 7 | bool cut[MAX]; 8 | 9 | int dfs(int v, int p) 10 | { 11 | int s = 1; 12 | for(const int &u : G[v]) 13 | if(!cut[u] and u != p) 14 | s += dfs(u, v); 15 | return Size[v] = s; 16 | } 17 | 18 | int Find_Centroid(int v, int p, int tot) 19 | { 20 | int next, cnt = 0; 21 | for(const int &u : G[v]) 22 | if(!cut[u] and u != p and cnt < Size[u]) 23 | { 24 | cnt = Size[u]; 25 | next = u; 26 | } 27 | if(cnt > tot/2) return Find_Centroid(next, v, tot); 28 | return v; 29 | } 30 | 31 | void build(int v, int p) 32 | { 33 | dfs(v, -1); 34 | int u = Find_Centroid(v, -1, Size[v]); 35 | cut[u] = true; 36 | Centroid_Tree[u] = p; 37 | if(p != -1) 38 | { 39 | cTree[u].push_back(p); 40 | cTree[p].push_back(u); 41 | } 42 | for(const int &w : G[u]) 43 | if(!cut[w]) 44 | build(w, u); 45 | } 46 | 47 | int main() 48 | { 49 | int u, v; 50 | memset(Centroid_Tree,-1, sizeof Centroid_Tree); 51 | cin >> n >> m; 52 | while(m--) 53 | { 54 | cin >> u >> v; 55 | u--; v--; 56 | G[u].push_back(v); 57 | G[v].push_back(u); 58 | } 59 | build(0, -1); 60 | for(int i = 0; i < n; i++) 61 | { 62 | cout << i+1 << ": "; 63 | for(int &w : cTree[i]) 64 | cout << w+1 << ' '; 65 | cout << '\n'; 66 | } 67 | 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /code/data_structures/color_update.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #define bug(x) cout << #x << " >>>>>>> " << x << '\n' 5 | #define _ << " , " << 6 | #define INF 0x3f3f3f3f 7 | 8 | #define ii pair 9 | #define fi first 10 | #define se second 11 | 12 | struct Color { 13 | int x; 14 | Color(int _x) : x(_x) {} 15 | Color() : x(-1) {} 16 | bool operator<(const Color &c) const { 17 | return x < c.x; 18 | } 19 | }; 20 | 21 | #define iic pair, Color> 22 | #define defaut_color Color(-1) 23 | 24 | struct ColorUpdate { 25 | set intervals; 26 | 27 | ColorUpdate(int begin = -INF, int end = INF) { 28 | intervals.insert( { {begin, end}, defaut_color } ); 29 | } 30 | 31 | void paint(int l, int r, Color c = defaut_color) { 32 | if(l > r) return; 33 | 34 | auto a = prev(intervals.upper_bound({{l, INF}, INF})); 35 | auto b = prev(intervals.upper_bound({{r, INF}, INF})); 36 | 37 | int l1 = a->fi.fi, r1 = l - 1; 38 | Color c1 = a->se; 39 | int l2 = r + 1, r2 = b->fi.se; 40 | Color c2 = b->se; 41 | 42 | intervals.erase(a, next(b)); 43 | 44 | if(l1 <= r1) intervals.insert({{l1, r1}, c1}); 45 | if(l2 <= r2) intervals.insert({{l2, r2}, c2}); 46 | if(l <= r) intervals.insert({{l, r}, c}); 47 | 48 | // printall(); 49 | } 50 | 51 | Color get_color_of(int x) { 52 | return prev(intervals.upper_bound({{x, INF}, INF}))->se; 53 | } 54 | 55 | // true if x is in some interval 56 | bool find(int x) { 57 | auto a = intervals.upper_bound({{x, INF}, INF}); 58 | if(a == intervals.begin()) return false; 59 | a--; 60 | if(a->fi.fi > x or a->fi.se < x) return false; 61 | return true; 62 | } 63 | 64 | ii get_interval_of(int x) { 65 | if(!find(x)) return {-INF, INF}; 66 | return prev(intervals.upper_bound({{x, INF}, INF}))->fi; 67 | } 68 | 69 | ii get_interval_of(int l, int r) { 70 | if(!find(l)) return {-INF, INF}; 71 | ii i = get_interval_of(l); 72 | if(i.fi <= r and r <= i.se) return i; 73 | return {-INF, INF}; 74 | } 75 | 76 | // x will be on the left side 77 | void cut_at(int x) { 78 | if(!find(x)) return; 79 | 80 | auto a = prev(intervals.upper_bound({{x, INF}, INF})); 81 | 82 | Color c = a->se; 83 | 84 | int l1 = a->fi.fi, r1 = x; 85 | int l2 = x + 1, r2 = a->fi.se; 86 | 87 | intervals.erase(a); 88 | 89 | if(l1 <= r1) intervals.insert({{l1, r1}, c}); 90 | if(l2 <= r2) intervals.insert({{l2, r2}, c}); 91 | } 92 | 93 | void remove_interval(int l, int r) { 94 | cut_at(l - 1); 95 | cut_at(r); 96 | 97 | auto a = prev(intervals.upper_bound({{l, INF}, INF})); 98 | auto b = prev(intervals.upper_bound({{r, INF}, INF})); 99 | 100 | intervals.erase(a, next(b)); 101 | } 102 | 103 | void remove_at(int x) { 104 | remove_interval(x, x); 105 | } 106 | 107 | void p_interval(iic i) { 108 | cout << "elements from " << i.fi.fi << " to " << i.fi.se; 109 | cout << " have color " << i.se.x << endl; 110 | } 111 | 112 | void printall() { 113 | cout << "\n\n\nColor Of The Elements:\n"; 114 | for(auto it : intervals) 115 | p_interval(it); 116 | cout << endl << endl; 117 | } 118 | }; 119 | 120 | int32_t main() { 121 | 122 | ios_base::sync_with_stdio(false); 123 | cin.tie(nullptr); 124 | 125 | ColorUpdate C(1, 100); 126 | 127 | for(int i = 3; i <= 50; i += 10) 128 | C.cut_at(i); 129 | 130 | C.remove_interval(16, 57); 131 | 132 | C.remove_at(100); 133 | C.remove_at(1); 134 | C.remove_at(2); 135 | C.remove_at(3); 136 | 137 | C.cut_at(20); 138 | 139 | C.printall(); 140 | 141 | return 0; 142 | } -------------------------------------------------------------------------------- /code/data_structures/dynamic_segment_tree_with_lazy_propagation.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | struct Node 5 | { 6 | int l, r, value; 7 | }; 8 | 9 | vector tree; 10 | vector lazy; 11 | 12 | int init() 13 | { 14 | tree.clear(); 15 | lazy.clear(); 16 | tree.emplace_back(); 17 | lazy.push_back(0); 18 | } 19 | 20 | void createL(int node) 21 | { 22 | tree[node].l = tree.size(); 23 | tree.emplace_back(); 24 | lazy.push_back(0); 25 | } 26 | 27 | void createR(int node) 28 | { 29 | tree[node].r = tree.size(); 30 | tree.emplace_back(); 31 | lazy.push_back(0); 32 | } 33 | 34 | void calc(int node) 35 | { 36 | tree[node].value = 0; 37 | if(tree[node].l) tree[node].value += tree[tree[node].l].value; 38 | if(tree[node].r) tree[node].value += tree[tree[node].r].value; 39 | } 40 | 41 | void push(int node, int start, int end) 42 | { 43 | // += 44 | tree[node].value = lazy[node] * (end - start + 1); 45 | if(start != end) 46 | { 47 | if(tree[node].l == 0) createL(node); 48 | if(tree[node].r == 0) createR(node); 49 | lazy[tree[node].l] = lazy[node]; // += 50 | lazy[tree[node].r] = lazy[node]; // += 51 | } 52 | lazy[node] = 0; 53 | } 54 | 55 | void update(int node, int start, int end, int l, int r, int value) 56 | { 57 | if(lazy[node]) 58 | push(node, start, end); 59 | 60 | if(start > r or l > end) return; 61 | 62 | if(l <= start and end <= r) 63 | { 64 | tree[node].value = value * (end - start + 1); // += 65 | if(start != end) 66 | { 67 | if(tree[node].l == 0) createL(node); 68 | if(tree[node].r == 0) createR(node); 69 | lazy[tree[node].l] = value; // += 70 | lazy[tree[node].r] = value; // += 71 | } 72 | } 73 | else 74 | { 75 | int mid = (start + end) / 2; 76 | if(tree[node].l == 0) createL(node); 77 | update(tree[node].l, start, mid, l, r, value); 78 | if(tree[node].r == 0) createR(node); 79 | update(tree[node].r, mid + 1, end, l, r, value); 80 | calc(node); 81 | } 82 | } 83 | 84 | int query(int node, int start, int end, int l, int r) 85 | { 86 | if(lazy[node]) 87 | push(node, start, end); 88 | 89 | if(start > r or l > end) return 0; 90 | 91 | if(l <= start and end <= r) return tree[node].value; 92 | 93 | int mid = (start + end) / 2, q1 = 0, q2 = 0; 94 | if(tree[node].l) q1 = query(tree[node].l, start, mid, l, r); 95 | if(tree[node].r) q2 = query(tree[node].r, mid + 1, end, l, r); 96 | return q1 + q2; 97 | } 98 | 99 | int main() 100 | { 101 | int n, q; 102 | 103 | cin >> n >> q; 104 | init(); 105 | for(int i = 0; i < n; i++) 106 | { 107 | int x; 108 | cin >> x; 109 | update(0, 0, n - 1, i, i, x); 110 | } 111 | while(q--) 112 | { 113 | int o, l, r, x; 114 | cin >> o >> l >> r; 115 | if(o == 1) 116 | { 117 | cin >> x; 118 | update(0, 0, n - 1, l - 1, r - 1, x); 119 | } 120 | else 121 | cout << query(0, 0, n - 1, l - 1, r - 1) << '\n'; 122 | } 123 | 124 | return 0; 125 | } 126 | -------------------------------------------------------------------------------- /code/data_structures/dynamic_segment_tree_with_vector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int MAX = 1e5; 4 | 5 | struct Node 6 | { 7 | int l, r, value; 8 | }; 9 | 10 | vector tree; 11 | 12 | int init() 13 | { 14 | tree.emplace_back(); 15 | } 16 | 17 | void calc(int node) 18 | { 19 | tree[node].value = 0; 20 | if(tree[node].l) tree[node].value += tree[tree[node].l].value; 21 | if(tree[node].r) tree[node].value += tree[tree[node].r].value; 22 | } 23 | 24 | void update(int node, int start, int end, int idx, int value) 25 | { 26 | if(start == end) 27 | tree[node].value = value; 28 | else 29 | { 30 | int mid = (start + end) / 2; 31 | if(start <= idx and idx <= mid) 32 | { 33 | if(tree[node].l == 0) 34 | { 35 | tree[node].l = tree.size(); 36 | tree.emplace_back(); 37 | } 38 | update(tree[node].l, start, mid, idx, value); 39 | } 40 | else 41 | { 42 | if(tree[node].r == 0) 43 | { 44 | tree[node].r = tree.size(); 45 | tree.emplace_back(); 46 | } 47 | update(tree[node].r, mid + 1, end, idx, value); 48 | } 49 | calc(node); 50 | } 51 | } 52 | 53 | int query(int node, int start, int end, int l, int r) 54 | { 55 | if(l > end or r < start) return 0; 56 | if(l <= start and end <= r) return tree[node].value; 57 | int mid = (start + end) / 2, q1 = 0, q2 = 0; 58 | if(tree[node].l) q1 = query(tree[node].l, start, mid, l, r); 59 | if(tree[node].r) q2 = query(tree[node].r, mid + 1, end, l, r); 60 | return q1 + q2; 61 | } 62 | 63 | int main() 64 | { 65 | int n, q; 66 | 67 | cin >> n >> q; 68 | init(); 69 | while(q--) 70 | { 71 | int o, l, r; 72 | cin >> o >> l >> r; 73 | if(o == 1) update(0, 0, n - 1, l - 1, r); 74 | else cout << query(0, 0, n - 1, l - 1, r - 1) << '\n'; 75 | } 76 | 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /code/data_structures/implicit_treap.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | struct Node 5 | { 6 | int valor, priority, size, sum; 7 | Node *l, *r; 8 | bool rev; 9 | Node(int _valor) : rev(false), sum(_valor), valor(_valor), 10 | priority((rand() << 16) ^ rand()), size(1), l(nullptr), r(nullptr) {} 11 | ~Node() { delete l; delete r; } 12 | 13 | void recalc() 14 | { 15 | size = 1; 16 | sum = valor; 17 | if(l) size += l->size, sum += l->sum; 18 | if(r) size += r->size, sum += r->sum; 19 | } 20 | }; 21 | 22 | struct Treap 23 | { 24 | int size(Node* t) { return t ? t->size : 0; } 25 | 26 | int size() const { return root ? root->size : 0; } 27 | 28 | Node* propagate(Node* t) 29 | { 30 | if(t == nullptr) return t; 31 | if(t->rev) 32 | { 33 | swap(t->l, t->r); 34 | if(t->l != nullptr) t->l->rev ^= 1; 35 | if(t->r != nullptr) t->r->rev ^= 1; 36 | t->rev = 0; 37 | } 38 | t->recalc(); 39 | return t; 40 | } 41 | 42 | int position(Node *t, int n) 43 | { 44 | //nao esta na treap, botar valor que noa esta no array... 45 | if(t == nullptr) return -1; 46 | propagate(t); 47 | if(n == size(t->l) + 1) return t->valor; 48 | else if(n <= size(t->l)) return position(t->l, n); 49 | else return position(t->r, n - size(t->l) - 1); 50 | } 51 | 52 | int at(int n) 53 | { 54 | return position(root, n); 55 | } 56 | 57 | Node* merge(Node *l, Node *r) 58 | { 59 | l = propagate(l); 60 | r = propagate(r); 61 | if(!l or !r) return l ? l : r; 62 | if(l->priority < r->priority) 63 | { 64 | l->r = merge(l->r, r); 65 | l->recalc(); 66 | return l; 67 | } 68 | else 69 | { 70 | r->l = merge(l, r->l); 71 | r->recalc(); 72 | return r; 73 | } 74 | } 75 | 76 | void split(Node *v, int valor, Node *&l, Node *&r) 77 | { 78 | v = propagate(v); 79 | l = r = nullptr; 80 | if(!v) return; 81 | if(size(v->l) < valor) 82 | { 83 | split(v->r, valor - size(v->l) - 1, v->r, r); 84 | l = v; 85 | }else 86 | { 87 | split(v->l, valor, l, v->l); 88 | r = v; 89 | } 90 | v->recalc(); 91 | } 92 | 93 | Node * root; 94 | Treap() : root(nullptr) {} 95 | ~Treap() { delete root; } 96 | 97 | void insert(int valor, int pos) 98 | { 99 | Node * l, * r; 100 | split(root, pos - 1, l, r); 101 | root = merge(merge(l, new Node(valor)), r); 102 | } 103 | 104 | void erase(int valor) 105 | { 106 | Node * l, * m, * r; 107 | split(root, valor - 1, l, m); 108 | split(m, 1, m, r); 109 | delete m; 110 | root = merge(l, r); 111 | } 112 | 113 | void reverse(int l, int r) 114 | { 115 | l--; r--; 116 | if(l > r) swap(l, r); 117 | Node *a, *b, *c, *d; 118 | split(root, l, a, d); 119 | split(d, r - l + 1, b, c); 120 | if(b) b->rev ^= 1; 121 | root = merge(a, merge(b, c)); 122 | } 123 | 124 | int query(int l, int r) 125 | { 126 | Node *a, *b, *c, *d; 127 | split(root, l - 1, a, b); 128 | split(b, r - l + 1, c, d); 129 | int ans = c->sum; 130 | root = merge(a, merge(c, d)); 131 | return ans; 132 | } 133 | 134 | /*void emOrdem(Node *node) 135 | { 136 | if(node == nullptr) return; 137 | emOrdem(node->l); 138 | printf("%d ", node->valor); 139 | emOrdem(node->r); 140 | }*/ 141 | 142 | }treap; 143 | 144 | int main() 145 | { 146 | srand(time(0)); 147 | 148 | for(int i = 1; i <= 6; i++) 149 | { 150 | int x; cin >> x; 151 | cout << x << ' '; 152 | treap.insert(x, i); 153 | } 154 | return 0; 155 | } 156 | -------------------------------------------------------------------------------- /code/data_structures/max_queue.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | struct MaxQueue 5 | { 6 | int plus = 0; 7 | deque> dq; 8 | 9 | bool empty() 10 | { 11 | return (int)dq.size() == 0; 12 | } 13 | 14 | void clear() 15 | { 16 | plus = 0; 17 | dq.clear(); 18 | } 19 | 20 | void add(int x) 21 | { // somar x em cada elemento da fila 22 | plus += x; 23 | } 24 | int max() 25 | { 26 | return dq.begin()->first + plus; 27 | } 28 | 29 | void push(int x) 30 | { 31 | x -= plus; 32 | int amt = 0; 33 | while (dq.size() and dq.back().first <= x) 34 | amt += dq.back().second + 1, dq.pop_back(); 35 | dq.push_back({ x, amt }); 36 | } 37 | 38 | void pop() 39 | { 40 | if (dq.empty()) return; 41 | if (!dq.front().second) dq.pop_front(); 42 | else dq.front().second--; 43 | } 44 | }; 45 | 46 | int main() 47 | { 48 | int n, aux; 49 | MaxQueue Q; 50 | cin >> n; 51 | for(int i = 0; i < n; i++) 52 | { 53 | int aux; 54 | cin >> aux; 55 | Q.push(aux); 56 | cout << "max " << Q.max() << '\n'; 57 | } 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /code/data_structures/merge_sort_tree.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | O nome eh Merge Sort Tree pois o array armazenado em 3 | um Node da Segment Tree eh igual ao gerado pelo algoritmo 4 | de ordenacao Merge Sort no Node correspondente da 5 | arvore de recursao. 6 | */ 7 | 8 | #include 9 | using namespace std; 10 | 11 | const int MAX = 131072; 12 | 13 | vector a[MAX], tree[MAX]; 14 | 15 | void build(int node, int start, int end) 16 | { 17 | if(start == end) 18 | tree[node] = a[start]; 19 | else 20 | { 21 | int mid = (start + end) / 2; 22 | build(2*node, start, mid); 23 | build(2*node + 1, mid + 1, end); 24 | merge(tree[2*node].begin(), tree[2*node].end(), 25 | tree[2*node + 1].begin(), tree[2*node + 1].end() 26 | , back_inserter(tree[node])); 27 | } 28 | } 29 | 30 | int query(int node, int start, int end, int l, int r, int k) 31 | { 32 | if(start > r or end < l) 33 | return 0; 34 | if(l <= start and end <= r) 35 | return upper_bound(tree[node].begin(), tree[node].end(), k) 36 | - tree[node].begin(); 37 | int mid = (start + end) / 2; 38 | int p1 = query(2*node, start, mid, l, r, k); 39 | int p2 = query(2*node + 1, mid + 1, end, l, r, k); 40 | return p1 + p2; 41 | } 42 | 43 | int main() 44 | { 45 | int n, aux; 46 | 47 | cin >> n; 48 | for(int i = 0; i < n; i++) 49 | { 50 | cin >> aux; 51 | a[i].push_back(aux); 52 | } 53 | build(1, 0, n-1); 54 | int l, r, k; 55 | cin >> l >> r >> k; 56 | //quantidade de elementos menores ou iguais a k na range [l - r]. 57 | cout << query(1, 0, n-1, l-1, r-1, k) << '\n'; 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /code/data_structures/merge_sort_tree_iterative.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define OO 0x3f3f3f3f 4 | 5 | struct MergeSortTree 6 | { 7 | int n; 8 | vector> tree; 9 | 10 | MergeSortTree(vector &a) 11 | { 12 | n = a.size(); 13 | tree.resize(n << 1); 14 | for(int i = 0; i < n; i++) 15 | tree[i + n] = vector{a[i]}; 16 | build(); 17 | } 18 | 19 | void build() 20 | { 21 | for(int i = n - 1; i > 0; --i) 22 | { 23 | int L = i << 1; 24 | int R = (i << 1) | 1; 25 | int l = 0, r = 0, sz = tree[L].size() + tree[R].size(); 26 | 27 | tree[i].resize(sz); 28 | 29 | tree[L].push_back(OO); 30 | tree[R].push_back(OO); 31 | 32 | for(int j = 0; j < sz; j++) 33 | if(tree[L][l] < tree[R][r]) 34 | tree[i][j] = tree[L][l++]; 35 | else 36 | tree[i][j] = tree[R][r++]; 37 | 38 | tree[L].pop_back(); 39 | tree[R].pop_back(); 40 | } 41 | } 42 | 43 | int queryMax(int l, int r, int x) 44 | { 45 | if(l >= r) return 0; 46 | int res = 0; 47 | for(l += n, r += n; l < r; l >>= 1, r >>= 1) 48 | { 49 | if(l & 1) 50 | { 51 | auto it = upper_bound(tree[l].begin(), tree[l].end(), x); 52 | int p = it - tree[l].begin(); 53 | if(it != tree[l].end()) 54 | { 55 | int p = it - tree[l].begin(); 56 | res += (int)tree[l].size() - p; 57 | } 58 | l++; 59 | } 60 | if(r & 1) 61 | { 62 | r--; 63 | auto it = upper_bound(tree[r].begin(), tree[r].end(), x); 64 | if(it != tree[r].end()) 65 | { 66 | int p = it - tree[r].begin(); 67 | res += (int)tree[r].size() - p; 68 | } 69 | } 70 | } 71 | return res; 72 | } 73 | 74 | int queryMin(int l, int r, int x) 75 | { 76 | if(l >= r) return 0; 77 | int res = 0; 78 | for(l += n, r += n; l < r; l >>= 1, r >>= 1) 79 | { 80 | if(l & 1) 81 | { 82 | auto it = lower_bound(tree[l].begin(), tree[l].end(), x); 83 | if(it == tree[l].end()) res += tree[l].size(); 84 | else res += it - tree[l].begin(); 85 | l++; 86 | } 87 | if(r & 1) 88 | { 89 | r--; 90 | auto it = lower_bound(tree[r].begin(), tree[r].end(), x); 91 | if(it == tree[r].end()) res += tree[r].size(); 92 | else res += it - tree[r].begin(); 93 | } 94 | } 95 | return res; 96 | } 97 | }; 98 | 99 | int32_t main() 100 | { 101 | int n; 102 | scanf(" %d", &n); 103 | vector v(n); 104 | for(int &w : v) cin >> w; 105 | MergeSortTree T(v); 106 | // query(l, r, x) [l, r) 107 | 108 | return 0; 109 | } 110 | -------------------------------------------------------------------------------- /code/data_structures/merge_sort_tree_range_order_statistics_queries.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int n; 5 | vector tree[100000]; 6 | vector> arr; 7 | 8 | void build(int node, int start, int end) 9 | { 10 | if(start == end) 11 | tree[node].push_back(arr[start].second); 12 | else 13 | { 14 | int mid = (start + end) / 2; 15 | build(2 * node, start, mid); 16 | build(2 * node + 1, mid + 1, end); 17 | merge(tree[2 * node].begin(), tree[2 * node].end(), 18 | tree[2 * node + 1].begin(), tree[2 * node + 1].end(), 19 | back_inserter(tree[node])); 20 | } 21 | } 22 | 23 | int query(int node, int start, int end, int l, int r, int k) 24 | { 25 | if(start == end) 26 | return arr[start].first; 27 | int M = upper_bound(tree[2 * node].begin(), tree[2 * node].end(), r) 28 | - lower_bound(tree[2 * node].begin(), tree[2 * node].end(), l); 29 | int mid = (start + end) / 2; 30 | if(M >= k) 31 | return query(2 * node, start, mid, l, r, k); 32 | else 33 | return query(2 * node + 1, mid + 1, end, l, r, k - M); 34 | } 35 | 36 | int main() 37 | { 38 | cin >> n; 39 | int aux; 40 | for(int i = 0; i < n; i++) 41 | { 42 | cin >> aux; 43 | arr.push_back({aux, i}); 44 | } 45 | sort(arr.begin(), arr.end()); 46 | build(1, 0, n-1); 47 | 48 | int l, r, k; 49 | while(cin >> l >> r >> k) 50 | cout << query(1, 0, n-1, l-1, r-1, k) << '\n'; 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /code/data_structures/merge_sort_tree_with_set.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | encontra o menor numero na range [L, R] que eh maior 3 | ou igual a K. build eh O(NlogNlogN) e query eh O(logNlogN) 4 | e o erasee eh O(logNlogN). 5 | */ 6 | 7 | 8 | #define ii pair 9 | #define value first 10 | #define index second 11 | const int MAX = 1e6; 12 | 13 | int n, m; 14 | vector> B, A; 15 | 16 | set tree[MAX]; 17 | 18 | void build(int node, int start, int end) 19 | { 20 | if(start == end) 21 | tree[node] = set{ii(A[start][1], start)}; 22 | else 23 | { 24 | int mid = (start + end) / 2; 25 | build(2*node, start, mid); 26 | build(2*node + 1, mid + 1, end); 27 | for(auto &it : tree[2 * node]) 28 | tree[node].insert(it); 29 | for(auto &it : tree[2 * node + 1]) 30 | tree[node].insert(it); 31 | } 32 | } 33 | 34 | ii query(int node, int start, int end, int l, int r, int k) 35 | { 36 | if(start > r or end < l) 37 | return ii(-1, -1); 38 | if(l <= start and end <= r) 39 | { 40 | auto it = tree[node].upper_bound({k, n + 1}); 41 | ii q = {-1, -1}; 42 | if(it != tree[node].begin()) q = *--it; 43 | return q; 44 | } 45 | int mid = (start + end) / 2; 46 | ii p1 = query(2 * node, start, mid, l, r, k); 47 | ii p2 = query(2 * node + 1, mid + 1, end, l, r, k); 48 | return p1.value <= p2.value ? p2 : p1; 49 | } 50 | 51 | void erasee(int node, int start, int end, ii p) 52 | { 53 | if(tree[node].count(p) == 0) return; 54 | if(start == end) 55 | { 56 | tree[node].erase(p); 57 | return; 58 | } 59 | int mid = (start + end) / 2; 60 | erasee(2 * node, start, mid, p); 61 | erasee(2 * node + 1, mid + 1, end, p); 62 | tree[node].erase(p); 63 | } 64 | -------------------------------------------------------------------------------- /code/data_structures/ordered_set_With_BIT.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int MAX = 1e5+10; 4 | 5 | int bit[MAX], arr[MAX]; 6 | 7 | int bitSearch(int v) 8 | { 9 | int sum = 0, pos = 0, LOGN = log2(MAX - 2); 10 | for(int i = LOGN; i >= 0; i--) 11 | if(pos + (1 << i) < MAX and sum + bit[pos + (1 << i)] < v) 12 | { 13 | sum += bit[pos + (1 << i)]; 14 | pos += (1 << i); 15 | } 16 | return pos + 1; 17 | // pos + 1, pq pos eh a maior posicao cuja soma do prefixo ate 18 | // ela eh menor que V 19 | } 20 | // essa funcao retorna o indice J no array em que a soma do 21 | // prefixo [1, J] eh o lower_bound para V 22 | // inserir os elemento na BIT com add(i, arr[i]), para todo i em [1, n] 23 | 24 | int query(int idx)// soma de um prefixo 25 | { 26 | int sum = 0; 27 | for(; idx > 0; idx -= idx&-idx) sum += bit[idx]; 28 | return sum; 29 | } 30 | 31 | void add(int idx, int k) 32 | { 33 | for(int i = idx; i < MAX; i += i&-i) bit[i] += k; 34 | } 35 | 36 | int smallerCount(int v) 37 | { 38 | return query(v); 39 | } 40 | 41 | int count(int v) 42 | { 43 | return query(v) - query(v - 1); 44 | } 45 | 46 | int greaterCount(int v) 47 | { 48 | return query(MAX - 3) - query(v - 1); 49 | } 50 | 51 | int orderOfKey(int v) 52 | { 53 | return smallerCount(v); 54 | } 55 | 56 | int kth(int k) 57 | { 58 | return bitSearch(k); 59 | } 60 | 61 | int main() 62 | { 63 | int n; 64 | 65 | cin >> n; 66 | for(int i = 1; i <= n; i++) 67 | { 68 | cin >> arr[i]; 69 | add(arr[i], 1); 70 | } 71 | cout << smallerCount(3) << '\n'; 72 | cout << count(3) << '\n'; 73 | cout << greaterCount(3) << '\n'; 74 | cout << kth(2) << '\n'; 75 | cout << orderOfKey(4) << '\n'; 76 | 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /code/data_structures/persistent_segment_tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int MAX = 1e5; 4 | 5 | struct Node 6 | { 7 | int l, r, value; 8 | }; 9 | 10 | vector tree; 11 | vector root; 12 | 13 | void init() 14 | { 15 | tree.emplace_back(); 16 | root.push_back(0); 17 | } 18 | 19 | void calc(int node) 20 | { 21 | tree[node].value = 0; 22 | if(tree[node].l) tree[node].value += tree[tree[node].l].value; 23 | if(tree[node].r) tree[node].value += tree[tree[node].r].value; 24 | } 25 | 26 | void update(int prev, int node, int start, int end, int idx, int value) 27 | { 28 | if(start == end) 29 | tree[node].value = value; 30 | else 31 | { 32 | int mid = (start + end) / 2; 33 | if(start <= idx and idx <= mid) 34 | { 35 | tree[node].r = tree[prev].r; 36 | if(tree[node].l == 0) 37 | { 38 | tree[node].l = tree.size(); 39 | tree.emplace_back(); 40 | } 41 | update(tree[prev].l, tree[node].l, start, mid, idx, value); 42 | } 43 | else 44 | { 45 | tree[node].l = tree[prev].l; 46 | if(tree[node].r == 0) 47 | { 48 | tree[node].r = tree.size(); 49 | tree.emplace_back(); 50 | } 51 | update(tree[prev].r, tree[node].r, mid + 1, end, idx, value); 52 | } 53 | calc(node); 54 | } 55 | } 56 | 57 | int query(int node, int start, int end, int l, int r) 58 | { 59 | if(l > end or r < start) return 0; 60 | if(l <= start and end <= r) return tree[node].value; 61 | int mid = (start + end) / 2, q1 = 0, q2 = 0; 62 | if(tree[node].l) q1 = query(tree[node].l, start, mid, l, r); 63 | if(tree[node].r) q2 = query(tree[node].r, mid + 1, end, l, r); 64 | return q1 + q2; 65 | } 66 | 67 | int main() 68 | { 69 | int n, q; 70 | 71 | cin >> n >> q; 72 | init(); 73 | while(q--) 74 | { 75 | int o, l, r; 76 | cin >> o >> l >> r; 77 | if(o == 1) 78 | { 79 | int prev = root.back(); 80 | root.push_back(tree.size()); 81 | tree.emplace_back(); 82 | update(prev, root.back(), 0, n - 1, l - 1, r); 83 | } 84 | else 85 | { 86 | int version; 87 | scanf(" %d", &version); 88 | cout << query(root[version], 0, n - 1, l - 1, r - 1) << '\n'; 89 | } 90 | } 91 | 92 | return 0; 93 | } 94 | -------------------------------------------------------------------------------- /code/data_structures/persistent_segment_tree_without_vector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #define _ << " , " << 5 | #define bug(x) cout << #x << " >>>>>>> " << x << endl; 6 | #define fastio ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0); 7 | 8 | const int MAX = 800100; 9 | const int LOG_MAX = 30; 10 | 11 | struct PersistentSegmentTree { 12 | int n; // the queries will be performed in the range [0, n - 1] 13 | int L[LOG_MAX * MAX]; // L[node] is the left child of node 14 | int R[LOG_MAX * MAX]; // R[node] is the right child of node 15 | int tree[LOG_MAX * MAX]; // tree[node] is the value stored in the node 16 | int root[MAX]; // stores the root of each version 17 | int next_vertex; // next index for a vertex 18 | int version_count; // number of different versions of the tree 19 | 20 | void calc(int node) { 21 | int sum = 0; 22 | if(L[node]) sum += tree[L[node]]; 23 | if(R[node]) sum += tree[R[node]]; 24 | tree[node] = sum; 25 | } 26 | void update(int prev, int node, int start, int end, int idx, int value) { 27 | if(start == end) 28 | tree[node] = tree[prev] + value; 29 | else { 30 | int mid = (start + end) / 2; 31 | if(start <= idx and idx <= mid) { 32 | R[node] = R[prev]; 33 | if(L[node] == 0) L[node] = next_vertex++; 34 | update(L[prev], L[node], start, mid, idx, value); 35 | } else { 36 | L[node] = L[prev]; 37 | if(R[node] == 0) R[node] = next_vertex++; 38 | update(R[prev], R[node], mid + 1, end, idx, value); 39 | } 40 | calc(node); 41 | } 42 | } 43 | int query(int node, int start, int end, int l, int r) { 44 | if(l > end or r < start) return 0; 45 | if(l <= start and end <= r) return tree[node]; 46 | int mid = (start + end) / 2, q1 = 0, q2 = 0; 47 | if(L[node]) q1 = query(L[node], start, mid, l, r); 48 | if(R[node]) q2 = query(R[node], mid + 1, end, l, r); 49 | return q1 + q2; 50 | } 51 | 52 | void init(int _n) { 53 | root[0] = 0; 54 | next_vertex = 1; 55 | version_count = 1; 56 | n = _n; 57 | } 58 | int update(int idx, int value, int prev_version = -1) { 59 | if(prev_version == -1) prev_version = version_count - 1; 60 | root[version_count] = next_vertex++; 61 | update(root[prev_version], root[version_count], 0, n - 1, idx, value); 62 | version_count++; 63 | return version_count - 1; 64 | } 65 | int query(int l, int r, int version = -1) { 66 | if(version == -1) version = version_count - 1; 67 | return query(root[version], 0, n - 1, l, r); 68 | } 69 | }; 70 | 71 | int n, q; 72 | PersistentSegmentTree PST; 73 | 74 | int32_t main() { 75 | fastio 76 | 77 | cin >> n >> q; 78 | 79 | PST.init(n); 80 | map lst; 81 | vector root(n); 82 | 83 | for(int i = 0; i < n; ++i) { 84 | int x; 85 | cin >> x; 86 | 87 | int l = -1; 88 | if(lst.count(x)) l = lst[x]; 89 | 90 | if(l != -1) PST.update(l, -1); 91 | 92 | root[i] = PST.update(i, 1); 93 | 94 | lst[x] = i; 95 | } 96 | 97 | while(q--) { 98 | int l, r; 99 | cin >> l >> r; l--; r--; 100 | cout << PST.query(l, r, root[r]) << '\n'; 101 | } 102 | 103 | return 0; 104 | } 105 | -------------------------------------------------------------------------------- /code/data_structures/segment_tree_iterative.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int MAX = 1e5 + 10; 4 | 5 | int tree[MAX << 1], n; 6 | 7 | void build() 8 | { 9 | for(int i = n - 1; i > 0; --i) tree[i] = tree[i << 1] + tree[i << 1 | 1]; 10 | } 11 | 12 | void update(int p, int value) 13 | { 14 | for(tree[p += n] = value; p > 1; p >>= 1) tree[p >> 1] = tree[p] + tree[p ^ 1]; 15 | } 16 | 17 | int query(int l, int r) 18 | { 19 | int res = 0; 20 | for(l += n, r += n; l < r; l >>= 1, r >>= 1) 21 | { 22 | if(l & 1) res += tree[l++]; 23 | if(r & 1) res += tree[--r]; 24 | } 25 | return res; 26 | } 27 | 28 | int main() 29 | { 30 | cin >> n; 31 | for(int i = 0; i < n; i++) 32 | cin >> tree[i + n]; 33 | build(); 34 | int q, l, r, o; 35 | cin >> q; 36 | while(q--) 37 | { 38 | cin >> o >> l >> r; 39 | if(o == 1) 40 | cout << query(l - 1, r) << '\n'; // soma de [l, r) 41 | else 42 | update(l - 1, r); // atualiza a posicoo l pra r 43 | } 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /code/data_structures/segment_tree_tree_2D.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int MAX = 1e3; 4 | 5 | int n, leaf; 6 | int arr[MAX][MAX]; 7 | int ST[4*MAX][4*MAX]; 8 | 9 | void buildLeaf(int k, int node, int l, int r) 10 | { 11 | if(l == r) 12 | ST[k][node] = arr[leaf][l]; 13 | else 14 | { 15 | int mid = (l + r) / 2; 16 | buildLeaf(k, 2*node, l, mid); 17 | buildLeaf(k, 2*node + 1, mid + 1, r); 18 | ST[k][node] = ST[k][2*node] + ST[k][2*node+1]; 19 | } 20 | } 21 | 22 | void build(int node, int l, int r) 23 | { 24 | if(l == r) 25 | buildLeaf(node, 1, 0, n-1), leaf++; 26 | else 27 | { 28 | int mid = (l + r) / 2; 29 | build(2*node, l, mid); 30 | build(2*node + 1, mid + 1, r); 31 | for(int i = 1; i < 4*n; i++) 32 | ST[node][i] = ST[2*node][i] + ST[2*node+1][i]; 33 | } 34 | } 35 | 36 | int queryNode(int k, int node, int l, int r, int cx, int cy) 37 | { 38 | if(l > cy or r < cx) 39 | return 0; 40 | if(cx <= l and r <= cy) 41 | return ST[k][node]; 42 | int mid = (l + r) / 2; 43 | int ans = queryNode(k, 2*node, l, mid, cx, cy); 44 | ans += queryNode(k, 2*node + 1, mid + 1, r, cx, cy); 45 | return ans; 46 | } 47 | 48 | int query(int node, int l, int r, int lx, int ly, int cx, int cy) 49 | { 50 | if(l > ly or r < lx) 51 | return 0; 52 | if(lx <= l and r <= ly) 53 | return queryNode(node, 1, 0, n-1, cx, cy); 54 | int mid = (l + r) / 2; 55 | int ans = query(2*node, l, mid, lx, ly, cx, cy); 56 | ans += query(2*node + 1, mid + 1, r, lx, ly, cx, cy); 57 | return ans; 58 | } 59 | 60 | void updateNode(int k, int node, int l, int r, int x, int y, int value) 61 | { 62 | if(l == r) 63 | ST[k][node] = arr[x][y] = value; 64 | else 65 | { 66 | int mid = (l + r) / 2; 67 | if(l <= y and y <= mid) 68 | updateNode(k, 2*node, l, mid, x, y, value); 69 | else 70 | updateNode(k, 2*node + 1, mid + 1, r, x, y, value); 71 | ST[k][node] = ST[k][2*node] + ST[k][2*node + 1]; 72 | } 73 | } 74 | 75 | void update(int node, int l, int r, int x, int y, int value) 76 | { 77 | if(l == r) 78 | updateNode(node, 1, 0, n-1, x, y, value); 79 | else 80 | { 81 | int mid = (l + r) / 2; 82 | if(l <= x and x <= mid) 83 | update(2*node, l, mid, x, y, value); 84 | else 85 | update(2*node + 1, mid + 1, r, x, y, value); 86 | for(int i = 1; i < 4*n; i++) 87 | ST[node][i] = ST[2*node][i] + ST[2*node+1][i]; 88 | } 89 | } 90 | 91 | int main() 92 | { 93 | cin >> n; 94 | for(int i = 0; i < n; i++) 95 | for(int j = 0; j < n; j++) 96 | cin >> arr[i][j]; 97 | build(1, 0, n-1); 98 | int o, a, b, c, d; 99 | while(cin >> o) 100 | { 101 | cin >> a >> b >> c; 102 | if(o == 1) 103 | update(1, 0, n-1, a-1, b-1, c); 104 | else 105 | { 106 | cin >> d; 107 | cout << query(1, 0, n-1, a-1, b-1, c-1, d-1) << '\n'; 108 | } 109 | } 110 | 111 | return 0; 112 | } 113 | -------------------------------------------------------------------------------- /code/data_structures/segment_tree_with_lazy_propagation.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #define int long long 5 | 6 | #define esq node << 1LL 7 | #define dir (node << 1) | 1LL 8 | 9 | struct SegmentTree { 10 | vector tree, lazy; 11 | int size; 12 | 13 | void build(int node, int start, int end, vector &a) { 14 | if(start == end) { 15 | tree[node] = a[start]; 16 | return; 17 | } 18 | int mid = (start + end) >> 1; 19 | build(esq, start, mid, a); 20 | build(dir, mid + 1, end, a); 21 | tree[node] = tree[esq] + tree[dir]; 22 | } 23 | 24 | SegmentTree() {} 25 | 26 | SegmentTree(int n) { 27 | size = n; 28 | tree.resize(size << 2); 29 | lazy.resize(size << 2); 30 | } 31 | 32 | void init(vector &a) { 33 | build(1, 0, size - 1, a); 34 | } 35 | 36 | // += add in the interval 37 | void push(int node, int start, int end) { 38 | tree[node] += lazy[node] * (end - start + 1); 39 | if(start != end) { 40 | lazy[esq] += lazy[node]; 41 | lazy[dir] += lazy[node]; 42 | } 43 | lazy[node] = 0; 44 | } 45 | 46 | int query(int node, int start, int end, int l, int r) { 47 | if(lazy[node]) push(node, start, end); 48 | if(l > end or start > r or l > r) return 0; 49 | if(l <= start and end <= r) return tree[node]; 50 | int mid = (start + end) >> 1; 51 | int q1 = query(esq, start, mid, l, r); 52 | int q2 = query(dir, mid + 1, end, l, r); 53 | return q1 + q2; 54 | } 55 | 56 | int query(int l, int r) { 57 | return query(1, 0, size - 1, l, r); 58 | } 59 | 60 | void update(int node, int start, int end, int l, int r, int v) { 61 | if(lazy[node]) push(node, start, end); 62 | if(l > end or start > r or l > r) return; 63 | if(l <= start and end <= r) 64 | { 65 | lazy[node] += v; 66 | push(node, start, end); 67 | return; 68 | } 69 | int mid = (start + end) >> 1; 70 | update(esq, start, mid, l, r, v); 71 | update(dir, mid + 1, end, l, r, v); 72 | tree[node] = tree[esq] + tree[dir]; 73 | } 74 | 75 | void update(int l, int r, int v) { 76 | update(1, 0, size - 1, l, r, v); 77 | } 78 | }; 79 | 80 | int32_t main() { 81 | 82 | ios_base::sync_with_stdio(false); 83 | cin.tie(nullptr); 84 | 85 | int n; 86 | cin >> n; 87 | SegmentTree T(n); 88 | 89 | return 0; 90 | } -------------------------------------------------------------------------------- /code/data_structures/sparse_table_2D.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int n, m; 5 | int M[505][505]; 6 | 7 | struct SparseTable 8 | { 9 | int SpT[9][501][9][501]; 10 | bool maxi; 11 | 12 | SparseTable(bool _maxi) 13 | { 14 | maxi = _maxi; 15 | build(); 16 | } 17 | 18 | void build() 19 | { 20 | // caso base 21 | for(int ir = 0; ir < n; ir++) 22 | { 23 | for(int ic = 0; ic < m; ic++) 24 | SpT[0][ir][0][ic] = M[ir][ic]; 25 | 26 | for(int jc = 1; (1 << jc) <= m; jc++) 27 | for(int ic = 0; ic + (1 << jc) <= m; ic++) 28 | if(maxi) 29 | SpT[0][ir][jc][ic] = max(SpT[0][ir][jc - 1][ic], 30 | SpT[0][ir][jc - 1][ic + (1 << (jc - 1))]); 31 | else 32 | SpT[0][ir][jc][ic] = min(SpT[0][ir][jc - 1][ic], 33 | SpT[0][ir][jc - 1][ic + (1 << (jc - 1))]); 34 | } 35 | 36 | // build 37 | for(int jr = 1; (1 << jr) <= n; jr++) 38 | for(int ir = 0; ir + (1 << jr) <= n; ir++) 39 | for(int jc = 0; (1 << jc) <= m; jc++) 40 | for(int ic = 0; ic + (1 << jc) <= m; ic++) 41 | if(maxi) 42 | SpT[jr][ir][jc][ic] = max( 43 | SpT[jr - 1][ir][jc][ic], 44 | SpT[jr - 1][ir + (1 << (jr - 1))][jc][ic] 45 | ); 46 | else 47 | SpT[jr][ir][jc][ic] = min( 48 | SpT[jr - 1][ir][jc][ic], 49 | SpT[jr - 1][ir + (1 << (jr - 1))][jc][ic] 50 | ); 51 | } 52 | 53 | //r1, c1 canto superior esquerdo 54 | //r2, c2 canto inferior direito 55 | int query(int r1, int c1, int r2, int c2) 56 | { 57 | int jr = (int)log2(r2 - r1 + 1); 58 | int jc = (int)log2(c2 - c1 + 1); 59 | int up, down; 60 | 61 | if(maxi) 62 | { 63 | up = max( 64 | SpT[jr][r1][jc][c1], 65 | SpT[jr][r1][jc][c2 - (1 << jc) + 1] 66 | ); 67 | down = max( 68 | SpT[jr][r2 - (1 << jr) + 1][jc][c1], 69 | SpT[jr][r2 - (1 << jr) + 1][jc][c2 - (1 << jc) + 1] 70 | ); 71 | return max(up, down); 72 | } 73 | else 74 | { 75 | up = min( 76 | SpT[jr][r1][jc][c1], 77 | SpT[jr][r1][jc][c2 - (1 << jc) + 1] 78 | ); 79 | down = max( 80 | SpT[jr][r2 - (1 << jr) + 1][jc][c1], 81 | SpT[jr][r2 - (1 << jr) + 1][jc][c2 - (1 << jc) + 1] 82 | ); 83 | return min(up, down); 84 | } 85 | } 86 | }; 87 | 88 | int32_t main() 89 | { 90 | cin >> n >> m; 91 | 92 | for(int i = 0; i < n; i++) 93 | for(int j = 0; j < m; j++) 94 | cin >> M[i][j]; 95 | 96 | SparseTable A(true); 97 | SparseTable B(false); 98 | 99 | int a, b, c, d; 100 | while(cin >> a >> b >> c >> d) 101 | cout << A.query(a, b, c, d) << ' ' << B.query(a, b, c, d) << '\n'; 102 | 103 | return 0; 104 | } -------------------------------------------------------------------------------- /code/data_structures/sparse_table_RMQ.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #define maxn 100000 3 | #define maxnlog 20 4 | 5 | using namespace std; 6 | 7 | const double EPS = 1e-6; 8 | 9 | int n, q, Sparse_Table[maxnlog][maxn]; 10 | 11 | void build() 12 | { 13 | for(int i = 1; (1 << i) <= n; i++) 14 | for(int j = 0; j + (1 << i) <= n; j++) 15 | Sparse_Table[i][j] = max(Sparse_Table[i-1][j], 16 | Sparse_Table[i-1][j+(1 << (i-1))]); 17 | } 18 | 19 | int range_query(int i, int j) 20 | { 21 | int sz = log2(j-i+1); 22 | return max(Sparse_Table[sz][i],Sparse_Table[sz][j+1-(1 << sz)]); 23 | } 24 | 25 | int main() 26 | { 27 | scanf("%d %d", &n, &q); 28 | for(int i = 0; i < n; i++) 29 | scanf("%d", &Sparse_Table[0][i]); 30 | build(); 31 | for(int i = 0; i < q ; i++) 32 | { 33 | int a, b; 34 | scanf("%d %d", &a, &b); 35 | cout << range_query(a,b) << endl; 36 | } 37 | 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /code/data_structures/treeIsomorfismWithMap.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int MAX = 1e5 + 10; 4 | 5 | int n, ID, degree[MAX]; 6 | map, int> formato; 7 | bool vis[MAX]; 8 | 9 | void init() 10 | { 11 | formato.clear(); 12 | ID = 1; 13 | } 14 | 15 | int dfs(int v, int p, vector> &G) 16 | { 17 | if((int)G[v].size() == 1) 18 | return 1; 19 | map ids; 20 | for(int &u : G[v]) 21 | { 22 | if(u == p) continue; 23 | int x = dfs(u, v, G); 24 | ids[x]++; 25 | } 26 | if(formato.count(ids) <= 0) 27 | formato[ids] = ++ID; 28 | return formato[ids]; 29 | } 30 | 31 | inline void findCenterAndComputeID(vector> &G, vector &val) 32 | { 33 | memset(vis, 0, sizeof(vis)); 34 | queue fila[2]; 35 | for(int i = 0; i < n; i++) 36 | if(degree[i] == 1) 37 | fila[0].push(i); 38 | int cnt = 0, turn = 0; 39 | while(cnt + 2 < n) 40 | { 41 | while(!fila[turn].empty()) 42 | { 43 | int u = fila[turn].front(); fila[turn].pop(); 44 | vis[u] = true; 45 | cnt++; 46 | for(int i = 0; i < G[u].size(); i++) 47 | if(!vis[G[u][i]]) 48 | { 49 | degree[G[u][i]]--; 50 | if(degree[G[u][i]] == 1) fila[1-turn].push(G[u][i]); 51 | } 52 | } 53 | turn ^= 1; 54 | } 55 | for(int i = 0; i < n; i++) 56 | { 57 | if(vis[i]) continue; 58 | val.push_back(dfs(i, -1, G)); 59 | } 60 | } 61 | 62 | int32_t main() 63 | { 64 | while(cin >> n) 65 | { 66 | init(); 67 | vector val[2]; 68 | for(int j = 0; j < 2; j++) 69 | { 70 | memset(degree, 0, sizeof(degree)); 71 | vector> G(n + 1); 72 | for(int i = 1; i < n; i++) 73 | { 74 | int u, v; 75 | scanf(" %d %d", &u, &v); u--; v--; 76 | G[u].push_back(v); 77 | G[v].push_back(u); 78 | degree[v]++; 79 | degree[u]++; 80 | } 81 | findCenterAndComputeID(G, val[j]); 82 | } 83 | bool fl = false; 84 | for(int &v0 : val[0]) 85 | for(int &v1 : val[1]) 86 | if(v0 == v1) 87 | fl = true; 88 | puts(fl ? "S" : "N"); 89 | } 90 | 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /code/data_structures/two_stacks_trick.cpp: -------------------------------------------------------------------------------- 1 | const int OO = 0x3f3f3f3f; 2 | 3 | struct Stack { 4 | vector s, smax = {-OO}, smin = {OO}; 5 | void push(int x) { 6 | s.push_back(x); 7 | smax.push_back(max(smax.back(), x)); 8 | smin.push_back(min(smin.back(), x)); 9 | } 10 | int pop() { 11 | int x = s.back(); 12 | s.pop_back(); 13 | smax.pop_back(); 14 | smin.pop_back(); 15 | return x; 16 | } 17 | int min_() { 18 | return smin.back(); 19 | } 20 | int max_() { 21 | return smax.back(); 22 | } 23 | bool empty() { 24 | return s.empty(); 25 | } 26 | }; 27 | 28 | Stack s1, s2; 29 | 30 | void push(int x) { 31 | s2.push(x); 32 | } 33 | 34 | void pop() { 35 | if(s1.empty()) { 36 | while(!s2.empty()) 37 | s1.push(s2.pop()); 38 | } 39 | s1.pop(); 40 | } 41 | 42 | int min_() { 43 | return min(s1.min_(), s2.min_()); 44 | } 45 | 46 | int max_() { 47 | return max(s1.max_(), s2.max_()); 48 | } 49 | -------------------------------------------------------------------------------- /code/data_structures/wavelet_tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 100100; 4 | const int MAX = 30 * N; 5 | // MAX = N * log(maxX - minX) 6 | // Queries in O(log(maxX - minX)) 7 | 8 | struct WaveletTree 9 | { 10 | int arr[N], aux[N]; 11 | int lo[MAX], hi[MAX]; 12 | vector freq[MAX]; 13 | int lef[MAX], rig[MAX]; 14 | int nextNode; 15 | 16 | WaveletTree(vector a, int minX, int maxX) 17 | { 18 | int sz = a.size(); 19 | for(int i = 0; i < sz; i++) 20 | arr[i] = a[i]; 21 | nextNode = 1; 22 | build(0, 0, sz, minX, maxX); 23 | } 24 | 25 | int stable_partition(int s, int e, int mid) 26 | { 27 | int pivot = 0; 28 | for(int i = s; i < e; i++) 29 | aux[i] = arr[i], pivot += (arr[i] <= mid); 30 | int l = s, r = s + pivot; 31 | for(int i = s; i < e; i++) 32 | if(aux[i] <= mid) 33 | arr[l++] = aux[i]; 34 | else 35 | arr[r++] = aux[i]; 36 | return l; 37 | } 38 | 39 | void build(int node, int s, int e, int minX, int maxX) 40 | { 41 | lo[node] = minX, hi[node] = maxX; 42 | if(lo[node] == hi[node] or s >= e) return; 43 | 44 | int mid = (minX + maxX - 1) / 2; 45 | 46 | freq[node].resize(e - s + 1); 47 | freq[node][0] = 0; 48 | 49 | for(int i = s; i < e; i++) 50 | freq[node][i - s + 1] = freq[node][i - s] + (arr[i] <= mid); 51 | 52 | int pivot = stable_partition(s, e, mid); 53 | 54 | lef[node] = nextNode++, rig[node] = nextNode++; 55 | 56 | build(lef[node], s, pivot, minX, mid); 57 | build(rig[node], pivot, e, mid + 1, maxX); 58 | } 59 | 60 | int went_right(int node, int i) 61 | { 62 | return i - freq[node][i]; 63 | } 64 | 65 | // less than ou equal to x in range [l, r] 66 | int lte(int l, int r, int x, int node = 0) 67 | { 68 | if(l > r or x < lo[node]) return 0; 69 | if(hi[node] <= x) return r - l + 1; 70 | 71 | int l1 = freq[node][l - 1] + 1, r1 = freq[node][r]; 72 | int l2 = went_right(node, l - 1) + 1, r2 = went_right(node, r); 73 | 74 | return lte(l1, r1, x, lef[node]) + lte(l2, r2, x, rig[node]); 75 | } 76 | 77 | // greater than ou equal to x in range [l, r] 78 | int gte(int l, int r, int x, int node = 0) 79 | { 80 | if(l > r or x > hi[node]) return 0; 81 | if(lo[node] >= x) return r - l + 1; 82 | 83 | int l1 = freq[node][l - 1] + 1, r1 = freq[node][r]; 84 | int l2 = went_right(node, l - 1) + 1, r2 = went_right(node, r); 85 | 86 | return gte(l1, r1, x, lef[node]) + gte(l2, r2, x, rig[node]); 87 | } 88 | 89 | // counting numbers equal to x in range [l, r] 90 | int count(int l, int r, int x, int node = 0) 91 | { 92 | if(l > r or lo[node] > x or hi[node] < x) return 0; 93 | 94 | if(lo[node] == hi[node] and lo[node] == x) return r - l + 1; 95 | 96 | int l1 = freq[node][l - 1] + 1, r1 = freq[node][r]; 97 | int l2 = went_right(node, l - 1) + 1, r2 = went_right(node, r); 98 | 99 | return count(l1, r1, x, lef[node]) + count(l2, r2, x, rig[node]); 100 | } 101 | 102 | // find kth number in range [l, r] 103 | int kth(int l, int r, int k, int node = 0) 104 | { 105 | if(l > r) return 0; 106 | if(lo[node] == hi[node]) return lo[node]; 107 | 108 | int inLeft = freq[node][r] - freq[node][l - 1]; 109 | int l1 = freq[node][l - 1] + 1, r1 = freq[node][r]; 110 | 111 | if(k <= inLeft) return kth(l1, r1, k, lef[node]); 112 | 113 | int l2 = went_right(node, l - 1) + 1, r2 = went_right(node, r); 114 | 115 | return kth(l2, r2, k - inLeft, rig[node]); 116 | } 117 | }; 118 | 119 | int main() 120 | { 121 | vector a = {2, 5, 3, 2, 4, 2}; 122 | 123 | WaveletTree T(a, 0, 9); 124 | 125 | cout << T.lte(3, 5, 3) << '\n'; 126 | cout << T.gte(3, 5, 3) << '\n'; 127 | cout << T.count(1, 6, 2) << '\n'; 128 | cout << T.kth(1, 6, 5) << '\n'; 129 | 130 | return 0; 131 | } 132 | -------------------------------------------------------------------------------- /code/dynamic_programming/Knapsack0-kSemValor.cpp: -------------------------------------------------------------------------------- 1 | // Knapsack 0 - k sem valor em O((N*W*LogK) / word) 2 | 3 | #include 4 | using namespace std; 5 | 6 | int n, W, weight[10000], K[10000]; 7 | bitset<10000> T[100]; 8 | 9 | bool knapsack() 10 | { 11 | T[0][0] = 1; 12 | for(int i = 1; i <= n; i++) 13 | { 14 | int s = K[i - 1]; 15 | T[i] = T[i - 1]; 16 | for(int p = 1; p <= s; s -= p, p *= 2) 17 | T[i] |= ((T[i] << (weight[i - 1] * p)) | T[i]); 18 | if(s) 19 | T[i] |= ((T[i] << (weight[i - 1] * s)) | T[i]); 20 | } 21 | return T[n][W]; 22 | } 23 | 24 | void retrieve() 25 | { 26 | vector> ans; 27 | for(int i = n; i > 0; i--) 28 | { 29 | int s = K[i - 1], qtd = 0; 30 | for(int p = 1; p <= s; p *= 2) 31 | if(W >= weight[i - 1] * p and T[i - 1][W - weight[i - 1] * p]) 32 | W -= weight[i - 1] * p, qtd += p, s -= p; 33 | if(W >= weight[i - 1] * s and T[i - 1][W - weight[i - 1] * s]) 34 | W -= s * weight[i - 1], qtd += s; 35 | if(qtd) ans.push_back({qtd, i - 1}); 36 | }//first eh q quantidade de pesos i - 1 37 | for(pair &w : ans) 38 | cout << w.first << ' ' << weight[w.second] << '\n'; 39 | } 40 | 41 | int main() 42 | { 43 | cin >> n; 44 | for(int i = 0; i < n; i++) 45 | cin >> weight[i]; 46 | for(int i = 0; i < n; i++) 47 | cin >> K[i]; 48 | cin >> W; 49 | cout << (knapsack() ? "possible\n" : "impossible\n"); 50 | retrieve(); 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /code/dynamic_programming/KnapsackWithCopies.cpp: -------------------------------------------------------------------------------- 1 | // O( S * sqrt( SumKi ) ) 2 | 3 | #include 4 | using namespace std; 5 | const int OO = 0x3f3f3f3f; 6 | 7 | int freq[50]; 8 | vector value, weight; 9 | int memo[5000][5000]; 10 | 11 | // Decompor o numero em uma soma de potencias 12 | //de 2 de tal forma que qualquer numero entre 0 e k 13 | // pode ser formado usando os numeros da decomposicao. 14 | void decomp(int k, int w, int v) 15 | { 16 | int i = 1; 17 | freq[1] = k; 18 | while(true) 19 | { 20 | int m = (freq[i] - 1) / 2; 21 | if(freq[i] - m * 2 == 0) break; 22 | freq[i] -= 2 * m; 23 | freq[2 * i] += m; 24 | i++; 25 | } 26 | for(int i = 0; i < 32; i++) 27 | { 28 | while(freq[i]--) 29 | { 30 | value.push_back(i * v); 31 | weight.push_back(i * w); 32 | } 33 | freq[i] = 0; 34 | } 35 | } 36 | 37 | int solve(int id, int W) 38 | { 39 | if(memo[id][W] != -1) 40 | return memo[id][W]; 41 | if(id == value.size() or !W) 42 | return memo[id][W] = 0; 43 | int ans = 0; 44 | if(weight[id] > W) 45 | ans = solve(id + 1, W); 46 | else 47 | ans = max(value[id] + solve(id + 1, W 48 | - weight[id]), solve(id + 1, W)); 49 | return memo[id][W] = ans; 50 | } 51 | 52 | int main() 53 | { 54 | int n, w, v, k, S; 55 | memset(memo, -1, sizeof(memo)); 56 | cin >> n >> S; 57 | for(int i = 0; i < n; i++) 58 | { 59 | cin >> v >> w >> k; 60 | decomp(k, w, v); 61 | } 62 | cout << solve(0, S) << '\n'; 63 | 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /code/dynamic_programming/KnapsackwithPDtopdown.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int n, W, weight[2005], value[2005]; 5 | int memo[2005][2005]; 6 | 7 | int solve(int id, int W) 8 | { 9 | if(memo[id][W] != -1) 10 | return memo[id][W]; 11 | if(id == n or !W) 12 | return memo[id][W] = 0; 13 | int ans = 0; 14 | if(weight[id] > W) 15 | ans = solve(id + 1, W); 16 | else 17 | ans = max(value[id] + solve(id + 1, 18 | W - weight[id]), solve(id + 1, W)); 19 | return memo[id][W] = ans; 20 | } 21 | 22 | void ans(int id, int W) 23 | { 24 | if(id == n or !W) 25 | return; 26 | if(solve(id + 1, W) == memo[id][W]) 27 | ans(id + 1, W); 28 | else 29 | { 30 | cout << id << ' '; 31 | ans(id + 1, W - weight[id]); 32 | } 33 | } 34 | 35 | int main() 36 | { 37 | memset(memo, -1, sizeof(memo)); 38 | cin >> n >> W; 39 | for(int i = 0; i < n; i++) 40 | cin >> weight[i] >> value[i]; 41 | cout << solve(0, W) << '\n'; 42 | cout << "Objetos escolhidos 0 - indexdos\n"; 43 | ans(0, W); 44 | puts(""); 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /code/dynamic_programming/coin_problem_topdown_dp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | using namespace std; 4 | 5 | vector coin; 6 | int memo[1000000]; 7 | 8 | int solve(int troco) 9 | { 10 | if(troco < 0) 11 | return (1 << 25); 12 | if(memo[troco] != -1) 13 | return memo[troco]; 14 | if(troco == 0) 15 | return 0; 16 | int ans = (1 << 25); 17 | for(int i = 0; i < coin.size(); i++) 18 | ans = min(ans, 1 + solve(troco - coin[i])); 19 | return memo[troco] = ans; 20 | } 21 | 22 | void ans(int troco) 23 | { 24 | if(troco < 0) 25 | return; 26 | if(troco == 0) 27 | return; 28 | for(int i = 0; i < coin.size(); i++) 29 | if(solve(troco - coin[i]) + 1 == memo[troco]) 30 | { 31 | cout << coin[i] << ' '; 32 | ans(troco - coin[i]); 33 | break; 34 | } 35 | } 36 | 37 | int main() 38 | { 39 | memset(memo, -1, sizeof(memo)); 40 | int n, troco; 41 | cin >> n >> troco; 42 | coin.resize(n); 43 | for(int &w : coin) 44 | cin >> w; 45 | cout << solve(troco) << '\n'; 46 | ans(troco); 47 | puts(""); 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /code/dynamic_programming/digit_DP_sum_of_digits_in_range.cpp: -------------------------------------------------------------------------------- 1 | #include "bits/stdc++.h" 2 | using namespace std; 3 | 4 | int dp[20][200][2]; 5 | 6 | int digitDP(int idx, int sum, int can, vector &digit) 7 | {// idx eh o indice atual, sum a soma dos digitos ate idx, 8 | //e can uma flag para indicar se pode colocar 9 | //qualquer valor a partir daqui 10 | if(idx == (int)digit.size()) 11 | return sum; 12 | if(dp[idx][sum][can] != -1) 13 | return dp[idx][sum][can]; 14 | int ans = 0; 15 | for(int i = 0; i < 10; i++) 16 | if(can or i <= digit[idx]) 17 | ans += digitDP(idx + 1, sum + i, 18 | can or i < digit[idx], digit); 19 | return dp[idx][sum][can] = ans; 20 | } 21 | 22 | int query(int x) // responde a consulta de 0 ate x 23 | { 24 | memset(dp, -1, sizeof(dp)); 25 | vector digit; 26 | while(x) 27 | { 28 | digit.push_back(x%10); 29 | x /= 10; 30 | } 31 | reverse(digit.begin(), digit.end()); 32 | return digitDP(0, 0, 0, digit); 33 | } 34 | 35 | int main() 36 | { 37 | int q, a, b; 38 | cin >> q; 39 | while(q--) 40 | { 41 | cin >> a >> b; 42 | cout << query(b) - query(a - 1) << '\n'; 43 | } 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /code/dynamic_programming/edit_distance_with_DP.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | string a, b; 5 | int PD[2008][2008]; 6 | 7 | int solve(int i, int j) 8 | { 9 | if(!i) return j; 10 | if(!j) return i; 11 | if(PD[i][j] != -1) 12 | return PD[i][j]; 13 | // substituir um caracter se for preciso 14 | int ans1 = solve(i - 1, j - 1) + (a[i] != b[j]); 15 | //apagar o caracter da string i 16 | int ans2 = solve(i - 1, j) + 1; 17 | //apagar o caracter da string j 18 | int ans3 = solve(i, j - 1) + 1; 19 | return PD[i][j] = min(ans1, min(ans2, ans3)); 20 | } 21 | 22 | int main() 23 | { 24 | int q; 25 | cin >> q; 26 | while(q--) 27 | { 28 | memset(PD, -1, sizeof(PD)); 29 | cin >> a >> b; 30 | a = "#" + a; 31 | b = "#" + b; 32 | cout << solve(a.size()-1, b.size()-1) << '\n'; 33 | } 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /code/dynamic_programming/kadane_2D.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int pd[100][100], A[100][100]; 5 | 6 | int main() 7 | { 8 | int n, m; 9 | cin >> n >> m; 10 | for(int i = 1; i <= n; i++) 11 | for(int j = 1; j <= m; j++) 12 | cin >> A[i][j], pd[i][j] = pd[i][j - 1] + A[i][j]; 13 | int ans = 0; 14 | for(int i = 1; i <= n; i++) 15 | for(int j = i + 1; j <= m; j++) 16 | { 17 | int sum = 0; 18 | for(int k = 1; k <= n; k++) 19 | { 20 | sum += pd[k][j] - pd[k][i - 1]; 21 | if(sum < 0) sum = 0; 22 | ans = max(ans, sum); 23 | } 24 | } 25 | cout << ans << '\n'; 26 | 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /code/dynamic_programming/kadane_3D.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int A, B, C; 5 | int par[22][22][22], pd[22][22][22]; 6 | 7 | int main() 8 | { 9 | cin >> A >> B >> C; 10 | for(int i = 1; i <= A; i++) 11 | for(int j = 1; j <= B; j++) 12 | for(int k = 1; k <= C; k++) 13 | cin >> par[i][j][k]; 14 | 15 | for(int i = 1; i <= A; i++) 16 | for(int j = 1; j <= B; j++) 17 | for(int k = 1; k <= C; k++) 18 | pd[i][j][k] = pd[i][j - 1][k] + pd[i][j][k - 1] 19 | - pd[i][j - 1][k - 1] + par[i][j][k]; 20 | 21 | int ans = -(1 << 25); 22 | for(int h1 = 1; h1 <= C; h1++) 23 | for(int h2 = h1; h2 <= C; h2++) 24 | for(int l1 = 1; l1 <= B; l1++) 25 | for(int l2 = l1; l2 <= B; l2++) 26 | { 27 | int sum = -(1 << 25); 28 | for(int i = 1; i <= A; i++) 29 | { 30 | int s = pd[i][l2][h2] - pd[i][l1 - 1][h2] 31 | - pd[i][l2][h1 - 1] + pd[i][l1 - 1][h1 - 1]; 32 | sum = max(sum + s, s); 33 | ans = max(ans, sum); 34 | } 35 | } 36 | cout << ans << '\n'; 37 | 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /code/dynamic_programming/knapsackErrichto.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define int long long 4 | const int OO = 0x3f3f3f3f3f3f3f3f; 5 | 6 | int n, w, maxi; 7 | int value[120], weight[120]; 8 | int dp[100040]; 9 | 10 | int32_t main() 11 | { 12 | cin >> n >> w; 13 | for(int i = 0; i < n; i++) 14 | cin >> weight[i] >> value[i]; 15 | // dp[i] = maximum total value of itens with total weight exactly 16 | for(int item = 0; item < n; item++) 17 | for(int cur_wei = w - weight[item]; cur_wei >= 0; cur_wei--) 18 | dp[cur_wei + weight[item]] = max(dp[cur_wei + weight[item]], 19 | dp[cur_wei] + value[item]); 20 | cout << *max_element(dp, dp + w + 1) << '\n'; 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /code/dynamic_programming/knapsack_with_copies_sqrtN_memory.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define bug(x) cout << #x << " >>>>>>> " << x << '\n' 4 | #define _ << " , " << 5 | //#define int long long 6 | #define Max(a, b) (a > b ? a : b) 7 | #define Min(a, b) (a < b ? a : b) 8 | #define ii pair 9 | #define fi first 10 | #define se second 11 | #define UNTIL(t) while (clock() < (t) * CLOCKS_PER_SEC) 12 | const int MAX = 20002; //2 * 10^5 13 | const int MOD = 1000000007; //10^9 + 7 14 | const int OO = 0x3f3f3f3f; // 0x3f3f3f3f; 15 | const double EPS = 1e-9; //10^-9 16 | mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); 17 | 18 | int n, S; 19 | int B[205]; 20 | int C[205]; 21 | int V[3500]; 22 | int W[3500]; 23 | int ID[3500]; 24 | int id = 1; 25 | int dp[MAX]; 26 | int linha[70][MAX], T[70][MAX]; 27 | int L[70]; 28 | 29 | void add(int j) 30 | { 31 | int sum = 0; 32 | for(int k = 0; sum + (1 << k) <= C[j]; sum += (1 << k), k++) 33 | { 34 | V[id] = B[j] * (1 << k); 35 | W[id] = (1 << k); 36 | ID[id] = j; 37 | id++; 38 | } 39 | int r = C[j] - sum; 40 | if(r > 0) 41 | { 42 | V[id] = B[j] * r; 43 | W[id] = r; 44 | ID[id] = j; 45 | id++; 46 | } 47 | } 48 | 49 | int32_t main() 50 | { 51 | cin >> n; 52 | for(int i = 1; i <= n; i++) cin >> B[i]; 53 | for(int i = 1; i <= n; i++) cin >> C[i]; 54 | for(int i = 1; i <= n; i++) add(i); 55 | cin >> S; 56 | 57 | for(int j = 1; j <= S; j++) 58 | dp[j] = OO; 59 | 60 | int cnt = 0, k = -1, sq = max(10, (int)sqrt(id * 1.)); 61 | for(int i = 1; i < id; i++) 62 | { 63 | if(cnt % sq == 0) 64 | { 65 | cnt = 0; 66 | k++; 67 | for(int j = 0; j <= S; j++) 68 | linha[k][j] = dp[j]; 69 | L[k] = i - 1; 70 | } 71 | for(int j = S; j >= V[i]; j--) 72 | dp[j] = Min(dp[j - V[i]] + W[i], dp[j]); 73 | cnt++; 74 | } 75 | 76 | int last_raw = id - 1, s = S; 77 | 78 | vector note(n + 1); 79 | 80 | while(last_raw >= 1) 81 | { 82 | int first_raw = last_raw - 1; 83 | while(first_raw > L[k]) 84 | first_raw--; 85 | 86 | for(int j = 0; j <= S; j++) 87 | T[0][j] = linha[k][j]; 88 | 89 | for(int i = 1; i <= last_raw - first_raw; i++) 90 | for(int j = 0; j <= S; j++) 91 | if(j >= V[i + first_raw]) 92 | T[i][j] = Min(T[i - 1][j], T[i - 1][j - V[i + first_raw]] + W[i + first_raw]); 93 | else 94 | T[i][j] = T[i - 1][j]; 95 | 96 | for(int i = last_raw - first_raw; i > 0; i--) 97 | if(T[i][s] != T[i - 1][s]) 98 | { 99 | note[ID[i + first_raw]] += W[i + first_raw]; 100 | s -= V[i + first_raw]; 101 | } 102 | 103 | last_raw = first_raw; 104 | k--; 105 | } 106 | 107 | int number_of_notes = 0; 108 | for(int &w : note) 109 | number_of_notes += w; 110 | 111 | cout << number_of_notes << '\n'; 112 | 113 | for(int i = 1; i <= n; i++) 114 | cout << note[i] << ' '; 115 | puts(""); 116 | 117 | 118 | return 0; 119 | } 120 | -------------------------------------------------------------------------------- /code/dynamic_programming/knapsack_with_repetition_recurrence.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #define Max(a, b) (a > b ? a : b) 5 | #define Min(a, b) (a < b ? a : b) 6 | #define ii pair 7 | #define fi first 8 | #define se second 9 | 10 | const int OO = 0x3f3f3f3f; 11 | 12 | void solve(){ 13 | int n, s; 14 | cin >> n >> s; 15 | vector items; 16 | for(int i = 0; i < n; ++i) { 17 | int w, c; 18 | cin >> w >> c; 19 | items.push_back({w, c}); 20 | } 21 | sort(items.begin(), items.end()); 22 | 23 | vector maxi(n); 24 | for(int i = 0; i < n; ++i) 25 | if(i) maxi[i] = Max(maxi[i - 1], items[i].se); 26 | else maxi[i] = items[i].se; 27 | 28 | int l = s, r = s; 29 | vector states = {s}; 30 | for(int i = 0; i < 36; ++i) { 31 | l = (l / 2) - 505; 32 | r = (r / 2) + 505; 33 | for(int j = Max(l, 1); j <= Min(r, s); ++j) 34 | states.push_back(j); 35 | } 36 | 37 | sort(states.begin(), states.end()); 38 | states.resize(unique(states.begin(), states.end()) - states.begin()); 39 | 40 | unordered_map dp; 41 | 42 | for(int &w : states) { 43 | long long ans = 0; 44 | auto it = upper_bound(items.begin(), items.end(), ii(w, OO)); 45 | if(it != items.begin()) { 46 | it--; 47 | int p = it - items.begin(); 48 | ans = maxi[p]; 49 | } 50 | 51 | l = Max((w / 2) - 505, 1); 52 | r = Min((w / 2) + 505, s); 53 | 54 | for(int j = l; j <= r; ++j) 55 | ans = Max(ans, dp[j] + dp[w - j]); 56 | 57 | dp[w] = ans; 58 | } 59 | 60 | cout << dp[s] << '\n'; 61 | } 62 | 63 | int32_t main() { 64 | solve(); 65 | return 0; 66 | } -------------------------------------------------------------------------------- /code/dynamic_programming/knapsack_zero_one_without_value.cpp: -------------------------------------------------------------------------------- 1 | // Knapsack 0 - 1 sem valor em O((N*W) / word) 2 | #include 3 | using namespace std; 4 | 5 | int n, W, weight[10000]; 6 | bitset<10000> T[100]; 7 | 8 | bool knapsack() 9 | { 10 | T[0][0] = 1; 11 | for(int i = 1; i <= n; i++) 12 | T[i] = ((T[i - 1] << weight[i - 1]) | T[i - 1]); 13 | return T[n][W]; 14 | } 15 | 16 | void retrieve() 17 | { 18 | vector ans; 19 | for(int i = n; i > 0; i--) 20 | if(W >= weight[i - 1] and T[i - 1][W - weight[i - 1]]) 21 | { 22 | ans.push_back(i - 1); 23 | W -= weight[i - 1]; 24 | } 25 | for(int &w : ans) cout << weight[w] << ' '; puts(""); 26 | } 27 | 28 | int main() 29 | { 30 | cin >> n; 31 | for(int i = 0; i < n; i++) 32 | cin >> weight[i]; 33 | cin >> W; 34 | cout << knapsack() << '\n'; 35 | retrieve(); 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /code/dynamic_programming/longest_common_subsequece_and_edit_distance.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // longest common substring 5 | 6 | int pd[1000][1000]; 7 | 8 | int LCS(string a, string b) 9 | { 10 | for(int i = 1; i <= a.size(); i++) 11 | for(int j = 1; j <= b.size(); j++) 12 | if(a[i-1] == b[j-1]) 13 | pd[i][j] = pd[i-1][j-1] + 1; 14 | else 15 | pd[i][j] = max(pd[i][j-1], pd[i-1][j]); 16 | return pd[a.size()][b.size()]; 17 | } 18 | 19 | int main() 20 | { 21 | string a, b; 22 | 23 | cin >> a >> b; 24 | int lcs = LCS(a, b); 25 | 26 | cout << lcs << '\n'; 27 | cout << "Edit Distance: " << a.size()+b.size()-2*lcs << '\n'; 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /code/dynamic_programming/longest_increasing_subsequence.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | void lis(vector &arr) 5 | { 6 | vector pilha; 7 | int pai[1000], pos[1000]; 8 | for(int i = 0; i < arr.size(); i++) 9 | { 10 | int p = int(upper_bound(pilha.begin(), 11 | pilha.end(), arr[i]) - pilha.begin()); 12 | if(p == pilha.size()) 13 | pilha.push_back(arr[i]); 14 | else 15 | pilha[p] = arr[i]; 16 | pos[p] = i; 17 | if(!p) 18 | pai[i] = -1; 19 | else 20 | pai[i] = pos[p - 1]; 21 | } 22 | vector L; 23 | int aux = pos[pilha.size() - 1]; 24 | cout << pilha.size() << '\n'; 25 | while(aux != -1) 26 | { 27 | L.push_back(arr[aux]); 28 | aux = pai[aux]; 29 | } 30 | reverse(L.begin(), L.end()); 31 | for(const int &w : L) 32 | cout << w << ' '; 33 | cout << '\n'; 34 | } 35 | 36 | int main() 37 | { 38 | int n; 39 | cin >> n; 40 | vector arr(n); 41 | for(int &w : arr) 42 | cin >> w; 43 | lis(arr); 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /code/dynamic_programming/subset_sum.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int MAX = 1e6 + 10; 5 | 6 | int n, x, weight[1005]; 7 | bool pd[MAX]; 8 | int ans[MAX]; 9 | 10 | void printAns(int m) 11 | { 12 | cout << ans[m] << ' '; 13 | if(m - ans[m] > 0) 14 | printAns(m - ans[m]); 15 | } 16 | 17 | int main() 18 | { 19 | cin >> n >> x; 20 | int sum = 0; 21 | for(int i = 0; i < n; i++) cin >> weight[i], sum += weight[i]; 22 | pd[0] = 1; 23 | for(int j = 0; j < n; j++) 24 | for(int i = sum; i >= 0; i--) 25 | if(pd[i] and !pd[i + weight[j]]) 26 | { 27 | ans[i + weight[j]] = weight[j]; 28 | pd[i + weight[j]] = 1; 29 | } 30 | 31 | printAns(x); 32 | puts(""); 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /code/dynamic_programming/traveling_salesman_problem_bottom_up_dp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int OO = 0x3f3f3f3f; 4 | 5 | int n; 6 | double dist[20][20]; 7 | double pd[1 << 17][20]; 8 | 9 | int tsp(int ori) 10 | { 11 | memset(pd, 63, sizeof(pd)); 12 | for(int i = 0; i < n; i++) 13 | if(i != ori) 14 | pd[1 << i][i] = dist[ori][i]; 15 | for(int k = 0; k < (1 << n); k++) 16 | for(int i = 0; i < n; i++) 17 | if(k & (1 << i)) 18 | for(int j = 0; j < n; j++) 19 | if((k & (1 << j)) and i != j) 20 | pd[k][j] = min(pd[k][j], pd[k ^ (1 << j)][i] + dist[i][j]); 21 | return pd[(1 << n) - 1][ori]; 22 | } 23 | 24 | int main() 25 | { 26 | // inicializar dist, dist[i][j] guarda a distancia de i para j no grafo 27 | // chamar tsp 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /code/dynamic_programming/traveling_salesman_problem_topdown_dp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int dist[22][22], m; 5 | int memo[20][1 << 20]; 6 | 7 | int solve(int id, int mask) { 8 | if(((1 << m) - 1) == mask) 9 | return dist[id][0]; 10 | if(memo[id][mask] != -1) 11 | return memo[id][mask]; 12 | int ans = INT_MAX; 13 | for(int i = 0; i < m; i++) 14 | if((mask & (1 << i)) == 0) 15 | ans = min(ans, dist[id][i] + solve(i, mask | (1 << i))); 16 | return memo[id][mask] = ans; 17 | } 18 | 19 | int main() { 20 | memset(memo, -1, sizeof(memo)); 21 | //inicializa a matriz dist com as distancias 22 | //de todo mundo pra todo mundo.. 23 | cout << solve(0, 1) << '\n'; 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /code/geometry/andrew_algorithm_convex_hull.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define X first 4 | #define Y second 5 | typedef pair ii; 6 | 7 | int cross(ii O, ii A, ii B) 8 | { 9 | return (((A.X - O.X) * (B.Y - O.Y)) - ((A.Y - O.Y) * (B.X - O.X))); 10 | } 11 | 12 | vector ConvexHull(vector P) 13 | { 14 | if(P.size() <= 1) return P; 15 | vector H(2*P.size()); 16 | int k = 0; 17 | sort(P.begin(), P.end()); 18 | //lower hull 19 | for(int i = 0; i < P.size(); i++) 20 | { 21 | while(k >= 2 and cross(H[k-2], H[k-1], P[i]) < 0) k--; 22 | H[k++] = P[i]; 23 | } 24 | //upper hull 25 | for(int i = P.size()-2, l = k + 1; i >= 0; i--) 26 | { 27 | while(k >= l and cross(H[k-2], H[k-1], P[i]) < 0) k--; 28 | H[k++] = P[i]; 29 | } 30 | H.resize(k-1); 31 | return H; 32 | } 33 | 34 | int main() 35 | { 36 | int n, x, y; 37 | vector P; 38 | 39 | cin >> n; 40 | while(n--) 41 | { 42 | cin >> x >> y; 43 | P.push_back({x, y}); 44 | } 45 | 46 | vector H = ConvexHull(P); 47 | 48 | for(int i = 0; i < H.size(); i++) 49 | cout << H[i].X << ' ' << H[i].Y << '\n'; 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /code/geometry/build_two_lines_that_go_through_all_points_of_a_set.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int MAX = 1e6 + 10; 5 | typedef long long ll; 6 | 7 | struct Point 8 | { 9 | ll x, y; 10 | Point(ll _x, ll _y) : x(_x), y(_y) {} 11 | Point() {} 12 | Point operator-(const Point& p) 13 | { 14 | return Point(x - p.x, y - p.y); 15 | } 16 | ll operator*(const Point& p) 17 | { 18 | return (x * p.y) - (y * p.x); 19 | } 20 | }; 21 | 22 | int n; 23 | int visit[MAX]; 24 | Point point[MAX]; 25 | 26 | bool inLine(int a, int b, int c) 27 | { 28 | return ((point[a] - point[c]) * (point[b] - point[c])) == 0LL; 29 | } 30 | 31 | bool check(int a, int b)// traca a reta AB e verifica se todos os 32 | //pontos que nao estao em AB estao contidos em uma mesma reta 33 | { 34 | memset(visit, 0, sizeof(visit)); 35 | visit[a] = visit[b] = 1; 36 | for(int i = 0; i < n; i++) 37 | if(!visit[i] and inLine(a, b, i)) 38 | visit[i] = 1;// marco todos os pontos que estao na reta AB 39 | vector c; 40 | for(int i = 0; i < n and c.size() < 2; i++) 41 | if(!visit[i]) 42 | c.push_back(i);// procuro dois pontos que nao estao na reta AB 43 | if(c.size() < 2) return true; 44 | visit[c[0]] = visit[c[1]] = 1; 45 | for(int i = 0; i < n; i++) 46 | if(!visit[i]) 47 | { // checo se o ponto que nao esta na reta AB esta na reta C0C1 48 | if(inLine(c[0], c[1], i)) 49 | visit[i] = 1; 50 | else 51 | return false; 52 | } 53 | return true; 54 | } 55 | 56 | int main() 57 | { 58 | cin >> n; 59 | for(int i = 0; i < n; i++) 60 | cin >> point[i].x >> point[i].y; 61 | if(n <= 2) return cout << "YES\n", 0; 62 | int k = 2; 63 | while(k < n and inLine(0, 1, k)) k++; 64 | if(k == n) return cout << "YES\n", 0; 65 | cout << ((check(0, 1) or check(0, k) 66 | or check(1, k)) ? "YES\n" : "NO\n"); 67 | 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /code/geometry/check_if_a_point_is_inside_a_convex_polygon.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define int long long 4 | #define ii pair 5 | #define fi first 6 | #define se second 7 | 8 | int n; 9 | vector P; 10 | 11 | ii operator-(ii a, ii b) 12 | { 13 | return {a.fi - b.fi, a.se - b.se}; 14 | } 15 | 16 | int operator*(ii a, ii b) 17 | { 18 | return a.fi * b.se - a.se * b.fi; 19 | } 20 | 21 | void setFirstPoint() 22 | { 23 | int pos = 0; 24 | for(int i = 0; i < n; i++) 25 | if(P[i].fi < P[pos].fi or P[i].fi == P[pos].fi and P[i].se < P[pos].se) 26 | pos = i; 27 | rotate(P.begin(), P.begin() + pos, P.end()); 28 | } 29 | 30 | bool pointInTriangle(ii a, ii b, ii c, ii p) 31 | { 32 | int s1 = abs((a - c) * (b - c)); 33 | int s2 = abs((a - p) * (b - p)) + abs((b - p) * (c - p)) + 34 | abs((c - p) * (a - p)); 35 | return s1 == s2;//mesma area 36 | } 37 | 38 | int dist(ii a, ii b) 39 | { 40 | return (a.fi - b.fi) * (a.fi - b.fi) + (a.se - b.se) * (a.se - b.se); 41 | } 42 | 43 | // O(logN) per query 44 | bool pointInConvexPolygon(ii p) 45 | { 46 | //adicionar = desconsidera pontos na borda 47 | if((P[1] - P[0]) * (p - P[0]) < 0) 48 | return false; 49 | //adicionar = desconsidera pontos na borda 50 | if((p - P[0]) * (P[n - 1] - P[0]) < 0) 51 | return false; 52 | //o ponto esta em cima do segento P[0], P[n-1] 53 | if((p - P[0]) * (P[n - 1] - P[0]) == 0) 54 | return dist(P[0], p) <= dist(P[0], P[n - 1]) and dist(P[n - 1], p) <= dist(P[0], P[n - 1]); 55 | //o ponto esta em cima do segento P[0], P[1] 56 | if((P[1] - P[0]) * (p - P[0]) == 0) 57 | return dist(P[0], p) <= dist(P[0], P[1]) and dist(P[1], p) <= dist(P[0], P[1]); 58 | // se o ponto esta entre os segmentos P[0], P[n] 59 | int l = 0, e = n - 1, ans = 0; 60 | while(l <= e) 61 | { 62 | int m = l + (e - l) / 2; 63 | if((P[m] - P[0]) * (p - P[0]) >= 0) l = m + 1, ans = m; 64 | else e = m - 1; 65 | } 66 | return pointInTriangle(P[ans], P[ans + 1], P[0], p); 67 | } 68 | 69 | int32_t main() 70 | { 71 | int q, x, y; 72 | cin >> n >> q; 73 | for(int i = 0; i < n; i++) 74 | {//poligono no sentido anti-horario 75 | cin >> x >> y; 76 | P.push_back({x, y}); 77 | } 78 | setFirstPoint(); 79 | while(q--) 80 | { 81 | cin >> x >> y; 82 | cout << (pointInConvexPolygon({x, y}) ? "Dentro" : "Fora") << '\n'; 83 | } 84 | 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /code/geometry/convex_hull_trick.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define type int 4 | const int MAX = 1e5; 5 | const int OO = 0x3f3f3f3f; 6 | 7 | struct line 8 | { 9 | type m, b; 10 | line(type _m, type _b){ m = _m, b = _b; } 11 | }; 12 | 13 | int pointer;//Keeps track of the best line from previous query 14 | vector hull;//store hull 15 | 16 | //Returns true if line l3 is always better than line l2 17 | bool bad(int l1, int l2, int l3) 18 | { 19 | /* 20 | intersection(l1,l2) has x-coordinate (b1-b2)/(m2-m1) 21 | intersection(l1,l3) has x-coordinate (b1-b3)/(m3-m1) 22 | set the former greater than the latter, and cross-multiply to 23 | eliminate division 24 | */ 25 | line L1 = hull[l1], L2 = hull[l2], L3 = hull[l3]; 26 | return (L3.b-L1.b)*(L1.m-L2.m) < (L2.b-L1.b)*(L1.m-L3.m); 27 | } 28 | 29 | //Adds a new line 30 | void add(type m, type b) 31 | { 32 | if(hull.size() > 0 and hull.back().m == m) return; 33 | //First, let's add it to the end 34 | hull.emplace_back(m, b); 35 | //If the penultimate is now made irrelevant between the antepenultimate 36 | //and the ultimate, remove it. Repeat as many times as necessary 37 | while(hull.size()>=3 and bad(hull.size()-3,hull.size()-2,hull.size()-1)) 38 | hull.erase(hull.end()-2); 39 | } 40 | 41 | //Returns y value of a function i 42 | type eval(int i, type x) 43 | { 44 | return hull[i].m * x + hull[i].b; 45 | } 46 | 47 | //Returns the minimum y-coordinate of any intersection 48 | //between a given vertical line and the lower envelope 49 | //O(N) for all queries (queries are in ascending order of x) 50 | type query(type x) 51 | { 52 | if(pointer >= hull.size()) 53 | pointer = hull.size() - 1; 54 | while(pointer < hull.size()-1 and eval(pointer+1, x) < eval(pointer, x)) 55 | pointer++; 56 | return eval(pointer, x); 57 | } 58 | 59 | //Returns the minimum y-coordinate of any intersection 60 | //between a given vertical line and the lower envelope 61 | //O(LogN) time (queries are in any order of x) 62 | type binarySearch(type x) 63 | { 64 | int b = 0, e = hull.size() - 1; 65 | while(b < e) 66 | { 67 | int mid = (b + e) / 2; 68 | if(eval(mid+1, x) < eval(mid, x)) b = mid + 1; 69 | else e = mid; 70 | } 71 | return eval(b, x); 72 | } 73 | 74 | /* 75 | Maximum Y coordenate query, we have two options: 76 | 1) Maximum Y-coordenate query: multiply m and b by -1 and 77 | make minimum Y-corrdenate query... 78 | 79 | 2) Order lines by increasing m if m is not equal, otherwise by decreasing b 80 | in the function query and binary Search change < to > 81 | eval(pointer+1, x) < eval(pointer, x) 82 | to, 83 | eval(pointer+1, x) > eval(pointer, x) 84 | */ 85 | 86 | int main() 87 | { 88 | int n; 89 | cin >> n; 90 | //Order lines by decreasing m if m is not equal, otherwise by increasing b 91 | for(int i = 0; i < n; i++) 92 | { 93 | int m, b; 94 | cin >> m >> b; 95 | add(m, b); 96 | } 97 | int q; 98 | cin >> q; 99 | vector queries(q);//queries are in ascending order of x - run in O(N) 100 | for(int &w : queries) 101 | cin >> w; 102 | //processing queries in ascending order of x 103 | for(int &w : queries) 104 | cout << query(w) << '\n'; 105 | 106 | int x; 107 | while(cin >> x)//queries are in any order of x - run in O(logN) 108 | cout << binarySearch(x) << '\n'; 109 | 110 | return 0; 111 | } 112 | -------------------------------------------------------------------------------- /code/geometry/distance_between_nearest_pair_of_points_2d.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int MAX = 1e4; 4 | const double EPS = 1e7; 5 | typedef pair ii; 6 | 7 | vector v; 8 | set sy, sx; 9 | int n; 10 | 11 | int main() 12 | { 13 | double x, y; 14 | cin >> n; 15 | for(int i = 0; i < n; i++) 16 | { 17 | cin >> x >> y; 18 | v.push_back({x, y}); 19 | } 20 | sort(v.begin(), v.end()); 21 | double d = 0x3f3f3f3f; 22 | for(int i = 0; i < n; i++) 23 | { 24 | x = v[i].first, y = v[i].second; 25 | while(!sx.empty()) 26 | { 27 | ii p = *(sx.begin()); 28 | if(p.first + d < x) 29 | { 30 | sy.erase({p.second, p.first}); 31 | sx.erase(p); 32 | } 33 | else 34 | break; 35 | } 36 | auto it = sy.lower_bound({int(floor(y-d))-1, 0}); 37 | while(it != sy.end() and it->first < y + d + 1) 38 | { 39 | d = min(d, hypot(x - it->second, y - it->first)); 40 | it++; 41 | } 42 | sy.insert({y, x}); 43 | sx.insert({x, y}); 44 | } 45 | cout << d << '\n'; 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /code/geometry/distance_between_nearest_pair_of_points_3d.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #define int long long 5 | 6 | #define OO 0x3f3f3f3f3f3f3f3f 7 | #define ii pair 8 | #define iii pair 9 | 10 | vector v; 11 | set sy, sx, sz; 12 | int n; 13 | 14 | int sq(int x) { 15 | return x * x; 16 | } 17 | 18 | double dist(iii a, iii b) { 19 | return sqrt(sq(a.first - b.first) + sq(a.second.first - b.second.first) + sq(a.second.second - b.second.second)); 20 | } 21 | 22 | int32_t main() { 23 | cin >> n; 24 | 25 | for(int i = 0; i < n; i++) { 26 | int x, y, z; 27 | cin >> x >> y >> z; 28 | v.push_back({x, {y, z}}); 29 | } 30 | 31 | sort(v.begin(), v.end()); 32 | 33 | double d = OO; 34 | 35 | for(int i = 0; i < n; i++) { 36 | int x = v[i].first, y = v[i].second.first, z = v[i].second.second; 37 | 38 | while(!sx.empty()) 39 | { 40 | iii p = *(sx.begin()); 41 | if(p.first + d < x) { 42 | sy.erase({p.second.first, {p.first, p.second.second}}); // y x z 43 | sz.erase({p.second.second, {p.first, p.second.first}}); // z x y 44 | sx.erase(p); 45 | } 46 | else 47 | break; 48 | } 49 | 50 | auto ity = sy.lower_bound({y-d-1, {0, 0}}); 51 | while(ity != sy.end() && ity->first < y + d + 1) 52 | { 53 | d = min(d, dist(v[i], {ity->second.first, {ity->first, ity->second.second}})); 54 | ity++; 55 | } 56 | 57 | auto itz = sz.lower_bound({z-d-1, {0, 0}}); 58 | while(itz != sz.end() && itz->first < z + d + 1) 59 | { 60 | d = min(d, dist(v[i], {itz->second.first, {itz->second.second, itz->first}})); 61 | itz++; 62 | } 63 | 64 | sy.insert({y, {x, z}}); 65 | sz.insert({z, {x, y}}); 66 | sx.insert({x, {y, z}}); 67 | } 68 | 69 | cout << fixed << setprecision(14) << d << '\n'; 70 | 71 | return 0; 72 | } -------------------------------------------------------------------------------- /code/geometry/dynamic_convex_hull_trick.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define type __int128 4 | #define int __int128 5 | #define gc getchar 6 | #define pc putchar 7 | #define Min(a, b) (a > b ? b : a) 8 | 9 | inline void scanint(int &k) 10 | { 11 | bool sinal = true; 12 | register char c; 13 | k = 0; 14 | for(c = gc(); sinal and (c < '0' or c > '9'); c = gc()) 15 | if(c == '-') 16 | sinal = false; 17 | for(; c >= '0' and c <= '9'; c = gc()) 18 | k = (k << 3) + (k << 1) + c - '0'; 19 | if(!sinal) k = -k; 20 | } 21 | 22 | inline void printint(int n) 23 | { 24 | if(n < 0) pc('-'); 25 | n = abs(n); 26 | int rev = n, cnt = 0; 27 | if(!n) 28 | { 29 | pc('0'); 30 | pc('\n'); 31 | return; 32 | } 33 | while(!(rev % 10)) 34 | cnt++, rev /= 10; 35 | rev = 0; 36 | while(n) 37 | rev = (rev << 3) + (rev << 1) + n % 10, n /= 10; 38 | while(rev) 39 | pc(rev % 10 + '0'), rev /= 10; 40 | while(cnt--) 41 | pc('0'); 42 | pc('\n'); 43 | } 44 | 45 | 46 | struct line 47 | { 48 | type m, b; 49 | line(type _m, type _b){ m = _m, b = _b; } 50 | line(){ m = 0, b = 0; } 51 | }; 52 | 53 | bool bad(int l1, int l2, int l3, vector &hull) 54 | { 55 | line L1 = hull[l1], L2 = hull[l2], L3 = hull[l3]; 56 | return (L3.b-L1.b)*(L1.m-L2.m) < (L2.b-L1.b)*(L1.m-L3.m); 57 | } 58 | 59 | void add(type m, type b, vector &hull) 60 | { 61 | if(hull.size() > 0 and hull.back().m == m) return; 62 | hull.emplace_back(m, b); 63 | while(hull.size()>=3 and bad(hull.size()-3,hull.size()-2,hull.size()-1, hull)) 64 | hull.erase(hull.end()-2); 65 | } 66 | 67 | type eval(int i, type x, vector &hull) 68 | { 69 | return hull[i].m * x + hull[i].b; 70 | } 71 | 72 | type binarySearch(type x, vector &hull) 73 | { 74 | int b = 0, e = hull.size() - 1; 75 | while(b < e) 76 | { 77 | int mid = (b + e) / 2; 78 | if(eval(mid+1, x, hull) < eval(mid, x, hull)) b = mid + 1; 79 | else e = mid; 80 | } 81 | return eval(b, x, hull); 82 | } 83 | 84 | //##########DAQUI PRA BAIXO EH O SUCESSO################ 85 | 86 | vector merge(vector a, vector b) 87 | { 88 | if(a.size() < b.size()) swap(a, b); 89 | for(int i = 0; i < b.size(); i++) 90 | a.push_back(b[i]); 91 | sort(a.begin(), a.end(), [](line c, line d) 92 | { return c.m == d.m ? c.b < d.b : c.m > d.m; }); 93 | b.clear(); 94 | for(int i = 0; i < a.size(); i++) 95 | add(a[i].m, a[i].b, b); 96 | return b; 97 | } 98 | 99 | vector> groups; 100 | 101 | void add(line l) 102 | { 103 | vector g = {l}; 104 | while(!groups.empty() and groups.back().size() <= g.size()) 105 | { 106 | g = merge(g, groups.back()); 107 | groups.pop_back(); 108 | } 109 | groups.push_back(g); 110 | } 111 | 112 | type query(int x) 113 | { 114 | int ans = 0; 115 | for(int i = 0; i < groups.size(); i++) 116 | ans = Min(ans, binarySearch(x, groups[i])); 117 | return -ans; 118 | } 119 | 120 | int32_t main() 121 | { 122 | int n, q; 123 | scanint(n); 124 | scanint(q); 125 | 126 | vector cyc(n + 1); 127 | 128 | while(q--) 129 | { 130 | int t, T; 131 | scanint(t); 132 | scanint(T); 133 | if(t % 2 == 1) 134 | { 135 | int N, C; 136 | scanint(C); 137 | scanint(N); 138 | int b = - N * T + cyc[C].m * T + cyc[C].b; 139 | //cout << N << ' ' << b << '\n'; 140 | add(line(-N, -b)); 141 | cyc[C] = line(N, b); 142 | } 143 | else 144 | printint(query(T)); 145 | } 146 | 147 | return 0; 148 | } 149 | -------------------------------------------------------------------------------- /code/geometry/enclosing_circle_R2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int n; 4 | double x[1005], y[1005], X, Y, d, e; 5 | double dist(double a, double b) { 6 | return a*a + b*b; 7 | } 8 | int main() { 9 | scanf("%d", &n); 10 | for (int i = 0; i < n; i++) { 11 | scanf("%lf%lf", &x[i], &y[i]); 12 | X += x[i]; Y += y[i]; 13 | } 14 | X /= n; Y /= n; 15 | double P = 0.1; 16 | for (int i = 0; i < 30000; i++) { 17 | int f = 0; 18 | d = dist(X - x[0], Y - y[0]); 19 | for (int j = 1; j < n; j++) { 20 | e = dist(X - x[j], Y - y[j]); 21 | if (d < e) { d = e; f = j; } 22 | } 23 | X += (x[f] - X)*P; 24 | Y += (y[f] - Y)*P; 25 | P *= 0.999; 26 | } 27 | printf("%.3lf %.3lf\n%.3lf", X, Y, sqrt(d)); 28 | } 29 | -------------------------------------------------------------------------------- /code/geometry/enclosing_circle_R3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int n; 4 | double x[105], y[105], z[105], X, Y, Z, d, e; 5 | double dist(double a, double b, double c) { 6 | return a*a + b*b + c*c; 7 | } 8 | int main() { 9 | scanf("%d", &n); 10 | for (int i = 0; i < n; i++) { 11 | scanf("%lf%lf%lf", &x[i], &y[i], &z[i]); 12 | X += x[i]; 13 | Y += y[i]; 14 | Z += z[i]; 15 | } 16 | X /= n; Y /= n; Z /= n; 17 | double P = 0.1; 18 | for (int i = 0; i < 70000; i++) { 19 | int f = 0; 20 | d = dist(X - x[0], Y - y[0], Z - z[0]); 21 | for (int j = 1; j < n; j++) { 22 | e = dist(X - x[j], Y - y[j], Z - z[j]); 23 | if (d < e) { 24 | d = e; 25 | f = j; 26 | } 27 | } 28 | X += (x[f] - X)*P; 29 | Y += (y[f] - Y)*P; 30 | Z += (z[f] - Z)*P; 31 | P *= 0.998; 32 | } 33 | printf("%.10lf %.10lf %.10lf", X, Y, Z); 34 | } 35 | -------------------------------------------------------------------------------- /code/geometry/graham_scan.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define ii pair 4 | #define fi first 5 | #define se second 6 | 7 | vector P; 8 | 9 | ii operator-(ii a, ii b) 10 | { 11 | return ii(a.fi - b.fi, a.se - b.se); 12 | } 13 | 14 | ii operator+(ii a, ii b) 15 | { 16 | return ii(a.fi + b.fi, a.se + b.se); 17 | } 18 | 19 | int operator*(ii a, ii b) 20 | { 21 | return a.fi * b.se - a.se * b.fi; 22 | } 23 | 24 | int dist(ii a, ii b) 25 | { 26 | return (a.fi - b.fi) * (a.fi - b.fi) + (a.se - b.se) * (a.se - b.se); 27 | } 28 | 29 | bool cmp(ii a, ii b) 30 | { 31 | int cross = (a - P[0]) * (b - P[0]); 32 | if(!cross) return dist(P[0], a) > dist(P[0], b); 33 | return cross > 0; 34 | } 35 | 36 | void setFirstPoint() 37 | { 38 | for(int i = 1; i < P.size(); i++) 39 | if(P[i].fi < P[0].fi or P[i].fi == P[0].fi and P[i].se < P[0].se) 40 | swap(P[0], P[i]); 41 | } 42 | 43 | vector GrahamScan() 44 | { 45 | setFirstPoint(); 46 | sort(P.begin() + 1, P.end(),cmp); 47 | vector H(P.size() * 2); 48 | int k = 0; 49 | for(int i = 0; i < P.size(); i++) 50 | { //crsso <= 0 para remover os pontos colineares 51 | while(k > 2 and (H[k - 1] - H[k - 2]) * (P[i] - H[k - 1]) < 0) k--; 52 | H[k++] = P[i]; 53 | } 54 | H.resize(k); 55 | return H; 56 | } 57 | 58 | int main() 59 | { 60 | int n; 61 | cin >> n; 62 | for(int i = 0; i < n; i++) 63 | { 64 | ii p; 65 | cin >> p.fi >> p.se; 66 | P.push_back(p); 67 | } 68 | vector H = GrahamScan(); 69 | for(int i = 0; i < H.size(); i++) 70 | cout << H[i].fi << ' ' << H[i].se << '\n'; 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /code/geometry/radial_sort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define type int 4 | #define point pair 5 | #define X first 6 | #define Y second 7 | 8 | point operator-(point a, point b) 9 | { 10 | return {a.X - b.X, a.Y - b.Y}; 11 | } 12 | 13 | type operator*(point a, point b) 14 | { 15 | return a.X * b.Y - a.Y * b.X; 16 | } 17 | 18 | int n; 19 | vector P; 20 | point R; 21 | 22 | int dist(point a, point b) 23 | { 24 | return (a.X - b.X) * (a.X - b.X) + (a.Y - b.Y) * (a.Y - b.Y); 25 | } 26 | 27 | bool cmp(point a, point b) 28 | { 29 | if((a - R).Y * (b - R).Y <= 0) return a.Y > R.Y; 30 | int c = (a - R) * (b - R); 31 | if(c == 0) return dist(R, a) <= dist(R, b); 32 | return c > 0; 33 | } 34 | 35 | int main() 36 | { 37 | cin >> n >> R.X >> R.Y; 38 | for(int i = 0; i < n; i++) 39 | { 40 | type x, y; 41 | cin >> x >> y; 42 | P.push_back({x, y}); 43 | } 44 | sort(P.begin(), P.end(), cmp); 45 | for(point p : P) cout << p.X << ' ' << p.Y << '\n'; 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /code/geometry/segment_intersection.cpp: -------------------------------------------------------------------------------- 1 | #define ll long long 2 | #define Pll complex 3 | #define Y imag() 4 | #define X real() 5 | 6 | bool intersec(Pll a, Pll b, Pll c, Pll d) 7 | { 8 | if(cross(c - a, c - b) * cross(d - a, d - b) <= 0 and 9 | cross(a - c, a - d) * cross(b - c, b - d) <= 0) 10 | return true; 11 | return false; 12 | } 13 | -------------------------------------------------------------------------------- /code/graph/BFS_zero_one.cpp: -------------------------------------------------------------------------------- 1 | // o peso das arestas eh 0 ou 1 2 | 3 | #include 4 | using namespace std; 5 | const int MAX = 1e5; 6 | const int OO = 0x3f3f3f3f; 7 | typedef pair ii; 8 | 9 | int n, m; 10 | vector G[MAX]; 11 | int dist[MAX]; 12 | deque dq; 13 | 14 | void zeroOneBfs(int v) 15 | { 16 | memset(dist, 63, sizeof(dist)); 17 | dist[v] = 0; 18 | dq.push_back(v); 19 | while(!dq.empty()) 20 | { 21 | int u = dq.front(); 22 | dq.pop_front(); 23 | for(int i = 0; i < G[u].size(); i++) 24 | { 25 | int w = G[u][i].first, d = G[u][i].second; 26 | if(dist[w] > dist[u] + d) 27 | { 28 | dist[w] = dist[u] + d; 29 | if(!d) dq.push_front(w); 30 | else dq.push_back(w); 31 | } 32 | } 33 | } 34 | for(int i = 0; i < n; i++) 35 | cout << dist[i] << ' '; 36 | puts(""); 37 | } 38 | 39 | int main() 40 | { 41 | cin >> n >> m; 42 | while(m--) 43 | { 44 | int u, v, w; 45 | cin >> u >> v >> w; u--; v--; 46 | G[u].push_back({v, w}); 47 | G[v].push_back({u, w}); 48 | } 49 | zeroOneBfs(0); 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /code/graph/MCE_MinimumEdgeCover.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | vector G[1000]; 5 | int b[1000], vis[1000], tempo; 6 | 7 | bool kuhn(int v) 8 | { 9 | if(vis[v] == tempo) 10 | return 0; 11 | vis[v] = tempo; 12 | for(const int &u : G[v]) 13 | if(!b[u] or kuhn(b[u])) 14 | return b[u] = v; 15 | return 0; 16 | } 17 | 18 | int main() 19 | { 20 | int n, m, e; 21 | cin >> n >> m >> e; 22 | while(e--) 23 | { 24 | int u, v; 25 | cin >> u >> v; 26 | G[u].push_back(v + n); 27 | } 28 | int ans = 0; 29 | tempo = 1; 30 | for(int i = 1; i <= n; i++) 31 | ans += kuhn(i), tempo++; 32 | 33 | 34 | //encontrar as arestas do Minimum Edge Cover 35 | vector covered(n + m + 10, false); 36 | vector> cover; 37 | for(int i = n + 1; i <= n + m; i++) 38 | if(b[i]) 39 | { 40 | covered[b[i]] = covered[i] = true; 41 | cover.push_back({b[i], i - n}); 42 | } 43 | for(int i = 1; i <= n; i++) 44 | { 45 | bool is_covered = covered[i]; 46 | for(const int &u : G[i]) 47 | if(!covered[u]) 48 | { 49 | is_covered = true; 50 | cover.push_back({i, u - n}); 51 | covered[i] = covered[u] = true; 52 | } 53 | if(!is_covered and !G[i].empty()) 54 | cover.push_back({i, G[i].front() - n}); 55 | } 56 | cout << "MEC = " << cover.size() << '\n'; 57 | for(int i = 0; i < cover.size(); i++) 58 | cout << cover[i].first << ' ' << cover[i].second << '\n'; 59 | 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /code/graph/MPC_MinimumPathCover.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int n, m; 5 | vector G[1000], bip[1000], ts; 6 | int vis[1000], b[1000], go[1000], tempo = 1; 7 | 8 | bool kuhn(int v) 9 | { 10 | if(vis[v] == tempo) 11 | return 0; 12 | vis[v] = tempo; 13 | for(const int &u : bip[v]) 14 | if(!b[u] or kuhn(b[u])) 15 | { 16 | go[v] = u - n; 17 | return b[u] = v; 18 | } 19 | return 0; 20 | } 21 | 22 | void topological_sort(int v) 23 | { 24 | vis[v] = tempo; 25 | for(const int &u : G[v]) 26 | if(vis[u] != tempo) 27 | topological_sort(u); 28 | ts.push_back(v); 29 | } 30 | 31 | int main() 32 | { 33 | cin >> n >> m; 34 | while(m--) 35 | { 36 | int u, v; 37 | cin >> u >> v; 38 | G[u].push_back(v); 39 | bip[u].push_back(v + n); 40 | } 41 | int ans = 0; 42 | for(int i = 1; i <= n; i++) 43 | ans += kuhn(i), tempo++; 44 | for(int i = 1; i <= n; i++) 45 | if(vis[i] != tempo) 46 | topological_sort(i); 47 | reverse(ts.begin(), ts.end()); 48 | tempo++; 49 | cout << n - ans << '\n'; 50 | for(int i = 0; i < n; i++) 51 | { 52 | int u = ts[i]; 53 | if(vis[u] != tempo) 54 | { 55 | while(u) 56 | { 57 | vis[u] = tempo; 58 | cout << u << ' '; 59 | u = go[u]; 60 | } 61 | puts(""); 62 | } 63 | } 64 | 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /code/graph/MVC_MinimumVertexCover.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | vector G[1000]; 5 | int b[1000], vis[1000], tempo; 6 | bool be[1000]; 7 | set r0, r1; 8 | 9 | bool kuhn(int v) 10 | { 11 | if(vis[v] == tempo) 12 | return 0; 13 | vis[v] = tempo; 14 | for(const int &u : G[v]) 15 | if(!b[u] or kuhn(b[u])) 16 | return b[u] = v; 17 | return 0; 18 | } 19 | 20 | void MVC(int v) 21 | { 22 | if(vis[v] == tempo) 23 | return; 24 | vis[v] = tempo; 25 | for(const int u : G[v]) 26 | if(b[u] != v and b[u]) 27 | { 28 | r1.insert(u); 29 | vis[b[u]] = tempo; 30 | } 31 | } 32 | 33 | int main() 34 | { 35 | int n, m, e; 36 | cin >> n >> m >> e; 37 | while(e--) 38 | { 39 | int u, v; 40 | cin >> u >> v; 41 | G[u].push_back(v); 42 | } 43 | int ans = 0; 44 | tempo = 1; 45 | for(int i = 1; i <= n; i++) 46 | ans += kuhn(i), tempo++; 47 | for(int i = n + 1; i <= n + m; i++) 48 | if(b[i]) 49 | be[i - n] = be[b[i]] = true; 50 | for(int i = 1; i <= n; i++) 51 | if(!be[i]) 52 | MVC(i); 53 | for(int i = 1 ; i <= n; i++) 54 | if(vis[i] < tempo) 55 | r0.insert(i); 56 | cout << "MVC = "<< ans << '\n'; 57 | cout << "tamanho lado esquerdo " << r0.size() << '\n'; 58 | for(auto it = r0.begin(); it != r0.end(); it++) 59 | cout << *it << ' '; 60 | puts(""); 61 | cout << "tamanho lado direito " << r1.size() << '\n'; 62 | for(auto it = r1.begin(); it != r1.end(); it++) 63 | cout << *it - n << ' '; 64 | puts(""); 65 | 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /code/graph/boruvka_MST.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int n, m; 5 | vector> edge; 6 | int pai[100100], sz[100100]; 7 | 8 | int find(int x) 9 | { 10 | return pai[x] == x ? x : pai[x] = find(pai[x]); 11 | } 12 | 13 | void join(int x, int y) 14 | { 15 | x = find(x); 16 | y = find(y); 17 | if(x == y) return; 18 | if(sz[x] > sz[y]) swap(x, y); 19 | pai[x] = y; 20 | sz[y] += sz[x]; 21 | } 22 | 23 | int main() 24 | { 25 | scanf(" %d %d", &n, &m); 26 | for(int i = 0; i < m; i++) 27 | { 28 | int u, v, w; 29 | scanf(" %d %d %d", &u, &v, &w); u--; v--; 30 | edge.push_back({w, v, u}); 31 | } 32 | for(int i = 0; i < n; i++) 33 | pai[i] = i, sz[i] = 1; 34 | int mst_cost = 0; 35 | bool fl = true; 36 | while(fl) 37 | { 38 | fl = false; 39 | vector aux(n, -1); 40 | for(int i = 0; i < m; i++) 41 | { 42 | int u = find(edge[i][1]), v = find(edge[i][2]), w = edge[i][0]; 43 | if(u == v) continue; 44 | if(aux[u] == -1) aux[u] = i; 45 | else if(edge[aux[u]][0] > w) aux[u] = i; 46 | if(aux[v] == -1) aux[v] = i; 47 | else if(edge[aux[v]][0] > w) aux[v] = i; 48 | } 49 | for(int i = 0; i < n; i++) 50 | { 51 | if(aux[i] == -1) continue; 52 | int u = find(edge[aux[i]][1]), v = find(edge[aux[i]][2]); 53 | if(u == v) continue; 54 | // add_edge edge[aux[i]][1] --- edge[aux[i]][2] in the MST 55 | join(u, v); 56 | mst_cost += edge[aux[i]][0]; 57 | fl = true; 58 | } 59 | } 60 | cout << mst_cost << '\n'; 61 | 62 | return 0; 63 | } 64 | 65 | -------------------------------------------------------------------------------- /code/graph/center_of_a_tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | const int MAX = 1e5; 3 | using namespace std; 4 | 5 | int n, degree[MAX]; 6 | vector G[MAX]; 7 | bool vis[MAX]; 8 | 9 | int findCenter() 10 | { 11 | queue fila[2]; 12 | for(int i = 0; i < n; i++) 13 | if(degree[i] == 1) 14 | fila[0].push(i); 15 | int cnt = 0, turn = 0; 16 | while(cnt + 2 < n) 17 | { 18 | while(!fila[turn].empty()) 19 | { 20 | int u = fila[turn].front(); fila[turn].pop(); 21 | vis[u] = true; 22 | cnt++; 23 | for(int i = 0; i < G[u].size(); i++) 24 | if(!vis[G[u][i]]) 25 | { 26 | degree[G[u][i]]--; 27 | if(degree[G[u][i]] == 1) 28 | fila[1-turn].push(G[u][i]); 29 | } 30 | } 31 | turn ^= 1; 32 | } 33 | cout << "the set of central vertices\n"; 34 | for(int i = 0; i < n; i++) 35 | if(!vis[i]) 36 | cout << i + 1 << '\n'; 37 | } 38 | 39 | int main() 40 | { 41 | cin >> n; 42 | for(int i = 1; i < n; i++) 43 | { 44 | int u, v; 45 | scanf("%d %d", &u, &v); u--; v--; 46 | G[u].push_back(v); 47 | G[v].push_back(u); 48 | degree[u]++; 49 | degree[v]++; 50 | } 51 | findCenter(); 52 | 53 | return 0; 54 | } 55 | 56 | 57 | -------------------------------------------------------------------------------- /code/graph/diameter_and_center_of_a_tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int MAX = 1e5; 4 | 5 | int n; 6 | vector G[MAX]; 7 | 8 | int bfs(int v, vector &dist) 9 | { 10 | queue q; 11 | q.push(v); 12 | dist[v] = 0; 13 | int lgv = -1; 14 | while(!q.empty()) 15 | { 16 | int u = q.front(); q.pop(); 17 | lgv = u; 18 | for(int &w : G[u]) 19 | if(dist[w] == -1) 20 | { 21 | dist[w] = dist[u] + 1; 22 | q.push(w); 23 | } 24 | } 25 | return lgv; 26 | } 27 | 28 | void findCenterAndDiameter(int w) 29 | { 30 | vector dist1(n + 1, -1); 31 | vector dist2(n + 1, -1); 32 | int v = bfs(w, dist1); 33 | int u = bfs(v, dist2); 34 | int d = dist2[u]; 35 | dist1.assign(n + 1, -1); 36 | u = bfs(u, dist1); 37 | cout << "center "; 38 | for(int i = 0; i < n; i++) 39 | { 40 | int d1 = dist1[i], d2 = dist2[i]; 41 | if(d1 == d / 2 and d2 == d - d / 2 or d2 == d / 2 and d1 == d - d / 2) 42 | cout << i + 1 << ' '; 43 | } 44 | cout << "\ndiameter " << d << '\n'; 45 | } 46 | 47 | int main() 48 | { 49 | cin >> n; 50 | for(int i = 1; i < n; i++) 51 | { 52 | int u, v; 53 | cin >> u >> v; u--; v--; 54 | G[u].push_back(v); 55 | G[v].push_back(u); 56 | } 57 | findCenterAndDiameter(0); 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /code/graph/dijkstra.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int OO = 0x3f3f3f3f; 4 | const int MAX = 1e5; 5 | 6 | typedef pair ii; 7 | 8 | int n, m; 9 | int dist[MAX]; 10 | vector G[MAX]; 11 | 12 | int dijkstra(int v, int z) 13 | { 14 | memset(dist, 63, sizeof(dist)); 15 | dist[v] = 0; 16 | priority_queue pq; 17 | pq.push({0, v}); 18 | while(!pq.empty()) 19 | { 20 | int u = pq.top().second; 21 | int d = -pq.top().first; 22 | pq.pop(); 23 | if(d > dist[u]) continue; 24 | if(u == z) return d; 25 | for(int i = 0; i < G[u].size(); i++) 26 | { 27 | int w = G[u][i].second, _d = G[u][i].first; 28 | if(dist[w] > d + _d) 29 | { 30 | dist[w] = d + _d; 31 | pq.push({-dist[w], w}); 32 | } 33 | } 34 | } 35 | return OO; 36 | } 37 | 38 | int main() 39 | { 40 | int u, v, w; 41 | 42 | cin >> n >> m; 43 | while(m--) 44 | { 45 | cin >> u >> v >> w; 46 | u--; v--; 47 | G[u].push_back({w, v}); 48 | G[v].push_back({w, u}); 49 | } 50 | cin >> u >> v; 51 | cout << dijkstra(u-1, v-1) << '\n'; 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /code/graph/dinic.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int MAX = 1e4; 4 | const int OO = 0x3f3f3f3f; 5 | 6 | struct edge 7 | { 8 | int v, f, c; 9 | edge(){} 10 | edge(int _v, int _f, int _c) 11 | { 12 | v = _v, f = _f, c = _c; 13 | } 14 | }; 15 | 16 | vector edges; 17 | vector G[MAX]; 18 | int dist[MAX], work[MAX]; 19 | 20 | void add_edge(int u, int v, int cp, int rc){ 21 | edges.push_back(edge(v, 0, cp)); 22 | G[u].push_back(edges.size()-1); 23 | edges.push_back(edge(u, 0, rc)); 24 | G[v].push_back(edges.size()-1); 25 | } 26 | 27 | bool bfs(int s, int t) 28 | { 29 | memset(dist, -1, sizeof(dist)); 30 | dist[s] = 0; 31 | queue q; 32 | q.push(s); 33 | while(!q.empty()) 34 | { 35 | int u = q.front(); 36 | q.pop(); 37 | for(int e : G[u]) 38 | if(dist[edges[e].v] == -1 and edges[e].c-edges[e].f > 0) 39 | { 40 | q.push(edges[e].v); 41 | dist[edges[e].v] = dist[u] + 1; 42 | } 43 | } 44 | return dist[t] != -1; 45 | } 46 | 47 | int dfs(int s, int t, int f) 48 | { 49 | if(s == t) return f; 50 | for(int &i = work[s]; i < G[s].size(); i++) 51 | { 52 | int e = G[s][i]; 53 | if(dist[edges[e].v] == dist[s] + 1 and edges[e].c-edges[e].f > 0) 54 | if(int a = dfs(edges[e].v, t, min(f, edges[e].c-edges[e].f))) 55 | { 56 | edges[e].f += a; 57 | edges[e^1].f -= a; 58 | return a; 59 | } 60 | } 61 | return 0; 62 | } 63 | 64 | int MaxFlow(int s, int t) 65 | { 66 | int mf = 0; 67 | while(bfs(s, t)) 68 | { 69 | memset(work, 0, sizeof(work)); 70 | while(int a = dfs(s, t, OO)) 71 | mf += a; 72 | } 73 | return mf; 74 | } 75 | 76 | int main() 77 | { 78 | int n, m, u, v, w; 79 | 80 | cin >> n >> m; 81 | while(m--) 82 | { 83 | cin >> u >> v >> w; 84 | add_edge(u-1, v-1, w, 0); 85 | } 86 | cin >> u >> v; 87 | cout << MaxFlow(u-1, v-1) << '\n'; 88 | 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /code/graph/erdos_gallai_theorem.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define int long long 4 | 5 | int32_t main() 6 | { 7 | int n; 8 | while(~scanf(" %lld", &n)) 9 | { 10 | vector degree(n), pref(n + 2); 11 | for(int &i : degree) 12 | scanf (" %lld", &i); 13 | sort(degree.begin(), degree.end(), greater()); 14 | for(int i = 0; i < n; i++) 15 | pref[i + 1] = pref[i] + degree[i]; 16 | bool fl = true; 17 | if(pref[n] & 1) 18 | fl = false; 19 | int j = n; 20 | for(int k = 1; k <= n and fl; k++) 21 | { 22 | int L = pref[k]; 23 | int R = k * (k - 1); 24 | while(j > 0 and degree[j - 1] < k) 25 | j--; 26 | int pos = max(j, k); 27 | R += pref[n] - pref[pos] + (pos - k) * k; 28 | if(L > R) fl = false; 29 | } 30 | puts(fl ? "possivel" : "impossivel"); 31 | } 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /code/graph/eulirian_path.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int32_t main() { 5 | 6 | int n, m; 7 | 8 | cin >> n >> m; 9 | vector> g(n); 10 | vector deg_in(n), deg_out(n); 11 | 12 | for(int i = 0; i < m; i++) { 13 | int u, v; 14 | cin >> u >> v; u--; v--; 15 | g[u].push_back(v); 16 | deg_in[v]++; 17 | deg_out[u]++; 18 | } 19 | 20 | int s = -1, f = -1; 21 | for(int i = 0; i < n; ++i) { 22 | if(deg_in[i] - deg_out[i] == 0) continue; 23 | 24 | if(s == -1 and deg_out[i] - deg_in[i] == 1) s = i; 25 | else if(f == -1 and deg_in[i] - deg_out[i] == 1) f = i; 26 | else return cout << "NO\n", 0; 27 | } 28 | 29 | if(s == -1 and f == -1) s = 0; 30 | else if(s != -1 and f == -1 or s == -1 and f != -1) return cout << "NO\n", 0; 31 | 32 | stack st; 33 | st.push(s); 34 | vector res; 35 | 36 | while(!st.empty()) { 37 | int v = st.top(); 38 | if(g[v].empty()) { 39 | res.push_back(v); 40 | st.pop(); 41 | } else { 42 | int u = g[v].back(); 43 | g[v].pop_back(); 44 | st.push(u); 45 | } 46 | } 47 | 48 | for(int i = 0; i < n; i++) 49 | if(g[i].empty() == false) 50 | return cout << "NO\n", 0; 51 | 52 | reverse(res.begin(), res.end()); 53 | 54 | for(int w : res) 55 | cout << w + 1 << ' '; 56 | cout << endl; 57 | 58 | return 0; 59 | } -------------------------------------------------------------------------------- /code/graph/floyd_sucessor_graph.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int n; 5 | int table[10000][20]; 6 | 7 | //table[i][j] armazena o sucessor de distancia 2^j do vertice i 8 | void build() 9 | { 10 | for(int j = 1; (1 << j) <= n; j++) 11 | for(int i = 0; i < n; i++) 12 | if(table[i][j-1] != -1) 13 | table[i][j] = table[table[i][j-1]][j-1]; 14 | } 15 | 16 | int succ(int u, int k) 17 | { 18 | while(k) 19 | { 20 | u = table[u][(int)log2(k&-k)]; 21 | if(u == -1) 22 | return -1;// nao existe 23 | k -= k&-k; 24 | } 25 | return u; 26 | } 27 | ////////////////////////////////////////////////////// 28 | 29 | 30 | //algoritmo de Floyd para encontrar o tamanho de um ciclo 31 | //alcancado a partir de um vertice u em um grafo sucessor 32 | int Floyd(int u) 33 | { 34 | int a = succ(u, 1); 35 | int b = succ(u, 2); 36 | 37 | //encontra um vertice no ciclo 38 | while(a != b) 39 | { 40 | a = succ(a, 1); 41 | b = succ(b, 2); 42 | if(a == -1 or b == -1) 43 | return -1;// nao existe ciclo 44 | } 45 | 46 | //a e b vao ficar posicionados no inicio do ciclo 47 | a = u; 48 | while(a != b) 49 | { 50 | a = succ(a, 1); 51 | b = succ(b, 1); 52 | } 53 | 54 | //percorre todo o ciclo contando o seu tamanho 55 | b = succ(a, 1); 56 | int lenght = 1; 57 | while(a != b) 58 | { 59 | b = succ(b, 1); 60 | lenght++; 61 | } 62 | return lenght; 63 | } 64 | ////////////////////////////////////////////////////// 65 | 66 | 67 | int main() 68 | { 69 | int u, v, m; 70 | 71 | cin >> n >> m; 72 | memset(table, -1, sizeof(table)); 73 | for(int i = 0; i < m; i++) 74 | { 75 | cin >> u >> v; u--; v--; 76 | table[u][0] = v; 77 | } 78 | build(); 79 | cin >> u >> v; 80 | cout << "O sucessor de " << u << " com " << v << 81 | " unidades a frente eh " << succ(u-1, v)+1 << '\n'; 82 | 83 | cout << '\n'; 84 | 85 | cin >> u; 86 | cout << "tamanho do ciclo iniciando em " << u << 87 | ": " << Floyd(u-1) << '\n'; 88 | 89 | return 0; 90 | } 91 | 92 | 93 | -------------------------------------------------------------------------------- /code/graph/ford_fulkerson.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | typedef pair ii; 4 | const int OO = 0x3f3f3f3f; 5 | const int MAX = 1e4; 6 | 7 | struct edge 8 | { 9 | int v, f, c; 10 | edge(){} 11 | edge(int _v, int _f, int _c) 12 | { 13 | v = _v, f = _f, c = _c; 14 | } 15 | }; 16 | 17 | vector edges; 18 | vector G[MAX]; 19 | int tempo = 1, cor[MAX]; 20 | 21 | void add_edge(int u, int v, int cp, int rc) 22 | { 23 | edges.push_back(edge(v, 0, cp)); 24 | G[u].push_back(edges.size()-1); 25 | edges.push_back(edge(u, 0, rc)); 26 | G[v].push_back(edges.size()-1); 27 | } 28 | 29 | int dfs(int s, int t, int f) 30 | { 31 | if(s == t) return f; 32 | cor[s] = tempo; 33 | for(int e : G[s]) 34 | if(cor[edges[e].v] < tempo and edges[e].c-edges[e].f > 0) 35 | if(int a = dfs(edges[e].v, t, min(f, edges[e].c-edges[e].f))) 36 | { 37 | edges[e].f += a; 38 | edges[e^1].f -= a; 39 | return a; 40 | } 41 | return 0; 42 | } 43 | 44 | int MaxFlow(int s, int t) 45 | { 46 | int mf = 0; 47 | while(int a = dfs(s, t, OO)) 48 | mf += a, tempo++; 49 | return mf; 50 | } 51 | 52 | int main() 53 | { 54 | int n, m, w, u, v; 55 | 56 | cin >> n >> m; 57 | while(m--) 58 | { 59 | cin >> u >> v >> w; 60 | add_edge(u-1, v-1, w, 0); 61 | } 62 | cin >> u >> v; 63 | cout << MaxFlow(u-1, v-1) << '\n'; 64 | 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /code/graph/hopcroft_karp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int OO = 0x3f3f3f3f; 4 | 5 | int n, m; 6 | vector G[10000]; 7 | queue q; 8 | int pairU[10000], pairV[10000], dist[10000]; 9 | 10 | bool bfs() 11 | { 12 | for(int u = 1; u <= m; u++) 13 | if(!pairU[u]) 14 | { 15 | dist[u] = 0; 16 | q.push(u); 17 | } 18 | else dist[u] = OO; 19 | dist[0] = OO; 20 | while(!q.empty()) 21 | { 22 | int u = q.front(); 23 | q.pop(); 24 | if(dist[u] < dist[0]) 25 | for(const int &v : G[u]) 26 | if(dist[pairV[v]] == OO) 27 | { 28 | dist[pairV[v]] = dist[u] + 1; 29 | q.push(pairV[v]); 30 | } 31 | } 32 | return (dist[0] != OO); 33 | } 34 | 35 | bool dfs(int u) 36 | { 37 | if(u) 38 | { 39 | for(const int &v : G[u]) 40 | if(dist[pairV[v]] == dist[u]+1) 41 | if (dfs(pairV[v])) 42 | { 43 | pairV[v] = u; 44 | pairU[u] = v; 45 | return true; 46 | } 47 | dist[u] = OO; 48 | return false; 49 | } 50 | return true; 51 | } 52 | 53 | int hopcroftKarp() 54 | { 55 | memset(pairU, 0, sizeof(pairU)); 56 | memset(pairV, 0, sizeof(pairV)); 57 | int result = 0; 58 | while(bfs()) 59 | for(int u = 1; u <= m; u++) 60 | if(!pairU[u] and dfs(u)) 61 | result++; 62 | return result; 63 | } 64 | 65 | int main() 66 | { 67 | n = m = 4; 68 | 69 | G[1].push_back(2); 70 | G[2].push_back(1); 71 | G[1].push_back(3); 72 | G[3].push_back(1); 73 | G[2].push_back(1); 74 | G[1].push_back(2); 75 | G[3].push_back(2); 76 | G[2].push_back(3); 77 | G[4].push_back(2); 78 | G[2].push_back(4); 79 | G[4].push_back(4); 80 | G[4].push_back(4); 81 | 82 | cout << hopcroftKarp() << '\n'; 83 | 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /code/graph/k_short_paths.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define int long long 4 | const int OO = 0x3f3f3f3f3f3f3f3f; 5 | const int MAX = 2000000; 6 | 7 | typedef pair ii; 8 | 9 | int n, m, k; 10 | vector G[MAX]; 11 | int cnt[MAX]; 12 | 13 | void dijkstra(int v) { 14 | priority_queue pq; 15 | pq.push({0, v}); 16 | int c = 0; 17 | while(!pq.empty()) { 18 | int u = -pq.top().second; 19 | int d = -pq.top().first; 20 | pq.pop(); 21 | cnt[u]++; 22 | if(cnt[u] > k) continue; 23 | if(u == n - 1) { 24 | cout << d << ' '; 25 | if(++c == k) { cout << '\n'; return; } 26 | } 27 | for(auto [_d, w] : G[u]) 28 | if(cnt[w] < k) 29 | pq.push({-(d + _d), -w}); 30 | } 31 | } 32 | 33 | int32_t main() { 34 | cin >> n >> m >> k; 35 | while(m--) { 36 | int u, v, w; 37 | cin >> u >> v >> w; u--; v--; 38 | G[u].push_back({w, v}); 39 | } 40 | dijkstra(0); 41 | 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /code/graph/knapsack_dijkstra.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int OO = 0x3f3f3f3f; 4 | #define ii pair 5 | #define fi first 6 | #define se second 7 | 8 | vector G[105]; 9 | int dist[100000008]; 10 | vector peso; 11 | 12 | void dijkstra() 13 | { 14 | memset(dist, 63, sizeof(dist)); 15 | dist[0] = 0; 16 | priority_queue pq; 17 | pq.push({0, 0}); 18 | while(!pq.empty()) 19 | { 20 | int u = pq.top().se; 21 | int d = -pq.top().fi; 22 | pq.pop(); 23 | if(d > dist[u]) continue; 24 | for(int i = 0; i < G[u].size(); i++) 25 | { 26 | int w = G[u][i].fi, dd = G[u][i].se; 27 | if(dist[w] > dist[u] + dd) 28 | { 29 | dist[w] = dist[u] + dd; 30 | pq.push({-dist[w], w}); 31 | } 32 | } 33 | } 34 | dist[0] = peso[0]; 35 | } 36 | 37 | int32_t main() 38 | { 39 | int n, e, d; 40 | cin >> n >> d >> e; 41 | // ler pesos 42 | peso = vector{d, 2 * d, 5 * d, 10 * d, 20 * d, 50 * d, 100 * d, 43 | 5 * e, 10 * e, 20 * e, 50 * e, 100 * e, 200 * e}; 44 | // ordena pra pegar o menor valor 45 | sort(peso.begin(), peso.end()); 46 | //montar grafo 47 | for(int i = 0; i < peso[0]; i++) 48 | for(int j = 0; j < peso.size(); j++) 49 | { 50 | int x = (i + peso[j]) % peso[0]; 51 | G[i].push_back({x, peso[j]}); 52 | } 53 | /* 54 | dist[i] eh o menor numero que eu consigo formar usando 55 | os meus objetos tal que dist[i] % peso[0] == i 56 | */ 57 | dijkstra(); 58 | 59 | /* 60 | se dist[X % peso[0]] <= X eh possivel gerar um valor X 61 | utilizando os valores do array peso 62 | OBS: cada valor pode ser usado infinitas vezes 63 | */ 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /code/graph/kuhn_MCBM.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int na, nb, m, tempo = 1; 5 | int b[105]; 6 | int cor[105]; 7 | vector G[105]; 8 | 9 | bool kuhn(int u) 10 | { 11 | if(cor[u] == tempo) 12 | return 0; 13 | cor[u] = tempo; 14 | //random_shuffle(G[u].begin(), G[u].end(), [](int x){ return rand() % x; }); 15 | for(const int &v : G[u]) 16 | if(!b[v] or kuhn(b[v])) 17 | return b[v] = u; 18 | return 0; 19 | } 20 | 21 | int main() 22 | { 23 | //srand(time(NULL)); 24 | cin >> na >> nb >> m; 25 | while(m--) 26 | { 27 | int u, v; 28 | cin >> u >> v; 29 | G[u].push_back(v + na); 30 | } 31 | tempo = 1; 32 | int ans = 0; 33 | for(int i = 1; i <= na; i++) 34 | ans += kuhn(i), tempo++; 35 | cout << "MCBM = " << ans << '\n'; 36 | for(int i = nb + 1; i <= na + nb; i++) 37 | if(b[i]) 38 | cout << b[i] << ' ' << i - na << '\n'; 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /code/graph/lca_with_square_root_decomposition.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | const int MAX = 50500; 3 | 4 | using namespace std; 5 | 6 | vector G[MAX]; 7 | int nivel[MAX], pai[MAX], jump[MAX], n, blk_sz; 8 | 9 | void dfs(int v, int d, int p) 10 | { 11 | pai[v] = p; 12 | nivel[v] = d; 13 | (nivel[v]%blk_sz == 0) ? jump[v] = pai[v] : jump[v] = jump[p]; 14 | for(const int &u : G[v]) 15 | if(u != p) 16 | dfs(u, d + 1, v); 17 | } 18 | 19 | int lcaTrivial(int u, int v) 20 | { 21 | while(u != v) 22 | (nivel[u] > nivel[v]) ? u = pai[u] : v = pai[v]; 23 | return u; 24 | } 25 | 26 | 27 | int lca(int u, int v) 28 | { 29 | while(jump[u] != jump[v]) 30 | (nivel[u] > nivel[v]) ? u = jump[u] : v = jump[v]; 31 | return lcaTrivial(u, v); 32 | } 33 | 34 | void build() 35 | { 36 | blk_sz = sqrt(n); 37 | dfs(0, 0, 0); 38 | } 39 | 40 | int main() 41 | { 42 | int x, y; 43 | cin >> n; 44 | for(int i = 0; i < n-1; i++) 45 | { 46 | cin >> x >> y; 47 | G[x-1].push_back(y-1); 48 | G[y-1].push_back(x-1); 49 | } 50 | build(); 51 | cin >> x >> y; 52 | cout << lca(x-1, y-1) + 1 << '\n'; 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /code/graph/lca_with_tree_linearization_and_segment_tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int MAX = 1e5; 4 | 5 | int pos[MAX]; 6 | int deft[MAX]; 7 | int segtree[5*MAX]; 8 | vector tl; 9 | vector G[MAX]; 10 | 11 | void tree_linearization(int v, int p, int d) 12 | { 13 | deft[v] = d; 14 | pos[v] = tl.size(); 15 | tl.push_back(v); 16 | for(const int &u : G[v]) 17 | if(u != p) 18 | { 19 | tree_linearization(u, v, d + 1); 20 | tl.push_back(v); 21 | } 22 | } 23 | 24 | void build(int node, int start, int end) 25 | { 26 | if(start == end) 27 | segtree[node] = tl[start]; 28 | else 29 | { 30 | int mid = (start+end)/2; 31 | build(2*node, start, mid); 32 | build(2*node+1, mid+1, end); 33 | if(deft[segtree[2*node]] < deft[segtree[2*node+1]]) 34 | segtree[node] = segtree[2*node]; 35 | else 36 | segtree[node] = segtree[2*node+1]; 37 | } 38 | } 39 | 40 | int lca(int node, int start, int end, int l, int r) 41 | { 42 | if(l > end or r < start) 43 | return -1; 44 | if(l <= start and end <= r) 45 | return segtree[node]; 46 | int mid = (start+end)/2; 47 | int p1 = lca(2*node, start, mid, l, r); 48 | int p2 = lca(2*node+1, mid+1, end, l, r); 49 | if(p1 == -1) return p2; 50 | if(p2 == -1) return p1; 51 | return deft[p1] < deft[p2] ? p1 : p2; 52 | } 53 | 54 | /*int _lca(int a, int b) 55 | { 56 | int ancestor = a, nivel = 0x3f3f3f3f; 57 | for(int i = pos[a]; i <= pos[b]; i++) 58 | if(deft[tl[i]] < nivel) 59 | { 60 | ancestor = tl[i]; 61 | nivel = deft[tl[i]]; 62 | } 63 | return ancestor; 64 | }*/ 65 | 66 | 67 | int main() 68 | { 69 | int n, u, v; 70 | 71 | cin >> n; 72 | for(int i = 0; i < n-1; i++) 73 | { 74 | cin >> u >> v; 75 | G[u].push_back(v); 76 | G[v].push_back(u); 77 | } 78 | 79 | 80 | tree_linearization(1, -1, 0); 81 | build(1, 0, tl.size()-1); 82 | 83 | /* 84 | for(int i = 1; i <= n; i++) 85 | cout << deft[i] << ' '; 86 | cout << '\n'; 87 | for(int i = 1; i <= n; i++) 88 | cout << pos[i] << ' '; 89 | cout << '\n'; 90 | for(const int &p : tl) 91 | cout << p << ' '; 92 | cout << '\n'; 93 | for(int i = 1; i <= 4*n; i++) 94 | cout << segtree[i] << ' '; 95 | cout << '\n';*/ 96 | 97 | while(cin >> u >> v) 98 | cout << /*_lca(u, v) << ' ' <<*/ 99 | lca(1, 0, tl.size()-1, pos[u], pos[v]) << '\n'; 100 | 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /code/graph/lca_with_tree_linearization_and_sparse_table.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int MAX = 1e5 + 10; 4 | 5 | int n, m; 6 | vector G[MAX], tl; 7 | int deft[MAX], SpT[27][MAX], pos[MAX]; 8 | 9 | void tree_linearization(int v, int p, int d) 10 | { 11 | deft[v] = d; 12 | pos[v] = tl.size(); 13 | tl.push_back(v); 14 | for(int &u : G[v]) 15 | { 16 | if(u != p) 17 | { 18 | tree_linearization(u, v, d + 1); 19 | tl.push_back(v); 20 | } 21 | } 22 | } 23 | 24 | void build(int tam) 25 | { 26 | for(int i = 0; (1 << i) <= tam; i++) 27 | { 28 | for(int j = 0; j + (1 << i) <= tam; j++) 29 | if(!i) 30 | SpT[i][j] = tl[j]; 31 | else if(deft[SpT[i-1][j]] < deft[SpT[i-1][j+(1<<(i-1))]]) 32 | SpT[i][j] = SpT[i-1][j]; 33 | else 34 | SpT[i][j] = SpT[i-1][j+(1<<(i-1))]; 35 | } 36 | } 37 | 38 | int lca(int i, int j) 39 | { 40 | int k = log2(j-i+1); 41 | if(deft[SpT[k][i]] < deft[SpT[k][j+1-(1<> n >> m; 52 | for(int i = 0; i < m; i++) 53 | { 54 | cin >> u >> v; 55 | G[u].push_back(v); 56 | G[v].push_back(u); 57 | } 58 | 59 | tree_linearization(1, -1, 0); 60 | build(tl.size()); 61 | 62 | cin >> q; 63 | while(q--) 64 | { 65 | cin >> u >> v; 66 | cout << lca(min(pos[u], pos[v]), max(pos[u], pos[v])) << '\n'; 67 | } 68 | 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /code/graph/longest_and_shortest_path_in_DAG.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const int OO = 0x3f3f3f3f; 4 | const int MAX = 1e6; 5 | 6 | using namespace std; 7 | 8 | int n, m; 9 | vector> G[MAX]; 10 | int dist1[MAX], dist2[MAX]; 11 | vector ts; 12 | bool cor[MAX]; 13 | 14 | void dfs(int v) 15 | { 16 | cor[v] = true; 17 | for(pair &w : G[v]) 18 | if(!cor[w.first]) 19 | dfs(w.first); 20 | ts.push_back(v); 21 | } 22 | 23 | // caminho de 0 a n-1 24 | pair longestAndShortestPathInDAG() 25 | { 26 | for(int i = 0; i <= n; i++) 27 | dist1[i] = -OO, dist2[i] = OO; 28 | dist1[0] = dist2[0] = 0; 29 | int p = 0; 30 | while(p < (int)ts.size()) 31 | { 32 | int v = ts[p++]; 33 | if(dist1[v] != -OO) 34 | for(int i = 0; i < (int)G[v].size(); i++) 35 | { 36 | int u = G[v][i].first, d = G[v][i].second; 37 | if(dist1[u] < dist1[v] + d) 38 | dist1[u] = dist1[v] + d; 39 | } 40 | if(dist2[v] != OO) 41 | for(int i = 0; i < (int)G[v].size(); i++) 42 | { 43 | int u = G[v][i].first, d = G[v][i].second; 44 | if(dist2[u] > dist2[v] + d) 45 | dist2[u] = dist2[v] + d; 46 | } 47 | } 48 | return {dist1[n-1], dist2[n-1]}; 49 | } 50 | 51 | int main() 52 | { 53 | cin >> n >> m; 54 | for(int i = 0; i < m; i++) 55 | { 56 | int u, v, w; 57 | cin >> u >> v >> w; u--; v--; 58 | G[u].push_back({v, w}); 59 | } 60 | for(int i = 0; i < n; i++) 61 | if(!cor[i]) 62 | dfs(i); 63 | reverse(ts.begin(), ts.end()); 64 | pair ans = longestAndShortestPathInDAG(); 65 | cout << "Longest Path " << ans.first << '\n'; 66 | cout << "Shortest Path " << ans.second << '\n'; 67 | 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /code/graph/maximum_clique.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | typedef long long ll; 4 | const int MAX = 43, C = 20; 5 | 6 | int n, m, dp[1 << C]; 7 | ll G[MAX]; 8 | 9 | int maxClique() 10 | { 11 | for(int i = 1; i < (1 << max(0, n - C)); i++) 12 | { 13 | int x = i; 14 | for(int j = 0; j < max(0, n - C); j++) 15 | if((i >> j) & 1) 16 | x &= G[j + C] >> C; 17 | if(x == i) dp[i] = __builtin_popcount(i); 18 | } 19 | for(int i = 1; i < (1 << max(0, n - C)); i++) 20 | for(int j = 0; j < max(0, n - C); j++) 21 | if((i >> j) & 1) 22 | dp[i] = max(dp[i], dp[i ^ (1 << j)]); 23 | int ans = 0; 24 | for(int i = 0; i < (1 << min(C, n)); i++){ 25 | int x = i, y = (1 << max(0, n - C)) - 1; 26 | for(int j = 0; j < min(C, n); j++) 27 | if((i >> j) & 1) 28 | x &= G[j], y &= G[j] >> C; 29 | if(x == i) 30 | ans = max(ans, __builtin_popcount(i) + dp[y]); 31 | } 32 | return ans; 33 | } 34 | 35 | int main() 36 | { 37 | cin >> n >> m; 38 | while(m--) 39 | { 40 | int u, v; 41 | cin >> u >> v; u--; v--; 42 | G[u] |= (1LL << v); 43 | G[v] |= (1LL << u); 44 | } 45 | for(int i = 0; i < n; i++) 46 | G[i] |= (1LL << i); 47 | cout << maxClique() << '\n'; 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /code/graph/min_cost_max_flow.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * from IME Library 3 | */ 4 | 5 | #include 6 | using namespace std; 7 | const int MAX = 1e3; 8 | const int OO = 0x3f3f3f3f; 9 | 10 | struct edge {int v, f, w, c; }; 11 | 12 | // flw_lmt eh a quantidade de de fluxo que posso passar 13 | // no maximo, alterar se necessario 14 | // node_count eh o valor do maior vertice no grafo... 15 | // inicializar node_count com numero de vertices no inicio... 16 | int node_count, flw_lmt = OO, p[MAX]; 17 | vector edges; 18 | vector G[MAX]; 19 | 20 | // u--->v, custo w e capacidade c 21 | void add_edge(int u, int v, int w, int c) 22 | { 23 | int k = edges.size(); 24 | node_count = max(node_count, u+1); 25 | node_count = max(node_count, v+1); 26 | G[u].push_back(k); 27 | G[v].push_back(k+1); 28 | edges.push_back({ v, 0, w, c }); 29 | edges.push_back({ u, 0, -w, 0 }); 30 | } 31 | 32 | void clear() 33 | { 34 | flw_lmt = OO; 35 | for(int i = 0; i < node_count; ++i) G[i].clear(); 36 | edges.clear(); 37 | node_count = 0; 38 | } 39 | 40 | bool SPFA(int s, int t) 41 | { 42 | vector dist(node_count, OO); 43 | vector et(node_count, 0); 44 | deque q; 45 | q.push_back(s), dist[s] = 0; 46 | while (!q.empty()) 47 | { 48 | int u = q.front(); q.pop_front(); 49 | et[u] = 2; 50 | for(int i : G[u]) 51 | { 52 | edge &e = edges[i]; 53 | int v = e.v; 54 | if (e.f < e.c and dist[v] > dist[u] + e.w) 55 | { 56 | dist[v] = dist[u] + e.w; 57 | if (et[v] == 0) q.push_back(v); 58 | else if (et[v] == 2) q.push_front(v); 59 | et[v] = 1; 60 | p[v] = i; 61 | } 62 | } 63 | } 64 | return dist[t] != OO; 65 | } 66 | 67 | int min_cost_max_flow(int s, int t) 68 | { 69 | int mf = 0, cost = 0; 70 | while(SPFA(s, t) and mf < flw_lmt) 71 | { 72 | int inc = flw_lmt - mf; 73 | for (int u = t; u != s; u = edges[p[u]^1].v) 74 | { 75 | edge &e = edges[p[u]]; 76 | inc = min(inc, e.c - e.f); 77 | } 78 | for (int u = t; u != s; u = edges[p[u]^1].v) 79 | { 80 | edge &e = edges[p[u]], &rev = edges[p[u]^1]; 81 | e.f += inc; 82 | rev.f -= inc; 83 | cost += inc * e.w; 84 | } 85 | if (!inc) break; 86 | mf += inc; 87 | } 88 | cout << "Max Flow " << mf << '\n'; 89 | cout << "Min Cost " << cost << '\n'; 90 | return cost; 91 | } 92 | 93 | int main() 94 | { 95 | 96 | 97 | return 0; 98 | } 99 | -------------------------------------------------------------------------------- /code/graph/prim.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int MAX = 1e5; 4 | const int OO = 0x3f3f3f3f; 5 | typedef pair ii; 6 | typedef pair iii; 7 | 8 | int n, m; 9 | vector G[MAX]; 10 | int dist[MAX], edge[MAX]; 11 | bool visit[MAX]; 12 | 13 | void prim(int s) 14 | { 15 | memset(visit, 0, sizeof(visit)); 16 | memset(dist, 63, sizeof(dist)); 17 | dist[s] = 0; 18 | priority_queue pq; 19 | pq.push({0, s}); 20 | while(!pq.empty()) 21 | { 22 | int u = pq.top().second; 23 | pq.pop(); 24 | if(visit[u]) continue; 25 | for(int i = 0; i < G[u].size(); i++) 26 | { 27 | int v = G[u][i].second, d = G[u][i].first; 28 | if(!visit[v] and dist[v] > d) 29 | { 30 | dist[v] = d; 31 | edge[v] = u; 32 | pq.push({-d, v}); 33 | } 34 | } 35 | visit[u] = true; 36 | } 37 | int ans = 0; 38 | edge[s] = -2; 39 | for(int i = 0; i < n; i++) 40 | { 41 | cout << edge[i]+1 << ' '; 42 | ans += dist[i]; 43 | } 44 | cout << '\n'; 45 | cout << ans << '\n'; 46 | } 47 | 48 | int main() 49 | { 50 | int u, v, w; 51 | 52 | cin >> n >> m; 53 | while(m--) 54 | { 55 | cin >> u >> v >> w; u--; v--; 56 | G[u].push_back({w, v}); 57 | G[v].push_back({w, u}); 58 | } 59 | prim(0); 60 | 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /code/graph/tree_isomorfism.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int ms = 100100; 5 | 6 | int degree[ms], vis[ms]; 7 | int size[ms]; 8 | int n; 9 | 10 | bool cmp(int a, int b) 11 | { 12 | return size[a] < size[b]; 13 | } 14 | 15 | void pre(vector> &edges, int on = 0) 16 | { 17 | size[on] = 1; 18 | for(auto to : edges[on]) 19 | { 20 | pre(edges, to); 21 | size[on] += size[to]; 22 | } 23 | sort(edges[on].begin(), edges[on].end(), cmp); 24 | } 25 | 26 | void solve(vector> &edges, string &str, int on = 0) 27 | { 28 | str += 'D'; 29 | for(int l = 0, r = 0; l < edges[on].size(); l = r) { 30 | while(r < edges[on].size() && 31 | size[edges[on][l]] == size[edges[on][r]]) r++; 32 | if(r == l + 1) 33 | solve(edges, str, edges[on][l]); 34 | else 35 | { 36 | priority_queue hp; 37 | for(int i = l; i < r; i++) { 38 | string temp; 39 | solve(edges, temp, edges[on][i]); 40 | hp.push(temp); 41 | } 42 | while(!hp.empty()) 43 | { 44 | str += hp.top(); 45 | hp.pop(); 46 | } 47 | } 48 | } 49 | str += 'U'; 50 | } 51 | 52 | // enraizar arvore 53 | void mount(vector> &graph, 54 | vector> &G, int v = 0, int p = -1) 55 | { 56 | for(int &u : G[v]) 57 | if(u != p) 58 | { 59 | graph[v].push_back(u); 60 | mount(graph, G, u, v); 61 | } 62 | } 63 | 64 | // achar centro da arvore e enraizar no centro 65 | void findCenterAndComputeStr(vector> &graph, 66 | vector> &G, string *str) 67 | { 68 | memset(vis, 0, sizeof(vis)); 69 | queue fila[2]; 70 | for(int i = 0; i < n; i++) 71 | if(degree[i] == 1) 72 | fila[0].push(i); 73 | int cnt = 0, turn = 0; 74 | while(cnt + 2 < n) 75 | { 76 | while(!fila[turn].empty()) 77 | { 78 | int u = fila[turn].front(); fila[turn].pop(); 79 | vis[u] = true; 80 | cnt++; 81 | for(int i = 0; i < G[u].size(); i++) 82 | if(!vis[G[u][i]]) 83 | { 84 | degree[G[u][i]]--; 85 | if(degree[G[u][i]] == 1) 86 | fila[1-turn].push(G[u][i]); 87 | } 88 | } 89 | turn ^= 1; 90 | } 91 | int k = 0; 92 | for(int i = 0; i < n; i++) 93 | { 94 | if(vis[i]) continue; 95 | graph.clear(); 96 | graph.resize(n + 1); 97 | mount(graph, G, i); 98 | pre(graph, i); 99 | solve(graph, str[k], i); 100 | k++; 101 | } 102 | } 103 | 104 | int main() 105 | { 106 | while(cin >> n) 107 | { 108 | string str[2][2]; 109 | for(int i = 0; i < 2; i++) 110 | { 111 | vector> graph, G; 112 | G.resize(n + 1); 113 | memset(degree, 0, sizeof(degree)); 114 | for(int j = 1; j < n; j++) 115 | { 116 | int u, v; 117 | scanf(" %d %d", &u, &v); v--; u--; 118 | 119 | G[v].push_back(u); 120 | G[u].push_back(v); 121 | degree[v]++; 122 | degree[u]++; 123 | } 124 | findCenterAndComputeStr(graph, G, str[i]); 125 | } 126 | bool fl = (str[0][0] == str[1][0]) or (str[0][0] == str[1][1]); 127 | fl |= ((str[0][1] == str[1][0]) or (str[0][0] == str[1][1])); 128 | puts(fl ? "S" : "N"); 129 | } 130 | 131 | return 0; 132 | } 133 | 134 | -------------------------------------------------------------------------------- /code/math/Mod_Integer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | 5 | template 6 | struct ModInt { 7 | const static T MOD = 1000000007; //1e9 + 7 8 | 9 | T v; explicit operator T() const { return v; } 10 | 11 | ModInt() { v = 0; } 12 | ModInt(T _v) { 13 | v = (-MOD < _v && _v < MOD) ? _v : _v % MOD; 14 | if (v < 0) v += MOD; 15 | } 16 | friend bool operator==(const ModInt& a, const ModInt& b) { 17 | return a.v == b.v; } 18 | friend bool operator!=(const ModInt& a, const ModInt& b) { 19 | return !(a == b); } 20 | friend bool operator<(const ModInt& a, const ModInt& b) { 21 | return a.v < b.v; } 22 | 23 | ModInt& operator+=(const ModInt& m) { 24 | if ((v += m.v) >= MOD) v -= MOD; 25 | return *this; } 26 | ModInt& operator-=(const ModInt& m) { 27 | if ((v -= m.v) < 0) v += MOD; 28 | return *this; } 29 | ModInt& operator*=(const ModInt& m) { 30 | v = v*m.v%MOD; return *this; } 31 | ModInt& operator/=(const ModInt& m) { return (*this) *= inv(m); } 32 | friend ModInt pow(ModInt a, T p) { 33 | assert(p >= 0); 34 | ModInt ans = 1; 35 | while(p) { 36 | if(p & 1) ans *= a; 37 | a *= a; 38 | p /= 2; 39 | } 40 | return ans; 41 | } 42 | friend ModInt inv(const ModInt& a) { assert(a.v != 0); 43 | return pow(a,MOD-2); } 44 | 45 | ModInt operator-() const { return ModInt(-v); } 46 | ModInt& operator++() { return *this += 1; } 47 | ModInt& operator--() { return *this -= 1; } 48 | ModInt operator++(int) { ModInt temp; temp.v = v++; return temp; } 49 | ModInt operator--(int) { ModInt temp; temp.v = v--; return temp; } 50 | friend ModInt operator+(ModInt a, const ModInt& b) { return a += b; } 51 | friend ModInt operator-(ModInt a, const ModInt& b) { return a -= b; } 52 | friend ModInt operator*(ModInt a, const ModInt& b) { return a *= b; } 53 | friend ModInt operator/(ModInt a, const ModInt& b) { return a /= b; } 54 | friend ostream& operator<<(ostream& os, const ModInt& m) { 55 | os << m.v; return os; 56 | } 57 | friend istream& operator>>(istream& is, ModInt& m) { 58 | T x; is >> x; 59 | m.v = x; 60 | return is; 61 | } 62 | }; 63 | 64 | int main(){ 65 | ModInt x = 5; 66 | cout << x << ' ' << inv(x) << '\n'; 67 | cout << x.MOD << '\n'; 68 | 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /code/math/baby_step_giant_step.cpp: -------------------------------------------------------------------------------- 1 | // a ^ kcongb mod m 2 | 3 | int value[1000008]; 4 | int cor[1000008], tempo = 1; 5 | 6 | // com vetor o modulo deve ser <= 10^7 fica O(sqrt(m)) 7 | inline int discreteLogarithm(int a, int b, int m) { 8 | tempo++; 9 | a %= m; b %= m; 10 | int n = (int)sqrt(m + .0) + 1, an = 1; 11 | for(int i = 1; i <= n; i++) an = (an * 1LL * a) % m; 12 | for(int i = 1, cur = an; i <= n; i++) { 13 | if(cor[cur] < tempo) value[cur] = i, cor[cur] = tempo; 14 | cur = (cur * 1LL * an) % m; 15 | } 16 | for(int j = 0, cur = b; j <= n; j++) { 17 | if(cor[cur] == tempo) { 18 | int ans = value[cur] * n - j; 19 | if(ans < m) 20 | return ans; 21 | } 22 | cur = (cur * 1LL * a) % m; 23 | } 24 | return -1; 25 | } 26 | 27 | // com mapa o modulo pode ser ateh <= 10^12 fica O(sqrt(m) * log(m)) 28 | int discreteLogarithm(int a, int b, int m) 29 | { 30 | a %= m; b %= m; 31 | int n = (int)sqrt(m + .0) + 1, an = 1; 32 | for(int i = 1; i <= n; i++) an = (an * a) % m; 33 | unordered_map value; 34 | for(int i = 1, cur = an; i <= n; i++) { 35 | if(!value.count(cur)) value[cur] = i; 36 | cur = (cur * an) % m; 37 | } 38 | for(int j = 0, cur = b; j <= n; j++) { 39 | if(value[cur]) { 40 | int ans = value[cur] * n - j; 41 | if(ans < m) 42 | return ans; 43 | } 44 | cur = (cur * a) % m; 45 | } 46 | return -1; 47 | } -------------------------------------------------------------------------------- /code/math/catalan_numbers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int MAX = 1e5 + 10; 5 | const long long MOD = 1000000000; 6 | 7 | int catalan[MAX]; 8 | 9 | void init() 10 | { 11 | catalan[0] = catalan[1] = 1; 12 | for(int i = 2; i <= 1000; i++) 13 | for(int j = 0; j < i; j++) 14 | { 15 | catalan[i] += (catalan[j] * catalan[i-j-1]) % MOD; 16 | if(catalan[i] >= MOD) 17 | catalan[i] -= MOD; 18 | } 19 | } 20 | 21 | int main() 22 | { 23 | init(); 24 | int n; 25 | 26 | while(cin >> n) 27 | printf("%d\n", catalan[n]); 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /code/math/chinese_remainder_theorem.cpp: -------------------------------------------------------------------------------- 1 | //codar em Python para evitar problemas de overflow 2 | // O(Tlog(lcm(n1*n2*..))) 3 | //https://codeforces.com/blog/entry/61290 4 | 5 | #include 6 | using namespace std; 7 | const int MAX = 20; 8 | #define ll long long 9 | 10 | ll GCD(ll a, ll b) { return (b == 0) ? a : GCD(b, a % b); } 11 | 12 | inline ll LCM(ll a, ll b) { return a / GCD(a, b) * b; } 13 | 14 | inline ll normalize(ll x, ll mod) { x %= mod; if (x < 0) x += mod; return x; } 15 | 16 | struct GCD_type { ll x, y, d; }; 17 | 18 | GCD_type ex_GCD(ll a, ll b) 19 | { 20 | if (b == 0) return {1, 0, a}; 21 | GCD_type pom = ex_GCD(b, a % b); 22 | return {pom.y, pom.x - a / b * pom.y, pom.d}; 23 | } 24 | 25 | int t; 26 | ll a[MAX], n[MAX], ans, lcm; 27 | 28 | int main() 29 | { 30 | cin >> t; 31 | for(int i = 1; i <= t; i++) 32 | cin >> a[i] >> n[i], normalize(a[i], n[i]); 33 | ans = a[1]; 34 | lcm = n[1]; 35 | for(int i = 2; i <= t; i++) 36 | { 37 | auto pom = ex_GCD(lcm, n[i]); 38 | ll x1 = pom.x; 39 | ll d = pom.d; 40 | if((a[i] - ans) % d != 0) return cerr << "No solutions" << endl, 0; 41 | ans = normalize(ans + x1 * (a[i] - ans) / d % (n[i] / d) * lcm, 42 | lcm * n[i] / d); 43 | lcm = LCM(lcm, n[i]); 44 | // you can save time by replacing above lcm * n[i] /d 45 | // by lcm = lcm * n[i] / d 46 | } 47 | cout << ans << " " << lcm << endl; 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /code/math/conversion_base.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int a,b; char sa[10000]; char sb[10000]; 5 | 6 | void rev(char s[]) 7 | { 8 | int l = strlen(s); 9 | for(int i = 0; i < l - 1 - i; i++) 10 | swap(s[i], s[l - 1 - i]); 11 | } 12 | 13 | void multi(char s[], int k) 14 | { 15 | int i, c = 0, d; 16 | for(i=0;s[i];i++) 17 | { 18 | d = (s[i] - '0') * k + c; 19 | c = d / b; d %= b; 20 | s[i] = '0' + d; 21 | } 22 | while(c) 23 | { 24 | s[i] = '0' + (c % b); i++; 25 | c /= b; 26 | } 27 | s[i] = '\0'; 28 | } 29 | 30 | void add(char s[], int k) 31 | { 32 | int i, c = k, d; 33 | for(i = 0; s[i]; i++) 34 | { 35 | d = (s[i] - '0') + c; 36 | c = d / b; d %= b; 37 | s[i] = '0' + d; 38 | } 39 | while(c) 40 | { 41 | s[i] = '0' + (c % b); i++; 42 | c /= b; 43 | } 44 | s[i]='\0'; 45 | } 46 | 47 | void trans(char s[]) 48 | { 49 | for(int i = 0; s[i]; i++) 50 | { 51 | char& c = s[i]; 52 | if(c >= 'A' && c <= 'Z') c = '0' + 10 + (c - 'A'); 53 | if(c >= 'a' && c <= 'z') c = '0' + 36 + (c - 'a'); 54 | } 55 | } 56 | 57 | void itrans(char s[]) 58 | { 59 | for(int i = 0; s[i]; i++) 60 | { 61 | char& c = s[i]; int d = c - '0'; 62 | if(d >= 10 && d <= 35) c = 'A' + (d - 10); 63 | if(d >= 36) c = 'a' + (d - 36); 64 | } 65 | } 66 | 67 | int main() 68 | { 69 | //digitos {0-9,A-Z,a-z} 70 | int q; cin>>q; 71 | int i,j; 72 | while(q) 73 | { 74 | q--; 75 | 76 | cin >> a >> b >> sa; sb[0] = '0'; sb[1] = '\0'; 77 | // a e b sao dados na base 10 78 | // sa eh dado na base a 79 | // converter sa da base a pra base b 80 | cout << a << " " << sa << '\n'; 81 | trans(sa); 82 | for(i = 0; sa[i]; i++) 83 | { 84 | multi(sb, a); 85 | add(sb, sa[i] - '0'); 86 | } 87 | rev(sb); 88 | itrans(sb); 89 | // sb eh a na base b 90 | cout << b << " " << sb << '\n'; 91 | puts(""); 92 | } 93 | return 0; 94 | } 95 | -------------------------------------------------------------------------------- /code/math/counting_number_of_times_that_a_digit_appears_until_n.cpp: -------------------------------------------------------------------------------- 1 | ll digits(int n, int d) 2 | { 3 | ll res = 0, pot = 1, rem = 0; 4 | while (n) 5 | { 6 | int x = n%10; 7 | n /= 10; 8 | if (x > d) res += (n+1)*pot; 9 | else res += n*pot; 10 | if (x == d) res += rem+1; 11 | if (d == 0) res -= pot; 12 | rem += pot * x; 13 | pot *= 10; 14 | } 15 | return res; 16 | } 17 | -------------------------------------------------------------------------------- /code/math/gaussian_elimination_for_max_subset_xor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #define ull unsigned long long 5 | 6 | int MSB(ull n) 7 | { 8 | int cnt = 0; 9 | while(n) 10 | { 11 | cnt++; 12 | n >>= 1; 13 | } 14 | return cnt; 15 | } 16 | 17 | int main() 18 | { 19 | int n; 20 | cin >> n; 21 | ull a[n]; 22 | for(int i = 0; i < n; i++) 23 | cin >> a[i]; 24 | int lengths[n]; 25 | for(int i = 0; i < n; i++) 26 | lengths[i] = MSB(a[i]); 27 | //eh um array que armazena os coeficientes 28 | //das equacoes 29 | vector buckets[65]; 30 | //para a Gaussian Elimination, semelhante 31 | //a linha da matriz em algebra linear 32 | for(int i = 0; i < n; i++) 33 | buckets[lengths[i]].push_back(a[i]); 34 | ull modified_array[100], m_index = 0; 35 | 36 | // Gaussian Elimination 37 | for(int i = 64; i > 0; i--) 38 | if(buckets[i].size()) 39 | { 40 | modified_array[m_index++] = buckets[i][0]; 41 | for(int j = 1; j < buckets[i].size(); j++) 42 | { 43 | ull temp = buckets[i][0] ^ buckets[i][j]; 44 | int len = MSB(temp); 45 | buckets[len].push_back(temp); 46 | } 47 | } 48 | ull ans = 0; 49 | for(int i = 0; i < m_index; i++) 50 | if(ans < (ans ^ modified_array[i])) 51 | ans = (ans ^ modified_array[i]); 52 | cout << ans << '\n'; 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /code/math/karatsuba.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | typedef vector vll; 5 | 6 | vll karatsubaMultiply(const vll &a, const vll &b) { 7 | int n = a.size(); 8 | vll res(n + n); 9 | if (n <= 32) { 10 | for (int i = 0; i < n; i++) 11 | for (int j = 0; j < n; j++) 12 | res[i + j] += a[i] * b[j]; 13 | return res; 14 | } 15 | 16 | int k = n >> 1; 17 | vll a1(a.begin(), a.begin() + k); 18 | vll a2(a.begin() + k, a.end()); 19 | vll b1(b.begin(), b.begin() + k); 20 | vll b2(b.begin() + k, b.end()); 21 | 22 | vll a1b1 = karatsubaMultiply(a1, b1); 23 | vll a2b2 = karatsubaMultiply(a2, b2); 24 | 25 | for(int i = 0; i < k; i++) 26 | a2[i] += a1[i]; 27 | for(int i = 0; i < k; i++) 28 | b2[i] += b1[i]; 29 | 30 | vll r = karatsubaMultiply(a2, b2); 31 | 32 | for(int i = 0; i < (int) a1b1.size(); i++) 33 | r[i] -= a1b1[i]; 34 | for(int i = 0; i < (int) a2b2.size(); i++) 35 | r[i] -= a2b2[i]; 36 | 37 | for(int i = 0; i < (int) r.size(); i++) 38 | res[i + k] += r[i]; 39 | for(int i = 0; i < (int) a1b1.size(); i++) 40 | res[i] += a1b1[i]; 41 | for(int i = 0; i < (int) a2b2.size(); i++) 42 | res[i + n] += a2b2[i]; 43 | return res; 44 | } 45 | 46 | int main() 47 | { 48 | vll a = {8, 7, 5}; 49 | vll b = {12}; 50 | 51 | vll c = karatsubaMultiply(a, b); 52 | 53 | for(auto it : c) cout << it << ' '; puts(""); 54 | 55 | return 0; 56 | } 57 | 58 | -------------------------------------------------------------------------------- /code/math/matrix_exponentiation.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define matrix vector> 4 | 5 | matrix init(int n, int m, int value = 0) 6 | { 7 | return vector>(n, vector(m, value)); 8 | } 9 | 10 | void printtt(const matrix &M) 11 | { 12 | for(int i = 0; i < M.size(); i++) 13 | { 14 | for(int j = 0; j < M[0].size(); j++) 15 | cout << M[i][j] << ' '; 16 | puts(""); 17 | } 18 | } 19 | 20 | matrix multiply(const matrix &A, const matrix &B) 21 | { 22 | matrix C = init(A.size(), B[0].size()); 23 | for(int i = 0; i < A.size(); i++) 24 | for(int j = 0; j < B[i].size(); j++) 25 | for(int k = 0; k < B.size(); k++) 26 | C[i][j] += A[i][k] * B[k][j]; 27 | return C; 28 | } 29 | 30 | matrix exp(matrix M, int k) 31 | { 32 | matrix I = init(M.size(), M[0].size()); 33 | for(int i = 0; i < M.size(); i++) I[i][i] = 1; 34 | while(k) 35 | if(k & 1) I = multiply(I, M), k--; 36 | else M = multiply(M, M), k /= 2; 37 | return I; 38 | } 39 | 40 | 41 | int determinantOfMatrix(matrix mat) 42 | { 43 | int n = mat.size(); 44 | int num1, num2, det = 1, index, total = 1; 45 | int temp[n + 1]; 46 | for(int i = 0; i < n; i++) 47 | { 48 | index = i; 49 | while(mat[index][i] == 0 and index < n) 50 | index++; 51 | if(index == n) 52 | continue; 53 | if(index != i) 54 | { 55 | for(int j = 0; j < n; j++) 56 | swap(mat[index][j], mat[i][j]); 57 | det = det*pow(-1,index-i); 58 | } 59 | for(int j = 0; j < n; j++) 60 | temp[j] = mat[i][j]; 61 | for(int j = i+1; j < n; j++) 62 | { 63 | num1 = temp[i]; 64 | num2 = mat[j][i]; 65 | for(int k = 0; k < n; k++) 66 | mat[j][k] = (num1 * mat[j][k]) - (num2 * temp[k]); 67 | total = total * num1; 68 | } 69 | } 70 | for(int i = 0; i < n; i++) 71 | det = det * mat[i][i]; 72 | return (det/total); 73 | } 74 | 75 | 76 | int32_t main() 77 | { 78 | int n, m; 79 | 80 | cin >> n >> m; 81 | matrix A = init(n, m); 82 | for(int i = 0; i < n; i++) 83 | for(int j = 0; j < m; j++) 84 | cin >> A[i][j]; 85 | matrix C = exp(A, 7); 86 | printtt(C); 87 | 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /code/math/miller_rabin.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define ll long long 4 | 5 | ll add(ll a, ll b, ll c) 6 | { 7 | ll ans = (a + b) % c; 8 | if(ans < 0) ans += c; 9 | return ans; 10 | } 11 | 12 | ll mulmod(ll a, ll b, ll c) 13 | { 14 | ll ans = 0; 15 | while(b) 16 | { 17 | if(b & 1) ans = add(ans, a, c); 18 | a = add(a, a, c); 19 | b /= 2; 20 | } 21 | return ans; 22 | } 23 | 24 | ll fexp(ll a, ll b, ll c) 25 | { 26 | ll ans = 1; 27 | while(b) 28 | { 29 | if(b & 1) ans = mulmod(ans, a, c); 30 | a = mulmod(a, a, c); 31 | b /= 2; 32 | } 33 | return ans; 34 | } 35 | 36 | bool miller(ll a, ll n) 37 | { 38 | if (a >= n) return true; 39 | ll s = 0, d = n - 1; 40 | while(d%2 == 0 and d) d >>= 1, s++; 41 | ll x = fexp(a, d, n); 42 | if(x == 1 or x == n - 1) return true; 43 | for(int r = 0; r < s; r++, x = mulmod(x, x, n)) 44 | { 45 | if (x == 1) return false; 46 | if (x == n-1) return true; 47 | } 48 | return false; 49 | } 50 | 51 | bool isprime(ll n) 52 | { 53 | int base[] = {2, 3, 5, 7, 11, 54 | 13, 17, 19, 23, 29, 31, 37}; 55 | for(int i = 0; i < 12; i++) 56 | if(!miller(base[i], n)) 57 | return false; 58 | return true; 59 | } 60 | 61 | int32_t main() 62 | { 63 | ll n; 64 | cin >> n; 65 | cout << (isprime(n) ? "PRIME\n" 66 | : "NOT PRIME\n"); 67 | 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /code/math/mobius.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | - mi(n) = 0 se n tem como divisor um outro numero 3 | natural ao quadrado 4 | - mi(n) = 1 se n nao tem como divisor um outro 5 | numero natural ao quadrado 6 | e eh decomposto em uma quantidade par de 7 | numeros primos 8 | - mi(n) = -1 se n nao tem como divisor um outro 9 | numero natural ao quadrado 10 | e eh decomposto em uma quantidade impar de 11 | numeros primos 12 | */ 13 | 14 | #include "bits/stdc++.h" 15 | using namespace std; 16 | const int MAX = 1e6; 17 | 18 | bool np[MAX]; 19 | int mob[MAX]; 20 | 21 | void mobius() 22 | { 23 | for(int i = 1; i < MAX; i++) 24 | mob[i] = 1; 25 | for(int i = 2; i < MAX; i++) 26 | { 27 | if(np[i]) continue; 28 | for(int j = i; j < MAX; j += i) 29 | { 30 | np[j] = true; 31 | mob[j] *= -1; 32 | if((j / i) % i == 0) 33 | mob[j] = 0; 34 | } 35 | } 36 | } 37 | 38 | int main() 39 | { 40 | mobius(); 41 | 42 | for(int i = 2; i <= 10; i++) 43 | cout << i << ' ' << mob[i] << '\n'; 44 | puts(""); 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /code/math/mod_gaussian_elimination.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | //#define int long long 4 | #define pb push_back 5 | #define inf 0x3f3f3f3f 6 | 7 | int MOD = 1000000007LL; 8 | 9 | inline int prod(int a, int b) 10 | { 11 | return ((((a % MOD) * 1LL * (b % MOD)) % MOD) + MOD) % MOD; 12 | } 13 | 14 | inline int sub(int a, int b) 15 | { 16 | return ((((a % MOD) - (b % MOD)) % MOD) + MOD) % MOD; 17 | } 18 | 19 | inline int expMod(int x, int e) 20 | { 21 | int ans = 1; 22 | while(e > 0) 23 | { 24 | if(e & 1LL) ans = prod(ans, x), e--; 25 | else x = prod(x, x), e /= 2; 26 | } 27 | return ans; 28 | } 29 | 30 | inline int inv(int x) 31 | { 32 | return expMod(x, MOD - 2); 33 | } 34 | 35 | inline int gauss (vector> a, int mod) 36 | { 37 | MOD = mod; 38 | 39 | int n = (int) a.size(); 40 | int m = (int) a[0].size(); 41 | 42 | vector where (m, -1); 43 | for(int col = 0, row = 0; col < m and row < n; ++col) 44 | { 45 | int sel = row; 46 | for(int i = row; i < n; ++i) 47 | if(abs(a[i][col]) > abs(a[sel][col])) 48 | sel = i; 49 | if(a[sel][col] == 0) 50 | continue; 51 | for(int i = col; i < m; ++i) 52 | swap(a[sel][i], a[row][i]); 53 | where[col] = row; 54 | for(int i = row + 1; i < n; ++i) 55 | { 56 | int c = prod(a[i][col], inv(a[row][col])); 57 | for(int j = col; j < m; ++j) 58 | a[i][j] = sub(a[i][j], prod(a[row][j], c)); 59 | } 60 | ++row; 61 | } 62 | int ans = 0; 63 | for(int i = 0; i < m; ++i) 64 | if(where[i] != -1) 65 | ans++; 66 | return n - ans; 67 | } 68 | 69 | int32_t main() 70 | { 71 | int n, m, a, k, t, caso = 1; 72 | 73 | cin >> t; 74 | while(t--) 75 | { 76 | scanf(" %d %d %d", &n, &m, &k); 77 | vector> A(n, vector(n)); 78 | while(m--) 79 | { 80 | int u, v; 81 | scanf(" %d %d", &u, &v), u--; v--; 82 | A[u][v] = A[v][u] = 1; 83 | if(u != v) A[u][v] = A[v][u] = k - 1; 84 | } 85 | for(int i = 0; i < n; i++) A[i][i] = 1; 86 | int ans = gauss(A, k); 87 | MOD = 1000000007LL; 88 | printf("Case %d: %d\n", caso++, expMod(k, ans)); 89 | } 90 | 91 | return 0; 92 | } 93 | 94 | -------------------------------------------------------------------------------- /code/math/modular_arithmetic.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define int long long 4 | const int MOD = 1000000007LL; 5 | 6 | int normalize(int x) 7 | { 8 | x = x % MOD; 9 | if(x < 0) x += MOD; 10 | return x; 11 | } 12 | 13 | int add(int a, int b) 14 | { 15 | return normalize(normalize(a) + normalize(b)); 16 | } 17 | 18 | int prod(int a, int b) 19 | { 20 | return normalize(normalize(a) * normalize(b)); 21 | } 22 | 23 | int sub(int a, int b) 24 | { 25 | return normalize(normalize(a) - normalize(b)); 26 | } 27 | 28 | int expMod(int x, int e) 29 | { 30 | int ans = 1; 31 | while(e > 0) 32 | { 33 | if(e & 1LL) ans = prod(ans, x), e--; 34 | else x = prod(x, x), e /= 2; 35 | } 36 | return normalize(ans); 37 | } 38 | 39 | int inv(int x) 40 | { 41 | return expMod(x, MOD - 2); 42 | } 43 | 44 | 45 | int extended_euclidean(int a, int b, int& x, int& y) { 46 | if (b == 0) { 47 | x = 1; 48 | y = 0; 49 | return a; 50 | } 51 | int x1, y1; 52 | int d = extended_euclidean(b, a % b, x1, y1); 53 | x = y1; 54 | y = x1 - y1 * (a / b); 55 | return d; 56 | } 57 | 58 | int inv(int a, int m) { 59 | int x, y; 60 | int g = extended_euclidean(a, m, x, y); 61 | if (g != 1) return -1; // nao tem inverso 62 | return ((x % m) + m) % m; 63 | } 64 | 65 | -------------------------------------------------------------------------------- /code/math/mulmod_trick.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | typedef long long ll; 4 | 5 | ll mulmod(ll a, ll b, ll m) 6 | { 7 | ll q = ll((long double)a*b/m); 8 | ll r = a * b - m * q; 9 | while(r < 0) r += m; 10 | while(r >= m) r -= m; 11 | return r; 12 | } 13 | 14 | int main() 15 | { 16 | ll a, b, c; 17 | 18 | cin >> a >> b >> c; 19 | cout << mulmod(a, b, c) << '\n'; 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /code/math/pollard_rho.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define ll long long 4 | 5 | ll llrand() 6 | { 7 | ll tmp = rand(); 8 | return (tmp << 31) | rand(); 9 | } 10 | 11 | ll add(ll a, ll b, ll c) 12 | { 13 | ll ans = (a + b) % c; 14 | if(ans < 0) ans += c; 15 | return ans; 16 | } 17 | 18 | ll mulmod(ll a, ll b, ll c) 19 | { 20 | ll ans = 0; 21 | while(b) 22 | { 23 | if(b & 1) ans = add(ans, a, c); 24 | a = add(a, a, c); 25 | b /= 2; 26 | } 27 | return ans; 28 | } 29 | 30 | ll rho(ll n) 31 | { 32 | if(n % 2 == 0) return 2; 33 | ll d = n; 34 | while(d == n) 35 | { 36 | ll c = llrand() % n, x = llrand() % n, y = x; 37 | do 38 | { 39 | x = add(mulmod(x, x, n), c, n); 40 | y = add(mulmod(y, y, n), c, n); 41 | y = add(mulmod(y, y, n), c, n); 42 | d = __gcd(abs(x - y), n); 43 | }while(d == 1); 44 | } 45 | return d; 46 | } 47 | 48 | // Miller-Rabin AQUI 49 | 50 | vector fac; 51 | 52 | void factors(ll n) // encontrar os fatores primos de N 53 | {// Usar Miller-Rabin para testar se N eh primo 54 | if(n == 1) return; 55 | if(isprime(n)) { fac.push_back(n); return; } 56 | ll d = rho(n); 57 | factors(d); 58 | factors(n / d); 59 | } 60 | 61 | int32_t main() 62 | { 63 | srand(time(NULL)); 64 | ll n; 65 | cin >> n; 66 | cout << rho(n) << '\n'; 67 | 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /code/miscellaneous/big_num_product.cpp: -------------------------------------------------------------------------------- 1 | string mul(string a, string b) 2 | { 3 | while(a.size() > b.size()) b = "0" + b; 4 | while(a.size() < b.size()) a = "0" + a; 5 | a = "00" + a; 6 | b = "00" + b; 7 | int ans = 0, n = a.size(), carry = 0; 8 | vector num(2 * n, 0); 9 | for(int i = n - 1; i >= 0; i--) 10 | for(int j = n - 1; j >= 0; j--) 11 | { 12 | int di = a[i] - '0'; 13 | int dj = b[j] - '0'; 14 | num[i + j + 1] += (di * dj) + carry; 15 | carry = (num[i + j + 1] / 10); 16 | num[i + j + 1] %= 10; 17 | } 18 | string r; 19 | for(int i = 0, fl = 0; i < 2 * n; i++) 20 | { 21 | if(num[i]) fl = 1; 22 | if(fl) r.push_back(num[i] + '0'); 23 | } 24 | return r; 25 | 26 | -------------------------------------------------------------------------------- /code/miscellaneous/count_divisors.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | long long add(long long a, long long b, long long c) 5 | { 6 | long long ans = (a + b) % c; 7 | if(ans < 0) ans += c; 8 | return ans; 9 | } 10 | 11 | long long mulmod(long long a, long long b, long long c) 12 | { 13 | long long ans = 0; 14 | while(b) 15 | { 16 | if(b & 1) ans = add(ans, a, c); 17 | a = add(a, a, c); 18 | b /= 2; 19 | } 20 | return ans; 21 | } 22 | 23 | long long fexp(long long a, long long b, long long c) 24 | { 25 | long long ans = 1; 26 | while(b) 27 | { 28 | if(b & 1) ans = mulmod(ans, a, c); 29 | a = mulmod(a, a, c); 30 | b /= 2; 31 | } 32 | return ans; 33 | } 34 | 35 | bool miller(long long a, long long n) 36 | { 37 | if (a >= n) return true; 38 | long long s = 0, d = n - 1; 39 | while(d%2 == 0 and d) d >>= 1, s++; 40 | long long x = fexp(a, d, n); 41 | if(x == 1 or x == n - 1) return true; 42 | for(int r = 0; r < s; r++, x = mulmod(x, x, n)) 43 | { 44 | if (x == 1) return false; 45 | if (x == n-1) return true; 46 | } 47 | return false; 48 | } 49 | 50 | bool isprime(long long n) 51 | { 52 | if(n < 2) return false; 53 | int base[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}; 54 | for(int i = 0; i < 12; i++) 55 | if(!miller(base[i], n)) 56 | return false; 57 | return true; 58 | } 59 | 60 | vector prime; 61 | bitset<10000000> composite; 62 | 63 | void sieve() 64 | { 65 | for(int i = 2; i < 10000000; i++) 66 | if(!composite[i]) 67 | { 68 | prime.push_back(i); 69 | for(int j = 2; i * j < 10000000; j++) 70 | composite[i * j] = 1; 71 | } 72 | } 73 | 74 | long long countDivisors(long long n) 75 | { 76 | int idx = 1; 77 | long long ans = 1, p = prime[0]; 78 | while(p * p * p <= n) 79 | { 80 | int cnt = 1; 81 | while(n % p == 0) 82 | n /= p, cnt++; 83 | ans *= cnt; 84 | p = prime[idx++]; 85 | } 86 | if(n == 1) return ans; 87 | if(isprime(n)) ans *= 2; 88 | else 89 | { 90 | long long sq = sqrt(n); 91 | if(sq * sq == n) 92 | ans *= 3; 93 | else if(n != 1) 94 | ans *= 4; 95 | } 96 | return ans; 97 | } 98 | 99 | int main() 100 | { 101 | long long n; 102 | cin >> n; 103 | sieve(); 104 | cout << countDivisors(n) << '\n'; 105 | 106 | return 0; 107 | } 108 | -------------------------------------------------------------------------------- /code/miscellaneous/count_sort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int n, m; 5 | int arr[100]; 6 | int cnt[10000]; 7 | int aux[100]; 8 | 9 | void count_sort() 10 | { 11 | for(int i = 0; i < n; i++) 12 | cnt[arr[i]]++; 13 | for(int i = 1; i <= m; i++) 14 | cnt[i] += cnt[i-1]; 15 | for(int i = 0; i < n; i++) 16 | aux[--cnt[arr[i]]] = arr[i]; 17 | memcpy(arr, aux, n*sizeof(int)); 18 | } 19 | 20 | int main() 21 | { 22 | cin >> n; 23 | for(int i = 0; i < n; i++) 24 | cin >> arr[i], m = max(arr[i], m); 25 | 26 | count_sort(); 27 | 28 | for(int i = 0; i < n; i++) 29 | cout << arr[i] << ' '; cout << '\n'; 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /code/miscellaneous/custom_hash_function_unordered_map_or_set.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 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 | //teste 20 | const int N = 2e5; 21 | 22 | void insert_numbers(long long x) 23 | { 24 | clock_t begin = clock(); 25 | unordered_map numbers; 26 | 27 | for (int i = 1; i <= N; i++) 28 | numbers[i * x] = i; 29 | 30 | long long sum = 0; 31 | 32 | for (auto &entry : numbers) 33 | sum += (entry.first / x) * entry.second; 34 | 35 | printf("x = %lld: %.3lf seconds, sum = %lld\n", x, (double) (clock() - begin) / CLOCKS_PER_SEC, sum); 36 | } 37 | 38 | int main() 39 | { 40 | insert_numbers(107897); 41 | insert_numbers(126271); 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /code/miscellaneous/divide_conquer_optimization.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #define maxn 20005 5 | #define maxnlog 22 6 | const long long OO = 0x3f3f3f3f3f3f3f3f; 7 | 8 | struct SparseTableDS 9 | { 10 | int Sparse_Table[maxnlog][maxn]; 11 | bool maxi; 12 | int n; 13 | 14 | void build() 15 | { 16 | for(int i = 1; (1 << i) <= n; i++) 17 | for(int j = 0; j + (1 << i) <= n; j++) 18 | { 19 | if(maxi) 20 | Sparse_Table[i][j] = max(Sparse_Table[i-1][j], 21 | Sparse_Table[i-1][j+(1 << (i-1))]); 22 | else 23 | Sparse_Table[i][j] = min(Sparse_Table[i-1][j], 24 | Sparse_Table[i-1][j+(1 << (i-1))]); 25 | } 26 | } 27 | 28 | int query(int i, int j) 29 | { 30 | int sz = log2(j-i+1); 31 | if(maxi) 32 | return max(Sparse_Table[sz][i],Sparse_Table[sz][j+1-(1 << sz)]); 33 | return min(Sparse_Table[sz][i],Sparse_Table[sz][j+1-(1 << sz)]); 34 | } 35 | 36 | 37 | void init(bool fl, vector &arr) 38 | { 39 | maxi = fl; 40 | if(!maxi) memset(Sparse_Table, 63, sizeof(Sparse_Table)); 41 | n = arr.size(); 42 | for(int i = 0; i < n; i++) 43 | Sparse_Table[0][i] = arr[i]; 44 | build(); 45 | } 46 | }; 47 | 48 | int n, k; 49 | SparseTableDS maxi, mini; 50 | 51 | long long dp_before[maxn]; 52 | long long dp_cur[maxn]; 53 | 54 | int get(int l, int r) 55 | { 56 | int a = maxi.query(l, r); 57 | int b = mini.query(l, r); 58 | return abs(a - b); 59 | } 60 | 61 | void compute(int l, int r, int optl, int optr) 62 | { 63 | if(l > r) return; 64 | 65 | int mid = (l + r) >> 1; 66 | int best = 0; 67 | int opt = optl; 68 | 69 | for(int k = optl; k < min(mid, optr + 1); k++) 70 | if(best < dp_before[k] + get(k + 1, mid)) 71 | { 72 | best = dp_before[k] + get(k + 1, mid); 73 | opt = k; 74 | } 75 | dp_cur[mid] = best; 76 | 77 | compute(l, mid - 1, optl, opt); 78 | compute(mid + 1, r, opt, optr); 79 | } 80 | 81 | int32_t main() 82 | { 83 | cin >> n >> k; 84 | vector arr(n); 85 | for(int &w : arr) scanf(" %d", &w); 86 | 87 | maxi.init(true, arr); 88 | mini.init(false, arr); 89 | 90 | for(int i = 0; i < n; i++) 91 | dp_cur[i] = get(0, i); 92 | 93 | for(int i = 2; i <= k; i++) 94 | { 95 | for(int j = 0; j < n; j++) 96 | { 97 | dp_before[j] = dp_cur[j]; 98 | dp_cur[j] = 0; 99 | } 100 | compute(i - 2, n - 1, i - 2, n - 1); 101 | 102 | } 103 | 104 | cout << dp_cur[n - 1] << endl; 105 | 106 | return 0; 107 | } 108 | -------------------------------------------------------------------------------- /code/miscellaneous/fastIO.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #define gc getchar_unlocked 5 | #define pc putchar_unlocked 6 | 7 | inline void scanint(int &k) 8 | { 9 | bool sinal = true; 10 | register char c; 11 | k = 0; 12 | for(c = gc(); sinal and (c < '0' or c > '9'); c = gc()) 13 | if(c == '-') 14 | sinal = false; 15 | for(; c >= '0' and c <= '9'; c = gc()) 16 | k = (k << 3) + (k << 1) + c - '0'; 17 | if(!sinal) k = -k; 18 | } 19 | 20 | inline void printint(int n) 21 | { 22 | if(n < 0) pc('-'); 23 | n = abs(n); 24 | int rev = n, cnt = 0; 25 | if(!n) 26 | { 27 | pc('0'); 28 | pc('\n'); 29 | return; 30 | } 31 | while(!(rev % 10)) 32 | cnt++, rev /= 10; 33 | rev = 0; 34 | while(n) 35 | rev = (rev << 3) + (rev << 1) + n % 10, n /= 10; 36 | while(rev) 37 | pc(rev % 10 + '0'), rev /= 10; 38 | while(cnt--) 39 | pc('0'); 40 | pc('\n'); 41 | } 42 | 43 | inline void scanstr(string &k) 44 | { 45 | register char c; 46 | k = ""; 47 | for(c = gc(); c < 'a' or c > 'z'; c = gc()); 48 | for(; c >= 'a' and c <= 'z'; c = gc()) k.push_back(c); 49 | } 50 | 51 | inline void printstr(string &k) 52 | { 53 | for(char &c : k) putchar(c); 54 | putchar('\n'); 55 | } 56 | 57 | int main() 58 | { 59 | int k; 60 | scanint(k); 61 | printint(k); 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /code/miscellaneous/fence_problem_with_max_flow.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int MAX = 1e4; 4 | const int OO = 0x3f3f3f3f; 5 | int SOURCE, SINK; 6 | 7 | struct edge 8 | { 9 | int v, f, c; 10 | edge(){} 11 | edge(int _v, int _f, int _c) 12 | { 13 | v = _v, f = _f, c = _c; 14 | } 15 | }; 16 | 17 | vector edges; 18 | vector G[MAX]; 19 | int dist[MAX], work[MAX]; 20 | 21 | void add_edge(int u, int v, int cp, int rc){ 22 | edges.push_back(edge(v, 0, cp)); 23 | G[u].push_back(edges.size()-1); 24 | edges.push_back(edge(u, 0, rc)); 25 | G[v].push_back(edges.size()-1); 26 | } 27 | 28 | bool bfs(int s, int t) 29 | { 30 | memset(dist, -1, sizeof(dist)); 31 | dist[s] = 0; 32 | queue q; 33 | q.push(s); 34 | while(!q.empty()) 35 | { 36 | int u = q.front(); 37 | q.pop(); 38 | for(int e : G[u]) 39 | if(dist[edges[e].v] == -1 and edges[e].c-edges[e].f > 0) 40 | { 41 | q.push(edges[e].v); 42 | dist[edges[e].v] = dist[u] + 1; 43 | } 44 | } 45 | return dist[t] != -1; 46 | } 47 | 48 | int dfs(int s, int t, int f) 49 | { 50 | if(s == t) return f; 51 | for(int &i = work[s]; i < G[s].size(); i++) 52 | { 53 | int e = G[s][i]; 54 | if(dist[edges[e].v] == dist[s] + 1 and edges[e].c-edges[e].f > 0) 55 | if(int a = dfs(edges[e].v, t, min(f, edges[e].c-edges[e].f))) 56 | { 57 | edges[e].f += a; 58 | edges[e^1].f -= a; 59 | return a; 60 | } 61 | } 62 | return 0; 63 | } 64 | 65 | int MaxFlow(int s, int t) 66 | { 67 | int mf = 0; 68 | while(bfs(s, t)) 69 | { 70 | memset(work, 0, sizeof(work)); 71 | while(int a = dfs(s, t, OO)) 72 | mf += a; 73 | } 74 | return mf; 75 | } 76 | 77 | int n, m, a, b; 78 | int dx[] = {1, 0, -1, 0}; 79 | int dy[] = {0, -1, 0, 1}; 80 | char ANS[60][60]; 81 | bool cor[MAX]; 82 | 83 | bool check(int x, int y) 84 | { 85 | return x >= 0 and x < n and y >= 0 and y < m; 86 | } 87 | 88 | int vertexIn(int i, int j) 89 | { 90 | return i * m + j; 91 | } 92 | 93 | int vertexOut(int i, int j) 94 | { 95 | return i * m + j + n * m + 1; 96 | } 97 | 98 | void mountANS(int v) 99 | { 100 | cor[v] = true; 101 | for(int &e : G[v]) 102 | { 103 | if(cor[edges[e].v]) continue; 104 | if(edges[e].c - edges[e].f > 0) 105 | mountANS(edges[e].v); 106 | } 107 | } 108 | 109 | int main() 110 | { 111 | memset(ANS, '.', sizeof(ANS)); 112 | cin >> n >> m >> a >> b; a--; b--; 113 | SOURCE = 2 * n * m + 2; 114 | SINK = 2 * n * m + 3; 115 | for(int i = 0; i < n; i++) 116 | for(int j = 0; j < m; j++) 117 | { 118 | int cost; 119 | cin >> cost; 120 | if(a == i and b == j) cost = OO; 121 | add_edge(vertexIn(i, j), vertexOut(i, j), cost, 0); 122 | if(cost == OO) add_edge(vertexOut(i, j), SINK, OO, 0); 123 | for(int k = 0; k < 4; k++) 124 | { 125 | int x = i + dx[k], y = j + dy[k]; 126 | if(check(x, y)) 127 | add_edge(vertexOut(i, j), 128 | vertexIn(x, y), OO, 0); 129 | } 130 | if(!i or !j or i == n - 1 or j == m - 1) 131 | add_edge(SOURCE, vertexIn(i, j), OO, 0); 132 | } 133 | cout << MaxFlow(SOURCE, SINK) << '\n'; 134 | mountANS(SOURCE); 135 | for(int i = 0; i < n * m; i++) 136 | for(int &e : G[i]) 137 | if(!(e & 1) and cor[i] and !cor[edges[e].v]) 138 | ANS[i / m][i % m] = 'X'; 139 | for(int i = 0; i < n; i++) 140 | { 141 | for(int j = 0; j < m; j++) 142 | cout << ANS[i][j]; 143 | puts(""); 144 | } 145 | return 0; 146 | } 147 | -------------------------------------------------------------------------------- /code/miscellaneous/gen_random_tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); 4 | 5 | int rand(int a, int b) { 6 | return a + rng() % (b - a + 1); 7 | } 8 | 9 | int main() { 10 | int n = rand(4, 20); 11 | cout << n << endl; 12 | vector> edges; 13 | for(int i = 2; i <= n; i++) 14 | edges.emplace_back(rand(1, i - 1), i); 15 | 16 | // re-naming vertices 17 | vector perm(n + 1); // re-naming vertices 18 | for(int i = 1; i <= n; ++i) 19 | perm[i] = i; 20 | 21 | // random order of labels 22 | shuffle(perm.begin() + 1, perm.end(), rng); 23 | // random order of edges 24 | shuffle(edges.begin(), edges.end(), rng); 25 | 26 | for(auto [u, v] : edges) { 27 | // random order of two vertices 28 | if(rng() % 2) swap(u, v); 29 | cout << perm[u] << ' ' << perm[v] << endl; 30 | } 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /code/miscellaneous/histogram.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | typedef long long ll; 5 | int n, vet[1000000]; 6 | 7 | ll histogram() 8 | { 9 | stack s; 10 | ll ans = 0, tp, cur; 11 | int i = 0; 12 | while(i < n or !s.empty()) 13 | { 14 | if(i < n and (s.empty() or vet[s.top()] <= vet[i])) 15 | s.push(i++); 16 | else 17 | { 18 | tp = s.top(); 19 | s.pop(); 20 | cur = vet[tp] * (s.empty() ? i : i - s.top() - 1); 21 | if(ans < cur) 22 | ans = cur; 23 | } 24 | } 25 | return ans; 26 | } 27 | 28 | int main() 29 | { 30 | while(cin >> n and n) 31 | { 32 | for(int i = 0; i < n; i++) 33 | cin >> vet[i]; 34 | cout << histogram() << '\n'; 35 | } 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /code/miscellaneous/inclusion_exclusion.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | contar a quantidade de numeros na range [1, b] 3 | que sao multiplos de pelo menos um numero na range [1, a] 4 | */ 5 | 6 | #include 7 | using namespace std; 8 | #define bug(x) cout << #x << " >>>>>>> " << x << '\n' 9 | #define _ << " , " << 10 | #define int long long 11 | #define Max(a, b) (a > b ? a : b) 12 | #define Min(a, b) (a < b ? a : b) 13 | #define ii pair 14 | #define fi first 15 | #define se second 16 | #define SZ(v) (int)v.size() 17 | #define UNTIL(t) while (clock() < (t) * CLOCKS_PER_SEC) 18 | const long long MAX = (long long)1e15; //2 * 10^5 19 | const int MOD = 1000000007; //10^9 + 7 20 | const int OO = 0x3f3f3f3f;//3f3f3f3f; 21 | const double EPS = 1e-9; //10^-9 22 | mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); 23 | 24 | vector prime = {3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127}; 25 | vector> lista; 26 | 27 | void add(int id) 28 | { 29 | vector aux; 30 | for(int k = 0; k < id; k++) 31 | { 32 | int i = SZ(lista[k]) - 1; 33 | while(i >= 0 and MAX / lista[k][i].fi / prime[id] == 0) i--; 34 | for(int j = 0; j <= i; j++) 35 | aux.push_back({lista[k][j].fi * prime[id], !lista[k][j].se}); 36 | } 37 | aux.push_back({prime[id], 1}); 38 | sort(aux.begin(), aux.end()); 39 | lista.push_back(aux); 40 | } 41 | 42 | int32_t main() 43 | { 44 | for(int i = 0; i < SZ(prime); i++) 45 | add(i); 46 | 47 | int t; 48 | 49 | scanf(" %lld", &t); 50 | 51 | while(t--) 52 | { 53 | int a, b; 54 | 55 | scanf(" %lld %lld", &a, &b); 56 | 57 | int ans = b / 2; 58 | int cnt_p = 0; 59 | 60 | for(int &w : prime) cnt_p += (w <= a); 61 | 62 | for(int i = 0; i < cnt_p; i++) 63 | { 64 | for(int j = 0; j < SZ(lista[i]); j++) 65 | { 66 | if(lista[i][j].fi > b) break; 67 | if(lista[i][j].se) ans += (b / lista[i][j].fi + 1) / 2; 68 | else ans -= (b / lista[i][j].fi + 1) / 2; 69 | } 70 | } 71 | printf("%lld\n", ans); 72 | } 73 | 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /code/miscellaneous/index_compression.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | const int MAX = 1e6 + 10; 3 | using namespace std; 4 | 5 | int n, arr[MAX], pos[MAX], newArr[MAX], realValue[MAX]; 6 | 7 | int main() 8 | { 9 | cin >> n; 10 | for(int i = 0; i < n; i++) 11 | cin >> arr[i], pos[i] = i; 12 | sort(pos, pos + n, [](int i, int j){ return arr[i] < arr[j]; }); 13 | int id = 1; 14 | for(int i = 0; i < n; i++) 15 | { 16 | if(!i) newArr[pos[i]] = id, realValue[id] = arr[pos[i]]; 17 | else if(arr[pos[i-1]] == arr[pos[i]]) newArr[pos[i]] = newArr[pos[i-1]]; 18 | else newArr[pos[i]] = ++id, realValue[id] = arr[pos[i]]; 19 | } 20 | for(int i = 0; i < n; i++) 21 | cout << arr[i] << ' ' << newArr[i] << 22 | ' ' << realValue[newArr[i]] << '\n'; 23 | 24 | 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /code/miscellaneous/karp_rabin.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Funcao de Hash: 3 | 4 | Tome uma string S[0 ... n-1] e deois inteiros A e B 5 | 6 | (S[0]*A^n-1 + S[1]*A^n-2 + S[2]*A^n-3 + S[3]*A^n-4 7 | ... S[N-1]*A^0) mod B 8 | */ 9 | 10 | #include 11 | using namespace std; 12 | const int MAX = 1e5; 13 | 14 | typedef long long ll; 15 | 16 | ll A = 911382323, B = 972663749; 17 | ll h1[MAX], h2[MAX], p[MAX]; 18 | int arr[MAX]; 19 | string s; 20 | 21 | ll buildH(ll *H, int k) 22 | { 23 | if(k == 0) 24 | return H[0] = s[0]; 25 | return H[k] = (buildH(H, k - 1)*A + s[k]) % B; 26 | } 27 | 28 | ll buildP(int k) 29 | { 30 | if(k == 0) 31 | return p[0] = 1; 32 | return p[k] = (buildP(k - 1)*A) % B; 33 | } 34 | 35 | ll vhash(ll *H, int a, int b) 36 | { 37 | if(a == 0) 38 | return H[b]; 39 | ll ans = (H[b] - H[a - 1] * p[b - a + 1]) % B; 40 | if(ans < 0) 41 | ans += B; 42 | return ans; 43 | } 44 | 45 | bool slidingWindow(int k) 46 | { 47 | if(k < 0 or k > s.size()) return false; 48 | for(int i = 0; i + k - 1 < s.size(); i++) 49 | if(vhash(h1, i, i + k - 1) == vhash(h2, s.size() 50 | - (i + k - 1) - 1, s.size() - (i + k - 1) - 2 + k)) 51 | return true; // A substring [i, i + k - 1] eh palindromo 52 | return false; 53 | } 54 | 55 | int buscab() 56 | { 57 | int tam = 0; 58 | for(int i = 0; i < s.size(); i++) 59 | arr[i] = 2*i + 1, tam++; 60 | int b = 0, e = tam, m, ans = 0; 61 | while(b <= e) 62 | { 63 | m = (b + e) / 2; 64 | slidingWindow(arr[m]) ? b = m + 1, ans = arr[m] : e = m - 1; 65 | } 66 | tam = 0; 67 | for(int i = 0; i < s.size(); i++) 68 | arr[i] = 2*i, tam++; 69 | b = 0, e = tam; 70 | while(b <= e) 71 | { 72 | m = (b + e) / 2; 73 | slidingWindow(arr[m]) ? b = m + 1, 74 | ans = max(arr[m], ans) : e = m - 1; 75 | } 76 | return ans; 77 | } 78 | 79 | int main() 80 | { 81 | cin >> s; 82 | buildH(h1, s.size()-1); 83 | reverse(s.begin(), s.end()); 84 | buildH(h2, s.size()-1); 85 | buildP(s.size()-1); 86 | reverse(s.begin(), s.end()); 87 | cout << buscab() << '\n'; 88 | 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /code/miscellaneous/knapsack_with_backtraking.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define pii pair 4 | #define fi first 5 | #define se second 6 | #define pb push_back 7 | 8 | int n,c; 9 | vector v; 10 | int res,aux; 11 | double c2,aux2; 12 | 13 | void bt(int i){ 14 | if(i == n) return; 15 | 16 | aux2 = 0; c2 = c; 17 | for(int j=i; j res) res = aux; 31 | bt(i+1); 32 | aux -= v[i].se; 33 | c += v[i].fi; 34 | } 35 | bt(i+1); 36 | } 37 | 38 | int32_t main(){ 39 | ios::sync_with_stdio(false);cin.tie(0); 40 | 41 | cin>>n>>c; 42 | for(int i = 0; i < n; i++) 43 | { 44 | int wei,value; cin>>wei>>value; 45 | v.pb({wei,value}); 46 | } 47 | 48 | sort(v.begin(), v.end(), [](pii a, pii b){ 49 | return (a.se+0.0)/a.fi > (b.se+0.0)/b.fi; 50 | }); 51 | 52 | bt(0); 53 | cout< 2 | using namespace std; 3 | 4 | // Knuth Optimization 5 | 6 | int pf[6000], n; 7 | int dp[6000][6000]; 8 | 9 | int sum(int l, int r) 10 | { 11 | return pf[r] - pf[l - 1]; 12 | } 13 | 14 | int solve(int l, int r) 15 | { 16 | if(l > r) return 0; 17 | if(dp[l][r] != -1) return dp[l][r]; 18 | int ans = (1 << 30); 19 | for(int i = l; i <= r; i++) 20 | ans = min(ans, sum(l, r) + solve(l, i - 1) + solve(i + 1, r)); 21 | return dp[l][r] = ans; 22 | } 23 | 24 | 25 | 26 | #define ii pair 27 | #define fi first 28 | #define se second 29 | 30 | ii DP[6000][6000]; 31 | 32 | //Point(l, r - 1) <= Point(l, r) <= Point(l + 1, r) 33 | ii knuth(int l, int r) 34 | { 35 | if(l == r) return {sum(l, r), l}; 36 | if(DP[l][r] != ii(-1, -1)) return DP[l][r]; 37 | int lef = knuth(l, r - 1).se; 38 | int rig = knuth(l + 1, r).se; 39 | int point = l, ans = (1 << 30); 40 | for(int i = lef; i <= rig; i++) 41 | { 42 | int cur = sum(l, r); 43 | if(i - 1 >= l) cur += knuth(l, i - 1).fi; 44 | if(i + 1 <= r) cur += knuth(i + 1, r).fi; 45 | if(cur < ans) ans = cur, point = i; 46 | } 47 | return DP[l][r] = {ans, point}; 48 | } 49 | 50 | int main() 51 | { 52 | memset(dp, -1, sizeof(dp)); 53 | cin >> n; 54 | //for(int i = 1; i <= n; i++) 55 | //cin >> pf[i], pf[i] += pf[i - 1]; 56 | //cout << solve(1, n) << endl; 57 | 58 | memset(DP, -1, sizeof(DP)); 59 | cout << knuth(1, n).fi << endl; 60 | 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /code/miscellaneous/lontest_substring_that_is_a_correct_bracket_sequence.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define OO 0x3f3f3f3f 4 | #define gc getchar 5 | #define pc putchar 6 | #define offset 1000000 7 | 8 | string str; 9 | int Sparse_Table[22][1000002], n; 10 | vector forest[2000002]; 11 | int pf[1000002], cnt[1000002]; 12 | 13 | inline void build() 14 | { 15 | for(int i = 1; (1 << i) < n; i++) 16 | for(int j = 0; j + (1 << i) < n; j++) 17 | Sparse_Table[i][j] = min(Sparse_Table[i-1][j], 18 | Sparse_Table[i-1][j+(1 << (i-1))]); 19 | } 20 | 21 | inline int range_query(int i, int j) 22 | { 23 | int sz = log2(j-i+1); 24 | return min(Sparse_Table[sz][i],Sparse_Table[sz][j+1-(1 << sz)]); 25 | } 26 | 27 | inline int countNumberOfElementEqualToXinLR(int l, int r, int x) 28 | { 29 | int p1 = lower_bound(forest[x + offset].begin(), forest[x + offset].end(), l) - forest[x + offset].begin(); 30 | int p2 = upper_bound(forest[x + offset].begin(), forest[x + offset].end(), r) - forest[x + offset].begin() - 1; 31 | if(p1 > p2) return -1; 32 | return p2 - p1 + 1; 33 | } 34 | 35 | inline int nxt(int i, int x) 36 | { 37 | int b = i, e = n - 1, ans = -1; 38 | while(b <= e) 39 | { 40 | int m = (b + e) >> 1; 41 | int v = range_query(i, m); 42 | if(v >= x) ans = m, b = m + 1; 43 | else e = m - 1; 44 | } 45 | return ans; 46 | } 47 | 48 | inline int queryIndex(int l, int r, int x) 49 | { 50 | int b = l, e = r, ans = -1; 51 | while(b <= e) 52 | { 53 | int m = (b + e) >> 1; 54 | if(countNumberOfElementEqualToXinLR(m, r, x) > 0) ans = m, b = m + 1; 55 | else e = m - 1; 56 | } 57 | return ans; 58 | } 59 | 60 | inline void scanstr(string &k) 61 | { 62 | register char c; 63 | k = ""; 64 | for(c = gc(); c != '(' and c != ')'; c = gc()); 65 | for(; c >= '(' and c <= ')'; c = gc()) k.push_back(c); 66 | } 67 | 68 | int main() 69 | { 70 | scanstr(str); 71 | n = str.size() + 1; 72 | for(int i = 1; i < n; i++) 73 | { 74 | pf[i] = pf[i - 1] + (str[i - 1] == '(' ? 1 : -1); 75 | Sparse_Table[0][i] = pf[i]; 76 | forest[pf[i] + offset].push_back(i); 77 | } 78 | build(); 79 | int ans = 0; 80 | cnt[0] = 1; 81 | for(int i = 1; i < n; i++) 82 | { 83 | if(str[i - 1] != '(') continue; 84 | int e = nxt(i, pf[i] - 1); 85 | if(e < i) continue; 86 | int p = queryIndex(i, e, pf[i] - 1); 87 | if(p < i) continue; 88 | int l = p - i + 1; 89 | cnt[l]++; 90 | if(l > ans) ans = l; 91 | } 92 | printf("%d %d\n", ans, cnt[ans]); 93 | 94 | return 0; 95 | } 96 | -------------------------------------------------------------------------------- /code/miscellaneous/maximum_subarray_xor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int MAX = 1e4 + 10; 5 | const int OO = 0x3f3f3f3f; 6 | const double EPS = 1e-9; 7 | 8 | #define bug(x) cout << #x << " = " << x << '\n' 9 | #define FOR(i, a, n) for(int i = a; i < n; i++) 10 | #define REP(i, n) FOR(i, 0, n) 11 | #define fi first 12 | #define se second 13 | #define pb push_back 14 | #define mt make_tuple 15 | #define all(vetor) vetor.begin(), vetor.end() 16 | #define X real() 17 | #define Y imag() 18 | //#define gc getchar_unlocked 19 | 20 | typedef long long ll; 21 | typedef long double ld; 22 | typedef pair ii; 23 | typedef pair iii; 24 | typedef complex Pll; 25 | typedef complex Pld; 26 | 27 | struct TrieNode 28 | { 29 | int value; 30 | TrieNode *children[2]; 31 | TrieNode() 32 | { 33 | value = 0; 34 | children[0] = children[1] = nullptr; 35 | } 36 | }; 37 | 38 | void insert(TrieNode *root, int n) 39 | { 40 | TrieNode *aux = root; 41 | for(int i = 31; i >= 0; i--) 42 | { 43 | bool b = (n & (1 << i)); 44 | if(aux->children[b] == nullptr) 45 | aux->children[b] = new TrieNode(); 46 | aux = aux->children[b]; 47 | } 48 | aux->value = n; 49 | } 50 | 51 | int query(TrieNode *root, int n) 52 | { 53 | TrieNode *aux = root; 54 | for(int i = 31; i >= 0; i--) 55 | { 56 | bool b = (n & (1 << i)); 57 | if(aux->children[1-b] != nullptr) 58 | aux = aux->children[1-b]; 59 | else 60 | aux = aux->children[b]; 61 | } 62 | return n ^ aux->value; 63 | } 64 | 65 | void maxSubArrayXor(int *arr, int n) 66 | { 67 | TrieNode *root = new TrieNode(); 68 | insert(root, 0); 69 | int px = 0, ans = INT_MIN, r = -1; 70 | for(int i = 0; i < n; i++) 71 | { 72 | px = px ^ arr[i]; 73 | insert(root, px); 74 | int num = max(ans, query(root, px)); 75 | if(num > ans) 76 | ans = num, r = i; 77 | } 78 | int l = r, xo = 0; 79 | for(; l >= 0; l--) 80 | { 81 | xo ^= arr[l]; 82 | if(xo == ans) 83 | break; 84 | } 85 | cout << "O Xor maximo eh: " << ans << '\n'; 86 | while(l <= r) 87 | cout << arr[l++] << ' '; 88 | cout << '\n'; 89 | } 90 | 91 | int main() 92 | { 93 | int arr[MAX], n; 94 | 95 | cin >> n; 96 | REP(i, n) cin >> arr[i]; 97 | maxSubArrayXor(arr, n); 98 | 99 | return 0; 100 | } 101 | -------------------------------------------------------------------------------- /code/miscellaneous/quick_sort_and_Select.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int n, arr[10000]; 5 | 6 | int quickselect(int l, int r, int k) 7 | { 8 | int j = l - 1; 9 | for(int i = l; i < r; i++) 10 | if(arr[i] <= arr[r]) 11 | swap(arr[++j], arr[i]); 12 | swap(arr[j+1], arr[r]); 13 | if(j+1 < k) return quickselect(j+2, r, k); 14 | else if(j+1 > k) return quickselect(l, j, k); 15 | return arr[j+1]; 16 | } 17 | 18 | void quicksort(int l, int r) 19 | { 20 | int j = l - 1; 21 | for(int i = l; i < r; i++) 22 | if(arr[i] <= arr[r]) 23 | swap(arr[++j], arr[i]); 24 | swap(arr[j+1], arr[r]); 25 | if(l < j) 26 | quicksort(l, j); 27 | if(j+2 < r) 28 | quicksort(j+2, r); 29 | } 30 | 31 | int main() 32 | { 33 | int k; 34 | cin >> n >> k; 35 | for(int i = 0; i < n; i++) cin >> arr[i]; 36 | cout << quickselect(0, n-1, k-1) << '\n'; 37 | 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /code/miscellaneous/rectangles_union_area.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define ii pair 4 | #define fi first 5 | #define se second 6 | 7 | struct Event 8 | { 9 | int x1, x2, y, t; 10 | Event(int _x1, int _x2, int _y, int _t) 11 | { 12 | x1 = _x1, x2 = _x2, y = _y, t = _t; 13 | } 14 | Event(){} 15 | }; 16 | 17 | ii tree[500800]; 18 | int lazy[500800]; 19 | 20 | int n; 21 | vector> segments, rect; 22 | int X1, Y1, X2, Y2, P; 23 | 24 | ii calc(ii a, ii b) 25 | { 26 | if(a.fi > b.fi) return b; 27 | else if(a.fi < b.fi) return a; 28 | return {a.fi, a.se + b.se}; 29 | } 30 | 31 | void build(int node, int start, int end) 32 | { 33 | if(start == end) 34 | tree[node] = {0, 1}, lazy[node] = 0; 35 | else 36 | { 37 | int mid = (start + end) / 2; 38 | build(2 * node, start, mid); 39 | build(2 * node + 1, mid + 1, end); 40 | tree[node] = calc(tree[2 * node], tree[2 * node + 1]); 41 | lazy[node] = 0; 42 | } 43 | } 44 | 45 | void push(int node, int start, int end) 46 | { 47 | tree[node].fi += lazy[node]; 48 | if(start != end) 49 | { 50 | lazy[2 * node] += lazy[node]; 51 | lazy[2 * node + 1] += lazy[node]; 52 | } 53 | lazy[node] = 0; 54 | } 55 | 56 | void update(int node, int start, int end, int l, int r, int v) 57 | { 58 | if(lazy[node]) push(node, start, end); 59 | if(start > r or end < l) return; 60 | if(l <= start and end <= r) 61 | { 62 | lazy[node] += v; 63 | push(node, start, end); 64 | return; 65 | } 66 | int mid = (start + end) / 2; 67 | update(2 * node, start, mid, l, r, v); 68 | update(2 * node + 1, mid + 1, end, l, r, v); 69 | tree[node] = calc(tree[2 * node], tree[2 * node + 1]); 70 | } 71 | 72 | int query(int node, int start, int end) 73 | { 74 | if(lazy[node]) push(node, start, end); 75 | return end - start + 1 - tree[node].se; 76 | } 77 | 78 | void mount(int r) 79 | { 80 | rect.clear(); 81 | for(auto &it : segments) 82 | { 83 | int x1 = max(min(it.fi.fi, it.se.fi) - r, X1); 84 | int y1 = max(min(it.fi.se, it.se.se) - r, Y1); 85 | int x2 = min(max(it.fi.fi, it.se.fi) + r, X2); 86 | int y2 = min(max(it.fi.se, it.se.se) + r, Y2); 87 | x2--; 88 | rect.push_back({{x1, y1}, {x2, y2}}); 89 | } 90 | } 91 | 92 | bool cmp(Event a, Event b) 93 | { 94 | if(a.y != b.y) return a.y < b.y; 95 | return a.t > b.t; 96 | } 97 | 98 | long long area(int r) 99 | { 100 | mount(r); 101 | vector eve; 102 | for(auto &it : rect) 103 | { 104 | eve.emplace_back(it.fi.fi, it.se.fi, it.fi.se, 1); 105 | eve.emplace_back(it.fi.fi, it.se.fi, it.se.se, -1); 106 | } 107 | sort(eve.begin(), eve.end(), cmp); 108 | build(1, 0, 100001); 109 | long long Y = 0, ans = 0; 110 | for(int i = 0; i < eve.size(); i++) 111 | { 112 | long long s = query(1, 0, 100001); 113 | long long aux = s * 1LL * (eve[i].y - Y); 114 | update(1, 0, 100001, eve[i].x1, eve[i].x2, eve[i].t); 115 | Y = eve[i].y; 116 | ans += aux; 117 | } 118 | return ans; 119 | } 120 | 121 | int32_t main() 122 | { 123 | scanf(" %d", &n); 124 | for(int i = 0; i < n; i++) 125 | { 126 | int x1, y1, x2, y2; 127 | scanf(" %d %d %d %d", &x1, &y1, &x2, &y2); 128 | segments.push_back({{x1, y1}, {x2, y2}}); 129 | } 130 | scanf(" %d %d %d %d %d", &P, &X1, &Y1, &X2, &Y2); 131 | 132 | long long tot = (X2 - X1) * 1LL * (Y2 - Y1); 133 | 134 | int b = 0, e = 100000, ans = 0; 135 | while(b <= e) 136 | { 137 | int mid = (b + e) / 2; 138 | long long A = area(mid); 139 | if(P * 1LL * tot <= 100LL * A) ans = mid, e = mid - 1; 140 | else b = mid + 1; 141 | } 142 | cout << ans << '\n'; 143 | 144 | return 0; 145 | } 146 | -------------------------------------------------------------------------------- /code/miscellaneous/square_root_decomposition.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int MAX = 1e5; 4 | 5 | int n, blk_sz; 6 | int arr[MAX], block[MAX]; 7 | 8 | void update(int idx, int val) 9 | { 10 | int blockNumber = idx/blk_sz; 11 | block[blockNumber] += val - arr[idx]; 12 | arr[idx] = val; 13 | } 14 | 15 | int query(int l, int r) 16 | { 17 | int sum = 0; 18 | while(l < r and l%blk_sz != 0 and l != 0) 19 | sum += arr[l], l++; 20 | while(l+blk_sz <= r) 21 | sum += block[l/blk_sz], l += blk_sz; 22 | while(l <= r) 23 | sum += arr[l], l++; 24 | return sum; 25 | } 26 | 27 | void build() 28 | { 29 | int blk_idx = -1; 30 | blk_sz = sqrt(n); 31 | for(int i = 0; i < n; i++) 32 | { 33 | if(i%blk_sz == 0) 34 | blk_idx++; 35 | block[blk_idx] += arr[i]; 36 | } 37 | } 38 | 39 | int main() 40 | { 41 | cin >> n; 42 | for(int i = 0; i < n; i++) 43 | cin >> arr[i]; 44 | build(); 45 | int o, l, r; 46 | while(cin >> o >> l >> r and o) 47 | if(o == 1) 48 | update(l-1, r); 49 | else 50 | cout << query(l-1, r-1) << '\n'; 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /code/miscellaneous/string_matching_hash_sqrtdecomp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int MAX = 1e5 + 100; 4 | 5 | typedef long long ll; 6 | 7 | #define ii pair 8 | #define fi first 9 | #define se second 10 | 11 | ll A = 911382323, B = 972663749; 12 | ll h[MAX], p[MAX]; 13 | string s; 14 | 15 | ll buildP(int k) 16 | { 17 | if(k == 0) 18 | return p[0] = 1; 19 | return p[k] = (buildP(k - 1)*A) % B; 20 | } 21 | 22 | int main() 23 | { 24 | ios_base::sync_with_stdio(false); 25 | cin.tie(NULL); 26 | 27 | cin >> s; 28 | buildP(s.size() + 10); 29 | 30 | int n = s.size(); 31 | int sz = sqrt(n); 32 | 33 | unordered_set AAAA; 34 | vector BBBB; 35 | 36 | string aux; 37 | 38 | while(cin >> aux) 39 | { 40 | long long value = 0, j = 0; 41 | while(j < aux.size()) 42 | { 43 | if(j == 0) value = aux[j]; 44 | else value = (value * A + aux[j]) % B; 45 | j++; 46 | } 47 | if(aux.size() > sz) 48 | BBBB.push_back({aux.size(), value}); 49 | else 50 | AAAA.insert(value); 51 | } 52 | sort(BBBB.begin(), BBBB.end()); 53 | 54 | string ans; 55 | 56 | int j = 0, i = 0; 57 | 58 | while(i < s.size()) 59 | { 60 | ans.push_back(s[i]); 61 | 62 | if(j == 0) h[j] = s[i]; 63 | else h[j] = (h[j - 1] * A + s[i]) % B; 64 | 65 | int leng = -1; 66 | long long vh; 67 | 68 | for(int k = j; k >= 0 and k >= j - sz - 1 and leng < 0; k--) 69 | { 70 | if(k == 0) vh = h[j]; 71 | else 72 | { 73 | vh = (h[j] - h[k - 1] * p[j - k + 1]) % B; 74 | if(vh < 0) vh += B; 75 | } 76 | if(AAAA.count(vh)) 77 | leng = j - k + 1; 78 | //length j - k + 1 79 | } 80 | 81 | if(leng == -1) 82 | { 83 | for(int k = 0; k < BBBB.size(); k++) 84 | { 85 | int a = j - BBBB[k].first + 1; 86 | 87 | if(a < 0) break; 88 | 89 | if(a == 0) vh = h[j]; 90 | else 91 | { 92 | vh = (h[j] - h[a - 1] * p[j - a + 1]) % B; 93 | if(vh < 0) vh += B; 94 | } 95 | 96 | if(vh == BBBB[k].se) 97 | leng = BBBB[k].fi; 98 | 99 | } 100 | } 101 | if(leng != -1) 102 | { 103 | j -= leng; 104 | while(leng--) ans.pop_back(); 105 | } 106 | ++j; 107 | i++; 108 | } 109 | cout << ans << '\n'; 110 | 111 | 112 | return 0; 113 | } 114 | -------------------------------------------------------------------------------- /code/string/KMP.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int MAX = 1e6; 4 | 5 | int n, m; 6 | // n eh o tamanho do texto e m eh o 7 | // tamanho do padrao 8 | int arr[MAX]; 9 | // array que guarda o tamanho do maior 10 | // prefixo proprio que tambem eh sufixo 11 | string t, p; // t eh o texto e p eh o padrao 12 | 13 | void build() // kMP Preprocess 14 | { 15 | int i = 0, j = 1; 16 | while(j < m) 17 | { 18 | if(p[i] == p[j]) 19 | arr[j] = ++i; 20 | else 21 | { 22 | i = 0; 23 | if(p[i] == p[j]) 24 | arr[j] = ++i; 25 | } 26 | j++; 27 | } 28 | } 29 | 30 | int matching() // KMP search 31 | { 32 | int i = 0, j = 0; 33 | while(j < n) 34 | { 35 | if(p[i] == t[j]) i++, j++; 36 | else if(i) i = arr[i - 1]; 37 | else j++; 38 | if(i == m) 39 | return j - m; 40 | // a substring P inicia na posicao j - m em T 41 | } 42 | return -1; // P nao eh substring de T 43 | } 44 | 45 | int main() 46 | { 47 | cin >> t >> p; 48 | n = (int)t.size(); 49 | m = (int)p.size(); 50 | build(); 51 | cout << matching() << '\n'; 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /code/string/LIS_LDS.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int MAX = 1e4; 4 | 5 | int n; 6 | int LI[MAX], LD[MAX]; 7 | vector arr; 8 | 9 | int LIS() { 10 | for(int i = 0; i < n; i++) 11 | LI[i] = 1; 12 | for(int i = n - 1; i >= 0; i--) 13 | for(int j = 0; j < i; j++) 14 | if(arr[j] < arr[i]) 15 | LI[j] = max(LI[j], LI[i] + 1); 16 | } 17 | 18 | int LDS() { 19 | reverse(arr.begin(), arr.end()); 20 | for(int i = 0; i < n; i++) 21 | LD[i] = 1; 22 | vector pilha; 23 | for(int i = 0; i < n; i++) { 24 | int p = (int)(lower_bound(pilha.begin(), 25 | pilha.end(), arr[i]) - pilha.begin()); 26 | if(p == pilha.size()) 27 | pilha.push_back(arr[i]); 28 | else 29 | pilha[p] = arr[i]; 30 | LD[i] = p + 1; 31 | } 32 | 33 | } 34 | 35 | int main() { 36 | cin >> n; arr.resize(n); 37 | for(int i = 0; i < n; i++) cin >> arr[i]; 38 | 39 | LIS(); 40 | LDS(); 41 | 42 | for(int i = 0; i < n; i++) 43 | cout << LI[i] << ' '; puts(""); 44 | for(int i = 0; i < n; i++) 45 | cout << LD[n - i - 1] << ' '; puts(""); 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /code/string/Z_function.cpp: -------------------------------------------------------------------------------- 1 | #include "bits/stdc++.h" 2 | #define Max(a, b) (a > b ? a : b) 3 | #define Min(a, b) (a < b ? a : b) 4 | using namespace std; 5 | const int MAX = 1e5; 6 | 7 | vector Z(string &s) 8 | { 9 | int n = s.size(), x = 0, y = 0; 10 | vector z(n); 11 | for(int i = 1; i < n; i++) 12 | { 13 | z[i] = Max(0, Min(z[i - x], y - i + 1)); 14 | while(i + z[i] < n and s[z[i]] == s[i + z[i]]) 15 | x = i, y = i + z[i], z[i]++; 16 | } 17 | return z; 18 | } 19 | 20 | int main() 21 | { 22 | string txt, pattern; 23 | 24 | cin >> txt >> pattern; 25 | string s = pattern + "#" + txt; 26 | vector z = Z(s); 27 | for(int &w : z) 28 | cout << w << ' '; 29 | cout << '\n'; 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /code/string/dynamic_trie.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | struct TrieNode 5 | { 6 | map childreen; 7 | bool isLeaf; 8 | TrieNode() 9 | { 10 | isLeaf = false; 11 | } 12 | }; 13 | 14 | void inserir(TrieNode *root, string s) 15 | { 16 | TrieNode *node = root; 17 | for(int i = 0; i < s.size(); i++) 18 | { 19 | int index = s[i] - 'a'; 20 | if(node->childreen.find(index) == node->childreen.end()) 21 | node->childreen[index] = new TrieNode(); 22 | node = node->childreen[index]; 23 | } 24 | node->isLeaf = true; 25 | } 26 | 27 | bool buscar(TrieNode *root, string s) 28 | { 29 | TrieNode *node = root; 30 | for(int i = 0; i < s.size(); i++) 31 | { 32 | int index = s[i] - 'a'; 33 | if(node->childreen.find(index) == node->childreen.end()) 34 | return false; 35 | node = node->childreen[index]; 36 | } 37 | return node->isLeaf; 38 | } 39 | 40 | bool remover(TrieNode *node, string s, int level) 41 | { 42 | if(node != nullptr) 43 | if(s.size() == level) 44 | { 45 | if(node->isLeaf) 46 | { 47 | node->isLeaf = false; 48 | return !node->childreen.size(); 49 | } 50 | } 51 | else 52 | { 53 | int index = s[level] - 'a'; 54 | if(remover(node->childreen[index], s, level+1)) 55 | { 56 | delete node->childreen[index]; 57 | node->childreen.erase(index); 58 | return !node->childreen.size(); 59 | } 60 | } 61 | return false; 62 | } 63 | 64 | int main() 65 | { 66 | TrieNode *root = new TrieNode(); 67 | 68 | inserir(root, "abc"); 69 | inserir(root, "abd"); 70 | inserir(root, "cfa"); 71 | remover(root, "abc", 0); 72 | printf(buscar(root, "abc") ? "yes\n" : "no\n"); 73 | printf(buscar(root, "abd") ? "yes\n" : "no\n"); 74 | 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /code/string/longest_common_substring.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int pd[10000][10000]; 5 | 6 | int max(int a, int b) 7 | { 8 | return a > b ? a : b; 9 | } 10 | 11 | int solve(char *a, char *b) 12 | { 13 | int i, j, ans = 0; 14 | int t1 = strlen(a), t2 = strlen(b); 15 | for(i = 1; i < t1; i++) 16 | for(j = 1; j < t2; j++) 17 | if(a[i-1] == b[j-1]) 18 | pd[i][j] = pd[i-1][j-1] + 1, 19 | ans = max(ans, pd[i][j]); 20 | else 21 | pd[i][j] = 0; 22 | return ans; 23 | } 24 | 25 | int main() 26 | { 27 | char s1[55], s2[55]; 28 | 29 | while(fgets(s1, 54, stdin) != NULL 30 | && fgets(s2, 54, stdin) != NULL) 31 | printf("%d\n", solve(s1, s2)); 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /code/string/manacher.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int MAX = 100; 4 | 5 | int lps[2*MAX+5]; 6 | char s[MAX]; 7 | 8 | int manacher() 9 | { 10 | int n = strlen(s); 11 | string p(2*n+3, '#'); 12 | p[0] = '^'; 13 | for(int i = 0; i < n; i++) 14 | p[2*(i+1)] = s[i]; 15 | p[2*n+2] = '$'; 16 | int k = 0, r = 0, m = 0; 17 | int l = p.length(); 18 | for(int i = 1; i < l; i++) 19 | { 20 | int o = 2*k - i; 21 | lps[i] = (r > i) ? min(r-i, lps[o]) : 0; 22 | while(p[i + 1 + lps[i]] == p[i - 1 - lps[i]]) 23 | lps[i]++; 24 | if(i + lps[i] > r) k = i, r = i + lps[i]; 25 | m = max(m, lps[i]); 26 | } 27 | /*for(int i = 1; i <= 2 * n + 1; i++) 28 | cout << lps[i] << ' '; 29 | puts("");*/ 30 | return m; 31 | } 32 | 33 | int main() 34 | { 35 | cin >> s; 36 | cout << manacher() << '\n'; 37 | return 0; 38 | } -------------------------------------------------------------------------------- /code/string/trie.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int MAX = 1e6; 4 | 5 | int trie[MAX][26], cnt[MAX], tsz = 1; 6 | bool leaf[MAX]; 7 | 8 | void insert(string s) 9 | { 10 | int cur = 1; 11 | cnt[cur]++; 12 | for(int i = 0; i < s.size(); i++) 13 | { 14 | int a = s[i] - 'a'; 15 | if(!trie[cur][a]) trie[cur][a] = ++tsz; 16 | cur = trie[cur][a]; 17 | cnt[cur]++; 18 | } 19 | leaf[cur] = true; 20 | } 21 | 22 | bool find(string s) 23 | { 24 | int cur = 1; 25 | for(int i = 0; i < s.size(); i++) 26 | { 27 | int a = s[i] - 'a'; 28 | if(!trie[cur][a] or !cnt[cur]) 29 | return false; 30 | cur = trie[cur][a]; 31 | } 32 | return leaf[cur] and cnt[cur]; 33 | } 34 | 35 | int remove(string s) 36 | { 37 | int cur = 1; 38 | for(int i = 0; i < s.size(); i++) 39 | { 40 | int a = s[i] - 'a'; 41 | cnt[cur]--; 42 | cur = trie[cur][a]; 43 | } 44 | leaf[cur] = false; 45 | cnt[cur]--; 46 | } 47 | 48 | int main() 49 | { 50 | string s; 51 | int n, o; 52 | while(cin >> o >> s) 53 | { 54 | if(o == 1) 55 | cout << (find(s) ? "found\n" : "not found\n"); 56 | else if(o == 2) 57 | insert(s); 58 | else 59 | remove(s); 60 | } 61 | 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /code/string/trie_static.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // as posicoes de 0 ate 25 representam as letras 5 | // de a ate z do alfabeto. 6 | // a posicao 26 armazena quantas strings terminam 7 | // nesse vertice. 8 | // a posicao 27 armazena quantas strings passam 9 | // nesse vertice. 10 | 11 | int trie[8000000][30], CUR = 1; 12 | 13 | // fl eh zero se for uma operacao de inserir 14 | // fl eh um se for uma operacao de buscar 15 | int add(string &s, int fl) 16 | { 17 | int root = 0; 18 | for(char &c : s) 19 | { 20 | if(trie[root][c - 'a'] == 0) 21 | { 22 | if(fl) return 0; 23 | trie[root][c - 'a'] = CUR++; 24 | } 25 | if(!fl) trie[root][27]++; 26 | root = trie[root][c - 'a']; 27 | } 28 | if(fl) return trie[root][26]; 29 | trie[root][26]++; 30 | return 1; 31 | } 32 | 33 | void sub(string &s) 34 | { 35 | int root = 0; 36 | for(char &c : s) 37 | if(trie[root][c - 'a'] and trie[root][27]) 38 | { 39 | trie[root][27]--; 40 | root = trie[root][c - 'a']; 41 | } 42 | trie[root][26]--; 43 | } 44 | 45 | int main() 46 | { 47 | int q; 48 | 49 | cin >> q; 50 | 51 | while(q--) 52 | { 53 | int o; 54 | string s; 55 | cin >> o >> s; 56 | if(o == 1) add(s, 0); 57 | else if(o == 2) puts(add(s, 1) ? "existe" : "nao existe"); 58 | else sub(s); 59 | } 60 | 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /code/string/trie_with_vector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | struct TrieNode 5 | { 6 | int child[26], size, cnt; 7 | TrieNode() 8 | { 9 | memset(child, 0, sizeof(child)); 10 | size = cnt = 0; 11 | } 12 | }; 13 | 14 | vector trie; 15 | 16 | void init() 17 | { 18 | trie.clear(); 19 | trie.push_back(TrieNode()); 20 | } 21 | 22 | void add(string s) 23 | { 24 | int root = 0; 25 | for(int i = 0; i < (int)s.size(); i++) 26 | { 27 | int index = s[i] - 'a'; 28 | if(trie[root].child[index] == 0) 29 | { 30 | trie[root].child[index] = trie.size(); 31 | trie.push_back(TrieNode()); 32 | } 33 | root = trie[root].child[index]; 34 | trie[root].size++; 35 | } 36 | trie[root].cnt++; 37 | } 38 | 39 | void sub(string s) 40 | { 41 | int root = 0; 42 | for(int i = 0; i < (int)s.size(); i++) 43 | { 44 | int index = s[i] - 'a'; 45 | root = trie[root].child[index]; 46 | trie[root].size--; 47 | } 48 | trie[root].cnt--; 49 | } 50 | 51 | int query(string s) 52 | { 53 | int root = 0; 54 | for(int i = 0; i < (int)s.size(); i++) 55 | { 56 | int index = s[i] - 'a'; 57 | if(!trie[trie[root].child[index]].size) 58 | return false; 59 | root = trie[root].child[index]; 60 | } 61 | return trie[root].cnt; 62 | } 63 | 64 | int main() 65 | { 66 | string s; 67 | int o; 68 | init(); 69 | while(cin >> o >> s) 70 | { 71 | if(o == 1) add(s); 72 | else if(o == 2) sub(s); 73 | else cout << query(s) << '\n'; 74 | } 75 | 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /code/useful_scripts/brute.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | // implement the brute force here 4 | 5 | int32_t main() { 6 | 7 | 8 | return 0; 9 | } -------------------------------------------------------------------------------- /code/useful_scripts/gen.cpp: -------------------------------------------------------------------------------- 1 | // simple matrix generator 2 | 3 | #include 4 | using namespace std; 5 | 6 | int rand(int a, int b) { 7 | return a + rand() % (b - a + 1); 8 | } 9 | 10 | int main(int argc, char* argv[]) { 11 | // atoi(s) converts an array of chars to int 12 | srand(atoi(argv[1])); 13 | 14 | int n = rand(1, 3), m = rand(1, 3); 15 | 16 | cout << n << ' ' << m << endl; 17 | for(int i = 0; i < n; i++) { 18 | for(int j = 0; j < m; j++) { 19 | cout << rand(1, 5) << ' '; 20 | } 21 | cout << endl; 22 | } 23 | 24 | return 0; 25 | } -------------------------------------------------------------------------------- /code/useful_scripts/gen_tree.cpp: -------------------------------------------------------------------------------- 1 | // generating a tree in a simple way (from Errichto) 2 | #include 3 | using namespace std; 4 | 5 | int rand(int a, int b) { 6 | return a + rand() % (b - a + 1); 7 | } 8 | 9 | int main(int argc, char* argv[]) { 10 | srand(atoi(argv[1])); 11 | int n = rand(2, 20); 12 | cout << n << '\n'; 13 | for(int i = 2; i <= n; ++i) 14 | cout << rand(1, i - 1) << ' ' << i << '\n'; 15 | return 0; 16 | } -------------------------------------------------------------------------------- /code/useful_scripts/gen_tree2.cpp: -------------------------------------------------------------------------------- 1 | // generating a tree in a not-so-stupid way (from Errichto) 2 | #include 3 | using namespace std; 4 | 5 | int rand(int a, int b) { 6 | return a + rand() % (b - a + 1); 7 | } 8 | 9 | int main(int argc, char* argv[]) { 10 | srand(atoi(argv[1])); 11 | int n = rand(2, 20); 12 | cout << n << '\n'; 13 | vector> edges; 14 | for(int i = 2; i <= n; ++i) 15 | edges.emplace_back(rand(1, i - 1), i); 16 | 17 | vector perm(n + 1); // re-naming vertices 18 | for(int i = 1; i <= n; ++i) 19 | perm[i] = i; 20 | 21 | random_shuffle(perm.begin() + 1, perm.end()); 22 | 23 | random_shuffle(edges.begin(), edges.end()); // random order of edges 24 | 25 | for(pair edge : edges) { 26 | int a = edge.first, b = edge.second; 27 | if(rand() % 2) 28 | swap(a, b); // random order of two vertices 29 | cout << perm[a] << ' ' << perm[b] << '\n'; 30 | } 31 | return 0; 32 | } -------------------------------------------------------------------------------- /code/useful_scripts/makefile: -------------------------------------------------------------------------------- 1 | CXX = g++ 2 | CXXFLAGS = -fsanitize=address,undefined -fno-omit-frame-pointer -g -Wall -Wshadow -std=c++17 -Wno-unused-result -Wno-sign-compare -Wno-char-subscripts #-fuse-ld=gold 3 | 4 | -------------------------------------------------------------------------------- /code/useful_scripts/sol.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | // implement your solution here 4 | 5 | int32_t main() { 6 | 7 | 8 | 9 | return 0; 10 | } -------------------------------------------------------------------------------- /code/useful_scripts/stress.sh: -------------------------------------------------------------------------------- 1 | make sol brute gen 2 | 3 | for ((i = 1; ; i++)) do 4 | ./gen $i > in 5 | ./sol < in > out 6 | ./brute < in > out2 7 | if (! cmp -s out out2) then 8 | echo "--> entrada:" 9 | cat in 10 | echo "--> saida sol" 11 | cat out 12 | echo "--> saida2 brute" 13 | cat out2 14 | break; 15 | fi 16 | echo $i 17 | done 18 | -------------------------------------------------------------------------------- /code/useful_scripts/stress_test_animated.sh: -------------------------------------------------------------------------------- 1 | make sol brute gen 2 | 3 | cmatrix & 4 | 5 | for ((i = 1; ; i++)) do 6 | ./gen $i > in 7 | ./sol < in > out 8 | ./brute < in > out2 9 | if (! cmp -s out out2) then 10 | kill -9 `pgrep -u matheus cmatrix` 11 | reset 12 | clear 13 | echo "--> entrada:" 14 | cat in 15 | echo "--> saida sol" 16 | cat out 17 | echo "--> saida2 brute" 18 | cat out2 19 | break; 20 | fi 21 | echo $i 22 | 23 | done -------------------------------------------------------------------------------- /code/useful_scripts/stress_with_checker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | make sol brute gen check 4 | 5 | for ((i = 1; ; i++)) do 6 | ./gen $i > in 7 | ./sol < in > out 8 | ./brute < in > out2 9 | ./check > log 10 | 11 | expected=correct 12 | result=$(< check.txt) 13 | 14 | if [ "$expected" != "$result" ]; then 15 | echo "--> entrada:" 16 | cat in 17 | echo "--> saida sol" 18 | cat out 19 | echo "--> saida2 brute" 20 | cat out2 21 | break; 22 | fi 23 | echo $i 24 | done 25 | -------------------------------------------------------------------------------- /latex/GEMP-Notebook.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Matheus-Monteiro/Competitive-Programming/d4bf27b2c59f0241884be8cfb7508580d1d01450/latex/GEMP-Notebook.pdf -------------------------------------------------------------------------------- /latex/generate_pdf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # This script was based in the file of the Stanford University ACM team 3 | 4 | import os 5 | title = "GEMP - UECE - ICPC Library" 6 | 7 | def get_sections(): 8 | sections = [] 9 | section_name = None 10 | with open("../README.md", 'r') as f: 11 | skip = 0 12 | for line in f: 13 | skip += 1 14 | if skip < 35: 15 | continue 16 | line = line.strip() 17 | if line[:2] == "**": 18 | section_name = line[2:-2] 19 | subsections = [] 20 | if section_name is not None: 21 | sections.append((section_name, subsections)) 22 | elif line[: 6] == "- [x] ": 23 | line = line[6: ] 24 | subsection_name = line[line.find('[') + 1 : line.find(']')] 25 | filename = line[line.find('(') + 1 : line.find(')')] 26 | 27 | if len(subsection_name) == 0: 28 | raise ValueError("Subsection parse error: %" % line) 29 | if section_name is None: 30 | print(line) 31 | raise ValueError("Subsection given without section") 32 | 33 | subsections.append(("../" + filename, subsection_name)) 34 | return sections 35 | 36 | def get_style(filename): 37 | ext = filename.lower().split('.')[-1] 38 | if ext in ['c', 'cc', 'cpp', 'h']: 39 | return 'cpp' 40 | elif ext in ['java']: 41 | return 'java' 42 | elif ext in ['py']: 43 | return 'py' 44 | elif ext in ['tex']: 45 | return 'tex' 46 | else: 47 | return 'txt' 48 | 49 | def get_tex(sections): 50 | tex = '' 51 | for (section_name, subsections) in sections: 52 | tex += '\\section{%s}\n' % section_name 53 | for (filename, subsection_name) in subsections: 54 | tex += '\\subsection{%s}\n' % subsection_name 55 | if(get_style(filename) == 'tex'): 56 | tex += '\\raggedbottom{\\input{%s}}\n' % filename 57 | else: 58 | tex += '\\raggedbottom\\lstinputlisting[style=%s]{%s}\n' % (get_style(filename), filename) 59 | tex += '\\hrulefill\n' 60 | tex += '\n' 61 | return tex 62 | 63 | if __name__ == "__main__": 64 | sections = get_sections() 65 | tex = get_tex(sections) 66 | with open('contents.tex', 'w') as f: 67 | f.write(tex) 68 | 69 | os.system("latexmk -pdf model/notebook.tex > generate_pdf.log") 70 | 71 | os.system("mv notebook.pdf GEMP-Notebook.pdf") 72 | os.system("rm contents.tex") 73 | os.system("rm notebook.*") 74 | os.system("rm generate_pdf.log") -------------------------------------------------------------------------------- /latex/model/notebook.tex: -------------------------------------------------------------------------------- 1 | \documentclass[10pt]{article} 2 | \usepackage[left=0.4in,right=0.4in,top=0.7in,bottom=0.4in]{geometry} 3 | \usepackage{hyperref} 4 | \usepackage{fancyhdr} 5 | \usepackage{listings} 6 | \usepackage{xcolor} 7 | \usepackage{tocloft} 8 | \usepackage{pdflscape} 9 | \usepackage{multicol} 10 | \usepackage{amsfonts} 11 | \usepackage{amssymb} 12 | \usepackage{amsmath} 13 | \usepackage[utf8]{inputenc} 14 | 15 | \renewcommand*{\ttdefault}{pcr} 16 | \renewcommand\cftsecfont{\fontsize{10}{11}\bfseries} 17 | \renewcommand\cftsecpagefont{\fontsize{10}{11}\mdseries} 18 | \renewcommand\cftsubsecfont{\fontsize{7}{8}\mdseries} 19 | \renewcommand\cftsubsecpagefont{\fontsize{7}{8}\mdseries} 20 | %\renewcommand\cftsecfont{\fontsize{12}{13}\bfseries} 21 | %\renewcommand\cftsecpagefont{\fontsize{12}{13}\mdseries} 22 | %\renewcommand\cftsubsecfont{\fontsize{9}{10}\mdseries} 23 | %\renewcommand\cftsubsecpagefont{\fontsize{9}{10}\mdseries} 24 | \renewcommand\cftsecafterpnum{\vspace{-1ex}} 25 | \renewcommand\cftsubsecafterpnum{\vspace{-1ex}} 26 | 27 | \lstdefinestyle{shared}{ 28 | belowcaptionskip=1\baselineskip, 29 | breaklines=true, 30 | xleftmargin=\parindent, 31 | showstringspaces=false, 32 | basicstyle=\fontsize{8}{9}\ttfamily, 33 | } 34 | \lstdefinestyle{cpp}{ 35 | style=shared, 36 | language=C++, 37 | tabsize=2, 38 | keywordstyle=\bfseries\color{green!40!black}, 39 | commentstyle=\itshape\color{red!80!black}, 40 | identifierstyle=\color{black}, 41 | stringstyle=\color{purple!40!black}, 42 | } 43 | \lstdefinestyle{java}{ 44 | style=shared, 45 | language=Java, 46 | tabsize=2, 47 | keywordstyle=\bfseries\color{green!40!black}, 48 | commentstyle=\itshape\color{purple!40!black}, 49 | identifierstyle=\color{blue}, 50 | stringstyle=\color{orange}, 51 | } 52 | \lstdefinestyle{py}{ 53 | style=shared, 54 | language=Python, 55 | tabsize=2, 56 | keywordstyle=\bfseries\color{green!40!black}, 57 | commentstyle=\itshape\color{purple!40!black}, 58 | identifierstyle=\color{blue}, 59 | stringstyle=\color{orange}, 60 | } 61 | \lstdefinestyle{txt}{ 62 | style=shared, 63 | } 64 | \lstset{escapechar=@} 65 | 66 | \pagestyle{fancy} 67 | \fancyhead[L]{GEMP - Universidade Estadual do Ceará - Campus Itaperi} 68 | \fancyhead[R]{\thepage} 69 | \fancyfoot[C]{} 70 | 71 | \fancypagestyle{plain} 72 | { 73 | \fancyhead[L]{GEMP - Universidade Estadual do Ceará - Campus Itaperi} 74 | \fancyhead[R]{\thepage} 75 | \fancyfoot[C]{} 76 | } 77 | 78 | \title{\vspace{-4ex}\Large{GEMP - UECE - ICPC Library}} 79 | \author{} 80 | \date{} 81 | 82 | \begin{document} 83 | \begin{landscape} 84 | \begin{multicols}{2} 85 | 86 | \maketitle 87 | \vspace{-13ex} 88 | \tableofcontents 89 | \pagestyle{fancy} 90 | 91 | \input contents.tex 92 | 93 | \end{multicols} 94 | \end{landscape} 95 | \end{document} 96 | --------------------------------------------------------------------------------