├── gcd.cpp ├── compress.cpp ├── dsu.cpp ├── bfs.cpp ├── prefix_function.cpp ├── z_function.cpp ├── sparse.cpp ├── kuhn.cpp ├── cnk.cpp ├── hashmap.cpp ├── checker.py ├── fenwick.cpp ├── dijkstra.cpp ├── geometry.cpp ├── radix_sort.cpp ├── palindromic_tree.cpp ├── alcotree.cpp ├── lca.cpp ├── gauss.cpp ├── centroid.cpp ├── segtree.cpp ├── manacher.cpp ├── segtree_dynamic.cpp ├── README.md ├── maxflow_ffa.cpp ├── aho_corasick.cpp ├── suffix_array.cpp ├── fft.cpp ├── treap.cpp ├── mincost_maxflow.cpp ├── dp_dnc.cpp ├── persistent_treap.cpp ├── burnside.cpp ├── suffix_automaton.cpp └── hld.cpp /gcd.cpp: -------------------------------------------------------------------------------- 1 | int gcd (int a, int b, int &x, int &y) { 2 | if (a == 0) { 3 | x = 0, y = 1; 4 | return b; 5 | } 6 | int _x, _y, d = gcd(b%a, a, _x, _y); 7 | x = _y-(b/a)*_x, y = _y; 8 | return d; 9 | } 10 | -------------------------------------------------------------------------------- /compress.cpp: -------------------------------------------------------------------------------- 1 | vector compress (vector a) { 2 | vector b = a; 3 | sort(b.begin(), b.end()); 4 | b.erase(unique(b.begin(), b.end()), b.end()); 5 | for (int &x : a) 6 | x = int(lower_bound(b.begin(), b.end(), x) - b.begin()); 7 | return a; 8 | } 9 | -------------------------------------------------------------------------------- /dsu.cpp: -------------------------------------------------------------------------------- 1 | int _p[maxn], s[maxn]; 2 | 3 | int p (int v) { return (_p[v] == v) ? v : _p[v] = p(_p[v]); } 4 | 5 | void unite (int a, int b) { 6 | a = p(a), b = p(b); 7 | if (s[a] > s[b]) swap(a, b); 8 | s[b] += s[a]; 9 | _p[a] = b; 10 | } 11 | 12 | for (int i = 0; i < n; i++) 13 | _p[i] = i; 14 | -------------------------------------------------------------------------------- /bfs.cpp: -------------------------------------------------------------------------------- 1 | vector bfs (int s) { 2 | vector d(n, -1); 3 | d[s] = 0; 4 | queue q; 5 | q.push(s); 6 | while (q.size()) { 7 | int v = q.front(); 8 | q.pop(); 9 | for (int u : g[v]) 10 | if (d[u] == -1) 11 | d[u] = d[v]+1, q.push(u); 12 | } 13 | return d; 14 | } 15 | -------------------------------------------------------------------------------- /prefix_function.cpp: -------------------------------------------------------------------------------- 1 | vector z_function (string s) { 2 | int n = (int) s.size(); 3 | vector p(n, 0); 4 | for (int i = 1; i < n; i++) { 5 | int cur = p[i - 1]; 6 | while (s[i] != s[cur] && cur > 0) 7 | cur = p[cur - 1]; 8 | if (s[i] == s[cur]) 9 | p[i] = cur + 1; 10 | } 11 | return p; 12 | } 13 | -------------------------------------------------------------------------------- /z_function.cpp: -------------------------------------------------------------------------------- 1 | vector z_function (string s) { 2 | int n = (int) s.size(); 3 | vector z(n, 0); 4 | int l = 0, r = 0; 5 | for (int i = 1; i < n; i++) { 6 | if (i <= r) z[i] = min(r-i+1, z[i-l]); 7 | while (i+z[i] < n && s[z[i]] == s[i+z[i]]) z[i]++; 8 | if (i+z[i]-1 > r) r = i+z[i]-1, l = i; 9 | } 10 | return z; 11 | } 12 | -------------------------------------------------------------------------------- /sparse.cpp: -------------------------------------------------------------------------------- 1 | const int maxn = 1e6, logn = 20; 2 | 3 | int a[maxn], lg[maxn], mx[maxn][logn]; 4 | 5 | int rmq (int l, int r) { 6 | int t = lg[r-l+1]; 7 | return max(mx[l][t], mx[r-(1<= 0; i--) { 15 | mx[i][0] = a[i]; 16 | for (int l = 0; l < logn-1; l++) 17 | mx[i][l+1] = max(mx[i][l], mx[i+(1< g[maxn]; 4 | int mt[maxn]; 5 | bool used[maxn]; 6 | 7 | bool kuhn (int v) { 8 | if (used[v]) return 0; 9 | used[v] = 1; 10 | for (int u : g[v]) { 11 | if (mt[u] == -1 || kuhn(mt[u])) { 12 | mt[u] = v; 13 | return 1; 14 | } 15 | } 16 | return 0; 17 | } 18 | 19 | memset(mt, -1, sizeof(mt)); 20 | for (int i = 0; i < n; i++) { 21 | memset(used, 0, sizeof(mt)); 22 | if (kuhn(i)) cnt++; 23 | } 24 | -------------------------------------------------------------------------------- /cnk.cpp: -------------------------------------------------------------------------------- 1 | int t[maxn]; 2 | 3 | int bp (int a, int n) { 4 | int ans = 1; 5 | while (n) { 6 | if (n&1) ans = ans*a % mod; 7 | a = a*a % mod; 8 | n >>= 1; 9 | } 10 | return ans; 11 | } 12 | 13 | int inv (int x) { 14 | return bp(x, mod-2); 15 | } 16 | 17 | int c (int n, int k) { 18 | return t[n]*inv(t[k]) % mod * inv(t[n-k]) % mod; 19 | } 20 | 21 | int d (int n, int k) { 22 | return c(n+k-1, k-1); 23 | } 24 | 25 | t[0] = 1; 26 | for (int i = 1; i < maxn; i++) 27 | t[i] = i*t[i-1] % mod; 28 | -------------------------------------------------------------------------------- /hashmap.cpp: -------------------------------------------------------------------------------- 1 | struct hashmap { 2 | const int size = (1<<24); 3 | int a[size] = {-1}, b[size]; 4 | 5 | static inline int h (int x) { return (x^179)*7; } 6 | 7 | void add (int x, int y) { 8 | int k = h(x) % size; 9 | while (a[k] != -1 && a[k] != x) 10 | k = (k+1) % size; 11 | a[k] = x, b[k] = y; 12 | } 13 | 14 | int get (int x) { 15 | for (int k = h(x) % size; a[k] != -1; k = (k+1) % size) 16 | if (a[k] == x) 17 | return b[k]; 18 | return -1; 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /checker.py: -------------------------------------------------------------------------------- 1 | from os import popen 2 | from random import randint, choice, uniform 3 | 4 | def gen(): 5 | n = randint(3, 5) 6 | # ... 7 | return test 8 | 9 | for i in range(100): 10 | print i 11 | f = open('test.txt', 'w') 12 | test = gen() 13 | f.write(test) 14 | f.close() 15 | v1 = popen('./stupid < test.txt').read() 16 | v2 = popen('./run < test.txt').read() 17 | if v1 != v2: 18 | print "TEST" 19 | print test 20 | print "GOOD" 21 | print v1 22 | print "BAD" 23 | print v2 24 | break 25 | -------------------------------------------------------------------------------- /fenwick.cpp: -------------------------------------------------------------------------------- 1 | struct fenwick { 2 | int n; 3 | vector t; 4 | fenwick (int _n) { 5 | n = _n; 6 | t.assign(n, 0); 7 | } 8 | int sum (int r) { 9 | int ans = 0; 10 | while (r >= 0) { 11 | ans += t[r]; 12 | r = (r & (r+1)) - 1; 13 | } 14 | return ans; 15 | } 16 | int sum (int l, int r) { 17 | return sum(r) - sum(l-1); 18 | } 19 | void add (int k, int x) { 20 | while (k < n) { 21 | t[k] += x; 22 | k = k | (k+1); 23 | } 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /dijkstra.cpp: -------------------------------------------------------------------------------- 1 | const int inf = 1e9; 2 | 3 | vector dijkstra(int s) { 4 | set< pair > q; 5 | q.insert({0, s}); 6 | vector d(n, inf); 7 | d[root] = 0; 8 | while (q.size()) { 9 | int v = q.begin()->second; 10 | q.erase(q.begin()); 11 | for (auto e : g[v]) { 12 | int u = e.first, w = e.second; 13 | if (d[u] > d[v] + w) { 14 | q.erase({d[u], u}); 15 | d[u] = d[v] + w; 16 | q.insert({d[u], u}); 17 | } 18 | } 19 | } 20 | return d; 21 | } 22 | -------------------------------------------------------------------------------- /geometry.cpp: -------------------------------------------------------------------------------- 1 | struct r { 2 | int x, y; 3 | r () {} 4 | r (int _x, int _y) { x = _x, y = _y; } 5 | }; 6 | 7 | r operator+ (r a, r b) { return r(a.x+b.x, a.y+b.y); } 8 | r operator- (r a, r b) { return r(a.x-b.x, a.y-b.y); } 9 | 10 | istream& operator>> (istream &in, r &p) { 11 | in >> p.x >> p.y; 12 | return in; 13 | } 14 | 15 | ostream& operator<< (ostream &out, r &p) { 16 | out << p.x << " " << p.y << "\n"; 17 | return out; 18 | } 19 | 20 | int operator* (r a, r b) { return a.x*b.x + a.y*b.y; } 21 | int operator^ (r a, r b) { return a.x*b.y - b.x*a.y; } 22 | -------------------------------------------------------------------------------- /radix_sort.cpp: -------------------------------------------------------------------------------- 1 | const int c = (1<<16); 2 | 3 | void csort (vector &a) { 4 | int n = (int) a.size(); 5 | vector b[c]; 6 | for (int i = 0; i < n; i++) 7 | b[a[i]%c].push_back(a[i]); 8 | int k = 0; 9 | for (int i = 0; i < c; i++) { 10 | for (size_t j = 0; j < b[i].size(); j++) 11 | a[k++] = b[i][j]; 12 | b[i].clear(); 13 | } 14 | for (int i = 0; i < n; i++) 15 | b[a[i]/c].push_back(a[i]); 16 | k = 0; 17 | for (int i = 0; i < c; i++) 18 | for (size_t j = 0; j < b[i].size(); j++) 19 | a[k++] = b[i][j]; 20 | } 21 | -------------------------------------------------------------------------------- /palindromic_tree.cpp: -------------------------------------------------------------------------------- 1 | const int maxn = 1e5, k = 26; 2 | 3 | int s[maxn], len[maxn], link[maxn], to[maxn][k]; 4 | 5 | int n, last, sz; 6 | 7 | void init () { 8 | s[n++] = -1; 9 | link[0] = 1; 10 | len[1] = -1; 11 | sz = 2; 12 | } 13 | 14 | int get_link (int v) { 15 | while (s[n-len[v]-2] != s[n-1]) v = link[v]; 16 | return v; 17 | } 18 | 19 | void add_letter (int c) { 20 | s[n++] = c; 21 | last = get_link(last); 22 | if (!to[last][c]) { 23 | len[sz] = len[last] + 2; 24 | link[sz] = to[get_link(link[last])][c]; 25 | to[last][c] = sz++; 26 | } 27 | last = to[last][c]; 28 | } 29 | -------------------------------------------------------------------------------- /alcotree.cpp: -------------------------------------------------------------------------------- 1 | const int maxn = 1e5; 2 | int t[2*maxn]; 3 | 4 | int n; 5 | 6 | void build () { 7 | for (int i = n-1; i > 0; i--) 8 | t[i] = max(t[i<<1], t[i<<1|1]); 9 | } 10 | 11 | void upd (int k, int x) { 12 | k += n; 13 | t[k] = x; 14 | while (k > 1) { 15 | t[k>>1] = max(t[k], t[k^1]); 16 | k >>= 1; 17 | } 18 | } 19 | 20 | int rmq (int l, int r) { 21 | int ans = 0; 22 | l += n, r += n; 23 | while (l <= r) { 24 | if (l&1) 25 | ans = max(ans, t[l++]); 26 | if (!(r&1)) 27 | ans = max(ans, t[r--]); 28 | l >>= 1, r >>= 1; 29 | } 30 | return ans; 31 | } 32 | -------------------------------------------------------------------------------- /lca.cpp: -------------------------------------------------------------------------------- 1 | const int maxn = 1e6, logn = 22; 2 | 3 | vector g[maxn]; 4 | int tin[maxn], tout[maxn]; 5 | int up[maxn][logn]; 6 | int t = 0; 7 | 8 | void dfs (int v) { 9 | for (int l = 1; l < logn; l++) 10 | up[v][l] = up[up[v][l-1]][l-1]; 11 | tin[v] = t++; 12 | for (int u : g[v]) { 13 | up[u][0] = v; 14 | dfs(u); 15 | } 16 | tout[v] = t++; 17 | } 18 | 19 | int a (int v, int u) { 20 | return tin[v] <= tin[u] && tin[u] <= tout[v]; 21 | } 22 | 23 | int lca (int v, int u) { 24 | if (a(v, u)) return v; 25 | if (a(u, v)) return u; 26 | for (int l = logn-1; l >= 0; l--) 27 | if ( !a(up[v][l], u) ) 28 | v = up[v][l]; 29 | return up[v][0]; 30 | } 31 | -------------------------------------------------------------------------------- /gauss.cpp: -------------------------------------------------------------------------------- 1 | typedef vector< vector > matrix; 2 | 3 | vector gauss (matrix a) { 4 | int n = (int) a.size(); 5 | for (int i = 0; i < n; i++) { 6 | int best = i; 7 | for (int j = i+1; j < n; j++) 8 | if (a[j][i] > a[best][i]) 9 | best = j; 10 | swap(a[best], a[i]); 11 | for (int j = n; j >= i; j--) 12 | a[i][j] /= a[i][i]; 13 | for (int j = 0; j < n; j++) 14 | if (j != i) 15 | for (int k = n; k >= i; k--) 16 | a[j][k] -= a[i][k]*a[j][i]; 17 | } 18 | vector ans(n); 19 | for (int i = 0; i < n; i++) 20 | ans[i] = a[i][n] / a[i][i]; 21 | return ans; 22 | } 23 | -------------------------------------------------------------------------------- /centroid.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int maxn = 1e5; 5 | vector g[maxn]; 6 | bool used[maxn]; 7 | int s[maxn]; 8 | 9 | void size (int v, int p = -1) { 10 | s[v] = 1; 11 | for (int u : g[v]) 12 | if (u != p && !used[u]) 13 | size(u, v), s[v] += s[u]; 14 | } 15 | 16 | int centroid (int v, int p, int n) { 17 | for (int u : g[v]) 18 | if (u != p && s[u] > n/2) 19 | return centroid(u, v, n); 20 | return v; 21 | } 22 | 23 | void solve (int v) { 24 | sizes(v); 25 | 26 | /* ... */ 27 | 28 | used[v] = 1; 29 | for (int u : g[v]) 30 | if (!used[u]) 31 | solve(centroid(u, v, s[u])); 32 | } 33 | 34 | int main () { 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /segtree.cpp: -------------------------------------------------------------------------------- 1 | struct segtree { 2 | int lb, rb; 3 | int sum = 0; 4 | segtree *l, *r; 5 | segtree (int _lb, int _rb) { 6 | lb = _lb, rb = _rb; 7 | if (lb != rb) { 8 | int t = (lb + rb) / 2; 9 | l = new segtree(lb, t); 10 | r = new segtree(t+1, rb); 11 | } 12 | } 13 | void add (int k, int x) { 14 | sum += x; 15 | if (lb != rb) { 16 | int t = (lb + rb) / 2; 17 | if (k <= t) l->add(k, x); 18 | else r->add(k, x); 19 | } 20 | } 21 | int get_sum (int lq, int rq) { 22 | if (lb >= lq && rb <= rq) return sum; 23 | if (lb > rq || rb < lq) return 0; 24 | return l->get_sum(lq, rq) + r->get_sum(lq, rq); 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /manacher.cpp: -------------------------------------------------------------------------------- 1 | vector manacher_odd (string s) { 2 | int n = (int) s.size(); 3 | vector d(n, 1); 4 | int l = 0, r = 0; 5 | for (int i = 1; i < n; i++) { 6 | if (i < r) d[i] = min(r-i+1, d[l+r-i]); 7 | while (i-d[i] >= 0 && i+d[i] < n && s[i-d[i]] == s[i+d[i]]) d[i]++; 8 | if (i+d[i]-1 > r) l = i-d[i]+1, r = i+d[i]-1; 9 | } 10 | return d; 11 | } 12 | 13 | vector manacher_even (string s) { 14 | int n = (int) s.size(); 15 | vector d(n, 0); 16 | int l = -1, r = -1; 17 | for (int i = 0; i < n-1; i++) { 18 | if (i < r) d[i] = min(r-i, d[l+r-i-1]); 19 | while (i-d[i] >= 0 && i+d[i]+1 < n && s[i-d[i]] == s[i+d[i]+1]) d[i]++; 20 | if (i+d[i] > r) l = i-d[i]+1, r = i+d[i]; 21 | } 22 | return d; 23 | } 24 | -------------------------------------------------------------------------------- /segtree_dynamic.cpp: -------------------------------------------------------------------------------- 1 | struct segtree { 2 | int lb, rb; 3 | int sum = 0; 4 | segtree *l = 0, *r = 0; 5 | segtree (int _lb, int _rb) { 6 | lb = _lb, rb = _rb; 7 | } 8 | void extend () { 9 | int t = (lb + rb) / 2; 10 | if (!l) { 11 | l = new segtree(lb, t); 12 | r = new segtree(t+1, rb); 13 | } 14 | } 15 | void add (int k, int x) { 16 | sum += x; 17 | if (lb != rb) { 18 | extend(); 19 | int t = (lb + rb) / 2; 20 | if (k <= t) l->add(k, x); 21 | else r->add(k, x); 22 | } 23 | } 24 | int get_sum (int lq, int rq) { 25 | if (lb >= lq && rb <= rq) return sum; 26 | if (lb > rq || rb < lq) return 0; 27 | extend(); 28 | return l->get_sum(lq, rq) + r->get_sum(lq, rq); 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # algo 2 | The snippets you are asked to code way too often in competitive programming. 3 | 4 | Code is intentionally simplified (no references, templates, inheritance, try-catches or stuff like that) so that you do not need to read a 300 pages long book to understand it. You are supposed to just copy and paste it during contest with minimal changes. 5 | 6 | Use at your own risk. I am pretty sure it at least compiles, but may contain minor bugs. 7 | 8 | Pull requests are welcome, since I do not do contests so actively anymore. 9 | 10 | TODO: 11 | * convex hull (!) 12 | * half-plane intersection 13 | * dinic's algorithm 14 | * long arithmetic 15 | * bridge finding (!) 16 | * minimum spanning tree 17 | * sqrt decomposition (!!) 18 | * string hashing 19 | * kth element in O(n) 20 | * bitset Gauss, bitset matmul (!) 21 | * better FFT or fast Karatsuba 22 | * persiistent data structures (!!) 23 | * dynamic connectivity (!) 24 | -------------------------------------------------------------------------------- /maxflow_ffa.cpp: -------------------------------------------------------------------------------- 1 | const int maxn = 1e5, inf = 1e9; 2 | 3 | struct edge { 4 | int to, cap; 5 | }; 6 | 7 | vector g[maxn]; 8 | vector e; 9 | bool used[maxn]; 10 | 11 | void add_edge (int u, int v, int w) { 12 | g[u].push_back(e.size()); 13 | e.push_back({v, w}); 14 | g[v].push_back(e.size()); 15 | e.push_back({u, 0}); 16 | } 17 | 18 | int dfs (int v, int t, int flow) { 19 | if (v == t) return flow; 20 | used[v] = 1; 21 | for (int _e : g[v]) { 22 | int u = e[_e].to, w = e[_e].cap; 23 | if (!used[u] && w > 0) { 24 | if (int d = dfs(u, t, min(flow, w))) { 25 | e[_e].cap -= d; 26 | e[_e^1].cap += d; 27 | return d; 28 | } 29 | } 30 | } 31 | return 0; 32 | } 33 | 34 | int maxflow (int s, int t) { 35 | int flow = 0; 36 | while (int d = dfs(s, t, inf)) 37 | flow += d, memset(used, 0, sizeof(used)); 38 | return flow; 39 | } 40 | -------------------------------------------------------------------------------- /aho_corasick.cpp: -------------------------------------------------------------------------------- 1 | const int k = 26; 2 | 3 | struct Vertex { 4 | Vertex *to[k] = {0}, *go[k] = {0}; 5 | Vertex *link = 0, *p; 6 | int pch; 7 | Vertex (int _pch, Vertex *_p) { pch = _pch, p = _p; } 8 | }; 9 | 10 | Vertex *root = new Vertex(-1, 0); 11 | 12 | Vertex* go (Vertex *v, int c); 13 | 14 | Vertex* link (Vertex *v) { 15 | if (!v->link) { 16 | if (v == root || v->p == root) v->link = root; 17 | else v->link = go(link(v->p), v->pch); 18 | } 19 | return v->link; 20 | } 21 | 22 | Vertex* go (Vertex *v, int c) { 23 | if (!v->go[c]) { 24 | if (v->to[c]) v->go[c] = v->to[c]; 25 | else if (v == root) v->go[c] = root; 26 | else v->go[c] = go(link(v), c); 27 | } 28 | return v->go[c]; 29 | } 30 | 31 | void add_string (string s) { 32 | Vertex *v = root; 33 | for (char _c : s) { 34 | int c = int(_c-'a'); 35 | if (!v->to[c]) v->to[c] = new Vertex(c, v); 36 | v = v->to[c]; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /suffix_array.cpp: -------------------------------------------------------------------------------- 1 | vector suffix_array (vector s) { 2 | s.push_back(0); 3 | int n = (int) s.size(); 4 | int cnt = 0, cls = 0; 5 | vector c(n), p(n); 6 | map< int, vector > t; 7 | for (int i = 0; i < n; i++) 8 | t[s[i]].push_back(i); 9 | for (auto x : t) { 10 | for (int u : x.second) 11 | c[u] = cls, p[cnt++] = u; 12 | cls++; 13 | } 14 | for (int l = 1; cls < n; l++) { 15 | vector< vector > a(cls); 16 | vector _c(n); 17 | int d = (1<(p.begin()+1, p.end()); 34 | } 35 | -------------------------------------------------------------------------------- /fft.cpp: -------------------------------------------------------------------------------- 1 | typedef complex CC; 2 | double pi = acos(-1); 3 | 4 | void fft (vector &a, int k = 1) { 5 | int n = (int) a.size(); 6 | if (n == 1) return; 7 | vector a0(n/2), a1(n/2); 8 | for (int i = 0; i < n/2; i++) { 9 | a0[i] = a[2*i]; 10 | a1[i] = a[2*i+1]; 11 | } 12 | fft(a0, k); 13 | fft(a1, k); 14 | double ang = k*2*pi/n; 15 | CC w(1), wn(cos(ang), sin(ang)); 16 | for (int i = 0; i < n/2; i++) { 17 | a[i] = a0[i] + w*a1[i]; 18 | a[i+n/2] = a0[i] - w*a1[i]; 19 | w *= wn; 20 | } 21 | } 22 | 23 | vector multiply(vector a, vector b) { 24 | size_t n = 1; 25 | while (n < max(a.size(), b.size())) n *= 2; 26 | n *= 2; 27 | vector _a(a.begin(), a.end()), _b(b.begin(), b.end()); 28 | _a.resize(n), _b.resize(n); 29 | 30 | fft(_a); 31 | fft(_b); 32 | for (size_t i = 0; i < n; i++) 33 | _a[i] *= _b[i]; 34 | fft(_a, -1); 35 | for (size_t i = 0; i < n; i++) 36 | _a[i] = complex (_a[i].real()/(double)n, _a[i].imag()); 37 | 38 | vector ans(n); 39 | for (size_t i = 0; i < n; i++) 40 | ans[i] = _a[i].real(); 41 | return ans; 42 | } 43 | -------------------------------------------------------------------------------- /treap.cpp: -------------------------------------------------------------------------------- 1 | struct Node { 2 | int key, prior, size = 1; 3 | Node *l = 0, *r = 0; 4 | Node (int _key) { key = _key, prior = rand(); } 5 | }; 6 | 7 | int size (Node *v) { return v ? v->size : 0; } 8 | 9 | void upd (Node *v) { v->size = 1 + size(v->l) + size(v->r); } 10 | 11 | Node* merge (Node *l, Node *r) { 12 | if (!l) return r; 13 | if (!r) return l; 14 | if (l->prior > r->prior) { 15 | l->r = merge(l->r, r); 16 | upd(l); 17 | return l; 18 | } 19 | else { 20 | r->l = merge(l, r->l); 21 | upd(r); 22 | return r; 23 | } 24 | } 25 | 26 | typedef pair Pair; 27 | 28 | Pair split (Node *p, int x) { 29 | if (!p) return {0, 0}; 30 | if (size(p->l) + 1 <= x) { 31 | Pair q = split(p->r, x-size(p->l)-1); 32 | p->r = q.first; 33 | upd(p); 34 | return {p, q.second}; 35 | } 36 | else { 37 | Pair q = split(p->l, x); 38 | p->l = q.second; 39 | upd(p); 40 | return {q.first, p}; 41 | } 42 | } 43 | 44 | Node *root = 0; 45 | 46 | void insert (int x) { 47 | Pair q = split(root, x); 48 | Node *t = new Node(x); 49 | root = merge(q.first, merge(t, q.second)); 50 | } 51 | -------------------------------------------------------------------------------- /mincost_maxflow.cpp: -------------------------------------------------------------------------------- 1 | const int maxn = 305, inf = 1e9; 2 | 3 | int cost[maxn][maxn], cap[maxn][maxn]; 4 | int d[maxn], pot[maxn], par[maxn]; 5 | 6 | int n; 7 | 8 | bool dijkstra (int s, int t) { 9 | set< pair > q; 10 | q.insert({0, s}); 11 | 12 | for (int i = 0; i < n; i++) 13 | d[i] = inf; 14 | d[s] = 0; 15 | 16 | while (!q.empty()) { 17 | int v = q.begin()->second; 18 | q.erase(q.begin()); 19 | for (int u = 0; u < n; u++) { 20 | int w = cost[v][u] + pot[v] - pot[u]; 21 | if (cap[v][u] && d[u] > d[v] + w) { 22 | q.erase({d[u], u}); 23 | d[u] = d[v] + w; 24 | par[u] = v; 25 | q.insert({d[u], u}); 26 | } 27 | } 28 | } 29 | 30 | return (d[t] < inf); 31 | } 32 | 33 | int mincost (int s, int t) { 34 | int ans = 0; 35 | while (dijkstra(s, t)) { 36 | memcpy(pot, d, sizeof(d)); 37 | int delta = inf; 38 | for (int v = t; v != s; v = par[v]) 39 | delta = min(delta, cap[par[v]][v]); 40 | for (int v = t; v != s; v = par[v]) { 41 | cap[par[v]][v] -= delta; 42 | cap[v][par[v]] += delta; 43 | ans += cost[par[v]][v]*delta; 44 | } 45 | } 46 | return ans; 47 | } 48 | -------------------------------------------------------------------------------- /dp_dnc.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // CF 321E 5 | // dp[n][k] = min( s[n][r] + dp[r][k-1] ); 6 | 7 | const int maxn = 4005, inf = 1e9; 8 | 9 | int c[maxn][maxn], s[maxn][maxn], dp[maxn][maxn]; 10 | 11 | void f (int l, int r, int _l, int _r, int k) { 12 | if (l > r) return; 13 | int t = (l+r)/2; 14 | int w = _l; 15 | for (int i = max(t, _l); i <= _r; i++) { 16 | int val = c[t][i] + dp[i+1][k-1]; 17 | if (val < dp[t][k]) dp[t][k] = val, w = i; 18 | } 19 | f(l, t-1, _l, w, k); 20 | f(t+1, r, w, _r, k); 21 | } 22 | 23 | int main () { 24 | int n, k; 25 | cin >> n >> k; 26 | 27 | for (int i = 0; i < n; i++) { 28 | for (int j = 0; j < n; j++) { 29 | char t = getchar(); 30 | while (t < '0' || t > '9') t = getchar(); 31 | s[i][j+1] = t-'0'; 32 | s[i][j+1] += s[i][j]; 33 | } 34 | } 35 | 36 | for (int i = 0; i < n; i++) 37 | for (int j = 0; j <= k; j++) 38 | dp[i][j] = inf; 39 | 40 | for (int i = 0; i < n; i++) 41 | for (int j = i+1; j < n; j++) 42 | c[i][j] = c[i][j-1] + s[j][j] - s[j][i]; 43 | 44 | for (int i = 0; i < n; i++) 45 | dp[i][1] = c[i][n-1]; 46 | 47 | for (int i = 2; i <= k; i++) 48 | f(0, n-1, 0, n-1, i); 49 | 50 | cout << dp[0][k]; 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /persistent_treap.cpp: -------------------------------------------------------------------------------- 1 | // untested and not very memory-efficient 2 | 3 | struct Node { 4 | int key, size = 1; 5 | Node *l = 0, *r = 0; 6 | Node (int _key) { key = _key; } 7 | }; 8 | 9 | int size (Node *v) { return v ? v->size : 0; } 10 | 11 | void upd (Node *v) { v->size = 1 + size(v->l) + size(v->r); } 12 | 13 | Node* copy (Node *v) { return v ? new Node(*v) : 0; } 14 | 15 | Node* merge (Node *l, Node *r) { 16 | l = copy(l), r = copy(r); 17 | if (!l) return r; 18 | if (!r) return l; 19 | if (rand() % (size(l) + size(r)) < size(l)) { 20 | l->r = merge(l->r, r); 21 | upd(l); 22 | return l; 23 | } 24 | else { 25 | r->l = merge(l, r->l); 26 | upd(r); 27 | return r; 28 | } 29 | } 30 | 31 | typedef pair Pair; 32 | 33 | Pair split (Node *p, int x) { 34 | p = copy(p); 35 | if (!p) return {0, 0}; 36 | if (size(p->l) + 1 <= x) { 37 | Pair q = split(p->r, x-size(p->l)-1); 38 | p->r = q.first; 39 | upd(p); 40 | return {p, q.second}; 41 | } 42 | else { 43 | Pair q = split(p->l, x); 44 | p->l = q.second; 45 | upd(p); 46 | return {q.first, p}; 47 | } 48 | } 49 | 50 | Node *root = 0; 51 | 52 | void insert (int x) { 53 | Pair q = split(root, x); 54 | Node *t = new Node(x); 55 | root = merge(q.first, merge(t, q.second)); 56 | } 57 | -------------------------------------------------------------------------------- /burnside.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // computes number of cube colorings with k colors 5 | 6 | int binpow (int a, int n) { 7 | int ans = 1; 8 | while (n) { 9 | if (n&1) ans *= a; 10 | a *= a; 11 | n >>= 1; 12 | } 13 | return ans; 14 | } 15 | 16 | const int k = 3, n = 6; 17 | 18 | vector multiply (vector a, vector b) { 19 | vector ans(n); 20 | for (int i = 0; i < n; i++) 21 | ans[i] = a[b[i]]; 22 | return ans; 23 | } 24 | 25 | int cycles (vector a) { 26 | bool used[n] = {0}; 27 | int ans = 0; 28 | for (int i = 0; i < n; i++) { 29 | if (!used[i]) { 30 | ans++; 31 | int p = i; 32 | while (!used[p]) { 33 | used[p] = 1; 34 | p = a[p]; 35 | } 36 | } 37 | } 38 | return ans; 39 | } 40 | 41 | int main () { 42 | set< vector > s; 43 | s.insert({0, 1, 2, 3, 4, 5}); 44 | vector p1 = {0, 1, 3, 4, 5, 2}, 45 | p2 = {2, 4, 1, 3, 0, 5}; 46 | for (int l = 0; l < 6; l++) { 47 | set< vector > t = s;; 48 | for (auto p : t) 49 | s.insert(multiply(p, p1)), s.insert(multiply(p, p2)); 50 | } 51 | 52 | int ans = 0; 53 | 54 | for (auto p : s) 55 | ans += binpow(k, cycles(p)); 56 | 57 | cout << ans / s.size(); 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /suffix_automaton.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | struct Vertex { 5 | map to; 6 | Vertex *link = 0; 7 | int len = 0; 8 | }; 9 | 10 | int main () { 11 | 12 | int n; 13 | cin >> n; 14 | 15 | Vertex *root = new Vertex, *cur = root; 16 | 17 | vector< stack > length_ordered; 18 | 19 | while (n--) { 20 | int c; 21 | cin >> c; 22 | Vertex *v = cur; 23 | cur = new Vertex; 24 | cur->len = v->len+1; 25 | length_ordered[cur->len].push_back(cur); 26 | while (v && !v->to[c]) 27 | v->to[c] = cur, v = v->link; 28 | if (!v) 29 | cur->link = root; 30 | else if (v->to[c]->len == v->len+1) 31 | cur->link = v->to[c]; 32 | else { 33 | Vertex *u = v->to[c]; 34 | Vertex *clone = new Vertex; 35 | clone->to = u->to; 36 | clone->link = u->link; 37 | clone->len = v->len+1; 38 | length_ordered[clone->len].push_back(clone); 39 | while (v && v->to[c] == u) 40 | v->to[c] = clone, v = v->link; 41 | cur->link = u->link = clone; 42 | } 43 | } 44 | 45 | add_string(s); 46 | 47 | long long ans = 0; 48 | 49 | for (int i = n; i >= 1; i--) { 50 | ans = max(ans, 1ll * v->cnt * v->len); 51 | if (v->link) 52 | v->link->cnt += v->cnt; 53 | } 54 | 55 | cout << ans; 56 | 57 | 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /hld.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // Timus 1553 "Caves and Tunnels" 5 | // this implementation is actually bad 6 | // google adamant's blogs how to code it 7 | 8 | struct segtree { 9 | int lb, rb; 10 | int mx = 0; 11 | segtree *l, *r; 12 | segtree (int _lb, int _rb) { 13 | lb = _lb, rb = _rb; 14 | if (lb != rb) { 15 | int t = (lb + rb) / 2; 16 | l = new segtree(lb, t); 17 | r = new segtree(t+1, rb); 18 | } 19 | } 20 | void upd (int k, int x) { 21 | if (lb == rb) mx += x; 22 | else { 23 | int t = (lb + rb) / 2; 24 | if (k <= t) l->upd(k, x); 25 | else r->upd(k, x); 26 | mx = max(l->mx, r->mx); 27 | } 28 | } 29 | int get_mx (int lq, int rq) { 30 | if (lb >= lq && rb <= rq) return mx; 31 | else if (lb > rq || rb < lq) return 0; 32 | return max(l->get_mx(lq, rq), r->get_mx(lq, rq)); 33 | } 34 | }; 35 | 36 | const int maxn = 1e5; 37 | int p[maxn], head[maxn], d[maxn], s[maxn]; 38 | int tin[maxn], tout[maxn]; 39 | segtree* tree[maxn]; 40 | vector g[maxn]; 41 | int timer = 0; 42 | 43 | void dfs1 (int v) { 44 | tin[v] = timer++; 45 | s[v] = 1; 46 | for (int u : g[v]) { 47 | if (u != p[v]) { 48 | d[u] = d[v]+1; 49 | p[u] = v; 50 | dfs1(u); 51 | s[v] += s[u]; 52 | } 53 | } 54 | tout[v] = timer++; 55 | } 56 | 57 | void dfs2 (int v) { 58 | if (g[v].empty() || (g[v].size() == 1 && p[v] != -1)) 59 | tree[v] = new segtree(0, d[v] - d[head[v]]); 60 | else{ 61 | int mx = -1; 62 | for (int u : g[v]) 63 | if (u != p[v] && (mx == -1 || s[u] > s[mx])) 64 | mx = u; 65 | for (int u : g[v]) 66 | if (u != p[v] && u != mx) 67 | head[u] = u, dfs2(u); 68 | head[mx] = head[v]; 69 | dfs2(mx); 70 | tree[v] = tree[mx]; 71 | } 72 | } 73 | 74 | int dist (int v) { 75 | return d[v]-d[head[v]]; 76 | } 77 | 78 | bool ancestor (int v, int u) { 79 | return tin[v] <= tin[u] && tin[u] <= tout[v]; 80 | } 81 | 82 | int query (int v, int u) { 83 | int ans = 0; 84 | while (!ancestor(head[v], u)) { 85 | ans = max(ans, tree[v]->get_mx(0, dist(v))); 86 | v = p[head[v]]; 87 | } 88 | while (!ancestor(head[u], v)) { 89 | ans = max(ans, tree[u]->get_mx(0, dist(u))); 90 | u = p[head[u]]; 91 | } 92 | if (dist(u) < dist(v)) swap(u, v); 93 | ans = max(ans, tree[v]->get_mx(dist(v), dist(u))); 94 | return ans; 95 | } 96 | 97 | int main () { 98 | ios::sync_with_stdio(false); 99 | cin.tie(0); 100 | 101 | int n; 102 | cin >> n; 103 | for (int i = 0; i < n-1; i++) { 104 | int u, v; 105 | cin >> u >> v; 106 | u--, v--; 107 | g[u].push_back(v); 108 | g[v].push_back(u); 109 | } 110 | head[0] = 0, p[0] = -1, d[0] = 0; 111 | dfs1(0); 112 | dfs2(0); 113 | int q; 114 | cin >> q; 115 | while (q--) { 116 | char type; 117 | cin >> type; 118 | if (type == 'I') { 119 | int v, t; 120 | cin >> v >> t; 121 | v--; 122 | tree[v]->upd(dist(v), t); 123 | } 124 | else{ 125 | int u, v; 126 | cin >> u >> v; 127 | u--, v--; 128 | cout << query(u, v) << "\n"; 129 | } 130 | } 131 | 132 | return 0; 133 | } 134 | --------------------------------------------------------------------------------