├── .gitignore ├── Dijkstra.cpp ├── DSU.cpp ├── README.md ├── MatrixExpo.cpp ├── template ├── debug.hpp └── template.cpp ├── KMP.cpp ├── SparseTable.cpp ├── FFT.cpp ├── Trie.cpp ├── FenwickTree.cpp ├── MergeSortTree.cpp ├── PersistentSegmentTree.cpp ├── SegmentTreeLazyPropagation.cpp ├── ModInt.cpp ├── geometry └── KDTree.cpp ├── NumberTheory.cpp ├── Mo.cpp ├── BiTrie.cpp ├── SegmentTree.cpp └── PersistentTrie.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | test.cpp 2 | .vscode 3 | .cph 4 | *.bin 5 | .DS_Store 6 | *.dSYM 7 | *.ign.* -------------------------------------------------------------------------------- /Dijkstra.cpp: -------------------------------------------------------------------------------- 1 | vector >> g; 2 | vector dist; 3 | vector previous; 4 | 5 | void dijkstra(int s) { 6 | int n = g.size(); 7 | dist.assign(n, 1e9); 8 | previous.assign(n, -1); 9 | dist[s] = 0; 10 | set> q; 11 | q.insert({0, s}); 12 | while (!q.empty()) { 13 | int v = q.begin()->second; 14 | q.erase(q.begin()); 15 | 16 | for (auto edge : g[v]) { 17 | int to = edge.first; 18 | int len = edge.second; 19 | 20 | if (dist[v] + len < dist[to]) { 21 | q.erase({dist[to], to}); 22 | dist[to] = dist[v] + len; 23 | previous[to] = v; 24 | q.insert({dist[to], to}); 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /DSU.cpp: -------------------------------------------------------------------------------- 1 | class DSU { 2 | public: 3 | int n; 4 | vector par; 5 | vector sz; 6 | int cnt; 7 | DSU(){} 8 | DSU(int N) { 9 | n = cnt = N; 10 | par.resize(n); sz.resize(n); 11 | while (N--) { 12 | par[N] = N; 13 | sz[N] = 1; 14 | } 15 | } 16 | int find(int p) { 17 | return par[p] == p? p: par[p] = find(par[p]); 18 | } 19 | bool connected(int p, int q) { 20 | return find(p) == find(q); 21 | } 22 | int size(int p) { 23 | return sz[find(p)]; 24 | } 25 | bool join(int p, int q) { 26 | int root1 = find(p); 27 | int root2 = find(q); 28 | if (root1 == root2) return 0; 29 | if (sz[root1] < sz[root2]) swap(root1, root2); 30 | par[root2] = root1; 31 | sz[root1] += sz[root2]; 32 | cnt--; 33 | return 1; 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Practicing 2 | 3 | * [CSES problemset](https://cses.fi/problemset/) 4 | * [Leetcode](https://leetcode.com/problemset/) 5 | * [Codeforces](https://codeforces.com/problemset) 6 | 7 | ### Youtube 8 | 9 | * [3blue1brown](https://www.youtube.com/c/3blue1brown/) 10 | * [NeatlyStructured](NeatlyStructured) 11 | * [Colin Galen](https://www.youtube.com/c/ColinGalen) 12 | * [WilliamFiset](https://www.youtube.com/c/WilliamFiset-videos) 13 | * [Back To Back SWE](https://www.youtube.com/channel/UCmJz2DV1a3yfgrR7GqRtUUA) 14 | * [Reducible](https://www.youtube.com/c/Reducible) 15 | 16 | ### Articles - Books 17 | 18 | * [cp-algorithms](https://cp-algorithms.com/) 19 | * [Competitive Programmer's Handbook](https://cses.fi/book/index.php) 20 | 21 | ### Tools 22 | 23 | * [code-library](https://github.com/ShahjalalShohag/code-library) 24 | * [kactl](https://github.com/kth-competitive-programming/kactl) 25 | * [WolframAlpha](https://www.wolframalpha.com/) 26 | * [Encyclopedia of sequences](https://oeis.org/) 27 | -------------------------------------------------------------------------------- /MatrixExpo.cpp: -------------------------------------------------------------------------------- 1 | const int MOD = (int)(1e9+7); 2 | 3 | class Matrix{ 4 | int n,m; 5 | vector > a; 6 | Matrix(int n, int m) { 7 | this->n = n; 8 | this->m = m; 9 | a.resize(n,vector (m)); 10 | } 11 | 12 | Matrix operator*(const Matrix& other) { 13 | assert(m == other.n); 14 | Matrix product(n,other.m); 15 | for(int i=0;i & operator[] (int i) { 27 | return a[i]; 28 | } 29 | }; 30 | 31 | Matrix getIdentity(int n) { 32 | Matrix ans(n,n); 33 | for(int i=0;i>= 1; 46 | } 47 | return res; 48 | } -------------------------------------------------------------------------------- /template/debug.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | using namespace std; 4 | 5 | void __print(int x) {cerr << x;} 6 | void __print(long x) {cerr << x;} 7 | void __print(unsigned x) {cerr << x;} 8 | void __print(unsigned long x) {cerr << x;} 9 | void __print(unsigned long long x) {cerr << x;} 10 | void __print(float x) {cerr << x;} 11 | void __print(double x) {cerr << x;} 12 | void __print(char x) {cerr << '\'' << x << '\'';} 13 | void __print(const char *x) {cerr << '\"' << x << '\"';} 14 | void __print(const string &x) {cerr << '\"' << x << '\"';} 15 | void __print(bool x) {cerr << (x ? "true" : "false");} 16 | 17 | template 18 | void __print(const pair &x) {cerr << '{'; __print(x.first); cerr << ','; __print(x.second); cerr << '}';} 19 | template 20 | void __print(const T &x) {int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), __print(i); cerr << "}";} 21 | void _print() {cerr << "]\n";} 22 | template 23 | void _print(T t, V... v) {__print(t); if (sizeof...(v)) cerr << ", "; _print(v...);} 24 | 25 | #define debug(x...) cerr << "[" << #x << "] = ["; _print(x) -------------------------------------------------------------------------------- /KMP.cpp: -------------------------------------------------------------------------------- 1 | // returns the longest proper prefix array of pattern p 2 | // where lps[i]=longest proper prefix which is also suffix of p[0...i] 3 | vector build_lps(string p) { 4 | int sz = p.size(); 5 | vector lps; 6 | lps.assign(sz + 1, 0); 7 | int j = 0; 8 | lps[0] = 0; 9 | for(int i = 1; i < sz; i++) { 10 | while(j >= 0 && p[i] != p[j]) { 11 | if(j >= 1) j = lps[j - 1]; 12 | else j = -1; 13 | } 14 | j++; 15 | lps[i] = j; 16 | } 17 | return lps; 18 | } 19 | // returns matches in vector ans in 0-indexed 20 | vector kmp(vector lps, string s, string p) { 21 | vector ans; 22 | int psz = p.size(), sz = s.size(); 23 | int j = 0; 24 | for(int i = 0; i < sz; i++) { 25 | while(j >= 0 && p[j] != s[i]) 26 | if(j >= 1) j = lps[j - 1]; 27 | else j = -1; 28 | j++; 29 | if(j == psz) { 30 | j = lps[j - 1]; 31 | // pattern found in string s at position i-psz+1 32 | ans.push_back(i - psz + 1); 33 | } 34 | // after each loop we have j=longest common suffix of s[0..i] which is also prefix of p 35 | } 36 | return ans; 37 | } 38 | 39 | vector kmp(string str, string pattern) { 40 | return kmp(build_lps(pattern), str, pattern); 41 | } 42 | -------------------------------------------------------------------------------- /template/template.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | using namespace __gnu_pbds; 7 | template using OrderedSet = tree, rb_tree_tag,tree_order_statistics_node_update>; 8 | template using OrderedMultiSet = tree, rb_tree_tag,tree_order_statistics_node_update>; 9 | #define int long long 10 | #define double long double 11 | #define endl '\n' 12 | #define ALL(a) a.begin(), a.end() 13 | #define RALL(a) a.rbegin(), a.rend() 14 | #define YESORNO(x) cout << (x? "YES\n": "NO\n") 15 | #define SZ(x) (int)(x.size()) 16 | template bool ckmin(T& a, const T b) { return b < a ? a = b, 1 : 0; } 17 | template bool ckmax(T& a, const T b) { return a < b ? a = b, 1 : 0; } 18 | 19 | #ifndef ONLINE_JUDGE 20 | #include "debug.hpp" 21 | #else 22 | #define debug(x...) 23 | #endif 24 | 25 | #define MULTIPLE_TEST_CASES true 26 | void solve(int testCase) { 27 | 28 | } 29 | 30 | int32_t main() { 31 | ios::sync_with_stdio(false); 32 | cin.tie(0); 33 | int t = 1; 34 | if (MULTIPLE_TEST_CASES) cin >> t; 35 | while (t--) { 36 | solve(t); 37 | } 38 | } -------------------------------------------------------------------------------- /SparseTable.cpp: -------------------------------------------------------------------------------- 1 | // from kactl library 2 | #define rep(i,a,b) for (int i = (a); i < (b); i++) 3 | template 4 | struct SparseTable { 5 | T fn(T a, T b) {return max(a, b); } 6 | vector> jmp; 7 | SparseTable(const vector& V) : jmp(1, V) { 8 | for (int pw = 1, k = 1; pw * 2 <= SZ(V); pw *= 2, ++k) { 9 | jmp.emplace_back(SZ(V) - pw * 2 + 1); 10 | rep(j,0,SZ(jmp[k])) 11 | jmp[k][j] = fn(jmp[k - 1][j], jmp[k - 1][j + pw]); 12 | } 13 | } 14 | T query(int a, int b) { b++; // [a,b] 15 | assert(a < b); // or return inf if a == b 16 | int dep = 31 - __builtin_clz(b - a); 17 | return fn(jmp[dep][a], jmp[dep][b - (1 << dep)]); 18 | } 19 | }; 20 | 21 | // with template function 22 | template 23 | struct SparseTable { 24 | vector> jmp; 25 | SparseTable(const vector& V) : jmp(1, V) { 26 | for (int pw = 1, k = 1; pw * 2 <= SZ(V); pw *= 2, ++k) { 27 | jmp.emplace_back(SZ(V) - pw * 2 + 1); 28 | rep(j,0,SZ(jmp[k])) 29 | jmp[k][j] = fn(jmp[k - 1][j], jmp[k - 1][j + pw]); 30 | } 31 | } 32 | T query(int a, int b) { b++; // [a,b] 33 | assert(a < b); // or return inf if a == b 34 | int dep = 31 - __builtin_clz(b - a); 35 | return fn(jmp[dep][a], jmp[dep][b - (1 << dep)]); 36 | } 37 | }; -------------------------------------------------------------------------------- /FFT.cpp: -------------------------------------------------------------------------------- 1 | // fft template from kactl library 2 | #define rep(i, a, b) for(int i = a; i < (b); ++i) 3 | #define ALL(x) begin(x), end(x) 4 | #define SZ(x) (int)(x).size() 5 | 6 | typedef complex C; 7 | typedef vector vd; 8 | void fft(vector& a) { 9 | int n = SZ(a), L = 31 - __builtin_clz(n); 10 | static vector> R(2, 1); 11 | static vector rt(2, 1); // (^ 10% faster if double) 12 | for (static int k = 2; k < n; k *= 2) { 13 | R.resize(n); rt.resize(n); 14 | auto x = polar(1.0L, acos(-1.0L) / k); 15 | rep(i,k,2*k) rt[i] = R[i] = i&1 ? R[i/2] * x : R[i/2]; 16 | } 17 | vector rev(n); 18 | rep(i,0,n) rev[i] = (rev[i / 2] | (i & 1) << L) / 2; 19 | rep(i,0,n) if (i < rev[i]) swap(a[i], a[rev[i]]); 20 | for (int k = 1; k < n; k *= 2) 21 | for (int i = 0; i < n; i += 2 * k) rep(j,0,k) { 22 | // C z = rt[j+k] * a[i+j+k]; // (25% faster if hand-rolled) /// include-line 23 | auto x = (double *)&rt[j+k], y = (double *)&a[i+j+k]; /// exclude-line 24 | C z(x[0]*y[0] - x[1]*y[1], x[0]*y[1] + x[1]*y[0]); /// exclude-line 25 | a[i + j + k] = a[i + j] - z; 26 | a[i + j] += z; 27 | } 28 | } 29 | vd conv(const vd& a, const vd& b) { 30 | if (a.empty() || b.empty()) return {}; 31 | vd res(SZ(a) + SZ(b) - 1); 32 | int L = 32 - __builtin_clz(SZ(res)), n = 1 << L; 33 | vector in(n), out(n); 34 | copy(ALL(a), begin(in)); 35 | rep(i,0,SZ(b)) in[i].imag(b[i]); 36 | fft(in); 37 | for (C& x : in) x *= x; 38 | rep(i,0,n) out[i] = in[-i & (n - 1)] - conj(in[i]); 39 | fft(out); 40 | rep(i,0,SZ(res)) res[i] = imag(out[i]) / (4 * n); 41 | return res; 42 | } -------------------------------------------------------------------------------- /Trie.cpp: -------------------------------------------------------------------------------- 1 | // source: https://gist.github.com/hrsvrdhn/1ae71c25ef1c620c022a544d52df8928 2 | struct Trie { 3 | map children; 4 | int prefixes; 5 | bool endofword; 6 | Trie() { 7 | prefixes=0; 8 | endofword=false; 9 | } 10 | void insert(string word) { 11 | Trie *current=this; 12 | for(int i=0;ichildren[ch]; 15 | if(!node) { 16 | node=new Trie(); 17 | current->children[word[i]]=node; 18 | } 19 | current=node; 20 | current->prefixes++; 21 | } 22 | current->endofword=true; 23 | } 24 | bool search(string word) { 25 | Trie *current=this; 26 | for(int i=0;ichildren[ch]; 29 | if(!node) 30 | return false; 31 | current=node; 32 | } 33 | return current->endofword; 34 | } 35 | int countPrefix(string word) { 36 | Trie *current=this; 37 | for(int i=0;ichildren[ch]; 40 | if(!node) { 41 | return 0; 42 | } 43 | current=node; 44 | } 45 | return current->prefixes; 46 | } 47 | void erase(string word) { 48 | if (!search(word)) return; 49 | Trie *current = this; 50 | for(int i = 0; i < word.size(); i++) { 51 | char ch = word[i]; 52 | Trie *node = current->children[ch]; 53 | node->prefixes--; 54 | if (node->prefixes == 0) { 55 | current->children.erase(ch); 56 | delete node; 57 | return; 58 | } 59 | current = node; 60 | } 61 | current->endofword = false; 62 | } 63 | }; 64 | -------------------------------------------------------------------------------- /FenwickTree.cpp: -------------------------------------------------------------------------------- 1 | class FenwickTree { 2 | const int IDENTITY = 0; 3 | int fn(int a, int b) { return a+b; } 4 | int invFn(int a, int b) { return a-b; } 5 | int diff(int i, int x) { return invFn(x, a[i]); } 6 | vector bit, a; 7 | public: 8 | FenwickTree(int n): bit(n, IDENTITY), a(n, IDENTITY) {} 9 | FenwickTree(vector &a): bit(SZ(a), IDENTITY), a(a) { 10 | for (int i = 0; i < SZ(a); i++) { 11 | bit[i] = fn(bit[i], a[i]); 12 | int r = i | (i+1); 13 | if (r < SZ(a)) bit[r] = fn(bit[r], bit[i]); 14 | } 15 | } 16 | void update(int i, int x) { 17 | int delta = diff(i,x); 18 | a[i] = x; 19 | for (int j = i; j < SZ(a); j |= (j+1)) { 20 | bit[j] = fn(bit[j], delta); 21 | } 22 | } 23 | int query(int r) { 24 | int res = IDENTITY; 25 | for (;r >= 0; r = (r & (r+1)) - 1) { 26 | res = fn(res, bit[r]); 27 | } 28 | return res; 29 | } 30 | int query(int l, int r) { 31 | return l == r ? a[l]: l > 0 ? invFn(query(r), query(l-1)): query(r); 32 | } 33 | }; 34 | 35 | // Kactl 36 | struct FT { 37 | vector s; 38 | FT(int n) : s(n) {} 39 | void update(int pos, int dif) { // a[pos] += dif 40 | for (; pos < s.size(); pos |= pos + 1) s[pos] += dif; 41 | } 42 | int query(int pos) { // sum of values in [0, pos) 43 | int res = 0; 44 | for (; pos > 0; pos &= pos - 1) res += s[pos-1]; 45 | return res; 46 | } 47 | int lower_bound(int sum) {// min pos st sum of [0, pos] >= sum 48 | // Returns n if no sum is >= sum, or -1 if empty sum is. 49 | if (sum <= 0) return -1; 50 | int pos = 0; 51 | for (int pw = 1 << 25; pw; pw >>= 1) { 52 | if (pos + pw <= s.size() && s[pos + pw-1] < sum) 53 | pos += pw, sum -= s[pos-1]; 54 | } 55 | return pos; 56 | } 57 | }; -------------------------------------------------------------------------------- /MergeSortTree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // answer query number of elements in [l, r] <= x 5 | typedef int T; 6 | struct Node { 7 | vector v; 8 | Node(Node &nodeA, Node &nodeB) { 9 | vector &a = nodeA.v, &b = nodeB.v; 10 | v.reserve(a.size() + b.size()); 11 | int ai = 0, bi = 0; 12 | while (ai < a.size() && bi < b.size()) { 13 | if (a[ai] < b[bi]) v.push_back(a[ai++]); 14 | else v.push_back(b[bi++]); 15 | } 16 | while (ai < a.size()) v.push_back(a[ai++]); 17 | while (bi < b.size()) v.push_back(b[bi++]); 18 | }; 19 | Node(vector &a): v(a) {} 20 | Node(T x) { v = vector(1, x); } 21 | Node() {} 22 | }; 23 | 24 | const Node identity = Node(0); 25 | struct MST { 26 | int n; 27 | vector tree; 28 | vector a; 29 | MST(int n): n(n) { 30 | tree.resize(4*n, identity); 31 | } 32 | MST(vector &a): n(a.size()), a(a) { 33 | tree.resize(4*n); 34 | build(1, 0, n - 1); 35 | } 36 | void build(int idx, int l, int r) { 37 | if (l == r) { 38 | tree[idx] = Node(a[l]); 39 | return ; 40 | } 41 | int mid = (l + r) / 2; 42 | build(2*idx, l, mid); 43 | build(2*idx+1, mid+1, r); 44 | tree[idx] = Node(tree[2*idx], tree[2*idx+1]); 45 | }; 46 | 47 | // number of elements less than or equal to val in [ql, ar] 48 | // in O(log^2) 49 | int query(int idx, int l, int r, int ql, int qr, T val) { 50 | if (ql > r || qr < l) { 51 | return 0; 52 | } 53 | if (l >= ql && r <= qr) { 54 | vector &arr = tree[idx].v; 55 | int ans = upper_bound(arr.begin(), arr.end(), val) - arr.begin(); 56 | return ans; 57 | } 58 | int mid = (l+r)/2; 59 | int ansL = query(2*idx, l, mid, ql, qr, val); 60 | int ansR = query(2*idx+1, mid+1, r, ql, qr, val); 61 | return ansL + ansR; 62 | } 63 | 64 | // number of elements less than or equal to val in [l, r] 65 | // in O(log^2) 66 | int query(int l, int r, T val) { 67 | return query(1, 0, n - 1, l, r, val); 68 | } 69 | }; -------------------------------------------------------------------------------- /PersistentSegmentTree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define ll long long 4 | 5 | // SRC: https://usaco.guide/adv/persistent?lang=cpp#index-implementation 6 | class PST { 7 | private: 8 | struct Node { 9 | ll val = 0; 10 | int l = 0, r = 0; 11 | }; 12 | 13 | const int n; 14 | vector tree; 15 | int timer = 1; 16 | 17 | Node join(int l, int r) { return Node{tree[l].val + tree[r].val, l, r}; } 18 | 19 | int build(int tl, int tr) { 20 | if (tl == tr) { 21 | tree[timer] = {0, 0, 0}; 22 | return timer++; 23 | } 24 | 25 | int mid = (tl + tr) / 2; 26 | tree[timer] = join(build(tl, mid), build(mid + 1, tr)); 27 | 28 | return timer++; 29 | } 30 | 31 | int build(int tl, int tr, const vector &arr) { 32 | if (tl == tr) { 33 | tree[timer] = {arr[tl], 0, 0}; 34 | return timer++; 35 | } 36 | 37 | int mid = (tl + tr) / 2; 38 | tree[timer] = join(build(tl, mid, arr), build(mid + 1, tr, arr)); 39 | 40 | return timer++; 41 | } 42 | 43 | int set(int v, int pos, int val, int tl, int tr) { 44 | if (tl == tr) { 45 | tree[timer] = {val, 0, 0}; 46 | return timer++; 47 | } 48 | 49 | int mid = (tl + tr) / 2; 50 | if (pos <= mid) { 51 | tree[timer] = join(set(tree[v].l, pos, val, tl, mid), tree[v].r); 52 | } else { 53 | tree[timer] = join(tree[v].l, set(tree[v].r, pos, val, mid + 1, tr)); 54 | } 55 | 56 | return timer++; 57 | } 58 | 59 | ll query(int v, int ql, int qr, int tl, int tr) { 60 | if (qr < tl || tr < ql) { return 0ll; } 61 | if (ql <= tl && tr <= qr) { return tree[v].val; } 62 | 63 | int mid = (tl + tr) / 2; 64 | return query(tree[v].l, ql, qr, tl, mid) + 65 | query(tree[v].r, ql, qr, mid + 1, tr); 66 | } 67 | 68 | public: 69 | PST(int n, int updates) : n(n), tree(2 * n + updates * (2 + ceil(log2(n)))) {} 70 | 71 | int build(const vector &arr) { return build(0, n - 1, arr); } 72 | 73 | int build() { return build(0, n - 1); } 74 | 75 | int set(int root, int pos, int val) { return set(root, pos, val, 0, n - 1); } 76 | 77 | ll query(int root, int l, int r) { return query(root, l, r, 0, n - 1); } 78 | 79 | int add_copy(int root) { 80 | tree[timer] = tree[root]; 81 | return timer++; 82 | } 83 | }; 84 | -------------------------------------------------------------------------------- /SegmentTreeLazyPropagation.cpp: -------------------------------------------------------------------------------- 1 | struct LazySegTree { 2 | vector all; 3 | int n; 4 | vector s; 5 | vector lazy; 6 | int identity = 0; 7 | 8 | int fn(int a, int b){ 9 | return a + b; 10 | } 11 | LazySegTree(int n) { 12 | this->n = n; 13 | s.assign(4 * n, identity); 14 | lazy.assign(4 * n, identity); 15 | all.assign(n, identity); 16 | } 17 | LazySegTree(vector &a){ 18 | n = a.size(); 19 | all = a; 20 | s.resize(4 * n); 21 | lazy.resize(4 * n); 22 | build(1, 0, n - 1); 23 | } 24 | void build(int node, int start, int end){ 25 | if (start == end){ 26 | s[node] = all[start]; 27 | return ; 28 | } 29 | int mid = (start + end) / 2; 30 | build(2 * node, start, mid); 31 | build(2 * node + 1, mid + 1, end); 32 | s[node] = fn(s[2*node], s[2*node + 1]); 33 | } 34 | 35 | void push_down(int node, int start, int end) { 36 | s[node] += lazy[node] * (end - start + 1); 37 | if (start != end){ 38 | lazy[2 * node] += lazy[node]; 39 | lazy[2 * node + 1] += lazy[node]; 40 | } 41 | lazy[node] = 0; 42 | } 43 | 44 | void update(int node, int start, int end, int l, int r, int val){ 45 | push_down(node, start, end); 46 | if (start > r || end < l) return ; 47 | if (start >= l && end <= r){ 48 | lazy[node] += val; 49 | push_down(node, start, end); 50 | return ; 51 | } 52 | int mid = (start + end) / 2; 53 | update(2 * node, start, mid, l, r, val); 54 | update(2 * node + 1, mid + 1, end, l, r, val); 55 | s[node] = fn(s[2 * node], s[2 * node + 1]); 56 | } 57 | void update(int l, int r, int val){ 58 | update(1, 0, n - 1, l, r, val); 59 | } 60 | 61 | int query(int node, int start, int end, const int l, const int r){ 62 | push_down(node, start, end); 63 | if (start > r || end < l) return identity; 64 | if (start >= l && end <= r) return s[node]; 65 | int mid = (start + end) / 2; 66 | int left = query(2 * node, start, mid, l, r); 67 | int right = query(2 * node + 1, mid + 1, end, l, r); 68 | return fn(left, right); 69 | } 70 | int query(int l, int r){ 71 | return query(1, 0, n - 1, l, r); 72 | } 73 | }; 74 | -------------------------------------------------------------------------------- /ModInt.cpp: -------------------------------------------------------------------------------- 1 | // https://github.com/ShahjalalShohag/code-library/blob/main/Math/Modint.cpp 2 | 3 | const int mod = 1e9 + 7; 4 | 5 | template 6 | struct modint { 7 | int32_t value; 8 | modint() = default; 9 | modint(int32_t value_) : value(value_) {} // make sure value is less than MOD 10 | inline modint operator + (modint other) const { int32_t c = this->value + other.value; return modint(c >= MOD ? c - MOD : c); } 11 | inline modint operator - (modint other) const { int32_t c = this->value - other.value; return modint(c < 0 ? c + MOD : c); } 12 | inline modint operator * (modint other) const { int32_t c = (int64_t)this->value * other.value % MOD; return modint(c < 0 ? c + MOD : c); } 13 | inline modint & operator += (modint other) { this->value += other.value; if (this->value >= MOD) this->value -= MOD; return *this; } 14 | inline modint & operator -= (modint other) { this->value -= other.value; if (this->value < 0) this->value += MOD; return *this; } 15 | inline modint & operator *= (modint other) { this->value = (int64_t)this->value * other.value % MOD; if (this->value < 0) this->value += MOD; return *this; } 16 | inline modint operator - () const { return modint(this->value ? MOD - this->value : 0); } 17 | modint pow(uint64_t k) const { modint x = *this, y = 1; for (; k; k >>= 1) { if (k & 1) y *= x; x *= x; } return y; } 18 | modint inv() const { return pow(MOD - 2); } // MOD must be a prime 19 | inline modint operator / (modint other) const { return *this * other.inv(); } 20 | inline modint operator /= (modint other) { return *this *= other.inv(); } 21 | inline bool operator == (modint other) const { return value == other.value; } 22 | inline bool operator != (modint other) const { return value != other.value; } 23 | inline bool operator < (modint other) const { return value < other.value; } 24 | inline bool operator > (modint other) const { return value > other.value; } 25 | }; 26 | template modint operator * (int64_t value, modint n) { return modint(value) * n; } 27 | template modint operator * (int32_t value, modint n) { return modint(value % MOD) * n; } 28 | template istream & operator >> (istream & in, modint &n) { return in >> n.value; } 29 | template ostream & operator << (ostream & out, modint n) { return out << n.value; } 30 | 31 | using mint = modint; 32 | -------------------------------------------------------------------------------- /geometry/KDTree.cpp: -------------------------------------------------------------------------------- 1 | // KD-tree for 2D points 2 | // - nearest neighbor search 3 | // - farthest point search 4 | // O(N log N) build, O(log N) query 5 | // Reference: Kctl (nearest) & Tweaked with ChatGpt for farthest point 6 | // Farthest is stress tested against brute force 7 | 8 | #include "Point.hpp" 9 | 10 | typedef Point P; 11 | 12 | const double INF = 1e18; 13 | 14 | bool on_x(const P& a, const P& b) { return a.x < b.x; } 15 | bool on_y(const P& a, const P& b) { return a.y < b.y; } 16 | 17 | struct Node { 18 | typedef double T; 19 | P pt; 20 | T x0 = INF, x1 = -INF, y0 = INF, y1 = -INF; 21 | Node *first = 0, *second = 0; 22 | 23 | T distance(const P& p) { 24 | T x = (p.x < x0 ? x0 : p.x > x1 ? x1 : p.x); 25 | T y = (p.y < y0 ? y0 : p.y > y1 ? y1 : p.y); 26 | return (P(x,y) - p).dist2(); 27 | } 28 | 29 | T maxDistance(const P& p) { 30 | T dx = max(abs(p.x - x0), abs(p.x - x1)); 31 | T dy = max(abs(p.y - y0), abs(p.y - y1)); 32 | return dx*dx + dy*dy; 33 | } 34 | 35 | Node(vector

&& vp) : pt(vp[0]) { 36 | for (P p : vp) { 37 | x0 = min(x0, p.x); x1 = max(x1, p.x); 38 | y0 = min(y0, p.y); y1 = max(y1, p.y); 39 | } 40 | if (vp.size() > 1) { 41 | sort(ALL(vp), x1 - x0 >= y1 - y0 ? on_x : on_y); 42 | int half = SZ(vp)/2; 43 | first = new Node({vp.begin(), vp.begin() + half}); 44 | second = new Node({vp.begin() + half, vp.end()}); 45 | } 46 | } 47 | }; 48 | 49 | struct KDTree { 50 | typedef double T; 51 | Node* root; 52 | KDTree(const vector

& vp) : root(new Node({ALL(vp)})) {} 53 | 54 | pair search(Node *node, const P& p) { 55 | if (!node->first) 56 | return {(p - node->pt).dist2(), node->pt}; 57 | 58 | Node *f = node->first, *s = node->second; 59 | T bfirst = f->distance(p), bsec = s->distance(p); 60 | if (bfirst > bsec) swap(bsec, bfirst), swap(f, s); 61 | 62 | auto best = search(f, p); 63 | if (bsec < best.first) 64 | best = min(best, search(s, p)); 65 | return best; 66 | } 67 | 68 | pair nearest(const P& p) { return search(root, p); } 69 | 70 | pair searchFarthest(Node *node, const P& p) { 71 | if (!node->first) 72 | return {(p - node->pt).dist2(), node->pt}; 73 | 74 | Node *f = node->first, *s = node->second; 75 | T bfirst = f->maxDistance(p), bsec = s->maxDistance(p); 76 | if (bfirst < bsec) swap(bsec, bfirst), swap(f, s); // search larger side first 77 | 78 | auto best = searchFarthest(f, p); 79 | if (bsec > best.first) 80 | best = max(best, searchFarthest(s, p)); 81 | return best; 82 | } 83 | 84 | pair farthest(const P& p) { return searchFarthest(root, p); } 85 | }; 86 | -------------------------------------------------------------------------------- /NumberTheory.cpp: -------------------------------------------------------------------------------- 1 | // Modular Arithmetic 2 | const int MOD = (1e9 + 7); 3 | 4 | int power(int a, int b, int c=MOD) { 5 | int res = 1; 6 | a %= c; 7 | while (b) { 8 | if (b&1) res = (res * a) % c; 9 | a = (a * a) % c; 10 | b >>= 1; 11 | } 12 | return res; 13 | } 14 | int inv(int a) { return power(a, MOD-2); } 15 | int addMod(int a, int b) { return ((a%MOD + b%MOD) % MOD + MOD) % MOD; } 16 | int subMod(int a, int b) { return addMod(a, -b); } 17 | int multMod(int a, int b) { return ((a%MOD * b%MOD) % MOD + MOD) % MOD; } 18 | int divMod(int a, int b) { return multMod(a, inv(b)); } 19 | 20 | // Sieve 21 | bitset<(int)1e6> SIEVE; 22 | void preSieve() { 23 | SIEVE[0]=SIEVE[1]=1; 24 | for (int i = 2; i*i < 1e6; i++) { 25 | if (!SIEVE[i]) { 26 | for (int j=i*i; j < 1e6; j+=i) { 27 | SIEVE[j]=1; 28 | } 29 | } 30 | } 31 | } 32 | 33 | // Prime factorization 34 | vector v(1e7+1); // v[i] = smallest prime factor of i 35 | void prePrimeFact() { 36 | for (int i = 0; i <= 1e7; i++) v[i] = i; 37 | for (int i = 2; i <= 1e7; i++) { 38 | if (v[i] != i) continue ; 39 | for (int j = i*i; j <= 1e7; j += i) { 40 | if (v[j]==j) v[j] = i; 41 | } 42 | } 43 | } 44 | vector primeFact(int n) { // with precalc - O(log) 45 | vector fct; 46 | while (n != 1) { 47 | int i = v[n]; 48 | while (n % i == 0) 49 | n /= i; 50 | fct.push_back(i); 51 | } 52 | return fct; 53 | } 54 | vector prime_fact(int n) { // without precalc - O(sqrt) 55 | vector ret; 56 | for (int i = 2; i*i <= n; i++) { 57 | if (n%i == 0) { 58 | ret.push_back(i); 59 | while (n%i == 0) 60 | n /= i; 61 | } 62 | } 63 | if (n > 1) ret.push_back(n); 64 | return ret; 65 | } 66 | 67 | // Factorial and Binomial Coefficient (n choose k) 68 | const int MAXN = 2e5 + 5; 69 | int fact[MAXN], ifact[MAXN]; 70 | void preFact() { 71 | fact[0] = ifact[0] = 1; 72 | for (int i = 1; i < MAXN; i++) { 73 | fact[i] = (fact[i-1] * i) % MOD; 74 | ifact[i] = (ifact[i-1] * inv(i)) % MOD; 75 | } 76 | } 77 | int nCk(int n, int k) { // (n choose k) 78 | return k > n? 0: (fact[n] * ((ifact[n-k] * ifact[k]) % MOD)) % MOD; 79 | } 80 | 81 | // Euler's totient function 82 | // a^phi(m) = 1 [modulo m] if a and m are coprimes 83 | int phi(int x) { 84 | int res = x; 85 | for (int i = 2; i*i <= x; i++) { 86 | if (x%i == 0) { 87 | while (x%i == 0) x /= i; 88 | res -= res / i; 89 | } 90 | } 91 | if (x > 1) res -= res / x; 92 | return res; 93 | } 94 | 95 | // phi preprocessing from 1 to n 96 | const int MAXN = 1e6 + 5; 97 | int PHI[MAXN]; 98 | void prePhi() { 99 | for (int i=0; i < MAXN; i++) PHI[i] = i; 100 | for (int i = 2; i < MAXN; i++) { 101 | if (PHI[i] == i) { 102 | for (int j = i; j < MAXN; j += i) { 103 | PHI[j] -= PHI[j] / i; 104 | } 105 | } 106 | } 107 | } 108 | 109 | int inv(int a, int m) { 110 | return power(a, PHI[m]-1, m); // or phi(m)-1 depends if m is big or no ! 111 | } 112 | -------------------------------------------------------------------------------- /Mo.cpp: -------------------------------------------------------------------------------- 1 | // CP Algorithms template 2 | void remove(idx); // TODO: remove value at idx from data structure 3 | void add(idx); // TODO: add value at idx from data structure 4 | int get_answer(); // TODO: extract the current answer of the data structure 5 | 6 | int block_size; 7 | 8 | struct Query { 9 | int l, r, idx; 10 | bool operator<(Query other) const 11 | { 12 | return make_pair(l / block_size, r) < 13 | make_pair(other.l / block_size, other.r); 14 | } 15 | }; 16 | 17 | vector mo_s_algorithm(vector queries) { 18 | vector answers(queries.size()); 19 | sort(queries.begin(), queries.end()); 20 | 21 | // TODO: initialize data structure 22 | 23 | int cur_l = 0; 24 | int cur_r = -1; 25 | // invariant: data structure will always reflect the range [cur_l, cur_r] 26 | for (Query q : queries) { 27 | while (cur_l > q.l) { 28 | cur_l--; 29 | add(cur_l); 30 | } 31 | while (cur_r < q.r) { 32 | cur_r++; 33 | add(cur_r); 34 | } 35 | while (cur_l < q.l) { 36 | remove(cur_l); 37 | cur_l++; 38 | } 39 | while (cur_r > q.r) { 40 | remove(cur_r); 41 | cur_r--; 42 | } 43 | answers[q.idx] = get_answer(); 44 | } 45 | return answers; 46 | } 47 | 48 | //////////////////////////////////////////////////////// 49 | // CP Algorithms template tweaked as nested functions // 50 | //////////////////////////////////////////////////////// 51 | int N = 1e5 + 10; 52 | int block_size = sqrt(N); 53 | 54 | struct Query { 55 | int l, r, idx; 56 | bool operator<(const Query &other) const 57 | { 58 | return make_tuple(l / block_size, r) < 59 | make_tuple(other.l / block_size, other.r); 60 | } 61 | }; 62 | 63 | // my usual solve function 64 | void solve() { 65 | int n, q; cin >> n >> q; 66 | block_size = sqrt(n); 67 | 68 | vector queries(q); 69 | vector answers(q); 70 | 71 | // TODO: remove value at idx from data structure 72 | function remove = [&](int idx) { 73 | }; 74 | 75 | // TODO: add value at idx from data structure 76 | function add = [&](int idx) { 77 | }; 78 | 79 | // TODO: extract the current answer of the data structure 80 | function get_answer = [&]() { 81 | return 1; 82 | }; 83 | 84 | 85 | function mos_algorithm = [&]() { 86 | sort(queries.begin(), queries.end()); 87 | 88 | // TODO: initialize data structure 89 | 90 | int cur_l = 0; 91 | int cur_r = -1; 92 | // invariant: data structure will always reflect the range [cur_l, cur_r] 93 | for (Query q : queries) { 94 | while (cur_l > q.l) { 95 | cur_l--; 96 | add(cur_l); 97 | } 98 | while (cur_r < q.r) { 99 | cur_r++; 100 | add(cur_r); 101 | } 102 | while (cur_l < q.l) { 103 | remove(cur_l); 104 | cur_l++; 105 | } 106 | while (cur_r > q.r) { 107 | remove(cur_r); 108 | cur_r--; 109 | } 110 | answers[q.idx] = get_answer(); 111 | } 112 | }; 113 | 114 | mos_algorithm(); 115 | } 116 | -------------------------------------------------------------------------------- /BiTrie.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Memory optimized version 3 | // src: AI generated based on the original source code 4 | // USAGE: Trie trie(n * Trie::B + 5); 5 | struct Trie { 6 | static const int B = 31; 7 | int sz = 1; 8 | struct node { 9 | int32_t nxt[2]; 10 | int sz; 11 | node() { 12 | nxt[0] = nxt[1] = 0; 13 | sz = 0; 14 | } 15 | }; 16 | vector data; 17 | int new_node() { 18 | return ++sz; 19 | } 20 | Trie(int mxSz) { 21 | data.assign(mxSz, node()); 22 | sz = 1; 23 | } 24 | void insert(int val) { 25 | int curr = 1; 26 | data[curr].sz++; 27 | for (int i = B - 1; i >= 0; i--) { 28 | int b = val >> i & 1; 29 | if (data[curr].nxt[b] == 0) data[curr].nxt[b] = new_node(); 30 | curr = data[curr].nxt[b]; 31 | data[curr].sz++; 32 | } 33 | } 34 | void erase(int val) { 35 | if (get_min(val) != 0) return; // Value not present in Trie 36 | int curr = 1; 37 | data[curr].sz--; // Decrement root size 38 | for (int i = B - 1; i >= 0; i--) { 39 | int b = val >> i & 1; 40 | int nxt_node = data[curr].nxt[b]; 41 | data[nxt_node].sz--; 42 | if (data[nxt_node].sz == 0) { 43 | data[curr].nxt[b] = 0; // Disconnect the branch 44 | return; 45 | } 46 | curr = nxt_node; 47 | } 48 | } 49 | int query(int x, int k) { // number of values s.t. val ^ x < k 50 | int cur = 1; 51 | int ans = 0; 52 | for (int i = B - 1; i >= 0; i--) { 53 | if (cur == 0) break; 54 | int b1 = x >> i & 1, b2 = k >> i & 1; 55 | if (b2 == 1) { 56 | if (data[cur].nxt[b1]) ans += data[data[cur].nxt[b1]].sz; 57 | cur = data[cur].nxt[!b1]; 58 | } else cur = data[cur].nxt[b1]; 59 | } 60 | return ans; 61 | } 62 | // Returns maximum of val ^ x 63 | int get_max(int x) { 64 | int curr = 1; 65 | int ans = 0; 66 | for (int i = B - 1; i >= 0; i--) { 67 | int k = x >> i & 1; 68 | if (data[curr].nxt[!k]) { 69 | curr = data[curr].nxt[!k]; 70 | ans <<= 1; 71 | ans++; 72 | } else { 73 | curr = data[curr].nxt[k]; 74 | ans <<= 1; 75 | } 76 | } 77 | return ans; 78 | } 79 | // Returns minimum of val ^ x 80 | int get_min(int x) { 81 | int curr = 1; 82 | int ans = 0; 83 | for (int i = B - 1; i >= 0; i--) { 84 | int k = x >> i & 1; 85 | if (data[curr].nxt[k]) { 86 | curr = data[curr].nxt[k]; 87 | ans <<= 1; 88 | } else { 89 | curr = data[curr].nxt[!k]; 90 | ans <<= 1; 91 | ans++; 92 | } 93 | } 94 | return ans; 95 | } 96 | }; 97 | 98 | // src: https://github.com/ShahjalalShohag/code-library/blob/main/Data%20Structures/Trie.cpp 99 | struct Trie { 100 | static const int B = 31; 101 | struct node { 102 | node* nxt[2]; 103 | int sz; 104 | node() { 105 | nxt[0] = nxt[1] = NULL; 106 | sz = 0; 107 | } 108 | } *root; 109 | Trie() { 110 | root = new node(); 111 | } 112 | void insert(int val) { 113 | node* cur = root; 114 | cur -> sz++; 115 | for (int i = B - 1; i >= 0; i--) { 116 | int b = val >> i & 1; 117 | if (cur -> nxt[b] == NULL) cur -> nxt[b] = new node(); 118 | cur = cur -> nxt[b]; 119 | cur -> sz++; 120 | } 121 | } 122 | void erase(int val) { 123 | if (get_min(val)) return ; // value not present 124 | node *cur = root; 125 | cur -> sz--; 126 | for (int i = B - 1; i >= 0; i--) { 127 | int b = val >> i & 1; 128 | node* nxtNode = cur -> nxt[b]; 129 | nxtNode -> sz--; 130 | if (nxtNode -> sz == 0) { 131 | cur -> nxt[b] = NULL; 132 | del(nxtNode); 133 | return; 134 | } 135 | cur = nxtNode; 136 | } 137 | } 138 | int query(int x, int k) { // number of values s.t. val ^ x < k 139 | node* cur = root; 140 | int ans = 0; 141 | for (int i = B - 1; i >= 0; i--) { 142 | if (cur == NULL) break; 143 | int b1 = x >> i & 1, b2 = k >> i & 1; 144 | if (b2 == 1) { 145 | if (cur -> nxt[b1]) ans += cur -> nxt[b1] -> sz; 146 | cur = cur -> nxt[!b1]; 147 | } else cur = cur -> nxt[b1]; 148 | } 149 | return ans; 150 | } 151 | int get_max(int x) { // returns maximum of val ^ x 152 | node* cur = root; 153 | int ans = 0; 154 | for (int i = B - 1; i >= 0; i--) { 155 | int k = x >> i & 1; 156 | if (cur -> nxt[!k]) cur = cur -> nxt[!k], ans <<= 1, ans++; 157 | else cur = cur -> nxt[k], ans <<= 1; 158 | } 159 | return ans; 160 | } 161 | int get_min(int x) { // returns minimum of val ^ x 162 | node* cur = root; 163 | int ans = 0; 164 | for (int i = B - 1; i >= 0; i--) { 165 | int k = x >> i & 1; 166 | if (cur -> nxt[k]) cur = cur -> nxt[k], ans <<= 1; 167 | else cur = cur -> nxt[!k], ans <<= 1, ans++; 168 | } 169 | return ans; 170 | } 171 | void del(node* cur) { 172 | for (int i = 0; i < 2; i++) if (cur -> nxt[i]) del(cur -> nxt[i]); 173 | delete(cur); 174 | } 175 | ~Trie() { del(root); } 176 | }; 177 | -------------------------------------------------------------------------------- /SegmentTree.cpp: -------------------------------------------------------------------------------- 1 | // from kactl 2 | struct SegTree { 3 | typedef int T; 4 | static const T identity = 0; 5 | T fn(T a, T b) { return a + b; } // (any associative fn) 6 | vector s; int n; 7 | SegTree(int n = 0, T def = identity) : s(2*n, def), n(n) {} 8 | SegTree(vector &a) : s(2*a.size()), n(a.size()) { 9 | for (int i = 0; i < n; i++) update(i, a[i]); 10 | } 11 | void update(int pos, T val) { 12 | for (s[pos += n] = val; pos /= 2;) 13 | s[pos] = fn(s[pos * 2], s[pos * 2 + 1]); 14 | } 15 | T query(int b, int e) { // query [b, e] 16 | T ra = identity, rb = identity; e++; 17 | for (b += n, e += n; b < e; b /= 2, e /= 2) { 18 | if (b % 2) ra = fn(ra, s[b++]); 19 | if (e % 2) rb = fn(s[--e], rb); 20 | } 21 | return fn(ra, rb); 22 | } 23 | }; 24 | 25 | 26 | // seg tree recursive implementation 27 | struct Tree { 28 | typedef int T; 29 | static constexpr T identity = 0; 30 | int n; 31 | vector tree; 32 | 33 | T fn(T a, T b) { return a + b; } 34 | 35 | Tree(vector &a) { 36 | n = a.size(); 37 | tree.resize(4 * n); 38 | build(1, 0, n - 1, a); 39 | } 40 | 41 | Tree(int n): n(n) { 42 | tree.assign(4 * n, identity); 43 | } 44 | 45 | void build(int idx, int l, int r, vector &a) { 46 | if (l == r) { 47 | tree[idx] = a[l]; 48 | return ; 49 | } 50 | int mid = (l+r) / 2; 51 | build(idx * 2, l, mid, a); 52 | build(idx * 2 + 1, mid+1, r, a); 53 | tree[idx] = fn(tree[2*idx],tree[2*idx+1]); 54 | } 55 | 56 | void update(int idx, int l, int r, int pos, T val) { 57 | if (l == r) { 58 | tree[idx] = val; 59 | return ; 60 | } 61 | if (pos < l || pos > r) return ; 62 | int mid = (l+r)/2; 63 | update(idx*2, l, mid, pos, val); 64 | update(idx*2+1, mid+1, r, pos, val); 65 | tree[idx] = fn(tree[2*idx], tree[2*idx+1]); 66 | } 67 | 68 | void update(int pos, T val) { 69 | return update(1, 0, n-1, pos, val); 70 | } 71 | 72 | T query(int idx, int l, int r, int ql, int qr) { 73 | if (ql <= l && r <= qr) { 74 | return tree[idx]; 75 | } 76 | if (l > qr || r < ql) { 77 | return identity; 78 | } 79 | int mid = (l + r) / 2; 80 | return fn(query(2*idx, l, mid, ql, qr), query(2*idx+1, mid+1, r, ql, qr)); 81 | } 82 | 83 | T query(int l, int r) { 84 | return query(1, 0, n-1, l, r); 85 | } 86 | }; 87 | 88 | 89 | // from https://github.com/jalalium/cpTemplates 90 | class SegTree2d { 91 | int lenx; 92 | int leny; 93 | vector> all; 94 | vector> seg; 95 | static const int identity = 0; 96 | int fn(int a, int b) {return a + b;} 97 | public: 98 | SegTree2d(){} 99 | SegTree2d(vector> inp) { 100 | lenx = inp.size(); 101 | leny = inp[0].size(); 102 | all = inp; 103 | seg.resize(4 *lenx); 104 | for (int i = 0; i < 4*lenx; i++) 105 | seg[i].resize(4*leny); 106 | buildx(1,1,0,lenx-1,0,leny-1); 107 | } 108 | // rows range: [lx , rx] 109 | // columns range: [ly , ry] 110 | int query(int lx,int rx,int ly,int ry) { 111 | return queryx(1,0,lenx-1,lx,rx,ly,ry); 112 | } 113 | // Update (x, y) 114 | void update(int x,int y, int val) { 115 | updatex(1,0,lenx-1,x,y,val); 116 | } 117 | int query(pair a, pair b) { 118 | return query(a.first, b.first, a.second, b.second); 119 | } 120 | private: 121 | void buildy(int idx, int idy, int lx, int rx, int ly, int ry) 122 | { 123 | if (ly==ry) 124 | { 125 | if (lx == rx) 126 | seg[idx][idy]= all[lx][ly]; 127 | else 128 | seg[idx][idy] = fn(seg[2*idx][idy] , seg[2*idx+1][idy]); 129 | } 130 | else 131 | { 132 | int midy=(ly+ry)/2; 133 | buildy(idx,2*idy,lx,rx,ly,midy); 134 | buildy(idx,2*idy+1,lx,rx,midy+1,ry); 135 | seg[idx][idy] = fn(seg[idx][2*idy], seg[idx][2*idy+1]); 136 | } 137 | } 138 | void buildx(int idx, int idy, int lx, int rx, int ly, int ry) 139 | { 140 | if (lx != rx) 141 | { 142 | int midx = (lx+rx)/2; 143 | buildx(2*idx,idy,lx,midx,ly,ry); 144 | buildx(2*idx+1,idy,midx+1,rx,ly,ry); 145 | } 146 | buildy(idx,idy,lx,rx,ly,ry); 147 | } 148 | int queryy(int idx, int idy, int tly,int tryy, int ly,int ry) 149 | { 150 | if (tly > ry || tryy < ly) 151 | return identity; 152 | if (tly >= ly && tryy <= ry) 153 | return seg[idx][idy]; 154 | int tmy = (tly+tryy)/2; 155 | return fn(queryy(idx,2*idy,tly,tmy,ly,ry), queryy(idx,2*idy+1,tmy+1,tryy,ly,ry)); 156 | } 157 | int queryx(int idx, int tlx,int trx, int lx,int rx,int ly,int ry) 158 | { 159 | if (tlx > rx || trx= lx && trx <= rx) 162 | return queryy(idx,1,0,leny-1,ly,ry); 163 | int tmx=(tlx+trx)/2; 164 | return fn(queryx(2*idx,tlx,tmx,lx,rx,ly,ry), queryx(2*idx+1,tmx+1,trx,lx,rx,ly,ry)); 165 | } 166 | void updatey(int idx, int tlx, int trx, int idy, int tly, int tryy, int y, int val) 167 | { 168 | if (tly == tryy) 169 | { 170 | if (tlx == trx) 171 | seg[idx][idy]=val; 172 | else 173 | seg[idx][idy] = fn(seg[2*idx][idy], seg[2*idx+1][idy]); 174 | } 175 | else 176 | { 177 | int tmy=(tly+tryy)/2; 178 | if (y <= tmy) 179 | updatey(idx,tlx,trx,2*idy,tly,tmy,y,val); 180 | else 181 | updatey(idx,tlx,trx,2*idy+1,tmy+1,tryy,y,val); 182 | seg[idx][idy] = fn(seg[idx][2*idy], seg[idx][2*idy+1]); 183 | } 184 | } 185 | void updatex(int idx, int tlx, int trx, int x, int y, int val) 186 | { 187 | if (tlx != trx) 188 | { 189 | int tmx = (tlx+trx)/2; 190 | if (x <= tmx) 191 | updatex(2*idx,tlx,tmx,x,y,val); 192 | else 193 | updatex(2*idx+1,tmx+1,trx,x,y,val); 194 | } 195 | updatey(idx, tlx, trx,1,0,leny-1,y, val); 196 | } 197 | }; 198 | 199 | -------------------------------------------------------------------------------- /PersistentTrie.cpp: -------------------------------------------------------------------------------- 1 | // Generated using Gemini 3 Pro 2 | // Tested in: https://www.codechef.com/problems/XRQRS 3 | struct PersistentTrie { 4 | static const int B = 31; 5 | 6 | // Memory pools 7 | vector ch[2]; 8 | vector sz; 9 | vector roots; 10 | 11 | PersistentTrie(int MX_UPDATES = 0) { 12 | if (MX_UPDATES) { 13 | // Reserve memory to prevent frequent reallocations 14 | ch[0].reserve(B * MX_UPDATES + 100); 15 | ch[1].reserve(B * MX_UPDATES + 100); 16 | sz.reserve(B * MX_UPDATES + 100); 17 | roots.reserve(MX_UPDATES + 100); 18 | } 19 | 20 | // Create the "null" node at index 0. 21 | // Important: ch[0][0] = 0 and ch[1][0] = 0 implies null points to null. 22 | ch[0].push_back(0); 23 | ch[1].push_back(0); 24 | sz.push_back(0); 25 | 26 | // Version 0 is an empty trie rooted at null node (0) 27 | roots.push_back(0); 28 | } 29 | 30 | int get_latest_version() const { 31 | return roots.size() - 1; 32 | } 33 | 34 | int copy_node(int src) { 35 | int left = ch[0][src]; 36 | int right = ch[1][src]; 37 | int s = sz[src]; 38 | 39 | ch[0].push_back(left); 40 | ch[1].push_back(right); 41 | sz.push_back(s); 42 | return sz.size() - 1; 43 | } 44 | 45 | int update(int prev_node, int val, int bit, int delta) { 46 | int cur = copy_node(prev_node); 47 | sz[cur] += delta; 48 | 49 | if (bit < 0) return cur; 50 | 51 | int b = (val >> bit) & 1; 52 | 53 | // Calculate the new child index FIRST. 54 | // If we did ch[b][cur] = update(...), the LHS reference could become invalid 55 | // if update() causes a vector resize. 56 | int child_node = update(ch[b][prev_node], val, bit - 1, delta); 57 | ch[b][cur] = child_node; 58 | 59 | return cur; 60 | } 61 | 62 | // Insert creates a NEW version based on version v 63 | int insert(int val, int v = -1) { 64 | if (v == -1) v = get_latest_version(); 65 | int new_root = update(roots[v], val, B - 1, 1); 66 | roots.push_back(new_root); 67 | return roots.size() - 1; 68 | } 69 | 70 | // Erase creates a NEW version based on version v 71 | void erase(int val, int v = -1) { 72 | if (v == -1) v = get_latest_version(); 73 | 74 | // If val doesn't exist, just duplicate the root to keep version indexing aligned 75 | if (query(val, 1, v) == 0) { 76 | roots.push_back(roots[v]); 77 | return; 78 | } 79 | 80 | int new_root = update(roots[v], val, B - 1, -1); 81 | roots.push_back(new_root); 82 | } 83 | 84 | // Count values in version 'v' such that (val ^ x) < k 85 | int query(int x, int k, int v) { 86 | int cur = roots[v]; 87 | int ans = 0; 88 | for (int i = B - 1; i >= 0; i--) { 89 | if (cur == 0 || sz[cur] == 0) break; 90 | 91 | int b1 = (x >> i) & 1; 92 | int b2 = (k >> i) & 1; 93 | 94 | if (b2 == 1) { 95 | // k has bit 1. 96 | // 1. Same direction (b1): XOR is 0. 0 < 1. All valid. 97 | int same = ch[b1][cur]; 98 | if (same) ans += sz[same]; 99 | 100 | // 2. Opp direction (!b1): XOR is 1. 1 !< 1. Check deeper. 101 | cur = ch[!b1][cur]; 102 | } else { 103 | // k has bit 0. 104 | // Must take path ensuring XOR bit is 0 (same direction b1). 105 | cur = ch[b1][cur]; 106 | } 107 | } 108 | return ans; 109 | } 110 | 111 | // Returns maximum of val ^ x in version 'v' 112 | int get_max(int x, int v) { 113 | int cur = roots[v]; 114 | if (cur == 0 || sz[cur] == 0) return 0; 115 | 116 | int ans = 0; 117 | for (int i = B - 1; i >= 0; i--) { 118 | int k = (x >> i) & 1; 119 | // Try opposite direction !k to maximize XOR 120 | int desired = ch[!k][cur]; 121 | if (desired && sz[desired] > 0) { 122 | cur = desired; 123 | ans += (1 << i); 124 | } else { 125 | cur = ch[k][cur]; 126 | } 127 | } 128 | return ans; 129 | } 130 | 131 | // Returns minimum of val ^ x in version 'v' 132 | int get_min(int x, int v) { 133 | int cur = roots[v]; 134 | if (cur == 0 || sz[cur] == 0) return 0; 135 | 136 | int ans = 0; 137 | for (int i = B - 1; i >= 0; i--) { 138 | int k = (x >> i) & 1; 139 | // Try same direction k to minimize XOR 140 | int desired = ch[k][cur]; 141 | if (desired && sz[desired] > 0) { 142 | cur = desired; 143 | } else { 144 | cur = ch[!k][cur]; 145 | ans += (1 << i); 146 | } 147 | } 148 | return ans; 149 | } 150 | 151 | // Count values inserted between version vl and vr such that (val ^ x) < k 152 | int range_query(int vl, int vr, int x, int k) { 153 | int curL = (vl == -1) ? 0 : roots[vl]; 154 | int curR = roots[vr]; 155 | 156 | int ans = 0; 157 | for (int i = B - 1; i >= 0; i--) { 158 | int cntR = (curR == 0) ? 0 : sz[curR]; 159 | int cntL = (curL == 0) ? 0 : sz[curL]; 160 | if (cntR - cntL <= 0) break; 161 | 162 | int b1 = (x >> i) & 1; 163 | int b2 = (k >> i) & 1; 164 | 165 | if (b2 == 1) { 166 | int childL = (curL == 0) ? 0 : ch[b1][curL]; 167 | int childR = (curR == 0) ? 0 : ch[b1][curR]; 168 | 169 | int cR = childR ? sz[childR] : 0; 170 | int cL = childL ? sz[childL] : 0; 171 | ans += (cR - cL); 172 | 173 | curL = (curL == 0) ? 0 : ch[!b1][curL]; 174 | curR = (curR == 0) ? 0 : ch[!b1][curR]; 175 | } else { 176 | curL = (curL == 0) ? 0 : ch[b1][curL]; 177 | curR = (curR == 0) ? 0 : ch[b1][curR]; 178 | } 179 | } 180 | return ans; 181 | } 182 | 183 | // Get max XOR with x using values inserted between version vl and vr 184 | int get_range_max(int vl, int vr, int x) { 185 | int curL = (vl == -1) ? 0 : roots[vl]; 186 | int curR = roots[vr]; 187 | 188 | // Safety check if range is empty 189 | int totL = (curL == 0) ? 0 : sz[curL]; 190 | int totR = (curR == 0) ? 0 : sz[curR]; 191 | if (totR - totL <= 0) return 0; 192 | 193 | int ans = 0; 194 | for (int i = B - 1; i >= 0; i--) { 195 | int k = (x >> i) & 1; 196 | 197 | // Try opposite direction !k 198 | int desiredL = (curL == 0) ? 0 : ch[!k][curL]; 199 | int desiredR = (curR == 0) ? 0 : ch[!k][curR]; 200 | 201 | int cR = desiredR ? sz[desiredR] : 0; 202 | int cL = desiredL ? sz[desiredL] : 0; 203 | 204 | if (cR - cL > 0) { 205 | curR = desiredR; 206 | curL = desiredL; 207 | ans |= (1 << i); 208 | } else { 209 | curL = (curL == 0) ? 0 : ch[k][curL]; 210 | curR = (curR == 0) ? 0 : ch[k][curR]; 211 | } 212 | } 213 | return ans; 214 | } 215 | 216 | // Get min XOR with x using values inserted between version vl and vr 217 | int get_range_min(int vl, int vr, int x) { 218 | int curL = (vl == -1) ? 0 : roots[vl]; 219 | int curR = roots[vr]; 220 | 221 | int totL = (curL == 0) ? 0 : sz[curL]; 222 | int totR = (curR == 0) ? 0 : sz[curR]; 223 | if (totR - totL <= 0) return 0; 224 | 225 | int ans = 0; 226 | for (int i = B - 1; i >= 0; i--) { 227 | int k = (x >> i) & 1; 228 | 229 | // Try SAME direction k 230 | int desiredL = (curL == 0) ? 0 : ch[k][curL]; 231 | int desiredR = (curR == 0) ? 0 : ch[k][curR]; 232 | 233 | int cR = desiredR ? sz[desiredR] : 0; 234 | int cL = desiredL ? sz[desiredL] : 0; 235 | 236 | if (cR - cL > 0) { 237 | curR = desiredR; 238 | curL = desiredL; 239 | } else { 240 | curL = (curL == 0) ? 0 : ch[!k][curL]; 241 | curR = (curR == 0) ? 0 : ch[!k][curR]; 242 | ans |= (1 << i); 243 | } 244 | } 245 | return ans; 246 | } 247 | }; 248 | --------------------------------------------------------------------------------