├── README.md ├── data-structures ├── disjoin-set-union.cpp ├── fenwick-tree.cpp ├── mos-tree.cpp ├── mos.cpp ├── persistent-dsu.cpp ├── persistent-segment-tree.cpp ├── segment-tree-massive-lazy-propagation.cpp ├── segment-tree.cpp ├── sparse-segment-tree-massive-lazy-propagation.cpp └── sparse-table.cpp ├── dp-optimizations └── divide-and-conquer-dp.cpp ├── graphs ├── articulation-points-and-bridges.cpp ├── bellman-ford.cpp ├── bipartite-graph.cpp ├── center-of-a-tree.cpp ├── centroid-of-a-tree.cpp ├── chu-liu.cpp ├── dijkstra.cpp ├── floyd-warshall.cpp ├── heavy-light-decomposition.cpp ├── kahns.cpp ├── kosaraju.cpp ├── kruskal.cpp ├── lowest-common-ancestor.cpp └── prims.cpp ├── math ├── math.cpp ├── matrix-exponentiation.cpp ├── modular.cpp ├── sieve.cpp ├── simplex.cpp └── sub-matrix-sum.cpp ├── strings ├── ahocorasick-automata.cpp ├── ahocorasick-no-simplified-automata.cpp ├── dynamic-ahocorasick.cpp ├── hashing.cpp ├── kmp-automata.cpp ├── kmp.cpp ├── manacher.cpp ├── suffix-array.cpp ├── trie.cpp └── z-function.cpp ├── useful-algorithms ├── kadanes-algorithm.cpp ├── longest-increasing-subsequence.cpp └── tortoise-and-hare.cpp └── utilities ├── README.md ├── create-contest.py ├── template.cpp ├── test.bsh └── vscode ├── README.md ├── keybindings.json └── tasks.json /README.md: -------------------------------------------------------------------------------- 1 | # CompetitiveProgramming 2 | 3 | Personal competitive programming notebook 4 | -------------------------------------------------------------------------------- /data-structures/disjoin-set-union.cpp: -------------------------------------------------------------------------------- 1 | struct Dsu{ 2 | int n, comp = n; 3 | vector p, len; 4 | Dsu(int n) : n(n){ 5 | p.assign(n + 10, 0); 6 | iota(p.begin(), p.end(), 0); 7 | len.assign(n + 10, 1); 8 | } 9 | int find(int n){ return p[n] = p[n] == n ? n : find(p[n]); } 10 | void join(int a, int b){ 11 | a = find(a), b = find(b); 12 | if(a == b) return; 13 | if(len[a] < len[b]) swap(a, b); 14 | len[a] += len[b]; 15 | p[b] = a; 16 | comp--; 17 | } 18 | }; -------------------------------------------------------------------------------- /data-structures/fenwick-tree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * FENWICK TREE 3 | * 4 | * Let, f be some reversible function and a[] be an array of integers of length n. 5 | * Fenwick tree is a data structure which: 6 | * calculates the value of function f in the given range [l,r] (i.e. f(a[l], a[l + 1], …, a[r])) in O(log n) time; 7 | * updates the value of an element of a[] in O(log n) time; 8 | * requires O(n) memory, or in other words, exactly the same memory required for a; 9 | * 10 | **/ 11 | 12 | struct FenwickTree{ 13 | vector bit; 14 | int n; 15 | 16 | FenwickTree(int N){ 17 | n = N; 18 | bit.assign(n, 0); 19 | } 20 | 21 | FenwickTree(ll a[], int N){ 22 | n = N; 23 | bit.assign(n, 0); 24 | for(int i = 0; i < n; i++) 25 | add(i, a[i]); 26 | } 27 | 28 | ll sum(int r){ 29 | ll ret = 0; 30 | for(; r >= 0; r = (r & (r + 1)) - 1) 31 | ret += bit[r]; 32 | return ret; 33 | } 34 | 35 | ll sum(int l, int r){ 36 | return sum(r) - sum(l - 1); 37 | } 38 | 39 | void add(int i, ll delta){ 40 | for(; i < n; i = i | (i + 1)) 41 | bit[i] += delta; 42 | } 43 | }; 44 | 45 | 46 | /** 47 | * FENWICK TREE 2D 48 | * 49 | * Let, f be some reversible function and a[][] be a n*m matrix. 50 | * Fenwick tree 2D is a data structure which: 51 | * calculates the value of function f in the given subsquare with opposite vertices at a[0][0] and a[x][y] in O(log (n*m)) time; 52 | * updates the value of an element of a[][] in O(log (n*m)) time; 53 | * requires O(n*m) memory, or in other words, exactly the same memory required for a[][]; 54 | * 55 | **/ 56 | 57 | struct FenwickTree2D { 58 | vector> bit; 59 | int n, m; 60 | 61 | FenwickTree2D(int N, int M){ 62 | n = N; 63 | m = M; 64 | bit.assign(n, vector(m, 0)); 65 | } 66 | 67 | FenwickTree2D(vector> &a, int N, int M){ 68 | n = N; 69 | m = M; 70 | bit.assign(n, vector(m, 0)); 71 | for(int i = 0; i < n; i++) 72 | for(int j = 0; j < m; j++) 73 | add(i, j, a[i][j]); 74 | } 75 | 76 | int sum(int x, int y){ 77 | ll ret = 0; 78 | for(int i = x; i >= 0; i = (i & (i + 1)) - 1) 79 | for(int j = y; j >= 0; j = (j & (j + 1)) - 1) 80 | ret += bit[i][j]; 81 | return ret; 82 | } 83 | 84 | void add(int x, int y, ll delta){ 85 | for (int i = x; i < n; i = i | (i + 1)) 86 | for (int j = y; j < m; j = j | (j + 1)) 87 | bit[i][j] += delta; 88 | } 89 | }; 90 | -------------------------------------------------------------------------------- /data-structures/mos-tree.cpp: -------------------------------------------------------------------------------- 1 | # include 2 | using namespace std; 3 | # define endl "\n" 4 | # define io_boost ios_base::sync_with_stdio(0);cin.tie(0); 5 | using ull = unsigned long long; 6 | using ll = long long; 7 | /* 8 | Que mira bobo ? 9 | JUANKI 10 | */ 11 | 12 | /** 13 | * STATEMENT: You are given a tree with N nodes. The tree nodes are numbered from 1 to N. Each node has an integer weight. 14 | * We will ask you to perform the following operation: 15 | * u - v : ask for how many different weights of nodes are on the path from u to v. 16 | * 17 | * SOLUTION: Transform the tree in to an array using MODIFIED version of euler tour path, apply mo's algorithm over the resulting array. 18 | * We have 2 cases, for a path u - v: 19 | * 1- if lca(u, v) != u && lca(u, v) != v, then the answer for the query is mos([out[u], in[v]] U {LCA(u, v)}). 20 | * 2- if lca(u, v) == u || lca(u, v) == v, then the answer for the query is mos([in[u], in[v]]) 21 | * 22 | * NOTE: if some vertex appears in a segment of the euler tour an odd number of times then its value is included in the segment, 23 | * it is not included otherwise. 24 | **/ 25 | 26 | 27 | const int MAXN = 40004, MAXM = 100005, LOG2N = 16; 28 | vector g[MAXN]; 29 | 30 | // EULER TOUR and LCA. 31 | 32 | int a[2 * MAXN], up[MAXN][LOG2N + 5], dist[MAXN], N, M, in[MAXN], out[MAXN], t = 0; 33 | ll w[MAXN]; 34 | 35 | void dfs(int u, int p, int h){ 36 | a[t] = u; 37 | in[u] = t; 38 | t++; 39 | dist[u] = h; 40 | up[u][0] = p; 41 | for(int i = 1; i <= LOG2N; i++) 42 | up[u][i] = up[up[u][i - 1]][i - 1]; 43 | for(int v: g[u]) 44 | if(v != p) dfs(v, u, h + 1); 45 | a[t] = u; 46 | out[u] = t; 47 | t++; 48 | } 49 | 50 | int lca(int u, int v){ 51 | if(dist[u] < dist[v]) swap(u, v); 52 | int offset = dist[u] - dist[v]; 53 | for(int i = 0; i <= LOG2N; i++) 54 | if(offset & (1 << i)) u = up[u][i]; 55 | if(u == v) return u; 56 | for(int i = LOG2N - 1; i >= 0; i--) 57 | if(up[u][i] != up[v][i]) 58 | u = up[u][i], v = up[v][i]; 59 | return up[u][0]; 60 | } 61 | 62 | // MO's ALGORITHM 63 | 64 | struct Query{ 65 | int l, r, idx, lca; 66 | }; 67 | Query queries[MAXM]; 68 | pair b[2 * MAXN]; 69 | 70 | // id[] stores ids coordinates compression for weights of the vertices. 71 | int BLOCK_SIZE, l, r, freq[2 * MAXN], res, ans[MAXM], id[2 * MAXN], cnt[MAXN]; 72 | 73 | bool cmp(Query &a, Query &b){ 74 | if(a.l / BLOCK_SIZE == b.l / BLOCK_SIZE) return a.r > b.r; 75 | else return a.l / BLOCK_SIZE < b.l / BLOCK_SIZE; 76 | } 77 | 78 | // freq[id[i]] frequency of the weight of the a[i] vertex. 79 | 80 | void add(int i){ 81 | if(!freq[id[i]]) res++; 82 | freq[id[i]]++; 83 | } 84 | 85 | void del(int i){ 86 | freq[id[i]]--; 87 | if(!freq[id[i]]) res--; 88 | } 89 | 90 | void update(int i){ 91 | cnt[a[i]]++; 92 | if(cnt[a[i]] % 2) add(i); // if we get an odd frequency then add the element. 93 | else del(i); // if we get an even frequency then delete the element. 94 | } 95 | 96 | 97 | int get_ans(int LCA){ 98 | if(LCA != -1){ // if we are in the first case then the answer is mos([out[u], in[v]] U {LCA(u, v)}). 99 | update(in[LCA]); 100 | int resi = res; 101 | update(in[LCA]); 102 | return resi; 103 | } 104 | else return res; 105 | } 106 | 107 | void mos(){ 108 | BLOCK_SIZE = sqrt(t); 109 | // Coordinates compression for weights 110 | for(int i = 0; i < t; i++) 111 | b[i] = {w[a[i]], i}; 112 | sort(b, b + t); 113 | int cid = 0; 114 | for(int i = 0; i < t; i++){ 115 | if(i != 0 && b[i - 1].first != b[i].first) cid++; 116 | id[b[i].second] = cid; 117 | } 118 | // Answering queries. 119 | sort(queries, queries + M, cmp); 120 | l = 1; 121 | r = 0; 122 | for(int i = 0; i < M; i++){ 123 | while(r < queries[i].r) update(++r); 124 | while(l > queries[i].l) update(--l); 125 | while(r > queries[i].r) update(r--); 126 | while(l < queries[i].l) update(l++); 127 | ans[queries[i].idx] = get_ans(queries[i].lca); 128 | } 129 | } 130 | 131 | 132 | int main(){ 133 | cin >> N >> M; 134 | for(int i = 0; i < N; i++) cin >> w[i]; 135 | for(int i = 0, u, v; i < N - 1; i++){ 136 | cin >> u >> v; 137 | u--; v--; 138 | g[u].push_back(v); 139 | g[v].push_back(u); 140 | } 141 | dfs(0, 0, 0); 142 | for(ll i = 0, u, v; i < M; i++){ 143 | cin >> u >> v; 144 | u--; v--; 145 | ll LCA = lca(u, v); 146 | if(in[u] > in[v]) swap(u, v); 147 | if(LCA == u){ 148 | queries[i].l = in[u]; 149 | queries[i].r = in[v]; 150 | queries[i].lca = -1; 151 | } 152 | else{ 153 | queries[i].l = out[u]; 154 | queries[i].r = in[v]; 155 | queries[i].lca = LCA; 156 | } 157 | queries[i].idx = i; 158 | } 159 | mos(); 160 | for(int i = 0; i < M; i++) cout << ans[i] << endl; 161 | return 0; 162 | } 163 | -------------------------------------------------------------------------------- /data-structures/mos.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * MO's Algorithm. 4 | * 5 | * Answer queries over a segment [l, r] of the array. For example frequency of the most repeated element in the segment [l, r] 6 | * Requires: add(int i), del(int i), get_ans() 7 | * 8 | * Time Complexity N * N / BLOCK_SIZE + BLOCK_SIZE * M 9 | * 10 | * */ 11 | 12 | struct Mos{ 13 | 14 | struct Query{ 15 | int l, r, idx; 16 | }; 17 | 18 | int N, M, BLOCK_SIZE, l, r; 19 | 20 | vector queries; 21 | vector ans, a; 22 | 23 | vector> b; 24 | vector id; 25 | 26 | Mos(int n, int m){ 27 | N = n; 28 | M = m; 29 | BLOCK_SIZE = sqrt(N); 30 | 31 | queries.assign(M, Query()); 32 | ans.assign(M, 0); 33 | a.assign(N, 0); 34 | 35 | b.assign(N, {0, 0}); 36 | id.assign(N, 0); 37 | } 38 | 39 | void add(int i){ 40 | } 41 | 42 | void del(int i){ 43 | } 44 | 45 | 46 | ll get_ans(){ 47 | return 0; 48 | } 49 | 50 | void mos(){ 51 | BLOCK_SIZE = sqrt(N); 52 | 53 | for(int i = 0; i < N; i++) b[i] = {a[i], i}; 54 | sort(b.begin(), b.end()); 55 | int cid = 0; 56 | for(int i = 0; i < N; i++){ 57 | if(i != 0 && b[i - 1].first != b[i].first) cid++; 58 | id[b[i].second] = cid; 59 | } 60 | 61 | sort(queries.begin(), queries.end(), [&](const auto &a, const auto &b){ 62 | if(a.l / BLOCK_SIZE == b.l / BLOCK_SIZE) return a.r > b.r; 63 | else return a.l / BLOCK_SIZE < b.l / BLOCK_SIZE; 64 | }); 65 | 66 | l = 0; 67 | r = -1; 68 | for(int i = 0; i < M; i++){ 69 | while(r < queries[i].r) add(++r); 70 | while(l > queries[i].l) add(--l); 71 | while(r > queries[i].r) del(r--); 72 | while(l < queries[i].l) del(l++); 73 | ans[queries[i].idx] = get_ans(); 74 | } 75 | } 76 | 77 | }; 78 | -------------------------------------------------------------------------------- /data-structures/persistent-dsu.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * PERSISTENT DSU 3 | * 4 | * Use save function in order to start saving history of operations. 5 | * If you want to return at the last check point use rollback function, once you've 6 | * rolled back the DSU to some checkpoint, that check point is lost, for each rollback 7 | * there must be one check point previously setted. 8 | * 9 | **/ 10 | 11 | 12 | struct DSU{ 13 | 14 | struct operation{ 15 | int a, b, lb; 16 | }; 17 | 18 | int n, comp = n; 19 | vector p, len; 20 | bool checkpoint = 0; 21 | stack history; 22 | DSU(int n) : n(n){ 23 | p.assign(n + 10, 0); 24 | iota(p.begin(), p.end(), 0); 25 | len.assign(n + 10, 1); 26 | } 27 | 28 | int find(int n){ return p[n] == n ? n : find(p[n]); } 29 | 30 | void join(int a, int b){ 31 | a = find(a), b = find(b); 32 | if(a == b) return; 33 | if(len[a] < len[b]) swap(a, b); 34 | if(checkpoint) history.push({a, b, len[b]}); 35 | len[a] += len[b]; 36 | p[b] = a; 37 | comp--; 38 | } 39 | 40 | void rollback(){ 41 | while(!history.empty()){ 42 | auto [a, b, lb] = history.top(); 43 | history.pop(); 44 | if(a == -1){ 45 | if(history.empty()) checkpoint = 0; 46 | return; 47 | } 48 | p[b] = b; 49 | comp++; 50 | len[a] -= lb; 51 | len[b] = lb; 52 | } 53 | checkpoint = 0; 54 | } 55 | 56 | void save(){ 57 | checkpoint = 1; 58 | history.push({-1, -1, -1}); 59 | } 60 | }; -------------------------------------------------------------------------------- /data-structures/persistent-segment-tree.cpp: -------------------------------------------------------------------------------- 1 | template struct Node { 2 | Node *left, *right; 3 | T v; 4 | Node() : left(this), right(this), v(0){} 5 | Node(Node *left, Node *right, T v) : left(left), right(right), v(v){} 6 | 7 | Node* update(int l, int r, int i, T val){ 8 | if(l == r) return new Node(nullptr, nullptr, v + val); 9 | int m = (l + r) / 2; 10 | if(i <= m) return new Node(left->update(l, m, i, val), right, v + val); 11 | return new Node(left, right->update(m + 1, r, i, val), v + val); 12 | } 13 | 14 | T get(int ss, int se, int qs, int qe){ 15 | if(qs <= ss && se <= qe) return v; 16 | if(ss > qe || se < qs) return 0; 17 | int m = (ss + se) / 2; 18 | return left->get(ss, m, qs, qe) + right->get(m + 1, se, qs, qe); 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /data-structures/segment-tree-massive-lazy-propagation.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * SEGMENT TREE FOR MASSIVE OPERATIONS WITH LAZY PROPAGATION 4 | * 5 | * Example: 6 | * assign value v to all elements on the segment from l to r. (lazy) 7 | * find the sum on the segment from l to r. (st) 8 | * 9 | * note: lazy operation must be distributive. 10 | * 11 | **/ 12 | 13 | template struct SegmentTree{ 14 | 15 | int N; 16 | vector st, lazy; 17 | vector tag; 18 | 19 | int R(int si){ return 2 * si + 2; } 20 | int L(int si){ return 2 * si + 1; } 21 | int MID(int ss, int se){ return (se + ss) / 2; } 22 | T NEUTRAL(){ return 0; } 23 | 24 | SegmentTree(vector &a) : N(a.size()){ 25 | st.assign(4 * N, 0); 26 | lazy.assign(4 * N, 0); 27 | tag.assign(4 * N, 0); 28 | build(a, 0, N - 1); 29 | } 30 | 31 | SegmentTree(int n) : N(n){ 32 | st.assign(4 * N, 0); 33 | lazy.assign(4 * N, 0); 34 | tag.assign(4 * N, 0); 35 | } 36 | 37 | void build(vector &a, int ss, int se, int si = 0){ 38 | if(ss == se){ 39 | st[si] = a[ss]; 40 | return; 41 | } 42 | build(a, ss, MID(ss, se), L(si)); 43 | build(a, MID(ss, se) + 1, se, R(si)); 44 | st[si] = st[L(si)] + st[R(si)]; 45 | } 46 | 47 | 48 | void push_down(int ss, int se, int si){ 49 | if(tag[si]){ 50 | st[L(si)] = lazy[si] * (MID(ss, se) - ss + 1); 51 | st[R(si)] = lazy[si] * (se - MID(ss, se)); 52 | lazy[L(si)] = lazy[R(si)] = lazy[si]; 53 | tag[L(si)] = tag[R(si)] = 1; 54 | tag[si] = 0; 55 | } 56 | } 57 | 58 | void update(int qs, int qe, T val){ return update(0, N - 1, 0, qs, qe, val); } 59 | void update(int ss, int se, int si, int qs, int qe, T val){ 60 | if(ss > qe || se < qs) return; 61 | if(qs <= ss && se <= qe){ 62 | st[si] = val * (se - ss + 1); 63 | lazy[si] = val; 64 | tag[si] = 1; 65 | return; 66 | } 67 | push_down(ss, se, si); 68 | update(ss, MID(ss, se), L(si), qs, qe, val); 69 | update(MID(ss, se) + 1, se, R(si), qs, qe, val); 70 | st[si] = st[L(si)] + st[R(si)]; 71 | } 72 | 73 | T get(int qs, int qe){ return get(0, N - 1, 0, qs, qe); } 74 | T get(int ss, int se, int si, int qs, int qe){ 75 | if(qs <= ss && se <= qe) return st[si]; 76 | if(ss > qe || se < qs) return NEUTRAL(); 77 | push_down(ss, se, si); 78 | return get(ss, MID(ss, se), L(si), qs, qe) + get(MID(ss, se) + 1, se, R(si), qs, qe); 79 | } 80 | 81 | }; 82 | -------------------------------------------------------------------------------- /data-structures/segment-tree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * SEGMENT TREE. 4 | * O(log(N)) per query. 5 | * REQUIRED: 6 | * - merge 7 | * - NEUTRAL 8 | * */ 9 | 10 | template struct SegmentTree{ 11 | int N; 12 | vector st; 13 | 14 | SegmentTree(vector &a) : N(a.size()){ 15 | st.assign(4 * N, 0); 16 | build(0, N - 1, 0, a); 17 | } 18 | 19 | SegmentTree(int n) : N(n){ st.assign(4 * N, 0); } 20 | 21 | int R(int si){ return 2 * si + 2; } 22 | int L(int si){ return 2 * si + 1; } 23 | int MID(int ss, int se){ return (ss + se) / 2; } 24 | T NEUTRAL(){ return 0; } 25 | 26 | T merge(T lval, T rval){ 27 | return NEUTRAL(); 28 | } 29 | 30 | void build(int ss, int se, int si, vector &a){ 31 | if(ss == se){ 32 | st[si] = a[ss]; 33 | return; 34 | } 35 | build(ss, MID(ss, se), L(si), a); 36 | build(MID(ss, se) + 1, se, R(si), a); 37 | st[si] = merge(st[L(si)], st[R(si)]); 38 | } 39 | 40 | T get(int qs, int qe){ return get(0, N - 1, 0, qs, qe); } 41 | T get(int ss, int se, int si, int qs, int qe){ 42 | if(qs <= ss && se <= qe) return st[si]; 43 | if(ss > qe || se < qs) return NEUTRAL(); 44 | return merge(get(ss, MID(ss, se), L(si), qs, qe), 45 | get(MID(ss, se) + 1, se, R(si), qs, qe)); 46 | } 47 | 48 | T update(int i, T val){ return update(0, N - 1, 0, i, val); } 49 | T update(int ss, int se, int si, int i, T val){ 50 | if(ss == se) return st[si] = val; 51 | if(i <= MID(ss, se)) return st[si] = merge(update(ss, MID(ss, se), L(si), i, val), 52 | st[R(si)]); 53 | else return st[si] = merge(st[L(si)], update(MID(ss, se) + 1, se, R(si), i, val)); 54 | } 55 | 56 | }; -------------------------------------------------------------------------------- /data-structures/sparse-segment-tree-massive-lazy-propagation.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * SPARSE SEGMENT TREE FOR MASSIVE OPERATIONS WITH LAZY PROPAGATION 4 | * 5 | * Example: 6 | * assign value v to all elements on the segment from l to r. (lazy) 7 | * find the sum on the segment from l to r. (st) 8 | * 9 | * note: lazy operation must be distributive. 10 | * 11 | **/ 12 | 13 | template struct Node{ 14 | Node *left = nullptr, *right = nullptr; 15 | T st = 0, lazy = 0; 16 | bool tag = false; 17 | int ss, se; 18 | 19 | Node(int ss, int se): ss(ss), se(se){} 20 | 21 | int mid(){ return (se + ss) / 2; } 22 | T NEUTRAL(){ return 0; } 23 | 24 | void push_down(){ 25 | if(left == nullptr && right == nullptr){ 26 | left = new Node(ss, mid()); 27 | right = new Node(mid() + 1, se); 28 | } 29 | if(tag){ 30 | left->st = lazy * (mid() - ss + 1); 31 | right->st = lazy * (se - mid()); 32 | left->lazy = right->lazy = lazy; 33 | left->tag = right->tag = 1; 34 | tag = 0; 35 | } 36 | } 37 | 38 | void update(int qs, int qe, T val){ 39 | if(ss > qe || se < qs) return; 40 | if(qs <= ss && se <= qe){ 41 | st = val * (se - ss + 1); 42 | lazy = val; 43 | tag = 1; 44 | return; 45 | } 46 | push_down(); 47 | left->update(qs, qe, val); 48 | right->update(qs, qe, val); 49 | st = left->st + right->st; 50 | } 51 | 52 | T get(int qs, int qe){ 53 | if(qs <= ss && se <= qe) return st; 54 | if(ss > qe || se < qs) return NEUTRAL(); 55 | push_down(); 56 | return left->get(qs, qe) + right->get(qs, qe); 57 | } 58 | 59 | }; 60 | -------------------------------------------------------------------------------- /data-structures/sparse-table.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * SPARSE TABLE: 3 | * 4 | * Sparse Table is a data structure, that allows answering range queries. It can answer most range queries in O(logn), 5 | * but its true power is answering range minimum queries (or equivalent range maximum queries). For those queries it 6 | * can compute the answer in O(1) time. The only drawback of this data structure is, that it can only be used on immutable 7 | * arrays. This means, that the array cannot be changed between two queries. If any element in the array changes, the 8 | * complete data structure has to be recomputed. 9 | * Build function time complexity: O(N logN) 10 | * 11 | **/ 12 | 13 | template struct SparseTable{ 14 | // lg2[i]: log2(i), st[][]: sparse table, a[]: array of elements 15 | int N, LOG2N; 16 | vector lg2; 17 | vector> st; 18 | 19 | SparseTable(vector &a, std::function f){ 20 | N = a.size(); 21 | LOG2N = log2(N) + 2; 22 | lg2.assign(N + 1, 0); 23 | st.assign(N, vector(LOG2N, 0)); 24 | 25 | // Delete this if the query does not need it 26 | lg2[1] = 0; 27 | for(int i = 2; i <= N; i++) lg2[i] = lg2[i / 2] + 1; 28 | 29 | for(int i = 0; i < N; i++) st[i][0] = a[i]; 30 | // st[i][j] is the answer for the range [i, i + 2^j - 1] 31 | for(int j = 1; j <= LOG2N; j++) 32 | for(int i = 0; i + (1 << j) <= N; i++) 33 | st[i][j] = f(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]); 34 | } 35 | 36 | // Find minimum in [L, R] 37 | T minimum(int L, int R){ 38 | int lg = lg2[R - L + 1]; 39 | return min(st[L][lg], st[R - (1 << lg) + 1][lg]); 40 | } 41 | 42 | // Find sum of elements in [L, R] 43 | T sum(int L, int R){ 44 | T ans = 0; 45 | for(int i = LOG2N; i >= 0; i--){ 46 | if(R - L + 1 >= (1 << i)){ 47 | ans += st[L][i]; 48 | L += (1 << i); 49 | } 50 | } 51 | return ans; 52 | } 53 | }; -------------------------------------------------------------------------------- /dp-optimizations/divide-and-conquer-dp.cpp: -------------------------------------------------------------------------------- 1 | 2 | const ll oo = 1e18; 3 | int m, n; 4 | vector dp_before(n), dp_cur(n); 5 | ll C(int i, int j); 6 | 7 | void compute(int l, int r, int optl, int optr){ 8 | if(l > r) return; 9 | 10 | int mid = (l + r) >> 1; 11 | pair best = {oo, -1}; 12 | for(int k = optl; k <= min(mid, optr); k++) 13 | best = min(best, {(k ? dp_before[k - 1] : 0) + C(k, mid), k}); 14 | 15 | dp_cur[mid] = best.first; 16 | int opt = best.second; 17 | 18 | compute(l, mid - 1, optl, opt); 19 | compute(mid + 1, r, opt, optr); 20 | } 21 | 22 | int solve(){ 23 | for(int i = 0; i < n; i++) dp_before[i] = C(0, i); 24 | 25 | for(int i = 1; i < m; i++) 26 | compute(0, n - 1, 0, n - 1), 27 | dp_before = dp_cur; 28 | 29 | return dp_before[n - 1]; 30 | } 31 | -------------------------------------------------------------------------------- /graphs/articulation-points-and-bridges.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Articulation points 3 | */ 4 | const int MAXN = 20000; 5 | int n, m, t, ans, disc[MAXN], low[MAXN]; 6 | bool vis[MAXN]; 7 | vector g[MAXN]; 8 | 9 | void dfs(int u, int p){ 10 | vis[u] = true; 11 | low[u] = disc[u] = ++t; 12 | bool has_back_edge = 0; 13 | int children = 0; 14 | for(int v: g[u]){ 15 | if(!vis[v]){ 16 | dfs(v, u); 17 | low[u] = min(low[u], low[v]); 18 | if(p != -1 && low[v] >= disc[u]) has_back_edge = 1;\ 19 | children++; 20 | } 21 | else if(v != p) low[u] = min(low[u], disc[v]); 22 | } 23 | if(has_back_edge) ans++; 24 | if(p == -1 && children > 1) ans++; 25 | } 26 | 27 | 28 | /* 29 | Bridges 30 | */ 31 | int n, m, q, t; 32 | const int MAXN = 1e5 + 5; 33 | bool vis[MAXN]; 34 | int disc[MAXN], low[MAXN], comp[MAXN]; 35 | 36 | vector g[MAXN]; 37 | vector> bridge; 38 | void dfs(int u, int p){ 39 | vis[u] = 1; 40 | disc[u] = low[u] = ++t; 41 | for(int v : g[u]){ 42 | if(!vis[v]){ 43 | dfs(v, u); 44 | low[u] = min(low[u], low[v]); 45 | if(low[v] > disc[u]) bridge.push_back({u, v}); 46 | } 47 | else if(v != p) low[u] = min(low[u], disc[v]); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /graphs/bellman-ford.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * BELLMAN FORD 4 | * 5 | * Find shortest distance from source (src) to all other vertices, graph could contain 6 | * negative weight edges. 7 | * Time complexity O(VE); 8 | * 9 | * */ 10 | 11 | const ll oo = numeric_limits::max(); 12 | int N, M; 13 | 14 | vector> edges; 15 | 16 | bool bellman_ford(int src, vector &dist){ 17 | dist.assign(N, oo); 18 | dist[src] = 0; 19 | bool x; 20 | for(int i = 0; i < N; i++){ 21 | x = 0; 22 | for(int j = 0; j < M; j++){ 23 | auto [u, v, w] = edges[j]; 24 | if(dist[u] != oo && dist[v] > dist[u] + w) 25 | dist[v] = dist[u] + w, 26 | x = 1; 27 | } 28 | } 29 | // return 1 if there is a negative weith cycle 30 | return x; 31 | } 32 | -------------------------------------------------------------------------------- /graphs/bipartite-graph.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * CHECK WHETHER A GRAPH IS BIPARTITE OR NOT. 3 | **/ 4 | 5 | const int MAXN = 100000; 6 | int N, M; 7 | vector g[MAXN]; 8 | 9 | bool bipartite(){ 10 | int color[MAXN]; 11 | memset(color, -1, sizeof(color)); 12 | queue q; 13 | color[0] = 1; 14 | q.push(0); 15 | while(!q.empty()){ 16 | int u = q.front(); 17 | q.pop(); 18 | for(int v: g[u]){ 19 | if(color[v] == -1){ 20 | color[v] = 1 - color[u]; 21 | q.push(v); 22 | } 23 | else if(color[v] == color[u]) return false; 24 | } 25 | } 26 | return true; 27 | } 28 | -------------------------------------------------------------------------------- /graphs/center-of-a-tree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * CENTER: 3 | * Every tree has a center consisting of one vertex or two adjacent vertices. 4 | * The center is the middle vertex or middle two vertices in every longest path. 5 | * **/ 6 | vector centers(vector t[], int n){ 7 | int root, maxdist = 0, parent[n]; 8 | function[], int)> dfs = [&](int u, int p, vector t[], int d){ 9 | if(maxdist < d){ 10 | maxdist = d; 11 | root = u; 12 | } 13 | parent[u] = p; 14 | for(int v: t[u]) 15 | if(v != p) 16 | dfs(v, u, t, d + 1); 17 | }; 18 | dfs(0, -1, t, 0); 19 | maxdist = 0; 20 | dfs(root, -1, t, 0); 21 | int cur = root; 22 | vector path; 23 | while (cur != -1){ 24 | path.push_back(cur); 25 | cur = parent[cur]; 26 | } 27 | if(path.size() % 2) return {path[path.size() / 2]}; 28 | else return{path[path.size() / 2], path[(path.size() / 2) - 1]}; 29 | } -------------------------------------------------------------------------------- /graphs/centroid-of-a-tree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * CENTROID: 3 | * let S(v) be the size of the subtree rooted on v. 4 | * 5 | * A centroid is a node v such that. 6 | * maxi(n - S(v), S(u1), S(u2), .. S(um)) <= n/2 7 | * where ui is the i'th child of v. 8 | * 9 | * Every tree only have one or two centroids. 10 | * 11 | * **/ 12 | vector centroids(vector g[], int n){ 13 | vector centroid; 14 | vector sz(n); 15 | function dfs = [&](int u, int prev) { 16 | sz[u] = 1; 17 | bool is_centroid = true; 18 | for (auto v : g[u]) if (v != prev) { 19 | dfs(v, u); 20 | sz[u] += sz[v]; 21 | if (sz[v] > n / 2) is_centroid = false; 22 | } 23 | if (n - sz[u] > n / 2) is_centroid = false; 24 | if (is_centroid) centroid.push_back(u); 25 | }; 26 | dfs(0, -1); 27 | return centroid; 28 | } -------------------------------------------------------------------------------- /graphs/chu-liu.cpp: -------------------------------------------------------------------------------- 1 | // O(n * m), finds MST over directed graphs 2 | 3 | template struct ChuLiu{ 4 | struct edge{ 5 | int u, v, id; 6 | T len; 7 | }; 8 | 9 | const T oo = numeric_limits::max(); 10 | int n; 11 | vector e; 12 | vector inc, dec, take, pre, num, id, vis; 13 | vector inw; 14 | 15 | void add_edge(int x, int y, T w){ 16 | inc.push_back(0); 17 | dec.push_back(0); 18 | take.push_back(0); 19 | e.push_back({x, y, (int) e.size(), w}); 20 | } 21 | 22 | ChuLiu(int n): n(n), pre(n), num(n), id(n), vis(n), inw(n){} 23 | 24 | T doit(int root){ 25 | auto e2 = e; 26 | T ans = 0; 27 | int eg = e.size() - 1, pos = e.size() - 1; 28 | while(1){ 29 | for(int i = 0; i < n; i++) 30 | inw[i] = oo, 31 | id[i] = vis[i] = -1; 32 | for(auto ed : e2) 33 | if(ed.len < inw[ed.v]){ 34 | inw[ed.v] = ed.len; 35 | pre[ed.v] = ed.u; 36 | num[ed.v] = ed.id; 37 | } 38 | inw[root] = 0; 39 | for(int i = 0; i < n; i++) 40 | if(inw[i] == oo) 41 | return -1; 42 | int tot = -1; 43 | for(int i = 0; i < n; i++){ 44 | ans += inw[i]; 45 | if(i != root) take[num[i]]++; 46 | int j = i; 47 | while(vis[j] != i && j != root && id[j] < 0) vis[j] = i, j = pre[j]; 48 | if(j != root && id[j] < 0){ 49 | id[j] = ++tot; 50 | for(int k = pre[j]; k != j ; k = pre[k]) id[k] = tot; 51 | } 52 | } 53 | if(tot < 0) break; 54 | for(int i = 0; i < n; i++) if(id[i] < 0) id[i] = ++tot; 55 | n = tot + 1; 56 | int j = 0; 57 | for(int i = 0; i < e2.size(); i++){ 58 | int v = e2[i].v; 59 | e2[j].v = id[e2[i].v]; 60 | e2[j].u = id[e2[i].u]; 61 | if(e2[j].v != e2[j].u){ 62 | e2[j].len = e2[i].len - inw[v]; 63 | inc.push_back(e2[i].id); 64 | dec.push_back(num[v]); 65 | take.push_back(0); 66 | e2[j++].id = ++pos; 67 | } 68 | } 69 | e2.resize(j); 70 | root = id[root]; 71 | } 72 | while(pos > eg){ 73 | if(take[pos] > 0) 74 | take[inc[pos]]++, 75 | take[dec[pos]]--; 76 | pos--; 77 | } 78 | return ans; 79 | } 80 | }; 81 | -------------------------------------------------------------------------------- /graphs/dijkstra.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * DIJKSTRA. 3 | * 4 | * Find shortest path from source to all other vertices. 5 | * 6 | * E: number of edges. 7 | * V: number of vertices. 8 | * time complexity: O(E log(V)) 9 | * 10 | * */ 11 | 12 | const ll oo = numeric_limits::max(), MAXN = 100000; 13 | vector> g[MAXN]; 14 | int N; 15 | 16 | void dijkstra(int src, vector &dist){ 17 | priority_queue, vector>, greater>> pq; 18 | dist.assign(N, oo); 19 | pq.push({0, src}); 20 | dist[src] = 0; 21 | while(!pq.empty()){ 22 | auto [pd, u] = pq.top(); 23 | pq.pop(); 24 | if(pd > dist[u]) continue; 25 | for(auto [w, v] : g[u]) 26 | if(dist[v] > dist[u] + w){ 27 | dist[v] = dist[u] + w; 28 | pq.push({dist[v], v}); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /graphs/floyd-warshall.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * FLOYD WARSHALL. 3 | * 4 | * Find shortest paths between all possible pair of vertices. 5 | * 6 | * V: number of vertices. 7 | * time complexity: O(V^3) 8 | * 9 | * */ 10 | 11 | const int MAXN = 1000, oo = numeric_limits::max(); 12 | int g[MAXN][MAXN], N, dist[MAXN][MAXN]; 13 | 14 | void floyd_warshall(){ 15 | for(int i = 0; i < N; i++) 16 | for(int j = 0; j < N; j++) 17 | dist[i][j] = g[i][j]; 18 | for(int k = 0; k < N; k++) 19 | for(int i = 0; i < N; i++) 20 | for(int j = 0; j < N; j++) 21 | if(dist[i][k] + dist[k][j] < dist[i][j]) 22 | dist[i][j] = dist[i][k] + dist[k][j]; 23 | } -------------------------------------------------------------------------------- /graphs/heavy-light-decomposition.cpp: -------------------------------------------------------------------------------- 1 | 2 | struct Hld{ 3 | vector parent, depth, heavy, head, pos, len; 4 | int cur_pos, n; 5 | 6 | int dfs(int u, vector g[]){ 7 | int size = 1, mx = 0; 8 | for(int v : g[u]) 9 | if(v != parent[u]){ 10 | parent[v] = u, depth[v] = depth[u] + 1; 11 | int v_size = dfs(v, g); 12 | size += v_size; 13 | if(v_size > mx) 14 | mx = v_size, heavy[u] = v; 15 | } 16 | return size; 17 | } 18 | 19 | void decompose(int u, int h, vector g[]){ 20 | head[u] = h, pos[u] = cur_pos++; 21 | if(heavy[u] != -1) decompose(heavy[u], h, g); 22 | for(int v : g[u]) 23 | if(v != parent[u] && v != heavy[u]) 24 | decompose(v, v, g); 25 | } 26 | 27 | Hld(int N, vector g[]){ 28 | n = N; 29 | parent = vector(n); 30 | depth = vector(n); 31 | heavy = vector(n, -1); 32 | head = vector(n); 33 | pos = vector(n); 34 | cur_pos = 0; 35 | 36 | dfs(0, g); 37 | decompose(0, 0, g); 38 | } 39 | 40 | }; 41 | 42 | 43 | -------------------------------------------------------------------------------- /graphs/kahns.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * KAHN'S ALGORITHM: 3 | * 4 | * Find the linear ordering of vertices (Topological sort) in a directed acyclic graph (DAG). 5 | * We can also check if the graph has a cycle using kahn's algorithm, if we did not visited all 6 | * the nodes in the graph, then unvisited nodes will not be at vector toposort, that means 7 | * if toposort.size() != N then there is a cycle in the graph. 8 | * 9 | * time complexity O(N + M). 10 | * 11 | **/ 12 | 13 | const int MAXN = 1e5; 14 | vector g[MAXN]; 15 | int N, M; 16 | 17 | vector kahns(){ 18 | vector toposort; 19 | int in_degree[N] = {0}; 20 | for(int u = 0; u < N; u++) 21 | for(int v: g[u]) 22 | in_degree[v]++; 23 | queue q; 24 | for(int u = 0; u < N; u++) 25 | if(!in_degree[u]) q.push(u); 26 | while(!q.empty()){ 27 | int u = q.front(); 28 | q.pop(); 29 | toposort.push_back(u); 30 | for(int v: g[u]) 31 | if(--in_degree[v] == 0) 32 | q.push(v); 33 | } 34 | // if toposort.size() != N : there is a cycle in the graph. 35 | return toposort; 36 | } 37 | -------------------------------------------------------------------------------- /graphs/kosaraju.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * KOSARAJU 4 | * find strongly connected components of a graph. 5 | * 6 | * */ 7 | 8 | void dfs(vector g[], stack &s, vector &visited, vector &component, 9 | int &cur_component, int u, bool save){ 10 | visited[u] = true; 11 | if(!save) component[u] = cur_component; 12 | for(int v: g[u]) 13 | if(!visited[v]) 14 | dfs(g, s, visited, component, cur_component, v, save); 15 | if(save) s.push(u); 16 | } 17 | 18 | vector kosaraju(vector g[], int N){ 19 | 20 | vector gt[N], component(N); 21 | int cur_component = 0; 22 | stack s; 23 | vector visited(N, 0); 24 | 25 | for(int u = 0; u < N; u++) 26 | for(int v : g[u]) gt[v].push_back(u); 27 | 28 | 29 | for(int i = 0; i < N; i++) 30 | if(!visited[i]) 31 | dfs(g, s, visited, component, cur_component, i, true); 32 | 33 | visited.assign(N, 0); 34 | 35 | cur_component = 0; 36 | while(!s.empty()){ 37 | int u = s.top(); 38 | s.pop(); 39 | if(!visited[u]) 40 | dfs(gt, s, visited, component, cur_component, u, false), 41 | cur_component++; 42 | } 43 | return component; 44 | } -------------------------------------------------------------------------------- /graphs/kruskal.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * KRUSKAL 4 | * find minimum spanning tree. 5 | * time complexity: O(E log(V)). 6 | * 7 | * */ 8 | 9 | struct edge{ 10 | ll w; 11 | int u, v; 12 | bool operator < (const edge &e){ 13 | return w < e.w; 14 | } 15 | }; 16 | 17 | const int MAXM = 100000, MAXN = 100000; 18 | edge edges[MAXM], mst[MAXN]; 19 | int N, M; 20 | 21 | struct Dsu{ 22 | int n, comp = n; 23 | vector p, len; 24 | Dsu(int n) : n(n){ 25 | p.assign(n + 10, 0); 26 | iota(p.begin(), p.end(), 0); 27 | len.assign(n + 10, 1); 28 | } 29 | int find(int n){ return p[n] = p[n] == n ? n : find(p[n]); } 30 | void join(int a, int b){ 31 | a = find(a), b = find(b); 32 | if(a == b) return; 33 | if(len[a] < len[b]) swap(a, b); 34 | len[a] += len[b]; 35 | p[b] = a; 36 | comp--; 37 | } 38 | }; 39 | 40 | ll kruskal(){ 41 | Dsu dsu(N); 42 | sort(edges, edges + M); 43 | ll sum = 0; 44 | for(int i = 0, e = 0; i < N - 1;){ 45 | int u = dsu.find(edges[e].u), v = dsu.find(edges[e].v); 46 | if(u != v){ 47 | dsu.join(u, v); 48 | mst[i++] = edges[e]; 49 | sum += edges[e].w; 50 | } 51 | e++; 52 | } 53 | return sum; 54 | } 55 | -------------------------------------------------------------------------------- /graphs/lowest-common-ancestor.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Lowest common ancestor (LCA). binary lifting 3 | * 4 | * O(nlgn) in dfs function and O(lg(n)) per query. 5 | * 6 | * We will find the LCA by lifting up each vertex until they find each other. 7 | * 8 | * Algorithm: 9 | * 1.- run dfs(root, root, 0) 10 | * 11 | * Binary lifting, we will jump in powers of 2. 12 | * up[u][i] means we jump up from vertex u, 2^i positions. 13 | * here we are calculating jumps for each power of 2. 14 | * 15 | * 2.- call lca(u, v) for each query 16 | * 17 | * First both u, v should be at the same distance from the root (height). 18 | * After that u is at the same hight of v, if u == v it means v was the LCA of u. 19 | * Then, we want to lift up u and v to be childs of the lca, if jumping from 20 | * u and v a distance 2^i ends in the same vertex (up[u][i] == up[v][i]) it 21 | * means that it is the LCA or the vertex is above the LCA, then we do not jump that distance, 22 | * we always want to be under the LCA in order to end at the childs of the LCA. 23 | * 24 | **/ 25 | 26 | struct Lca{ 27 | int N, LOG2N, root; 28 | vector dist; 29 | vector> up; 30 | 31 | Lca(int n, int r, vector g[]){ 32 | N = n; 33 | root = r; 34 | LOG2N = log2(N); 35 | up.assign(N + 5, vector(LOG2N + 1, 0)); 36 | dist.assign(N + 5, 0); 37 | dfs(root, root, 0, g); 38 | } 39 | 40 | void dfs(int u, int p, int h, vector g[]){ 41 | dist[u] = h; 42 | up[u][0] = p; 43 | 44 | for(int i = 1; i <= LOG2N; i++) 45 | up[u][i] = up[up[u][i - 1]][i - 1]; 46 | 47 | for(int v: g[u]) 48 | if(v != p) dfs(v, u, h + 1, g); 49 | } 50 | 51 | int lca(int u, int v){ 52 | if(dist[u] < dist[v]) swap(u, v); 53 | 54 | int offset = dist[u] - dist[v]; 55 | 56 | for(int i = 0; i <= LOG2N; i++) 57 | if(offset & (1 << i)) u = up[u][i]; 58 | 59 | if(u == v) return u; 60 | 61 | for(int i = LOG2N - 1; i >= 0; i--) 62 | if(up[u][i] != up[v][i]) 63 | u = up[u][i], v = up[v][i]; 64 | 65 | return up[u][0]; 66 | } 67 | 68 | }; 69 | 70 | 71 | /** 72 | * Lowest common ancestor (LCA). euler tour + sparse table. 73 | * 74 | * We will find the LCA of each query by building the euler tour and finding the vertex with the minimun height 75 | * in the segment [first[u], first[v]]. First[] stores for each vertex v its first occurrence in euler tour. 76 | * 77 | **/ 78 | 79 | struct Lca{ 80 | int N, LOG2N; 81 | vector first, height, lg2, path; 82 | vector> st; 83 | 84 | Lca(int n, int root, vector g[]){ 85 | N = n; 86 | first.assign(N + 5, 0); 87 | height.assign(N + 5, 0); 88 | 89 | dfs(root, root, 0, g); 90 | LOG2N = log2(path.size() + 5); 91 | lg2.assign(path.size() + 5, 0); 92 | st.assign(path.size() + 5, vector(LOG2N + 5, 0)); 93 | build(); 94 | } 95 | 96 | void dfs(int u, int p, int h, vector g[]){ 97 | height[u] = h; 98 | first[u] = path.size(); 99 | path.push_back(u); 100 | 101 | for(int v: g[u]) 102 | if(v != p) 103 | dfs(v, u, h + 1, g), 104 | path.push_back(u); 105 | } 106 | 107 | void build(){ 108 | 109 | lg2[1] = 0; 110 | 111 | for(int i = 2; i <= path.size(); i++) lg2[i] = lg2[i / 2] + 1; 112 | for(int i = 0; i < path.size(); i++) st[i][0] = path[i]; 113 | for(int j = 1; j <= LOG2N; j++){ 114 | for(int i = 0; i + (1 << j) <= path.size(); i++){ 115 | int a = st[i][j - 1], b = st[i + (1 << (j - 1))][j - 1]; 116 | st[i][j] = height[a] < height[b] ? a : b; 117 | } 118 | } 119 | } 120 | 121 | int lca(int u, int v){ 122 | int L = first[u], R = first[v]; 123 | if(L > R) swap(L, R); 124 | int lg = lg2[R - L + 1]; 125 | int l = st[L][lg], r = st[R - (1 << lg) + 1][lg]; 126 | if(height[l] < height[r]) return l; 127 | else return r; 128 | } 129 | 130 | }; -------------------------------------------------------------------------------- /graphs/prims.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * PRIM'S ALGORITHM 4 | * find Minimum Spanning Tree (MST). 5 | * Time complexity O(E log(V)) 6 | * 7 | * */ 8 | 9 | const ll oo = numeric_limits::max(); 10 | 11 | const int MAXN = 100000; 12 | int N, M; 13 | vector> g[MAXN]; 14 | 15 | vector prim(){ 16 | bool in_mst[N] = {false}; 17 | vector key(N, oo); 18 | vector parent(N, -1); 19 | priority_queue, vector>, greater>> pq; 20 | pq.push({0, 0}); 21 | key[0] = 0; 22 | while(!pq.empty()){ 23 | int u = pq.top().second; 24 | pq.pop(); 25 | in_mst[u] = true; 26 | for(auto [w, v]: g[u]) 27 | if(!in_mst[v] && key[v] > w){ 28 | key[v] = w; 29 | parent[v] = u; 30 | pq.push({w, v}); 31 | } 32 | } 33 | return parent; 34 | } 35 | -------------------------------------------------------------------------------- /math/math.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * FAST EXPONENTIATION. 4 | * 5 | * x ^ n = { 6 | * x if n = 1; 7 | * (x ^ (n / 2)) ^ 2 if n % 2 = 0; 8 | * x * x ^ (n - 1) if n % 2 != 0; 9 | * } 10 | * 11 | **/ 12 | ull binpow(ull a, ull b, ull m) { 13 | a %= m; 14 | ull res = 1; 15 | while(b > 0){ 16 | if(b & 1) res = res * a % m; 17 | a = a * a % m; 18 | b >>= 1; 19 | } 20 | return res; 21 | } 22 | 23 | 24 | /** 25 | * 26 | * CHOOSE (Binomial coefficient). 27 | * 28 | **/ 29 | ull choose(ull n, ull k){ 30 | if(k == 0 || k == n) return 1; 31 | return choose(n - 1, k - 1) + choose(n - 1, k); 32 | } 33 | 34 | ull choose(ull n, ull k){ 35 | ull C[k+1] = {0}; 36 | C[0] = 1; 37 | for(ull i = 1; i <= n; i++) 38 | for(ull j = min(i, k); j > 0; j--) 39 | C[j] = C[j] + C[j - 1]; 40 | return C[k]; 41 | } 42 | 43 | 44 | /** 45 | * 46 | * GET ALL PRIME FACTORS 47 | * Time complexity: 48 | * O(sqrt(n)), upper bound, when n is prime then function 49 | * reaches worst case. 50 | * 51 | **/ 52 | void prime_factors(int n){ 53 | while(n % 2 == 0) cout << 2 << " ", n = n / 2; 54 | 55 | for(int i = 3; i * i <= n; i += 2) 56 | while(n % i == 0) cout << i << " ", n = n / i; 57 | 58 | if(n > 2) cout << n << " "; 59 | } 60 | -------------------------------------------------------------------------------- /math/matrix-exponentiation.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * MATRIX EXPONENTIATION. 4 | * This file provides a fast way of calculating m^r, where m is a NxN square matrix 5 | * Time complexity: O(N^3 * log(r)) 6 | * 7 | * USAGE: 8 | * We can calculate linear dps (such as fibonacci) by using this technique, 9 | * this technique is useful when n is too big. 10 | * This file includes the example of calculating fibonacci of n by calculating: 11 | * 12 | * res = init * m ^ (n - 1) 13 | * 14 | * where init = {{0, 1}} and m = m = {{0, 1}, {1, 1}}, finally fibonacci(n) = res[0][1] 15 | * 16 | **/ 17 | 18 | const ull MOD = 1e5 + 7; 19 | 20 | template struct Matrix{ 21 | vector> m; 22 | int N, M; 23 | Matrix(bool identity, int rows, int columns){ 24 | N = rows; M = columns; 25 | m.resize(N, vector(M, 0)); 26 | if(identity && N == M) 27 | for(int i = 0; i < N; i++) m[i][i] = 1; 28 | } 29 | Matrix operator * (const Matrix &o){ 30 | Matrix r(false, N, o.M); 31 | for(int i = 0; i < N; i++) 32 | for(int j = 0; j < o.M; j++) 33 | for(int k = 0; k < M; k++) r.m[i][j] = (r.m[i][j] + (m[i][k] % MOD * o.m[k][j] % MOD) % MOD) % MOD; 34 | return r; 35 | } 36 | }; 37 | 38 | template Matrix fpow(Matrix M, ull r){ 39 | Matrix ans(true, M.N, M.N); 40 | for(; r; M = M * M, r >>= 1) 41 | if(r & 1) ans = ans * M; 42 | return ans; 43 | } 44 | 45 | ull fibonacci(ull n){ 46 | if(n == 0) return 0; 47 | if(n == 1) return 1; 48 | Matrix I(false, 1, 2), M(false, 2, 2); 49 | I.m = {{0, 1}}; 50 | M.m = {{0, 1}, {1, 1}}; 51 | M = fpow(M, n - 1); 52 | return (I * M).m[0][1]; 53 | } 54 | -------------------------------------------------------------------------------- /math/modular.cpp: -------------------------------------------------------------------------------- 1 | struct mint { 2 | static ll& mod(){ 3 | static ll MOD = 0; 4 | return MOD; 5 | } 6 | static void set_mod(const ll p){ mod() = p; } 7 | ll value; 8 | mint(ll v = 0) { value = v % mod(); if (value < 0) value += mod();} 9 | mint(ll a, ll b) : value(0){ *this += a; *this /= b;} 10 | mint& operator+=(mint const& b) {value += b.value; if (value >= mod()) value -= mod(); return *this;} 11 | mint& operator-=(mint const& b) {value -= b.value; if (value < 0) value += mod();return *this;} 12 | mint& operator*=(mint const& b) {value = (ll)value * b.value % mod();return *this;} 13 | friend mint powmod(mint a, ll e) { 14 | mint res = 1; while (e) { if (e&1) res *= a; a *= a; e >>= 1; } 15 | return res; 16 | } 17 | friend mint inv(mint a) { return powmod(a, mod() - 2); } 18 | mint& operator/=(mint const& b) { return *this *= inv(b); } 19 | friend mint operator+(mint a, mint const b) { return a += b; } 20 | friend mint operator-(mint a, mint const b) { return a -= b; } 21 | friend mint operator-(mint const a) { return 0 - a; } 22 | friend mint operator*(mint a, mint const b) { return a *= b; } 23 | friend mint operator/(mint a, mint const b) { return a /= b; } 24 | friend std::ostream& operator<<(std::ostream& os, mint const& a) {return os << a.value;} 25 | friend bool operator==(mint const& a, mint const& b) {return a.value == b.value;} 26 | friend bool operator!=(mint const& a, mint const& b) {return a.value != b.value;} 27 | }; 28 | 29 | 30 | const ll mod = 1e9 + 7; 31 | template struct Modular { 32 | ll value; 33 | static const ll MOD_value = MOD; 34 | Modular(ll v = 0) { value = v % MOD; if (value < 0) value += MOD;} 35 | Modular(ll a, ll b) : value(0){ *this += a; *this /= b;} 36 | Modular& operator+=(Modular const& b) {value += b.value; if (value >= MOD) value -= MOD; return *this;} 37 | Modular& operator-=(Modular const& b) {value -= b.value; if (value < 0) value += MOD;return *this;} 38 | Modular& operator*=(Modular const& b) {value = (ll)value * b.value % MOD;return *this;} 39 | friend Modular powmod(Modular a, ll e) { 40 | Modular res = 1; while (e) { if (e&1) res *= a; a *= a; e >>= 1; } 41 | return res; 42 | } 43 | friend Modular inv(Modular a) { return powmod(a, MOD - 2); } 44 | Modular& operator/=(Modular const& b) { return *this *= inv(b); } 45 | friend Modular operator+(Modular a, Modular const b) { return a += b; } 46 | friend Modular operator-(Modular a, Modular const b) { return a -= b; } 47 | friend Modular operator-(Modular const a) { return 0 - a; } 48 | friend Modular operator*(Modular a, Modular const b) { return a *= b; } 49 | friend Modular operator/(Modular a, Modular const b) { return a /= b; } 50 | friend std::ostream& operator<<(std::ostream& os, Modular const& a) {return os << a.value;} 51 | friend bool operator==(Modular const& a, Modular const& b) {return a.value == b.value;} 52 | friend bool operator!=(Modular const& a, Modular const& b) {return a.value != b.value;} 53 | }; typedef Modular<> mi; 54 | -------------------------------------------------------------------------------- /math/sieve.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * SIEVE OF ERATOSTHENES 4 | * Time complexity: O(n) 5 | * 6 | **/ 7 | const int MAXN = 1000000; 8 | vector pr; 9 | int lp[MAXN]; 10 | 11 | void sieve(int N){ 12 | for(int i = 2; i <= N; i++){ 13 | if (lp[i] == 0) { 14 | lp[i] = i; 15 | pr.push_back(i); 16 | } 17 | for(int j = 0; j < pr.size() && pr[j] <= lp[i] && i * pr[j] <= N; j++) 18 | lp[i * pr[j]] = pr[j]; 19 | } 20 | } 21 | 22 | 23 | /** 24 | * 25 | * SIEVE OF ERATOSTHENES CLASSIC SOLUTION 26 | * Time complexity: O(n log(log n)) 27 | * 28 | **/ 29 | void sieve_of_eratosthenes(int n){ 30 | bool prime[n + 1]; 31 | memset(prime, true, sizeof(prime)); 32 | for(int p = 2; p * p <= n; p++){ 33 | if(prime[p] == true){ 34 | for(int i = p * p; i <= n; i += p) 35 | prime[i] = false; 36 | } 37 | } 38 | for(int p = 2; p <= n; p++) 39 | if(prime[p]) cout << p << " "; 40 | } -------------------------------------------------------------------------------- /math/simplex.cpp: -------------------------------------------------------------------------------- 1 | const double EPS = 1e-7; 2 | namespace Simplex { 3 | vector X,Y; 4 | vector > A; 5 | vector b,c; 6 | double z; 7 | int n,m; 8 | void pivot(int x,int y){ 9 | swap(X[y],Y[x]); 10 | b[x]/=A[x][y]; 11 | for (int i = 0; i < m; i++) { 12 | if(i!=y)A[x][i]/=A[x][y]; 13 | } 14 | A[x][y]=1/A[x][y]; 15 | for (int i = 0; i < n; i++) { 16 | if(i!=x&&abs(A[i][y])>EPS){ 17 | b[i]-=A[i][y]*b[x]; 18 | for (int j = 0; j < m; j++) if(j!=y)A[i][j]-=A[i][y]*A[x][j]; 19 | A[i][y]=-A[i][y]*A[x][y]; 20 | } 21 | } 22 | z+=c[y]*b[x]; 23 | for (int i = 0; i < m; i++) { 24 | if(i!=y)c[i]-=c[y]*A[x][i]; 25 | } 26 | c[y]=-c[y]*A[x][y]; 27 | } 28 | pair > simplex( // maximize c^T x s.t. Ax<=b, x>=0 29 | vector > _A, vector _b, vector _c){ 30 | // returns pair (maximum value, solution vector) 31 | A=_A;b=_b;c=_c; 32 | n=b.size();m=c.size();z=0.; 33 | X=vector(m);Y=vector(n); 34 | for (int i = 0; i < m; i++) X[i] = i; 35 | for (int i = 0; i < n; i++) Y[i]=i+m; 36 | while(1){ 37 | int x=-1,y=-1; 38 | double mn=-EPS; 39 | for (int i = 0; i < n; i++) if(b[i]=0); // no solution to Ax<=b 43 | pivot(x,y); 44 | } 45 | while(1){ 46 | double mx=EPS; 47 | int x=-1,y=-1; 48 | for (int i = 0; i < m; i++) if(c[i]>mx)mx=c[i],y=i; 49 | if(y<0)break; 50 | double mn=1e200; 51 | for (int i = 0; i < n; i++) if(A[i][y]>EPS&&b[i]/A[i][y]=0); // c^T x is unbounded 53 | pivot(x,y); 54 | } 55 | vector r(m); 56 | for (int i = 0; i < n; i++) if(Y[i] void build(vector> &M, vector> &S){ 2 | int n = M.size(), m = M[0].size(); 3 | S.assign(n, vector(m, 0)); 4 | for(int i = 0; i < m; i++) S[0][i] = M[0][i]; 5 | for(int i = 1; i < n; i++) 6 | for(int j = 0; j < m; j++) S[i][j] = M[i][j] + S[i - 1][j]; 7 | for(int i = 0; i < n; i++) 8 | for(int j = 1; j < m; j++) S[i][j] += S[i][j - 1]; 9 | } 10 | 11 | // get sum in the sub-matrix with oppsite vertices at (a, b), (c, d) 12 | template int query(int a, int b, int c, int d, vector> &S){ 13 | int res = S[c][d]; 14 | if(a > 0) res = res - S[a - 1][d]; 15 | if(b > 0) res = res - S[c][b - 1]; 16 | if(a > 0 && b > 0) res = res + S[a - 1][b - 1]; 17 | return res; 18 | } 19 | -------------------------------------------------------------------------------- /strings/ahocorasick-automata.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * AHO CORASICK AUTOMATA. 4 | * 5 | * time complexity O(|txt| * sqrt(sum(|pattern_i|))). 6 | * 7 | **/ 8 | 9 | const int TRIE_LEN = 400005; // Dictionary size * length of words 10 | 11 | vector dictionary; 12 | string txt; 13 | int trie[TRIE_LEN][26], nodes = 1, failure[TRIE_LEN], fail_out[TRIE_LEN]; 14 | bool end_word[TRIE_LEN]; 15 | 16 | void build_bfs(){ 17 | queue q; 18 | q.push(0); 19 | while(!q.empty()){ 20 | int u = q.front(); q.pop(); 21 | for(int i = 0; i < 26; i++){ 22 | int v = trie[u][i]; 23 | // as long as there is no link to i and all links are defined for nodes above we must create the link of the automata 24 | // it means if the trie has not a child using i then we must create the link. 25 | if(!v) trie[u][i] = trie[failure[u]][i]; 26 | else q.push(v); 27 | if(!u || !v) continue; 28 | failure[v] = trie[failure[u]][i]; 29 | fail_out[v] = end_word[failure[v]] ? failure[v] : fail_out[failure[v]]; 30 | } 31 | } 32 | } 33 | 34 | void build(){ 35 | for(int i = 0; i < dictionary.size(); i++){ 36 | string &s = dictionary[i]; 37 | int cur = 0; 38 | for(char c: s){ 39 | int cc = c - 'a'; 40 | if(!trie[cur][cc]) trie[cur][cc] = nodes++; 41 | cur = trie[cur][cc]; 42 | } 43 | end_word[cur] = true; 44 | } 45 | build_bfs(); 46 | } 47 | 48 | void check(){ 49 | int cur = 0; 50 | for(char c : txt){ 51 | int cc = c - 'a'; 52 | cur = trie[cur][cc]; 53 | int f = cur; 54 | while(f){ 55 | if(end_word[f]); // do something 56 | f = fail_out[f]; 57 | } 58 | //do something 59 | } 60 | } -------------------------------------------------------------------------------- /strings/ahocorasick-no-simplified-automata.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * AHO CORASICK NO SIMPLIFIED AUTOMATA. 4 | * 5 | * time complexity O(|txt| * sqrt(sum(|pattern_i|))). 6 | * 7 | **/ 8 | 9 | const int TRIE_LEN = 2000005; // Dictionary size * length of words 10 | 11 | 12 | vector dictionary; 13 | vector queries; // in case of single query replace this with a single string 14 | 15 | int trie[TRIE_LEN][26], nodes = 1, failure[TRIE_LEN], fail_out[TRIE_LEN]; 16 | bool end_word[TRIE_LEN]; 17 | 18 | void build_bfs(){ 19 | queue q; 20 | q.push(0); 21 | while(!q.empty()){ 22 | int u = q.front(); q.pop(); 23 | for(int i = 0; i < 26; i++){ 24 | int v = trie[u][i]; 25 | if(v){ 26 | q.push(v); 27 | if(u){ 28 | failure[v] = failure[u]; 29 | while(failure[v] && !trie[failure[v]][i]) 30 | failure[v] = failure[failure[v]]; 31 | failure[v] = trie[failure[v]][i]; 32 | fail_out[v] = end_word[failure[v]] ? failure[v] : fail_out[failure[v]]; 33 | } 34 | } 35 | } 36 | } 37 | } 38 | 39 | // call build before using the automata 40 | void build(){ 41 | for(auto & s : dictionary){ 42 | int cur = 0; 43 | for(char c: s){ 44 | int cc = c - 'a'; 45 | if(!trie[cur][cc]) trie[cur][cc] = nodes++; 46 | cur = trie[cur][cc]; 47 | } 48 | end_word[cur] = true; 49 | } 50 | build_bfs(); 51 | } 52 | 53 | // in case of single query we can iterate over the single query, instead of passing the index of the query. 54 | 55 | void check(int i){ 56 | int cur = 0; 57 | for(char c : queries[i]){ 58 | int cc = c - 'a'; 59 | 60 | while(cur && !trie[cur][cc]) cur = failure[cur]; // this while is the difference with the simplified one 61 | cur = trie[cur][cc]; 62 | 63 | int f = cur; 64 | while(f){ 65 | if(end_word[f]); // do something 66 | f = fail_out[f]; 67 | } 68 | //do something 69 | } 70 | 71 | return; 72 | } -------------------------------------------------------------------------------- /strings/dynamic-ahocorasick.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * DYNAMIC AHO CORASICK 3 | * As long as the trie of the aho corasick cannot be modified once it built, this code 4 | * uses a technique to dynamize data structures that are not dynamic. 5 | * The idea of this technique is to store several aho corasicks of size equals to a power of two 6 | * and then the answer is the sum of the answer of all aho corasicks. 7 | * 8 | * */ 9 | 10 | const int TRIE_LEN = 300000; // Dictionary size * length of words 11 | const int LOG_TRIE_LEN = 20; // log2(TRIE_LEN) 12 | 13 | struct Automata{ 14 | map> trie; 15 | int fail_out[TRIE_LEN]; 16 | bool end_word[TRIE_LEN]; 17 | vector dict; 18 | int nodes = 1; 19 | bool built = false; 20 | void clear(){ 21 | nodes = 1; 22 | built = false; 23 | memset(fail_out, 0, sizeof(fail_out)); 24 | memset(end_word, 0, sizeof(end_word)); 25 | trie.clear(); 26 | } 27 | 28 | void build_bfs(){ 29 | queue q; 30 | q.push(0); 31 | int failure[TRIE_LEN] = {0}; 32 | while(!q.empty()){ 33 | int u = q.front(); q.pop(); 34 | for(int i = 0; i < 26; i++){ 35 | int v = trie[u][i]; 36 | if(!v) trie[u][i] = trie[failure[u]][i]; 37 | else q.push(v); 38 | if(!u || !v) continue; 39 | failure[v] = trie[failure[u]][i]; 40 | fail_out[v] = end_word[failure[v]] ? failure[v] : fail_out[failure[v]]; 41 | } 42 | } 43 | } 44 | 45 | void build(){ 46 | clear(); 47 | built = true; 48 | for(string &s: dict){ 49 | int cur = 0; 50 | for(char c: s){ 51 | int cc = c - 'a'; 52 | if(!trie[cur][cc]) trie[cur][cc] = nodes++; 53 | cur = trie[cur][cc]; 54 | } 55 | end_word[cur] = true; 56 | } 57 | build_bfs(); 58 | } 59 | 60 | int check(string &s){ 61 | int cur = 0, ans = 0; 62 | for(char c : s){ 63 | int cc = c - 'a'; 64 | cur = trie[cur][cc]; 65 | int f = cur; 66 | while(f){ 67 | if(end_word[f]) ans++; 68 | f = fail_out[f]; 69 | } 70 | } 71 | return ans; 72 | } 73 | 74 | }; 75 | 76 | struct DynamicAutomata{ 77 | Automata ahos[LOG_TRIE_LEN]; 78 | void add(string &s){ 79 | vector dict; 80 | dict.push_back(s); 81 | for(int i = 0; i < LOG_TRIE_LEN; i++){ 82 | if(!ahos[i].dict.size()){ 83 | std::move(dict.begin(), dict.end(), std::back_inserter(ahos[i].dict)); 84 | break; 85 | } 86 | else{ 87 | std::move(ahos[i].dict.begin(), ahos[i].dict.end(), std::back_inserter(dict)); 88 | ahos[i].dict.clear(); 89 | ahos[i].built = false; 90 | } 91 | } 92 | } 93 | 94 | int count(string &s){ 95 | int ans = 0; 96 | for(int i = 0; i < LOG_TRIE_LEN; i++){ 97 | if(ahos[i].dict.size()){ 98 | if(!ahos[i].built) ahos[i].build(); 99 | ans += ahos[i].check(s); 100 | } 101 | } 102 | return ans; 103 | } 104 | }; 105 | 106 | DynamicAutomata insertions, deletions; 107 | 108 | int count(string &s){ 109 | return insertions.count(S) - deletions.count(S); 110 | } 111 | -------------------------------------------------------------------------------- /strings/hashing.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * ROLLING HASH 4 | * s: string to hash 5 | * b: base constant, normally set as the size of the alphabet 6 | * p: prime number to take the modulo. 7 | * 8 | * hash(s) = sum(s[i] * b ^ i) % p, for all i in [i, n = s.size()] 9 | * or 10 | * hash(s) = sum(s[i] * b ^ (n - 1 - i)) % p, for all i in [i, n = s.size()] 11 | * 12 | * NOTE: some times it is useful to use double hash one with, b1 = alphabet size, 13 | * and another with, b2 = alphabet size + 5. 14 | * 15 | * PRIMES: 1000000007, 10657331232548839, 790738119649411319 16 | */ 17 | 18 | struct Hash{ 19 | vector h, b; 20 | ll B, p; 21 | string s; 22 | 23 | Hash(const string &_s, int _B=31, int _p=1000000007){ 24 | s = _s, B = _B, p = _p; 25 | h.assign(s.size() + 5, 0); 26 | b.assign(s.size() + 5, 0); 27 | rolling_hash(); 28 | } 29 | 30 | void rolling_hash(){ 31 | h[0] = 0; 32 | h[1] = (s[0] - 'a' + 1); 33 | b[0] = 1; 34 | for(int i = 1; i < s.size(); i++){ 35 | h[i + 1] = ((h[i] * B) % p + (s[i] - 'a' + 1LL)) % p; 36 | b[i] = (B * b[i - 1]) % p; 37 | } 38 | } 39 | 40 | 41 | ll get_hash(int l, int r){ 42 | return (h[r + 1] - ((h[l] * b[r - l + 1]) % p) + p) % p; 43 | } 44 | 45 | }; 46 | 47 | /** 48 | * GENERATE RANDOM NUMBER IN [a, b] 49 | */ 50 | 51 | mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count()); 52 | ull random(ull a, ull b){ 53 | return uniform_int_distribution(a, b)(rng); 54 | } 55 | -------------------------------------------------------------------------------- /strings/kmp-automata.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * KMP AUTOMATA. 3 | * Find all occurrences of p in txt (pattern searching), this version is useful for dynamic programing problems. 4 | * Preprocessing time complexity: O(n * vocabulary_size). 5 | * Time complexity: O(n), less than normal kmp. 6 | **/ 7 | 8 | string txt, p; 9 | int lps[1000000], automata[1000000][26]; 10 | 11 | void LPS(){ 12 | memset(lps, 0, sizeof(lps)); 13 | int n = p.size(), j = 1, i = 0; 14 | while(j < n){ 15 | if(p[j] == p[i]) lps[j++] = ++i; 16 | else if(i == 0) lps[j++] = 0; 17 | else i = lps[i - 1]; 18 | } 19 | } 20 | 21 | int find_k(int j, int c){ 22 | if(j == p.size()) j = lps[j - 1]; 23 | else if(c == (p[j] - 'a')) return j + 1; 24 | while(j){ 25 | if(automata[j][c] != -1) return automata[j][c]; 26 | if(c == (p[j] - 'a')) return j + 1; 27 | j = lps[j - 1]; 28 | } 29 | return c == (p[j] - 'a')? 1 : 0; 30 | } 31 | 32 | void build_automata(){ 33 | LPS(); 34 | memset(automata, -1, sizeof(automata)); 35 | for(int i = 0; i <= p.size(); i++) 36 | for(int j = 0; j < 26; j++) 37 | automata[i][j] = find_k(i, j); 38 | } 39 | 40 | vector find_pattern(){ 41 | build_automata(); 42 | vector ans; 43 | int i = 0, j = 0; 44 | while(i < txt.size()){ 45 | j = automata[j][txt[i] - 'a']; 46 | if(j == p.size()) ans.push_back(i - j + 1); 47 | i++; 48 | } 49 | return ans; 50 | } -------------------------------------------------------------------------------- /strings/kmp.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * KMP. 3 | * You are given a string s of length n. The prefix function for this string is defined as an array lps of length n, where 4 | * lps[i] is the length of the longest proper prefix of the substring s[0...i] which is also a suffix of this substring. 5 | * A proper prefix of a string is a prefix that is not equal to the string itself. By definition, lps[0] = 0. 6 | * Time complexity: O(n) 7 | **/ 8 | 9 | string txt, p; 10 | int lps[1000000]; 11 | 12 | void LPS(){ 13 | memset(lps, 0, sizeof(lps)); 14 | int n = p.size(), j = 1, i = 0; 15 | while(j < n){ 16 | if(p[j] == p[i]) lps[j++] = ++i; 17 | else if(i == 0) lps[j++] = 0; 18 | else i = lps[i - 1]; 19 | } 20 | } 21 | 22 | vector find_pattern(){ 23 | LPS(); 24 | vector ans; 25 | int i = 0, j = 0; 26 | while(i < txt.size()){ 27 | if(txt[i] == p[j]){j++; i++;} 28 | if(j == p.size()){ 29 | ans.push_back(i - j + 1); 30 | j = lps[j - 1]; 31 | } 32 | else if(i < txt.size() && p[j] != txt[i]){ 33 | if(j != 0) j = lps[j - 1]; 34 | else i++; 35 | } 36 | } 37 | return ans; 38 | } 39 | -------------------------------------------------------------------------------- /strings/manacher.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * MANACHER. 4 | * 5 | * Given string s with length n. Find all the pairs (i, j) such that substring s[i … j] 6 | * is a palindrome. For each position i = 0 … n − 1 we'll find the values d1[i] and d2[i], 7 | * denoting the number of palindromes accordingly with odd and even lengths respectively with 8 | * centers in the position i. For even length palindromes they have 2 center for example: 9 | * "baab", has two centers (positions 1 and 2). 10 | * d2[] will use right most center as the center of the palindrome, in the example above d2[] 11 | * will use position 2. 12 | * 13 | * time complexity: O(n). 14 | * 15 | **/ 16 | 17 | void manacher(string &s, vector &d1, vector &d2){ 18 | int n = s.size(); 19 | d1.assign(n, 0); 20 | for(int i = 0, l = 0, r = -1; i < n; i++) { 21 | int k = (i > r) ? 1 : min(d1[l + r - i], r - i + 1); 22 | while(0 <= i - k && i + k < n && s[i - k] == s[i + k]) k++; 23 | d1[i] = k--; 24 | if(i + k > r){ 25 | l = i - k; 26 | r = i + k; 27 | } 28 | } 29 | d2.assign(n, 0); 30 | for(int i = 0, l = 0, r = -1; i < n; i++){ 31 | int k = (i > r) ? 0 : min(d2[l + r - i + 1], r - i + 1); 32 | while(0 <= i - k - 1 && i + k < n && s[i - k - 1] == s[i + k]) k++; 33 | d2[i] = k--; 34 | if(i + k > r){ 35 | l = i - k - 1; 36 | r = i + k ; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /strings/suffix-array.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * SUFFIX ARRAY: 3 | * A suffix array will contain integers that represent the starting 4 | * indexes of the all the suffixes of a given string, after the 5 | * aforementioned suffixes are sorted. 6 | * 7 | * For example if we have the string "abaab", the suffix array for this string will be: 8 | * 2. aab 9 | * 3. ab 10 | * 0. abaab 11 | * 4. b 12 | * 1. baab 13 | * 14 | * Time complexity: O(nlg(n)) 15 | * 16 | **/ 17 | 18 | struct SufixArray{ 19 | 20 | struct SparseTable{ 21 | int N, LOG2N; 22 | vector lg2; 23 | vector> st; 24 | 25 | void build(vector &a){ 26 | N = a.size(); 27 | LOG2N = log2(N) + 2; 28 | lg2.assign(N + 1, 0); 29 | st.assign(N, vector(LOG2N, 0)); 30 | lg2[1] = 0; 31 | for(int i = 2; i <= N; i++) lg2[i] = lg2[i / 2] + 1; 32 | for(int i = 0; i < N; i++) st[i][0] = a[i]; 33 | for(int j = 1; j <= LOG2N; j++) 34 | for(int i = 0; i + (1 << j) <= N; i++) 35 | st[i][j] = min(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]); 36 | } 37 | int minimum(int L, int R){ 38 | int lg = lg2[R - L + 1]; 39 | return min(st[L][lg], st[R - (1 << lg) + 1][lg]); 40 | } 41 | }; 42 | 43 | int n; 44 | vector p, lcp; // sorted suffixes 45 | vector mp; 46 | SparseTable st; 47 | 48 | SufixArray(string s) : n(s.size() + 1){ 49 | s += "$"; 50 | p.assign(n, 0); 51 | mp.assign(n, 0); 52 | lcp.assign(n - 1, 0); 53 | build(s); 54 | lcp_build(s); 55 | for(int i = 0; i < n; i++) mp[p[i]] = i; 56 | st.build(lcp); 57 | } 58 | 59 | void build(const string &s){ 60 | const int alphabet = 256; 61 | vector c(n), cnt(max(alphabet, n), 0); 62 | for(int i = 0; i < n; i++) cnt[s[i]]++; 63 | for(int i = 1; i < alphabet; i++) cnt[i] += cnt[i-1]; 64 | for(int i = 0; i < n; i++) p[--cnt[s[i]]] = i; 65 | c[p[0]] = 0; 66 | int classes = 1; 67 | for(int i = 1; i < n; i++){ 68 | if(s[p[i]] != s[p[i-1]]) 69 | classes++; 70 | c[p[i]] = classes - 1; 71 | } 72 | vector pn(n), cn(n); 73 | for(int h = 0; (1 << h) < n; h++){ 74 | for(int i = 0; i < n; i++){ 75 | pn[i] = p[i] - (1 << h); 76 | if(pn[i] < 0) 77 | pn[i] += n; 78 | } 79 | fill(cnt.begin(), cnt.begin() + classes, 0); 80 | for(int i = 0; i < n; i++) cnt[c[pn[i]]]++; 81 | for(int i = 1; i < classes; i++) cnt[i] += cnt[i-1]; 82 | for(int i = n-1; i >= 0; i--) p[--cnt[c[pn[i]]]] = pn[i]; 83 | cn[p[0]] = 0; 84 | classes = 1; 85 | for(int i = 1; i < n; i++){ 86 | pair cur = {c[p[i]], c[(p[i] + (1 << h)) % n]}; 87 | pair prev = {c[p[i-1]], c[(p[i-1] + (1 << h)) % n]}; 88 | if(cur != prev) 89 | classes++; 90 | cn[p[i]] = classes - 1; 91 | } 92 | c.swap(cn); 93 | } 94 | } 95 | 96 | void lcp_build(const string &s){ 97 | int n = s.size(); 98 | vector rank(n, 0); 99 | for(int i = 0; i < n; i++) rank[p[i]] = i; 100 | int k = 0; 101 | for(int i = 0; i < n; i++){ 102 | if(rank[i] == n - 1){ 103 | k = 0; 104 | continue; 105 | } 106 | int j = p[rank[i] + 1]; 107 | while(i + k < n && j + k < n && s[i + k] == s[j + k]) k++; 108 | lcp[rank[i]] = k; 109 | if(k) k--; 110 | } 111 | } 112 | 113 | int get_lcp(int i, int j){ 114 | int l = mp[i], r = mp[j]; 115 | if(r < l) swap(l, r); 116 | assert(l != r); 117 | return st.minimum(l, r - 1); 118 | } 119 | }; -------------------------------------------------------------------------------- /strings/trie.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * TRIE. 4 | * (Tree of prefixes). 5 | * Check if t has a prefix in the set of prefixes added in add(s) function 6 | * 7 | * time complexity add(s): O(s.size()). 8 | * time complexity check(t): O(t.size()). 9 | * 10 | * 11 | **/ 12 | struct Trie{ 13 | 14 | vector end_word; 15 | int nodes = 1; 16 | vector> trie; 17 | 18 | Trie(int TRIE_LEN = 400005,int ALPHA_SIZE = 26){ // Dictionary size * length of words 19 | end_word.assign(TRIE_LEN, 0); 20 | trie.assign(TRIE_LEN, vector(ALPHA_SIZE, 0)); 21 | } 22 | 23 | void add(const string &s){ 24 | int cur = 0; 25 | for(char c: s){ 26 | int cc = c - 'a'; 27 | if(!trie[cur][cc]) trie[cur][cc] = nodes++; 28 | cur = trie[cur][cc]; 29 | } 30 | end_word[cur] = true; 31 | } 32 | 33 | bool check(const string &t){ 34 | int cur = 0; 35 | for(char c: t){ 36 | int cc = c - 'a'; 37 | cur = trie[cur][cc]; 38 | if(end_word[cur]) return true; 39 | if(!cur) return false; 40 | } 41 | return false; 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /strings/z-function.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Z-FUNCTION 4 | * 5 | * z[i] is the length of the longest common prefix between s and the suffix of s starting 6 | * at position i. 7 | * 8 | * Time complexity: O(n) 9 | **/ 10 | 11 | vector z_function(string &s){ 12 | int n = s.length(); 13 | vector z(n, 0); 14 | for(int i = 1, l = 0, r = 0; i < n; ++i){ 15 | if(i <= r) z[i] = min (r - i + 1, z[i - l]); 16 | while(i + z[i] < n && s[z[i]] == s[i + z[i]]) ++z[i]; 17 | if(i + z[i] - 1 > r) l = i, r = i + z[i] - 1; 18 | } 19 | return z; 20 | } -------------------------------------------------------------------------------- /useful-algorithms/kadanes-algorithm.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * KADANE'S ALGORITHM 3 | * 4 | * The simple idea of Kadane's algorithm is to look for all positive contiguous segments of the array 5 | * (sum is used for this). And keep track of maximum sum contiguous segment among all positive segments 6 | * (maxi used for this). Each time we get a positive-sum compare it with maxi and update maxi if it is 7 | * greater than maxi. 8 | * 9 | * Time complexity: O(n) 10 | * 11 | **/ 12 | 13 | int kadane(vector &a){ 14 | int n = a.size(); 15 | int sum = 0, maxi = 0; 16 | for(int i = 0; i < n; i++){ 17 | sum += a[i]; 18 | maxi = max(maxi, sum); 19 | if(sum < 0) sum = 0; 20 | } 21 | return maxi; 22 | } -------------------------------------------------------------------------------- /useful-algorithms/longest-increasing-subsequence.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * LIS, longest incriasing subsequence. 4 | * NOTE: 5 | * if the sequence is not strictly grater change line 19 for using upper_bound instead of 6 | * lower_bound and chance line 30 for using s[i] <= s[pos] instead of s[i] < s[pos]. 7 | * 8 | * This problem could also be solved using a segment tree/bit dp. 9 | * For each element in s, find dp.set(s[i], max(dp(s[i], s[i]), dp(0, s[i] - 1) + 1)) 10 | * 11 | * */ 12 | 13 | vector lis(vector &s){ 14 | int len = 0, n = s.size(); 15 | vector l; 16 | int lis_len[MAXN], pos; 17 | for(int i = 0; i < n; i++){ 18 | int j = lower_bound(l.begin(), l.end(), s[i]) - l.begin(); 19 | if(j == l.size()) l.push_back(s[i]); 20 | else l[j] = s[i]; 21 | lis_len[i] = j + 1; 22 | if(lis_len[i] > len){ 23 | len = lis_len[i]; 24 | pos = i; 25 | } 26 | } 27 | vector lis(len); 28 | lis[len - 1] = s[pos]; 29 | for(int i = pos - 1, j = len - 2; i >= 0; i--){ 30 | if(s[i] < s[pos] && lis_len[i] == lis_len[pos] - 1){ 31 | pos = i; 32 | lis[j] = s[i]; 33 | j--; 34 | } 35 | } 36 | return lis; 37 | } 38 | -------------------------------------------------------------------------------- /useful-algorithms/tortoise-and-hare.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * TORTOISE AND HARE. 4 | * Detect cycle in a linked list. Algorithm returns node that starts the cycle and length 5 | * of the cycle. 6 | * 7 | * */ 8 | 9 | struct Node{ 10 | int data; 11 | Node *next = nullptr; 12 | }; 13 | 14 | pair tortoise_and_hare(Node *head){ 15 | Node *tortoise = head, *hare = head; 16 | bool loop = false; 17 | while(tortoise && hare && hare->next){ 18 | hare = hare->next->next; 19 | tortoise = tortoise->next; 20 | if(tortoise == hare){ 21 | loop = true; 22 | break; 23 | } 24 | } 25 | if(!loop) return {nullptr, 0}; // there is no loop 26 | tortoise = head; 27 | while(hare != tortoise){ 28 | hare = hare->next; 29 | tortoise = tortoise->next; 30 | } 31 | int len = 1; 32 | hare = tortoise->next; 33 | while(hare != tortoise){ 34 | hare = hare->next; 35 | len ++; 36 | } 37 | return {tortoise, len}; 38 | } -------------------------------------------------------------------------------- /utilities/README.md: -------------------------------------------------------------------------------- 1 | # Competitive Programming Contest Setup 2 | 3 | This Python script, `create_contest.py`, helps you set up a competitive programming contest workspace with directories and files for each problem, as well as configure Visual Studio Code for a better workflow. 4 | 5 | ## Usage 6 | 7 | ``` 8 | python create_contest.py | clean | delete 9 | ``` 10 | 11 | ### Parameters 12 | 13 | - ``: The number of problems in the contest (integer between 1 and 26). It will create the corresponding number of directories (A, B, C, ...) containing the `.cpp` file, four input files, and a test script. 14 | - `clean`: Deletes all contest directories (A to Z) if they exist. 15 | - `delete`: Resets the Visual Studio Code configuration (removes `tasks.json` and clears `keybindings.json`), and deletes all contest directories (A to Z) if they exist. 16 | 17 | ## Setup 18 | 19 | 1. Make sure you have Python 3 installed on your system. 20 | 2. Download the `create_contest.py` script. 21 | 3. Ensure you have internet access, as the script will download necessary files from GitHub. 22 | 4. (Optional) Configure the `keybindings_path` variable in the script for your specific operating system (the script is pre-configured for macOS; Linux and Windows paths are commented out). 23 | 5. Run the script using the command line with the desired parameters as explained above. 24 | 25 | ## Visual Studio Code Configuration 26 | 27 | The script automatically configures Visual Studio Code for the contest. It downloads `tasks.json` and `keybindings.json` files and places them in the appropriate locations. You can customize these files as per your preference by directly modifying the content in the `create_contest.py` script or adjusting the files after they have been placed by the script. 28 | 29 | ## During Contest 30 | 31 | With the provided `tasks.json` and `keybindings.json` files configured, you can use the following shortcuts to compile and run your code: 32 | 33 | - `Ctrl+Alt+0`: Execute the compiled program without any input file. 34 | - `Ctrl+Alt+1`: Compile and run the program using `in1` as input. 35 | - `Ctrl+Alt+2`: Compile and run the program using `in2` as input. 36 | - `Ctrl+Alt+3`: Compile and run the program using `in3` as input. 37 | - `Ctrl+Alt+4`: Compile and run the program using `in4` as input. 38 | - `Ctrl+Alt+5`: Compile and run the program using `in5` as input. 39 | - `Ctrl+Alt+6`: Compile and run the program using `in6` as input. 40 | 41 | Make sure to create the input files (e.g., `in1`, `in2`, `in3`, etc.) in the same directory as your source code file. 42 | 43 | Happy coding! 44 | -------------------------------------------------------------------------------- /utilities/create-contest.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | import sys 4 | import requests 5 | import json 6 | import platform 7 | 8 | 9 | keybindings_path = '~/Library/Application Support/Code/User' 10 | # For Linux, uncomment the following line: 11 | # keybindings_path = '~/.config/Code/User' 12 | # For Windows, uncomment the following line: 13 | # keybindings_path = r'%APPDATA%\Code\User' 14 | 15 | def download_file(url): 16 | response = requests.get(url) 17 | if response.status_code == 200: 18 | return response.text 19 | else: 20 | print(f"Error downloading {url}: HTTP {response.status_code}") 21 | sys.exit(1) 22 | 23 | def create_contest_files(num, template_content, test_content): 24 | if num < 1 or num > 26: 25 | print("Please provide a number between 1 and 26.") 26 | return 27 | 28 | for i in range(num): 29 | dir_name = chr(ord('A') + i) 30 | os.makedirs(dir_name, exist_ok=True) 31 | 32 | cpp_file = os.path.join(dir_name, f"{dir_name}.cpp") 33 | with open(cpp_file, "w") as f: 34 | f.write(template_content) 35 | 36 | test_file = os.path.join(dir_name, "test.bsh") 37 | with open(test_file, "w") as f: 38 | f.write(test_content) 39 | 40 | for j in range(1, 5): 41 | input_file = os.path.join(dir_name, f"in{j}") 42 | with open(input_file, "w") as f: 43 | pass # Creates empty input files 44 | 45 | def delete_contest_files(): 46 | for i in range(26): 47 | dir_name = chr(ord('A') + i) 48 | if os.path.exists(dir_name): 49 | shutil.rmtree(dir_name) 50 | 51 | def setup_vscode(tasks_content, keybindings_content): 52 | vscode_dir = os.path.join(os.getcwd(), '.vscode') 53 | 54 | if not os.path.exists(vscode_dir): 55 | os.makedirs(vscode_dir) 56 | 57 | tasks_file = os.path.join(vscode_dir, 'tasks.json') 58 | if not os.path.exists(tasks_file): 59 | with open(tasks_file, "w") as f: 60 | f.write(tasks_content) 61 | 62 | if keybindings_path: 63 | keybindings_file = os.path.join(os.path.expanduser(keybindings_path), 'keybindings.json') 64 | with open(keybindings_file, "w") as f: 65 | f.write(keybindings_content) 66 | 67 | def reset_vscode_config(): 68 | vscode_dir = os.path.join(os.getcwd(), '.vscode') 69 | 70 | tasks_file = os.path.join(vscode_dir, 'tasks.json') 71 | if os.path.exists(tasks_file): 72 | os.remove(tasks_file) 73 | 74 | if keybindings_path: 75 | keybindings_file = os.path.join(os.path.expanduser(keybindings_path), 'keybindings.json') 76 | if os.path.exists(keybindings_file): 77 | with open(keybindings_file, "w") as f: 78 | f.write("[]") 79 | 80 | if __name__ == "__main__": 81 | if len(sys.argv) < 2: 82 | print("Usage: python create_contest.py | clean | delete") 83 | sys.exit(1) 84 | 85 | if sys.argv[1].lower() == "clean": 86 | delete_contest_files() 87 | elif sys.argv[1].lower() == "delete": 88 | reset_vscode_config() 89 | delete_contest_files() 90 | else: 91 | num = int(sys.argv[1]) 92 | template_content = download_file("https://raw.githubusercontent.com/juankipedia/CompetitiveProgramming/master/utilities/template.cpp") 93 | test_content = download_file("https://raw.githubusercontent.com/juankipedia/CompetitiveProgramming/master/utilities/test.bsh") 94 | tasks_content = download_file("https://raw.githubusercontent.com/juankipedia/CompetitiveProgramming/master/utilities/vscode/tasks.json") 95 | keybindings_content = download_file("https://raw.githubusercontent.com/juankipedia/CompetitiveProgramming/master/utilities/vscode/keybindings.json") 96 | 97 | create_contest_files(num, template_content, test_content) 98 | setup_vscode(tasks_content, keybindings_content) 99 | 100 | -------------------------------------------------------------------------------- /utilities/template.cpp: -------------------------------------------------------------------------------- 1 | # include 2 | using namespace std; 3 | # define endl "\n" 4 | # define io_boost ios_base::sync_with_stdio(0);cin.tie(0); 5 | using ull = unsigned long long; 6 | using ll = long long; 7 | /* 8 | JUANKI 9 | */ 10 | 11 | int main(){ 12 | io_boost; 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /utilities/test.bsh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | VAR1=1; 3 | VAR2=1; 4 | dir_name=$(basename $(pwd)) 5 | executable="${dir_name}.out" 6 | 7 | while [[ $VAR1 = $VAR2 ]] 8 | do 9 | ./generate.out > in4 # gen generates the test, in4 just stores the test 10 | VAR1=$(./${executable} < in4) # your solution 11 | VAR2=$(./correct.out < in4) # brute force solution 12 | if [[ $VAR1 = $VAR2 ]] 13 | then 14 | echo "OK" 15 | fi 16 | done 17 | echo "Wrong Answer, test case:" 18 | cat in4 19 | echo "Answer: " $VAR2 20 | echo "Output: " $VAR1 21 | -------------------------------------------------------------------------------- /utilities/vscode/README.md: -------------------------------------------------------------------------------- 1 | # Competitive Programming VSCode Setup 2 | 3 | This guide will help you set up Visual Studio Code (VSCode) for competitive programming using the provided `tasks.json` and `keybindings.json` files. 4 | 5 | ## Prerequisites 6 | 7 | 1. Visual Studio Code installed. 8 | 2. GCC Compiler installed. 9 | 10 | ## Setup 11 | 12 | ### 1. Configure tasks 13 | 14 | The provided `tasks.json` file contains tasks to compile and run your code using test cases. 15 | 16 | To configure tasks in VSCode: 17 | 18 | 1. Open your competitive programming folder in VSCode. 19 | 2. In the Explorer pane, expand the `.vscode` folder. If it doesn't exist, create it. 20 | 3. Inside the `.vscode` folder, create or edit the `tasks.json` file. 21 | 4. Copy and paste the contents of the provided `tasks.json` file into your `tasks.json` file and save it. 22 | 23 | ### 2. Configure keybindings 24 | 25 | The provided `keybindings.json` file contains custom keybindings for running tasks. 26 | 27 | To configure keybindings in VSCode: 28 | 29 | 1. Open the Command Palette with `Ctrl+Shift+P` or `Cmd+Shift+P` (macOS). 30 | 2. Type "Open Keyboard Shortcuts (JSON)" and select the command. 31 | 3. Copy and paste the contents of the provided `keybindings.json` file into your `keybindings.json` file and save it. 32 | 33 | ## Usage 34 | 35 | With the provided `tasks.json` and `keybindings.json` files configured, you can use the following shortcuts to compile and run your code: 36 | 37 | - `Ctrl+Alt+0`: Execute the compiled program without any input file. 38 | - `Ctrl+Alt+1`: Compile and run the program using `in1` as input. 39 | - `Ctrl+Alt+2`: Compile and run the program using `in2` as input. 40 | - `Ctrl+Alt+3`: Compile and run the program using `in3` as input. 41 | - `Ctrl+Alt+4`: Compile and run the program using `in4` as input. 42 | - `Ctrl+Alt+5`: Compile and run the program using `in5` as input. 43 | - `Ctrl+Alt+6`: Compile and run the program using `in6` as input. 44 | 45 | Make sure to create the input files (e.g., `in1`, `in2`, `in3`, etc.) in the same directory as your source code file. 46 | 47 | Happy coding! 48 | -------------------------------------------------------------------------------- /utilities/vscode/keybindings.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "key": "ctrl+alt+0", 4 | "command": "workbench.action.tasks.runTask", 5 | "args": "execute" 6 | }, 7 | { 8 | "key": "ctrl+alt+1", 9 | "command": "workbench.action.tasks.runTask", 10 | "args": "run1" 11 | }, 12 | { 13 | "key": "ctrl+alt+2", 14 | "command": "workbench.action.tasks.runTask", 15 | "args": "run2" 16 | }, 17 | { 18 | "key": "ctrl+alt+3", 19 | "command": "workbench.action.tasks.runTask", 20 | "args": "run1" 21 | }, 22 | { 23 | "key": "ctrl+alt+3", 24 | "command": "workbench.action.tasks.runTask", 25 | "args": "run3" 26 | }, 27 | { 28 | "key": "ctrl+alt+4", 29 | "command": "workbench.action.tasks.runTask", 30 | "args": "run4" 31 | }, 32 | { 33 | "key": "ctrl+alt+5", 34 | "command": "workbench.action.tasks.runTask", 35 | "args": "run5" 36 | }, 37 | { 38 | "key": "ctrl+alt+6", 39 | "command": "workbench.action.tasks.runTask", 40 | "args": "run6" 41 | }, 42 | ] 43 | -------------------------------------------------------------------------------- /utilities/vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "compile", 6 | "type": "shell", 7 | "command": "g++-12 -std=c++17 -O2 ${file} -o ${fileDirname}/${fileBasenameNoExtension}.out", 8 | "presentation": { 9 | "reveal": "always", 10 | "panel": "new" 11 | } 12 | }, 13 | { 14 | "label": "execute", 15 | "type": "shell", 16 | "command": "${fileDirname}/${fileBasenameNoExtension}.out", 17 | "presentation": { 18 | "reveal": "always", 19 | "panel": "new" 20 | }, 21 | "dependsOn": ["compile"] 22 | }, 23 | { 24 | "label": "run1", 25 | "type": "shell", 26 | "command": "${fileDirname}/${fileBasenameNoExtension}.out < ${fileDirname}/in1", 27 | "presentation": { 28 | "reveal": "always", 29 | "panel": "new" 30 | }, 31 | "dependsOn": ["compile"] 32 | }, 33 | { 34 | "label": "run2", 35 | "type": "shell", 36 | "command": "${fileDirname}/${fileBasenameNoExtension}.out < ${fileDirname}/in2", 37 | "presentation": { 38 | "reveal": "always", 39 | "panel": "new" 40 | }, 41 | "dependsOn": ["compile"] 42 | }, 43 | { 44 | "label": "run3", 45 | "type": "shell", 46 | "command": "${fileDirname}/${fileBasenameNoExtension}.out < ${fileDirname}/in3", 47 | "presentation": { 48 | "reveal": "always", 49 | "panel": "new" 50 | }, 51 | "dependsOn": ["compile"] 52 | }, 53 | { 54 | "label": "run4", 55 | "type": "shell", 56 | "command": "${fileDirname}/${fileBasenameNoExtension}.out < ${fileDirname}/in4", 57 | "presentation": { 58 | "reveal": "always", 59 | "panel": "new" 60 | }, 61 | "dependsOn": ["compile"] 62 | }, 63 | { 64 | "label": "run5", 65 | "type": "shell", 66 | "command": "${fileDirname}/${fileBasenameNoExtension}.out < ${fileDirname}/in5", 67 | "presentation": { 68 | "reveal": "always", 69 | "panel": "new" 70 | }, 71 | "dependsOn": ["compile"] 72 | }, 73 | { 74 | "label": "run6", 75 | "type": "shell", 76 | "command": "${fileDirname}/${fileBasenameNoExtension}.out < ${fileDirname}/in6", 77 | "presentation": { 78 | "reveal": "always", 79 | "panel": "new" 80 | }, 81 | "dependsOn": ["compile"] 82 | } 83 | ] 84 | } 85 | --------------------------------------------------------------------------------