├── Benchmarking utilities ├── benchmark.cpp └── description.txt ├── Binary Search ├── const_intervals.cpp ├── description.txt └── first_to_satisfy.cpp ├── Bump Allocator (Turning dynamic allocation into static allocation) ├── bump_allocator.cpp └── description.txt ├── Centroid Decomposition ├── centroid.cpp └── description.txt ├── Chinese Remainder Theorem ├── crt.cpp └── description.txt ├── Convex Hull Trick ├── convex_hull_trick.cpp └── description.txt ├── Coordinate Compression ├── coord comp.cpp └── description.txt ├── FFT ├── description.txt ├── fft.cpp ├── fftmod.cpp └── ntt.cpp ├── Fast IO ├── description.txt ├── read_float.cpp └── read_int.cpp ├── Gaussian Elimination ├── description.txt └── gauss.cpp ├── Geometry ├── base.cpp ├── circle.cpp ├── convex.cpp ├── description.txt ├── halfplane.cpp ├── polygon.cpp └── segment.cpp ├── LCA (Lowest Common Ancestor) ├── description.txt ├── lca binary lifting.cpp └── lca rmq.cpp ├── Linear Recurrence (Berlekamp Massey, K-th term) ├── BerlekampMassey.cpp ├── Kth-term.cpp └── description.txt ├── Longest Increasing Subsequence(LIS) ├── description.txt └── lis.cpp ├── Manacher (Finds the length of the longest odd and even palindromes centered on an index): O(N) ├── description.txt └── manacher.cpp ├── Matrix Exponentiation ├── description.txt └── matrixexpo.cpp ├── Max Flow (Dinic's, HLPP) ├── description.txt ├── dinic.cpp └── hlpp.cpp ├── Miller Rabin: primality test ├── description.txt └── millerabin.cpp ├── Min Cost Max Flow ├── bellman-ford.cpp └── description.txt ├── Minimum Rotation: O(N) ├── description.txt └── min_rotation.cpp ├── Mod Sum: sum_{i=0}^{to-1} (k*i+c)%m: log(m) with large constant ├── description.txt └── modsum.cpp ├── Number Theory Sieves ├── description.txt ├── mobius.cpp ├── primes.cpp ├── segmented sieve.cpp └── totient.cpp ├── Numerical Integration (Simpson's) ├── adaptive.cpp └── description.txt ├── Permutation Mapping: Permutations to └── from integers - order preserving │ ├── description.txt │ └── intperm.cpp ├── README.md ├── Random Snippets (Stuff that's not reusable but were painful to write that I wrote nicely and am happy with) ├── description.txt └── merging two paths on tree.cpp ├── SOS DP (Sum over Subsets DP) ├── description.txt └── sosdp.cpp ├── Segment tree ├── 2D BIT.cpp ├── 2D Seg.cpp ├── abstract.cpp ├── description.txt ├── dynamic.cpp ├── lazy propagation.cpp ├── pointer.cpp ├── range modify point query.cpp └── range query point modify (standard).cpp ├── Suffix Array ├── description.txt └── suffix_array.cpp ├── Treap ├── description.txt └── treap.cpp ├── Tree Diameter: O(N) ├── description.txt └── diameter.cpp └── get_gists.py /Benchmarking utilities/benchmark.cpp: -------------------------------------------------------------------------------- 1 | struct timeit { 2 | decltype(chrono::high_resolution_clock::now()) begin; 3 | const string label; 4 | timeit(string label = "???") : label(label) { begin = chrono::high_resolution_clock::now(); } 5 | ~timeit() { 6 | auto end = chrono::high_resolution_clock::now(); 7 | auto duration = chrono::duration_cast(end - begin).count(); 8 | cerr << duration << "ms elapsed [" << label << "]" << endl; 9 | } 10 | }; -------------------------------------------------------------------------------- /Benchmarking utilities/description.txt: -------------------------------------------------------------------------------- 1 | Benchmarking utilities 2 | -------------------------------------------------------------------------------- /Binary Search/const_intervals.cpp: -------------------------------------------------------------------------------- 1 | void rec(int from, int to, function f, int &i, int &p, int q, vector> &ints) { 2 | if (p == q) 3 | return; 4 | if (from == to) { 5 | ints.push_back({i, to, p}); 6 | i = to; 7 | p = q; 8 | } else { 9 | int mid = (from + to) >> 1; 10 | rec(from, mid, f, i, p, f(mid), ints); 11 | rec(mid + 1, to, f, i, p, q, ints); 12 | } 13 | } 14 | void constantIntervals(int from, int to, function f, vector> &ints) { 15 | if (to <= from) 16 | return; 17 | int i = from; 18 | int p = f(i), q = f(to - 1); 19 | rec(from, to - 1, f, i, p, q, ints); 20 | ints.push_back({i, to, q}); 21 | } -------------------------------------------------------------------------------- /Binary Search/description.txt: -------------------------------------------------------------------------------- 1 | Binary Search 2 | -------------------------------------------------------------------------------- /Binary Search/first_to_satisfy.cpp: -------------------------------------------------------------------------------- 1 | int binSearch(int l, int r) { 2 | int mid = (l+r)/2; 3 | if (l==r) return l; 4 | if (f(mid)) return binSearch(l, mid); 5 | else return binSearch(mid+1, r); 6 | } -------------------------------------------------------------------------------- /Bump Allocator (Turning dynamic allocation into static allocation)/bump_allocator.cpp: -------------------------------------------------------------------------------- 1 | static char buf[450 << 20]; 2 | void *operator new(size_t s) { 3 | static size_t i = sizeof buf; 4 | assert(s < i); 5 | return (void *)&buf[i -= s]; 6 | } 7 | void operator delete(void *) {} -------------------------------------------------------------------------------- /Bump Allocator (Turning dynamic allocation into static allocation)/description.txt: -------------------------------------------------------------------------------- 1 | Bump Allocator (Turning dynamic allocation into static allocation) 2 | -------------------------------------------------------------------------------- /Centroid Decomposition/centroid.cpp: -------------------------------------------------------------------------------- 1 | int sz[MAXN]; 2 | int cpar[MAXN]; 3 | bool dead[MAXN]; 4 | int sizedfs(int cur, int p) { 5 | sz[cur] = 1; 6 | for (auto i : adj[cur]) { 7 | if (i != p && !dead[i]) 8 | sz[cur] += sizedfs(i, cur); 9 | } 10 | return sz[cur]; 11 | } 12 | int getCentroid(int cur, int p, int n) { 13 | for (auto i : adj[cur]) { 14 | if (i != p && !dead[i] && sz[i] > n / 2) 15 | return getCentroid(i, cur, n); 16 | } 17 | return cur; 18 | } 19 | void decompose(int cur, int p) { 20 | sizedfs(cur, cur); 21 | int centr = getCentroid(cur, cur, sz[cur]); 22 | cpar[centr] = p; 23 | dead[centr] = true; 24 | for (auto i : adj[centr]) { 25 | if (!dead[i] && i != p) 26 | decompose(i, centr); 27 | }; 28 | } -------------------------------------------------------------------------------- /Centroid Decomposition/description.txt: -------------------------------------------------------------------------------- 1 | Centroid Decomposition 2 | -------------------------------------------------------------------------------- /Chinese Remainder Theorem/crt.cpp: -------------------------------------------------------------------------------- 1 | ll chinese(ll a, ll m, ll b, ll n) { //x = a %m, x = b%n, gcd(m,n)=1 2 | ll x, y; 3 | euclid(m, n, x, y); 4 | ll ret = a * (y + m) % m * n + b * (x + n) % n * m; 5 | if (ret >= m * n) 6 | ret -= m * n; 7 | return ret; 8 | } 9 | ll chinese_common(ll a, ll m, ll b, ll n) { // gcd(m,n) != 1 10 | ll d = __gcd(m, n); 11 | if (((b -= a) %= n) < 0) 12 | b += n; 13 | if (b % d) 14 | return -1; // No solution 15 | return d * chinese(ll(0), m / d, b / d, n / d) + a; 16 | } -------------------------------------------------------------------------------- /Chinese Remainder Theorem/description.txt: -------------------------------------------------------------------------------- 1 | Chinese Remainder Theorem 2 | -------------------------------------------------------------------------------- /Convex Hull Trick/convex_hull_trick.cpp: -------------------------------------------------------------------------------- 1 | struct Line { 2 | mutable ll m, b, p; 3 | bool operator<(const Line &o) const { return m < o.m; } 4 | bool operator<(const ll &x) const { return p < x; } 5 | }; 6 | 7 | struct LineContainer : multiset> { // upper convex hull. 8 | // (for doubles, use inf = 1/.0, div(a,b) = a/b) 9 | const ll inf = LLONG_MAX; 10 | ll div(ll a, ll b) { return a / b - ((a ^ b) < 0 && a % b); } 11 | bool isect(iterator x, iterator y) { 12 | if (y == end()) { 13 | x->p = inf; 14 | return false; 15 | } 16 | if (x->m == y->m) 17 | x->p = x->b > y->b ? inf : -inf; 18 | else 19 | x->p = div(y->b - x->b, x->m - y->m); 20 | return x->p >= y->p; 21 | } 22 | void add(ll m, ll b) { 23 | auto z = insert({m, b, 0}), y = z++, x = y; 24 | while (isect(y, z)) 25 | z = erase(z); 26 | if (x != begin() && isect(--x, y)) 27 | isect(x, y = erase(y)); 28 | while ((y = x) != begin() && (--x)->p >= y->p) 29 | isect(x, erase(y)); 30 | } 31 | ll query(ll x) { 32 | assert(!empty()); 33 | auto l = *lower_bound(x); 34 | return l.m * x + l.b; 35 | } 36 | }; -------------------------------------------------------------------------------- /Convex Hull Trick/description.txt: -------------------------------------------------------------------------------- 1 | Convex Hull Trick 2 | -------------------------------------------------------------------------------- /Coordinate Compression/coord comp.cpp: -------------------------------------------------------------------------------- 1 | map comp, decomp; 2 | int A[]; 3 | // insert everything into map; 4 | for (int i=0; i struct FFT { 2 | constexpr static int lg2(int n) { return 32 - __builtin_clz(n - 1); } 3 | const static int MAXN = 1 << lg2(maxn); 4 | typedef complex cpx; 5 | int rev[MAXN]; 6 | cpx rt[MAXN]; 7 | FFT() { 8 | rt[1] = cpx{1, 0}; 9 | for (int k = 2; k < MAXN; k *= 2) { 10 | cpx z[] = {1, polar(1.0, M_PI / k)}; 11 | for (int i = k; i < 2 * k; i++) 12 | rt[i] = rt[i / 2] * z[i & 1]; 13 | } 14 | } 15 | void fft(cpx *a, int n) { 16 | for (int i = 0; i < n; i++) 17 | rev[i] = (rev[i / 2] | (i & 1) << lg2(n)) / 2; 18 | for (int i = 0; i < n; i++) 19 | if (i < rev[i]) 20 | swap(a[i], a[rev[i]]); 21 | for (int k = 1; k < n; k *= 2) 22 | for (int i = 0; i < n; i += 2 * k) 23 | for (int j = 0; j < k; j++) { 24 | auto x = (double *)&rt[j + k], y = (double *)&a[i + j + k]; 25 | cpx z(x[0] * y[0] - x[1] * y[1], x[0] * y[1] + x[1] * y[0]); 26 | a[i + j + k] = a[i + j] - z; 27 | a[i + j] += z; 28 | } 29 | } 30 | 31 | cpx in[MAXN], out[MAXN]; 32 | vector multiply(const vector &a, const vector &b) { 33 | int n = 1 << lg2(a.size() + b.size() - 1); 34 | fill(in, in + n, cpx{0, 0}), fill(out, out + n, cpx{0, 0}); 35 | copy(a.begin(), a.end(), begin(in)); 36 | for (int i = 0; i < b.size(); i++) 37 | in[i].imag(b[i]); 38 | fft(in, n); 39 | for (int i = 0; i < n; i++) 40 | in[i] *= in[i]; 41 | for (int i = 0; i < n; i++) 42 | out[i] = in[(n - i) & (n - 1)] - conj(in[i]); 43 | fft(out, n); 44 | vector res(n); 45 | for (int i = 0; i < n; i++) 46 | res[i] = out[i].imag() / (4 * n); 47 | return res; 48 | } 49 | }; -------------------------------------------------------------------------------- /FFT/fftmod.cpp: -------------------------------------------------------------------------------- 1 | template struct FFTMod { 2 | constexpr static int lg2(int n) { return 32 - __builtin_clz(n - 1); } 3 | const static int MAXN = 1 << lg2(maxn); 4 | typedef complex cpx; 5 | int rev[MAXN]; 6 | cpx rt[MAXN]; 7 | FFTMod() { 8 | rt[1] = cpx{1, 0}; 9 | for (int k = 2; k < MAXN; k *= 2) { 10 | cpx z[] = {1, polar(1.0, M_PI / k)}; 11 | for (int i = k; i < 2 * k; i++) 12 | rt[i] = rt[i / 2] * z[i & 1]; 13 | } 14 | } 15 | void fft(cpx *a, int n) { 16 | for (int i = 0; i < n; i++) 17 | rev[i] = (rev[i / 2] | (i & 1) << lg2(n)) / 2; 18 | for (int i = 0; i < n; i++) 19 | if (i < rev[i]) 20 | swap(a[i], a[rev[i]]); 21 | for (int k = 1; k < n; k *= 2) 22 | for (int i = 0; i < n; i += 2 * k) 23 | for (int j = 0; j < k; j++) { 24 | auto x = (double *)&rt[j + k], y = (double *)&a[i + j + k]; 25 | cpx z(x[0] * y[0] - x[1] * y[1], x[0] * y[1] + x[1] * y[0]); 26 | a[i + j + k] = a[i + j] - z; 27 | a[i + j] += z; 28 | } 29 | } 30 | 31 | cpx in[2][MAXN], out[2][MAXN]; 32 | vector multiply(const vector &a, const vector &b) { 33 | int cut = sqrt(MOD); 34 | int n = 1 << lg2(a.size() + b.size()-1); 35 | fill(in[0], in[0] + n, cpx{0, 0}), fill(in[1], in[1] + n, cpx{0, 0}); 36 | for (int i = 0; i < a.size(); i++) 37 | in[0][i] = {a[i] / cut, a[i] % cut}; 38 | for (int i = 0; i < b.size(); i++) 39 | in[1][i] = {b[i] / cut, b[i] % cut}; 40 | fft(in[0], n), fft(in[1], n); 41 | for (int i = 0; i < n; i++) { 42 | int j = (n - i) & (n - 1); 43 | cpx fl = (in[0][i] + conj(in[0][j])) * cpx{0.5, 0}, fs = (in[0][i] - conj(in[0][j])) * cpx{0, -0.5}, 44 | gl = (in[1][i] + conj(in[1][j])) * cpx{0.5, 0}, gs = (in[1][i] - conj(in[1][j])) * cpx{0, -0.5}; 45 | out[0][i] = (fl * gl) + (fl * gs) * cpx{0, 1}; 46 | out[1][i] = (fs * gl) + (fs * gs) * cpx{0, 1}; 47 | } 48 | reverse(out[0] + 1, out[0] + n), reverse(out[1] + 1, out[1] + n); 49 | fft(out[0], n), fft(out[1], n); 50 | for (int i = 0; i < n; i++) 51 | out[0][i] /= n, out[1][i] /= n; 52 | vector res(n); 53 | for (int i = 0; i < n; i++) { 54 | ll av = round(out[0][i].real()); 55 | ll bv = round(out[0][i].imag()) + round(out[1][i].real()); 56 | ll cv = round(out[1][i].imag()); 57 | av %= MOD, bv %= MOD, cv %= MOD; 58 | res[i] = av * cut * cut + bv * cut + cv; 59 | res[i] = (res[i] % MOD + MOD) % MOD; 60 | } 61 | return vector(res.begin(), res.end()); 62 | } 63 | }; -------------------------------------------------------------------------------- /FFT/ntt.cpp: -------------------------------------------------------------------------------- 1 | template struct NTT { 2 | constexpr static int lg2(int n) { return 32 - __builtin_clz(n - 1); } 3 | const static int MAXN = 1 << lg2(maxn); 4 | const static int MOD = 998244353; 5 | const static int root = 3; 6 | int rev[MAXN], rt[MAXN]; 7 | 8 | inline int mul(const int a, const int b) { return (long long)a * b % MOD; } 9 | inline int sub(const int a, const int b) { return b > a ? a - b + MOD : a - b; } 10 | inline int add(const int a, const int b) { return a + b >= MOD ? a + b - MOD : a + b; } 11 | 12 | int binExp(int base, long long exp) { 13 | if (exp == 0) 14 | return 1; 15 | return mul(binExp(mul(base, base), exp / 2), exp & 1 ? base : 1); 16 | } 17 | NTT() { 18 | int curL = (MOD - 1) >> 2; 19 | rt[1] = 1; 20 | for (int k = 2; k < MAXN; k *= 2) { 21 | int z = binExp(root, curL); 22 | curL >>= 1; 23 | for (int i = k / 2; i < k; i++) { 24 | rt[2 * i] = rt[i], rt[2 * i + 1] = mul(rt[i], z); 25 | } 26 | } 27 | } 28 | void ntt(int *a, int n) { 29 | for (int i = 0; i < n; i++) 30 | rev[i] = (rev[i / 2] | (i & 1) << lg2(n)) / 2; 31 | for (int i = 0; i < n; i++) 32 | if (i < rev[i]) 33 | swap(a[i], a[rev[i]]); 34 | for (int k = 1; k < n; k *= 2) 35 | for (int i = 0; i < n; i += 2 * k) 36 | for (int j = 0; j < k; j++) { 37 | int z = mul(rt[j + k], a[i + j + k]); 38 | a[i + j + k] = sub(a[i + j], z); 39 | a[i + j] = add(a[i + j], z); 40 | } 41 | } 42 | int in[2][MAXN]; 43 | vector multiply(const vector &a, const vector &b) { 44 | int n = 1 << lg2(a.size() + b.size()-1); 45 | copy(a.begin(), a.end(), in[0]), copy(b.begin(), b.end(), in[1]); 46 | ntt(in[0], n), ntt(in[1], n); 47 | int invN = binExp(n, MOD - 2); 48 | for (int i = 0; i < n; i++) 49 | in[0][i] = mul(mul(in[0][i], in[1][i]), invN); 50 | reverse(in[0] + 1, in[0] + n); 51 | ntt(in[0], n); 52 | return vector(begin(in[0]), end(in[0])); 53 | } 54 | }; -------------------------------------------------------------------------------- /Fast IO/description.txt: -------------------------------------------------------------------------------- 1 | Fast IO 2 | -------------------------------------------------------------------------------- /Fast IO/read_float.cpp: -------------------------------------------------------------------------------- 1 | char gc() { 2 | #ifdef _WIN32 3 | return _getchar_nolock(); 4 | #else 5 | return getchar_unlocked(); 6 | #endif 7 | } 8 | void read_float() {} 9 | template inline void read_float(T &a, S &... b) { 10 | int c, s = 1, fp = 0, fpl = 1; 11 | while (isspace(c = gc())); 12 | if (c == '-') s = -1, c = gc(); 13 | for (a = c - '0'; isdigit(c = gc()); a = a * 10 + c - '0'); 14 | a *= s; 15 | if (c == '.') 16 | for (; isdigit(c = gc()); fp = fp * 10 + c - '0', fpl *= 10); 17 | a += (double)fp / fpl; 18 | read_float(b...); 19 | } -------------------------------------------------------------------------------- /Fast IO/read_int.cpp: -------------------------------------------------------------------------------- 1 | char gc() { 2 | #ifdef _WIN32 3 | return _getchar_nolock(); 4 | #else 5 | return getchar_unlocked(); 6 | #endif 7 | } 8 | void read_int() {} 9 | template inline void read_int(T &a, S &... b) { 10 | char c, s = 1; 11 | while (isspace(c = gc())); 12 | if (c == '-') s = -1, c = gc(); 13 | for (a = c - '0'; isdigit(c = gc()); a = a * 10 + c - '0'); 14 | a *= s; 15 | read_int(b...); 16 | } -------------------------------------------------------------------------------- /Gaussian Elimination/description.txt: -------------------------------------------------------------------------------- 1 | Gaussian Elimination 2 | -------------------------------------------------------------------------------- /Gaussian Elimination/gauss.cpp: -------------------------------------------------------------------------------- 1 | int gauss(vector> a, vector &ans) { 2 | const double EPS = 1e-6; 3 | int n = (int)a.size(); 4 | int m = (int)a[0].size() - 1; 5 | 6 | vector where(m, -1); 7 | for (int col = 0, row = 0; col < m && row < n; ++col) { 8 | int sel = row; 9 | for (int i = row; i < n; ++i) 10 | if (abs(a[i][col]) > abs(a[sel][col])) 11 | sel = i; 12 | if (abs(a[sel][col]) < EPS) 13 | continue; 14 | for (int i = col; i <= m; ++i) 15 | swap(a[sel][i], a[row][i]); 16 | where[col] = row; 17 | 18 | for (int i = 0; i < n; ++i) 19 | if (i != row) { 20 | double c = a[i][col] / a[row][col]; 21 | for (int j = col; j <= m; ++j) 22 | a[i][j] -= a[row][j] * c; 23 | } 24 | ++row; 25 | } 26 | 27 | ans.assign(m, 0); 28 | for (int i = 0; i < m; ++i) 29 | if (where[i] != -1) 30 | ans[i] = a[where[i]][m] / a[where[i]][i]; 31 | for (int i = 0; i < n; ++i) { 32 | double sum = 0; 33 | for (int j = 0; j < m; ++j) 34 | sum += ans[j] * a[i][j]; 35 | if (abs(sum - a[i][m]) > EPS) 36 | return 0; 37 | } 38 | 39 | for (int i = 0; i < m; ++i) 40 | if (where[i] == -1) 41 | return -1; 42 | return 1; 43 | } -------------------------------------------------------------------------------- /Geometry/base.cpp: -------------------------------------------------------------------------------- 1 | /** Constants Start **/ 2 | const double PI = acos(-1.0); 3 | const double EPS = 1e-8; 4 | const double INF = 1e9 + 5; 5 | template int sgn(T x) { return x < -EPS ? -1 : x > EPS; } 6 | /** Constants End **/ 7 | /** Base Start **/ 8 | struct pt { 9 | T x, y; 10 | pt operator+(pt p) { return {x + p.x, y + p.y}; } 11 | pt operator-(pt p) { return {x - p.x, y - p.y}; } 12 | pt operator-() { return {-x, -y}; } 13 | pt operator*(pt p) { return {x * p.x, y * p.y}; } 14 | pt operator*(T d) { return {x * d, y * d}; } 15 | pt operator/(T d) { return {x / d, y / d}; } 16 | bool operator==(pt p) { return x == p.x && y == p.y; } 17 | bool operator!=(pt p) { return !(*this == p); } 18 | bool operator<(pt p) const { return make_pair(x, y) < make_pair(p.x, p.y); } 19 | bool operator>(pt p) { return p < *this; } 20 | T sq() { return x * x + y * y; } 21 | double abs() { return sqrt(sq()); } 22 | pt translate(pt v) { return *this + v; } 23 | pt perp() { return {-y, x}; } 24 | pt rot(double a) { return {x * cos(a) - y * sin(a), x * sin(a) + y * cos(a)}; } 25 | }; 26 | ostream &operator<<(ostream &os, pt p) { return cout << "(" << p.x << "," << p.y << ")"; } 27 | istream &operator>>(istream &is, pt p) { return cin >> p.x >> p.y; } 28 | pt scale(pt c, double factor, pt p) { return c + (p - c) * factor; } 29 | T dot(pt v, pt w) { return v.x * w.x + v.y * w.y; } 30 | T cross(pt v, pt w) { return v.x * w.y - v.y * w.x; } 31 | T orient(pt a, pt b, pt c) { return cross(b - a, c - a); } 32 | int orientS(pt a, pt b, pt c) { return sgn(orient(a, b, c)); } 33 | T orient(pt b, pt c) { return cross(b, c); } 34 | bool half(pt p) { 35 | assert(p.x != 0 || p.y != 0); 36 | return p.y > 0 || (p.y == 0 && p.x < 0); 37 | } 38 | auto polarCmp(pt o = {0, 0}) { 39 | return [o](pt v, pt w) { return make_tuple(half(v - o), 0, v.sq()) < make_tuple(half(w - o), cross(v - o, w - o), w.sq()); }; 40 | } 41 | struct line { 42 | pt v; 43 | T c; 44 | line() {} 45 | // From direction vector v and y-intercept c 46 | line(pt v, T c) : v(v), c(c) { assert(v.sq() != 0); } 47 | // From equation ax+by=c 48 | line(T a, T b, T c) : v({b, -a}), c(c) { assert(v.sq() != 0); } 49 | // From points P and Q 50 | line(pt p, pt q) : v(q - p), c(cross(v, p)) { assert(v.sq() != 0); } 51 | // - these work with T = int 52 | T side(pt p) { return cross(v, p) - c; } 53 | double dist(pt p) { return abs(side(p)) / v.abs(); } 54 | double sqDist(pt p) { return side(p) * side(p) / (double)v.sq(); } 55 | line perpThrough(pt p) { return {p, p + v.perp()}; } 56 | bool cmpProj(pt p, pt q) { return dot(v, p) < dot(v, q); } 57 | line translate(pt t) { return {v, c + cross(v, t)}; } 58 | // - these require T = double 59 | line shiftLeft(double dist) { return {v, c + dist * v.abs()}; } 60 | pt proj(pt p) { return p - v.perp() * side(p) / v.sq(); } 61 | pt refl(pt p) { return p - v.perp() * 2 * side(p) / v.sq(); } 62 | }; 63 | pair inter(line l1, line l2) { 64 | T d = cross(l1.v, l2.v); 65 | if (d == 0) 66 | return {false, pt{0, 0}}; 67 | return {true, (l2.v * l1.c - l1.v * l2.c) / d}; // requires floating-point coordinates 68 | } 69 | bool properInter(pt a, pt b, pt c, pt d, pt &out) { 70 | double oa = orient(c, d, a), ob = orient(c, d, b), oc = orient(a, b, c), od = orient(a, b, d); 71 | if (sgn(oa) * sgn(ob) < 0 && sgn(oc) * sgn(od) < 0) { 72 | out = (a * ob - b * oa) / (ob - oa); 73 | return true; 74 | } 75 | return false; 76 | } 77 | bool inDisk(pt a, pt b, pt p) { return dot(a - p, b - p) <= 0; } 78 | bool onSegment(pt a, pt b, pt p) { return orientS(a, b, p) == 0 && inDisk(a, b, p); } 79 | /** Base End **/ -------------------------------------------------------------------------------- /Geometry/circle.cpp: -------------------------------------------------------------------------------- 1 | /* Circle Start */ 2 | struct circle { 3 | pt c; 4 | double r; 5 | }; 6 | pt circumCenter(pt a, pt b, pt c) { 7 | b = b - a, c = c - a; // consider coordinates relative to A 8 | assert(cross(b, c) != 0); // no circumcircle if A,B,C aligned 9 | return a + (b * c.sq() - c * b.sq()).perp() / cross(b, c) / 2; 10 | } 11 | double circumRadius(pt a, pt b, pt c) { return (a - b).abs() * (b - c).abs() * (c - a).abs() / abs(orient(a, b, c)) / 2.; } 12 | circle circumCircle(pt a, pt b, pt c) { return {circumCenter(a, b, c), circumRadius(a, b, c)}; } 13 | int circleLine(circle c, line l, pair &out) { 14 | double h2 = c.r * c.r - l.sqDist(c.c); 15 | if (h2 >= 0) { // the line touches the circle 16 | pt p = l.proj(c.c); // point P 17 | pt h = l.v * sqrt(h2) / l.v.abs(); // vector parallel to l, of length h 18 | out = {p - h, p + h}; 19 | } 20 | return 1 + sgn(h2); 21 | } 22 | int circleCircle(circle c1, circle c2, pair &out) { 23 | pt d = c2.c - c1.c; 24 | double d2 = d.sq(); 25 | if (d2 == 0) { // concentric circles 26 | assert(c1.r != c2.r); 27 | return 0; 28 | } 29 | double pd = (d2 + c1.r * c1.r - c2.r * c2.r) / 2; // = |O_1P| * d 30 | double h2 = c1.r * c1.r - pd * pd / d2; // = hˆ2 31 | if (h2 >= 0) { 32 | pt p = c1.c + d * pd / d2, h = d.perp() * sqrt(h2 / d2); 33 | out = {p - h, p + h}; 34 | } 35 | return 1 + sgn(h2); 36 | } 37 | int tangents(circle c1, circle c2, bool inner, vector> &out) { 38 | if (inner) 39 | c2.r = -c2.r; 40 | pt d = c2.c - c1.c; 41 | double dr = c1.r - c2.r, d2 = d.sq(), h2 = d2 - dr * dr; 42 | if (d2 == 0 || h2 < 0) { 43 | assert(h2 != 0); 44 | return 0; 45 | } 46 | for (int sign : {-1, 1}) { 47 | pt v = (d * dr + d.perp() * sqrt(h2) * sign) / d2; 48 | out.push_back({c1.c + v * c1.r, c2.c + v * c2.r}); 49 | } 50 | return 1 + (h2 > 0); 51 | } 52 | 53 | // IMPORTANT: random_shuffle(pts.begin(), pts.end()) 54 | circle MEC(vector &pts, vector ch = {}) { // Minimum Enclosing Circle 55 | if (pts.empty() || ch.size() == 3) { 56 | if (ch.size() == 0) 57 | return {0, -1}; 58 | else if (ch.size() == 1) 59 | return {ch[0], 0}; 60 | else if (ch.size() == 2) 61 | return {(ch[0] + ch[1]) / 2, (ch[0] - ch[1]).abs() / 2}; 62 | else 63 | return circumCircle(ch[0], ch[1], ch[2]); 64 | } 65 | auto p = pts.back(); 66 | pts.pop_back(); 67 | auto c = MEC(pts, ch); 68 | if (sgn((p - c.c).abs() - c.r) > 0) { 69 | ch.push_back(p); 70 | c = MEC(pts, ch); 71 | } 72 | pts.push_back(p); 73 | return c; 74 | } 75 | /* Circle End */ -------------------------------------------------------------------------------- /Geometry/convex.cpp: -------------------------------------------------------------------------------- 1 | /* Convex Start */ 2 | vector convexHull(vector &pts) { // O(n log n) 3 | sort(pts.begin(), pts.end()); 4 | vector hull; 5 | for (int phase = 0; phase < 2; ++phase) { 6 | auto start = hull.size(); 7 | for (auto &point : pts) { 8 | while (hull.size() >= start + 2 && orientS(hull[hull.size() - 2], hull.back(), point) <= 0) 9 | hull.pop_back(); 10 | hull.push_back(point); 11 | } 12 | hull.pop_back(); 13 | reverse(pts.begin(), pts.end()); 14 | } 15 | if (hull.size() == 2 && hull[0] == hull[1]) 16 | hull.pop_back(); 17 | return hull; 18 | } 19 | // if strict, returns false when A is on the boundary. 20 | bool inConvex(vector &l, pt p, bool strict = true) { // O(log n) 21 | int a = 1, b = l.size() - 1, c; 22 | if (orientS(l[0], l[a], l[b]) > 0) 23 | swap(a, b); 24 | if (orientS(l[0], l[a], p) > 0 || orientS(l[0], l[b], p) < 0 || (strict && (orientS(l[0], l[a], p) == 0 || orientS(l[0], l[b], p) == 0))) 25 | return false; 26 | while (abs(a - b) > 1) { 27 | c = (a + b) / 2; 28 | if (orientS(l[0], l[c], p) > 0) 29 | b = c; 30 | else 31 | a = c; 32 | } 33 | return orientS(l[a], l[b], p) < 0 ? true : !strict; 34 | } 35 | // Max distance across a convex polygon 36 | T convexDiameter(vector poly) { // O(n) 37 | int n = poly.size(); 38 | auto res = T(0); 39 | for (int i = 0, j = n < 2 ? 0 : 1; i < j; ++i) 40 | for (;; j = (j + 1) % n) { 41 | res = max(res, (poly[i] - poly[j]).sq()); 42 | if (orientS({0, 0}, poly[(j + 1) % n] - poly[j], poly[i + 1] - poly[i]) >= 0) 43 | break; 44 | } 45 | return res; 46 | } 47 | vector convexConvex(vector &P, vector &Q) { // O(log n) 48 | const int n = P.size(), m = Q.size(); 49 | int a = 0, b = 0, aa = 0, ba = 0; 50 | enum { Pin, Qin, Unknown } in = Unknown; 51 | vector R; 52 | do { 53 | int a1 = (a + n - 1) % n, b1 = (b + m - 1) % m; 54 | double C = cross(P[a] - P[a1], Q[b] - Q[b1]); 55 | double A = cross(P[a1] - Q[b], P[a] - Q[b]); 56 | double B = cross(Q[b1] - P[a], Q[b] - P[a]); 57 | pt r; 58 | if (properInter(P[a1], P[a], Q[b1], Q[b], r)) { 59 | if (in == Unknown) 60 | aa = ba = 0; 61 | R.push_back(r); 62 | in = B > 0 ? Pin : (A > 0 ? Qin : in); 63 | } 64 | if (C == 0 && B == 0 && A == 0) { 65 | if (in == Pin) { 66 | b = (b + 1) % m; 67 | ++ba; 68 | } else { 69 | a = (a + 1) % m; 70 | ++aa; 71 | } 72 | } else if ((C >= 0 && A > 0) || (C < 0 && B <= 0)) { 73 | if (in == Pin) 74 | R.push_back(P[a]); 75 | a = (a + 1) % n; 76 | ++aa; 77 | } else { 78 | if (in == Qin) 79 | R.push_back(Q[b]); 80 | b = (b + 1) % m; 81 | ++ba; 82 | } 83 | } while ((aa < n || ba < m) && aa < 2 * n && ba < 2 * m); 84 | if (in == Unknown) { 85 | if (inConvex(Q, P[0])) 86 | return P; 87 | if (inConvex(P, Q[0])) 88 | return Q; 89 | } 90 | return R; 91 | } 92 | /** Convex End **/ -------------------------------------------------------------------------------- /Geometry/description.txt: -------------------------------------------------------------------------------- 1 | Geometry 2 | -------------------------------------------------------------------------------- /Geometry/halfplane.cpp: -------------------------------------------------------------------------------- 1 | bool checkhp(line &a, line &b, line &me) { return sgn(me.side(inter(a, b).second)) > 0; } 2 | vector halfPlaneIntersection(vector border) { // O(n log n): Finds convex polygon of intersecting half planes. 3 | border.push_back(line{pt{-INF, -INF}, pt{INF, -INF}}); 4 | border.push_back(line{pt{INF, -INF}, pt{INF, INF}}); 5 | border.push_back(line{pt{INF, INF}, pt{-INF, INF}}); 6 | border.push_back(line{pt{-INF, INF}, pt{-INF, -INF}}); 7 | 8 | sort(border.begin(), border.end(), [](auto a, auto b) { return polarCmp()(a.v, b.v); }); 9 | auto eq = [](line a, line b) { return sgn(atan2(a.v.y, a.v.x) - atan2(b.v.y, b.v.x)) == 0; }; 10 | border.resize(unique(border.begin(), border.end(), eq) - border.begin()); 11 | deque deq; 12 | for (int i = 0; i < border.size(); ++i) { 13 | line cur = border[i]; 14 | while (deq.size() > 1 && !checkhp(deq[deq.size() - 2], deq[deq.size() - 1], cur)) 15 | deq.pop_back(); 16 | while (deq.size() > 1 && !checkhp(deq[0], deq[1], cur)) 17 | deq.pop_front(); 18 | deq.push_back(cur); 19 | } 20 | while (deq.size() > 1 && !checkhp(deq[deq.size() - 2], deq[deq.size() - 1], deq[0])) 21 | deq.pop_back(); 22 | 23 | vector pts; 24 | for (int i = 0; i < deq.size(); i++) 25 | pts.push_back(inter(deq[i], deq[(i + 1) % deq.size()]).second); 26 | return pts; 27 | } -------------------------------------------------------------------------------- /Geometry/polygon.cpp: -------------------------------------------------------------------------------- 1 | /* Polygon Start */ 2 | double areaTriangle(pt a, pt b, pt c) { return abs(cross(b - a, c - a)) / 2.0; } 3 | double areaPolygon(vector p) { // if negative, p is in clock-wise order. 4 | double area = 0.0; 5 | for (int i = 0, n = p.size(); i < n; i++) 6 | area += cross(p[i], p[(i + 1) % n]); // wrap back to 0 if i == n -1 7 | return area / 2.0; 8 | } 9 | // true if P at least as high as A (blue part) 10 | bool above(pt a, pt p) { return p.y >= a.y; } 11 | // check if [PQ] crosses ray from A 12 | bool crossesRay(pt a, pt p, pt q) { return (above(q, a) - above(p, a)) * orient(a, p, q) > 0; } 13 | // if strict, returns false when A is on the boundary 14 | bool inPolygon(vector &p, pt a, bool strict = true) { 15 | int numCrossings = 0; 16 | for (int i = 0, n = p.size(); i < n; i++) { 17 | if (onSegment(p[i], p[(i + 1) % n], a)) 18 | return !strict; 19 | numCrossings += crossesRay(a, p[i], p[(i + 1) % n]); 20 | } 21 | return numCrossings & 1; // inside if odd number of crossings 22 | } 23 | /* Polygon End */ -------------------------------------------------------------------------------- /Geometry/segment.cpp: -------------------------------------------------------------------------------- 1 | /** Line Segment Start **/ 2 | set inters(pt a, pt b, pt c, pt d) { 3 | pt out; 4 | if (properInter(a, b, c, d, out)) 5 | return {out}; 6 | set s; 7 | if (onSegment(c, d, a) == true) 8 | s.insert(a); 9 | if (onSegment(c, d, b)) 10 | s.insert(b); 11 | if (onSegment(a, b, c)) 12 | s.insert(c); 13 | if (onSegment(a, b, d)) 14 | s.insert(d); 15 | return s; 16 | } 17 | double segPoint(pt a, pt b, pt p) { 18 | if (a != b) { 19 | line l(a, b); 20 | if (l.cmpProj(a, p) && l.cmpProj(p, b)) // if closest to projection 21 | return l.dist(p); // output distance to line 22 | } 23 | return min((p - a).abs(), (p - b).abs()); // otherwise distance to A or B 24 | } 25 | double segSeg(pt a, pt b, pt c, pt d) { 26 | pt dummy; 27 | if (properInter(a, b, c, d, dummy)) 28 | return 0; 29 | return min({segPoint(a, b, c), segPoint(a, b, d), segPoint(c, d, a), segPoint(c, d, b)}); 30 | } 31 | /** Line Segment End **/ -------------------------------------------------------------------------------- /LCA (Lowest Common Ancestor)/description.txt: -------------------------------------------------------------------------------- 1 | LCA (Lowest Common Ancestor) 2 | -------------------------------------------------------------------------------- /LCA (Lowest Common Ancestor)/lca binary lifting.cpp: -------------------------------------------------------------------------------- 1 | template struct LCA { // O(log N) queries 2 | const static int MAXB = 32 - __builtin_clz(MAXN); 3 | int tin[MAXN], tout[MAXN], depth[MAXN], timer = 0; 4 | int pars[MAXN][MAXB]; 5 | void calclca(int cur, int p = 0, int d = 0) { 6 | depth[cur] = d; 7 | tin[cur] = ++timer; 8 | pars[cur][0] = p; 9 | for (int d = 1; d < MAXB; d++) 10 | pars[cur][d] = pars[pars[cur][d - 1]][d - 1]; 11 | for (auto i : adj[cur]) { 12 | if (i == p) 13 | continue; 14 | calclca(i, cur, d + 1); 15 | } 16 | tout[cur] = ++timer; 17 | } 18 | bool isAncestor(int p, int x) { return tin[p] <= tin[x] && tout[p] >= tout[x]; } 19 | int query(int a, int b) { 20 | if (isAncestor(a, b)) 21 | return a; 22 | if (isAncestor(b, a)) 23 | return b; 24 | for (int d = MAXB - 1; d >= 0; d--) { 25 | if (!isAncestor(pars[a][d], b)) 26 | a = pars[a][d]; 27 | } 28 | return pars[a][0]; 29 | } 30 | int dist(int a, int b) { 31 | int lca = query(a, b); 32 | return depth[a] + depth[b] - 2 * depth[lca]; 33 | } 34 | }; -------------------------------------------------------------------------------- /LCA (Lowest Common Ancestor)/lca rmq.cpp: -------------------------------------------------------------------------------- 1 | template struct LCA { // O(1) queries 2 | const static int MAXB = 32 - __builtin_clz(MAXN); 3 | int tim[MAXN], depth[MAXN]; 4 | array st[MAXN * 2][MAXB]; 5 | vector> euler; 6 | void calc(vector adj[], int cur = 0, int p = 0, int d = 0) { 7 | depth[cur] = d; 8 | tim[cur] = euler.size(); 9 | euler.push_back({d, cur}); 10 | for (auto i : adj[cur]) { 11 | if (i == p) 12 | continue; 13 | calc(adj, i, cur, d + 1); 14 | euler.push_back({d, cur}); 15 | } 16 | if (p == cur) { 17 | for (int i = 0; i < euler.size(); i++) 18 | st[i][0] = euler[i]; 19 | for (int j = 1; j <= MAXB; j++) 20 | for (int i = 0; i + (1 << j) <= euler.size(); i++) 21 | st[i][j] = min(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]); 22 | } 23 | } 24 | int query(int a, int b) { 25 | if (a == b) 26 | return a; 27 | if ((a = tim[a]) > (b = tim[b])) 28 | swap(a, b); 29 | int k = 31 - __builtin_clz(b - a); 30 | return min(st[a][k], st[b - (1 << k)][k])[1]; 31 | } 32 | int dist(int a, int b) { 33 | int lca = query(a, b); 34 | return depth[a] + depth[b] - 2 * depth[lca]; 35 | } 36 | }; -------------------------------------------------------------------------------- /Linear Recurrence (Berlekamp Massey, K-th term)/BerlekampMassey.cpp: -------------------------------------------------------------------------------- 1 | vector BerlekampMassey(vector s) { 2 | int n = s.size(), L = 0, m = 0; 3 | vector C(n), B(n), T; 4 | C[0] = B[0] = 1; 5 | 6 | ll b = 1; 7 | for (int i = 0; i < n; i++) { 8 | m++; 9 | ll d = s[i] % MOD; 10 | for (int j = 1; j < L + 1; j++) 11 | d = (d + C[j] * s[i - j]) % MOD; 12 | if (!d) 13 | continue; 14 | T = C; 15 | ll coef = d * binExp(b, MOD - 2) % MOD; 16 | for (int j = m; j < n; j++) 17 | C[j] = (C[j] - coef * B[j - m]) % MOD; 18 | if (2 * L > i) 19 | continue; 20 | L = i + 1 - L; 21 | B = T, b = d, m = 0; 22 | } 23 | C.resize(L + 1); 24 | C.erase(C.begin()); 25 | for (auto &x : C) 26 | x = (MOD - x) % MOD; 27 | return C; 28 | } -------------------------------------------------------------------------------- /Linear Recurrence (Berlekamp Massey, K-th term)/Kth-term.cpp: -------------------------------------------------------------------------------- 1 | typedef vector Poly; 2 | ll linearRec(Poly S, Poly tr, ll k) { 3 | int n = S.size(); 4 | auto combine = [&](Poly a, Poly b) { 5 | Poly res(n * 2 + 1); 6 | for (int i = 0; i < n + 1; i++) 7 | for (int j = 0; j < n + 1; j++) 8 | res[i + j] = (res[i + j] + a[i] * b[j]) % MOD; 9 | for (int i = 2 * n; i > n; --i) 10 | for (int j = 0; j < n; j++) 11 | res[i - 1 - j] = (res[i - 1 - j] + res[i] * tr[j]) % MOD; 12 | res.resize(n + 1); 13 | return res; 14 | }; 15 | Poly pol(n + 1), e(pol); 16 | pol[0] = e[1] = 1; 17 | for (++k; k; k /= 2) { 18 | if (k % 2) 19 | pol = combine(pol, e); 20 | e = combine(e, e); 21 | } 22 | ll res = 0; 23 | for (int i = 0; i < n; i++) 24 | res = (res + pol[i + 1] * S[i]) % MOD; 25 | return res; 26 | } -------------------------------------------------------------------------------- /Linear Recurrence (Berlekamp Massey, K-th term)/description.txt: -------------------------------------------------------------------------------- 1 | Linear Recurrence (Berlekamp Massey, K-th term) 2 | -------------------------------------------------------------------------------- /Longest Increasing Subsequence(LIS)/description.txt: -------------------------------------------------------------------------------- 1 | Longest Increasing Subsequence(LIS) 2 | -------------------------------------------------------------------------------- /Longest Increasing Subsequence(LIS)/lis.cpp: -------------------------------------------------------------------------------- 1 | vector ans; 2 | for (auto x : A) { 3 | auto it = lower_bound(ans.begin(), ans.end(), x); 4 | if (it == ans.end()) 5 | ans.push_back(x); 6 | else 7 | *it = x; 8 | } -------------------------------------------------------------------------------- /Manacher (Finds the length of the longest odd and even palindromes centered on an index): O(N)/description.txt: -------------------------------------------------------------------------------- 1 | Manacher (Finds the length of the longest odd and even palindromes centered on an index): O(N) 2 | -------------------------------------------------------------------------------- /Manacher (Finds the length of the longest odd and even palindromes centered on an index): O(N)/manacher.cpp: -------------------------------------------------------------------------------- 1 | array, 2> manacher(string &s) { // (even, odd) 2 | int n = s.size(); 3 | array, 2> p = {vector(n), vector(n)}; 4 | for (int z = 0, l = 0, r = 0; z < 2; z++, l = 0, r = 0) 5 | for (int i = 0; i < n; i++) { 6 | if (i < r) 7 | p[z][i] = min(r - i + !z, p[z][l + r - i + !z]); 8 | int L = i - p[z][i], R = i + p[z][i] - !z; 9 | while (L - 1 >= 0 && R + 1 < n && s[L - 1] == s[R + 1]) 10 | p[z][i]++, L--, R++; 11 | if (R > r) 12 | l = L, r = R; 13 | } 14 | return p; 15 | } -------------------------------------------------------------------------------- /Matrix Exponentiation/description.txt: -------------------------------------------------------------------------------- 1 | Matrix Exponentiation 2 | -------------------------------------------------------------------------------- /Matrix Exponentiation/matrixexpo.cpp: -------------------------------------------------------------------------------- 1 | struct matrix { 2 | vector> cells; 3 | 4 | matrix(vector> input) : cells(input) {} 5 | matrix(ll n, ll m, ll val) { 6 | cells.resize(n); 7 | vector row(m); 8 | fill(row.begin(), row.end(), val); 9 | fill(cells.begin(), cells.end(), row); 10 | } 11 | matrix(ll n) : matrix(n, n, 0) { 12 | for (ll i = 0; i < n; i++) { 13 | cells[i][i] = 1; 14 | } 15 | } 16 | 17 | matrix operator*(matrix b) { 18 | assert(cells[0].size() == b.cells.size()); 19 | ll n = cells.size(), m = b.cells[0].size(); 20 | matrix result(n, m, 0); 21 | for (ll i = 0; i < n; i++) { 22 | for (ll j = 0; j < m; j++) { 23 | for (ll k = 0; k < b.cells.size(); k++) 24 | result.cells[i][j] += cells[i][k] * b.cells[k][j]; 25 | } 26 | } 27 | return result; 28 | } 29 | }; 30 | 31 | matrix matPow(matrix base, ll exp) { 32 | if (exp == 0) 33 | return matrix(base.cells.size()); 34 | return matPow(base * base, exp / 2) * (exp % 2 == 1 ? base : matrix(base.cells.size())); 35 | } -------------------------------------------------------------------------------- /Max Flow (Dinic's, HLPP)/description.txt: -------------------------------------------------------------------------------- 1 | Max Flow (Dinic's, HLPP) 2 | -------------------------------------------------------------------------------- /Max Flow (Dinic's, HLPP)/dinic.cpp: -------------------------------------------------------------------------------- 1 | template struct Dinic { 2 | const static bool SCALING = false; // non-scaling = V^2E, Scaling=VElog(U) with higher constant 3 | int lim = 1; 4 | const T INF = numeric_limits::max(); 5 | struct edge { 6 | int to, rev; 7 | T cap, flow; 8 | }; 9 | int s = MAXV - 2, t = MAXV - 1; 10 | 11 | int level[MAXV], ptr[MAXV]; 12 | vector adj[MAXV]; 13 | void addEdge(int a, int b, T cap, bool isDirected = true) { 14 | adj[a].push_back({b, adj[b].size(), cap, 0}); 15 | adj[b].push_back({a, adj[a].size() - 1, isDirected ? 0 : cap, 0}); 16 | } 17 | bool bfs() { 18 | queue q({s}); 19 | fill(all(level), -1); 20 | level[s] = 0; 21 | while (!q.empty() && level[t] == -1) { 22 | int v = q.front(); 23 | q.pop(); 24 | for (auto e : adj[v]) { 25 | if (level[e.to] == -1 && e.flow < e.cap && (!SCALING || e.cap - e.flow >= lim)) { 26 | q.push(e.to); 27 | level[e.to] = level[v] + 1; 28 | } 29 | } 30 | } 31 | return level[t] != -1; 32 | } 33 | T dfs(int v, T flow) { 34 | if (v == t || !flow) 35 | return flow; 36 | for (; ptr[v] < adj[v].size(); ptr[v]++) { 37 | edge &e = adj[v][ptr[v]]; 38 | if (level[e.to] != level[v] + 1) 39 | continue; 40 | if (T pushed = dfs(e.to, min(flow, e.cap - e.flow))) { 41 | e.flow += pushed; 42 | adj[e.to][e.rev].flow -= pushed; 43 | return pushed; 44 | } 45 | } 46 | return 0; 47 | } 48 | long long calc() { 49 | long long flow = 0; 50 | for (lim = SCALING ? (1 << 30) : 1; lim > 0; lim >>= 1) { 51 | while (bfs()) { 52 | fill(all(ptr), 0); 53 | while (T pushed = dfs(s, INF)) 54 | flow += pushed; 55 | } 56 | } 57 | return flow; 58 | } 59 | }; -------------------------------------------------------------------------------- /Max Flow (Dinic's, HLPP)/hlpp.cpp: -------------------------------------------------------------------------------- 1 | template struct HLPP { 2 | const T INF = numeric_limits::max(); 3 | struct edge { 4 | int to, rev; 5 | T f; 6 | }; 7 | int s = MAXN - 1, t = MAXN - 2; 8 | vector adj[MAXN]; 9 | vector lst[MAXN], gap[MAXN]; 10 | T excess[MAXN]; 11 | int highest, height[MAXN], cnt[MAXN], work; 12 | void addEdge(int from, int to, int f, bool isDirected = true) { 13 | adj[from].push_back({to, adj[to].size(), f}); 14 | adj[to].push_back({from, adj[from].size() - 1, isDirected ? 0 : f}); 15 | } 16 | void updHeight(int v, int nh) { 17 | work++; 18 | if (height[v] != MAXN) 19 | cnt[height[v]]--; 20 | height[v] = nh; 21 | if (nh == MAXN) 22 | return; 23 | cnt[nh]++, highest = nh; 24 | gap[nh].push_back(v); 25 | if (excess[v] > 0) 26 | lst[nh].push_back(v); 27 | } 28 | void globalRelabel() { 29 | work = 0; 30 | fill(all(height), MAXN); 31 | fill(all(cnt), 0); 32 | for (int i = 0; i < highest; i++) 33 | lst[i].clear(), gap[i].clear(); 34 | height[t] = 0; 35 | queue q({t}); 36 | while (!q.empty()) { 37 | int v = q.front(); 38 | q.pop(); 39 | for (auto &e : adj[v]) 40 | if (height[e.to] == MAXN && adj[e.to][e.rev].f > 0) 41 | q.push(e.to), updHeight(e.to, height[v] + 1); 42 | highest = height[v]; 43 | } 44 | } 45 | void push(int v, edge &e) { 46 | if (excess[e.to] == 0) 47 | lst[height[e.to]].push_back(e.to); 48 | T df = min(excess[v], e.f); 49 | e.f -= df, adj[e.to][e.rev].f += df; 50 | excess[v] -= df, excess[e.to] += df; 51 | } 52 | void discharge(int v) { 53 | int nh = MAXN; 54 | for (auto &e : adj[v]) { 55 | if (e.f > 0) { 56 | if (height[v] == height[e.to] + 1) { 57 | push(v, e); 58 | if (excess[v] <= 0) 59 | return; 60 | } else 61 | nh = min(nh, height[e.to] + 1); 62 | } 63 | } 64 | if (cnt[height[v]] > 1) 65 | updHeight(v, nh); 66 | else { 67 | for (int i = height[v]; i <= highest; i++) { 68 | for (auto j : gap[i]) 69 | updHeight(j, MAXN); 70 | gap[i].clear(); 71 | } 72 | } 73 | } 74 | T calc(int heur_n = MAXN) { 75 | fill(all(excess), 0); 76 | excess[s] = INF, excess[t] = -INF; 77 | globalRelabel(); 78 | for (auto &e : adj[s]) 79 | push(s, e); 80 | for (; highest >= 0; highest--) { 81 | while (!lst[highest].empty()) { 82 | int v = lst[highest].back(); 83 | lst[highest].pop_back(); 84 | discharge(v); 85 | if (work > 4 * heur_n) 86 | globalRelabel(); 87 | } 88 | } 89 | return excess[t] + INF; 90 | } 91 | }; -------------------------------------------------------------------------------- /Miller Rabin: primality test/description.txt: -------------------------------------------------------------------------------- 1 | Miller Rabin: primality test 2 | -------------------------------------------------------------------------------- /Miller Rabin: primality test/millerabin.cpp: -------------------------------------------------------------------------------- 1 | bool isPrime(ull n) { 2 | if (n < 2 || n % 2 == 0 || n % 3 == 0) 3 | return n - 2 < 2; 4 | ull s = __builtin_ctzll(n - 1), d = n >> s; // counts trailing zeros 5 | for (auto a : {2, 325, 9375, 28178, 450775, 9780504, 1795265022}) { 6 | ull p = binExp(a, d, n), i = s; 7 | while (p != 1 && p != n - 1 && a % n && i--) 8 | p = binExp(p, 2, n); 9 | if (p != n - 1 && i != s) 10 | return 0; 11 | } 12 | return 1; 13 | } -------------------------------------------------------------------------------- /Min Cost Max Flow/bellman-ford.cpp: -------------------------------------------------------------------------------- 1 | struct MinCostFlow { 2 | const static int MAXV = MAXN; 3 | const int INF = 1e9 + 5; 4 | const int s = MAXV - 2, t = MAXV - 1; 5 | struct edge { 6 | int from, to, cap, flow, cost; 7 | }; 8 | 9 | int cost[MAXV][MAXV]; 10 | vector edges; 11 | int dist[MAXV]; 12 | int par[MAXV]; 13 | 14 | int minCost(int flow) { 15 | int result = 0; 16 | while (true) { 17 | fill(begin(dist), end(dist), INF); 18 | dist[s] = 0; 19 | while (true) { 20 | bool change = false; 21 | for (int i = 0; i < edges.size(); i++) { 22 | edge e = edges[i]; 23 | if (e.flow == e.cap || dist[e.from] == INF) 24 | continue; 25 | if (dist[e.to] > dist[e.from] + e.cost) { 26 | dist[e.to] = dist[e.from] + e.cost; 27 | par[e.to] = i; 28 | change = true; 29 | } 30 | } 31 | if (!change) 32 | break; 33 | } 34 | 35 | if (dist[t] == INF) { 36 | return -1; 37 | } 38 | 39 | int push = flow; 40 | int cur = t; 41 | while (cur != s) { 42 | edge tmp = edges[par[cur]]; 43 | int from = tmp.from, can_push = tmp.cap - tmp.flow; 44 | push = min(push, can_push); 45 | cur = from; 46 | } 47 | 48 | flow -= push; 49 | cur = t; 50 | while (cur != s) { 51 | edge tmp = edges[par[cur]]; 52 | int from = tmp.from; 53 | edges[par[cur]].flow += push; 54 | edges[par[cur] ^ 1].flow -= push; 55 | result += push * tmp.cost; 56 | cur = from; 57 | } 58 | 59 | if (flow == 0) 60 | break; 61 | } 62 | return result; 63 | } 64 | 65 | void addEdge(int from, int to, int cap, int cost) { 66 | edges.push_back({from, to, cap, 0, cost}); 67 | edges.push_back({to, from, cap, cap, -cost}); 68 | } 69 | }; -------------------------------------------------------------------------------- /Min Cost Max Flow/description.txt: -------------------------------------------------------------------------------- 1 | Min Cost Max Flow 2 | -------------------------------------------------------------------------------- /Minimum Rotation: O(N)/description.txt: -------------------------------------------------------------------------------- 1 | Minimum Rotation: O(N) 2 | -------------------------------------------------------------------------------- /Minimum Rotation: O(N)/min_rotation.cpp: -------------------------------------------------------------------------------- 1 | int min_rotation(string s) { 2 | int a = 0, N = s.size(); 3 | s += s; 4 | for (int b = 0; b < N; b++) 5 | for (int i = 0; i < N; i++) { 6 | if (a + i == b || s[a + i] < s[b + i]) { 7 | b += max(0, i - 1); 8 | break; 9 | } 10 | if (s[a + i] > s[b + i]) { 11 | a = b; 12 | break; 13 | } 14 | } 15 | return a; 16 | } -------------------------------------------------------------------------------- /Mod Sum: sum_{i=0}^{to-1} (k*i+c)%m: log(m) with large constant/description.txt: -------------------------------------------------------------------------------- 1 | Mod Sum: sum_{i=0}^{to-1} (k*i+c)%m: log(m) with large constant 2 | -------------------------------------------------------------------------------- /Mod Sum: sum_{i=0}^{to-1} (k*i+c)%m: log(m) with large constant/modsum.cpp: -------------------------------------------------------------------------------- 1 | typedef unsigned long long ull; 2 | ull sumsq(ull to) { return to / 2 * ((to - 1) | 1); } 3 | ull divsum(ull to, ull c, ull k, ull m) { 4 | ull res = k / m * sumsq(to) + c / m * to; 5 | k %= m, c %= m; 6 | if (!k) 7 | return res; 8 | ull to2 = (to * k + c) / m; 9 | return res + (to - 1) * to2 - divsum(to2, m - 1 - c, m, k); 10 | } 11 | ll modsum(ull to, ll c, ll k, ll m) { // sum_{i=0}^{to-1} (k*i+c)%m: mod is inside summation 12 | c = ((c % m) + m) % m; 13 | k = ((k % m) + m) % m; 14 | return to * c + k * sumsq(to) - m * divsum(to, c, k, m); 15 | } -------------------------------------------------------------------------------- /Number Theory Sieves/description.txt: -------------------------------------------------------------------------------- 1 | Number Theory Sieves 2 | -------------------------------------------------------------------------------- /Number Theory Sieves/mobius.cpp: -------------------------------------------------------------------------------- 1 | int mobius[MAXPR]; 2 | bool sieve[MAXPR]; 3 | vector primes; 4 | void calcMobius() { 5 | mobius[1] = 1; 6 | for (int i = 2; i < MAXPR; i++) { 7 | if (!sieve[i]) { 8 | primes.push_back(i); 9 | mobius[i] = -1; 10 | } 11 | for (int j = 0; j < primes.size() && i * primes[j] < MAXPR; j++) { 12 | sieve[i * primes[j]] = true; 13 | if (i % primes[j] == 0) { 14 | mobius[i * primes[j]] = 0; 15 | break; 16 | } 17 | mobius[i * primes[j]] = mobius[i] * -1; 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /Number Theory Sieves/primes.cpp: -------------------------------------------------------------------------------- 1 | bool sieve[MAXPR]; 2 | vector primes; 3 | void calcPrimes() { 4 | for (int i = 2; i < MAXPR; i++) { 5 | if (!sieve[i]) 6 | primes.push_back(i); 7 | for (int j = 0; j < primes.size() && i * primes[j] < MAXPR; j++) { 8 | sieve[primes[j] * i] = true; 9 | if (i % primes[j] == 0) 10 | break; 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /Number Theory Sieves/segmented sieve.cpp: -------------------------------------------------------------------------------- 1 | vector primes; 2 | const int MAXPR = MAXN; 3 | void calcPrimes() { 4 | const int S = round(sqrt(MAXPR)); 5 | vector sieve(S + 1, true); 6 | vector> cp; 7 | primes.push_back(2); 8 | for (int i = 3; i < S; i += 2) { 9 | if (!sieve[i]) 10 | continue; 11 | cp.push_back({i, (i * i - 1) / 2}); 12 | for (int j = i * i; j <= S; j += 2 * i) 13 | sieve[j] = false; 14 | } 15 | vector block(S); 16 | int high = (MAXPR - 1) / 2; 17 | for (int low = 0; low <= high; low += S) { 18 | fill(block.begin(), block.end(), true); 19 | for (auto &i : cp) { 20 | int p = i[0], idx = i[1]; 21 | for (; idx < S; idx += p) 22 | block[idx] = false; 23 | i[1] = idx - S; 24 | } 25 | if (low == 0) 26 | block[0] = false; 27 | for (int i = 0; i < S && low + i <= high; i++) 28 | if (block[i]) 29 | primes.push_back((low + i) * 2 + 1); 30 | }; 31 | } -------------------------------------------------------------------------------- /Number Theory Sieves/totient.cpp: -------------------------------------------------------------------------------- 1 | bool sieve[MAXPR]; 2 | int phi[MAXPR]; 3 | vector primes; 4 | void calcTotient() { 5 | phi[1] = 1; 6 | for (int i = 2; i < MAXPR; i++) { 7 | if (!sieve[i]) { 8 | primes.push_back(i); 9 | phi[i] = i - 1; 10 | } 11 | for (int j = 0; j < primes.size() && i * primes[j] < MAXPR; j++) { 12 | sieve[i * primes[j]] = true; 13 | if (i % primes[j] == 0) { 14 | phi[i * primes[j]] = phi[i] * primes[j]; 15 | break; 16 | } 17 | phi[i * primes[j]] = phi[i] * phi[primes[j]]; 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /Numerical Integration (Simpson's)/adaptive.cpp: -------------------------------------------------------------------------------- 1 | double simpson(function f, double a, double b) { 2 | double c = (a + b) / 2; 3 | return (b - a) / 6 * (f(a) + 4 * f(c) + f(b)); 4 | } 5 | double rec(function f, double a, double b, double eps, double S, bool rel = true) { 6 | double c = (a + b) / 2; 7 | double S1 = simpson(f, a, c), S2 = simpson(f, c, b), T = S1 + S2; 8 | if (abs(T - S) <= 15 * eps || b - a < 1e-10 || (rel && abs((T - S) / S) <= 15 * eps)) 9 | return T + (T - S) / 15; 10 | return rec(f, a, c, eps / 2, S1, rel) + rec(f, c, b, eps / 2, S2, rel); 11 | } 12 | double integrate(function f, double a, double b, double eps = 1e-8, bool rel = true) { 13 | return rec(f, a, b, eps, simpson(f, a, b), rel); 14 | } 15 | -------------------------------------------------------------------------------- /Numerical Integration (Simpson's)/description.txt: -------------------------------------------------------------------------------- 1 | Numerical Integration (Simpson's) 2 | -------------------------------------------------------------------------------- /Permutation Mapping: Permutations to/from integers - order preserving/description.txt: -------------------------------------------------------------------------------- 1 | Permutation Mapping: Permutations to/from integers - order preserving 2 | -------------------------------------------------------------------------------- /Permutation Mapping: Permutations to/from integers - order preserving/intperm.cpp: -------------------------------------------------------------------------------- 1 | int fac; 2 | template int perm_to_int(It begin, It end) { 3 | int x = 0, n = 0; 4 | for (It i = begin; i != end; ++i, ++n) 5 | if (*i < *begin) 6 | ++x; 7 | int val = 0; 8 | if (n > 2) 9 | val = perm_to_int(++begin, end); 10 | else 11 | val = 0; 12 | val += fac[n - 1] * x; 13 | return val; 14 | } 15 | template void int_to_perm(int val, It begin, It end) { 16 | int fac = fac[end - begin - 1]; 17 | // Note that the division result will fit in an integer ! 18 | int x = val / fac; 19 | nth_element(begin, begin + x, end); 20 | swap(*begin, *(begin + x)); 21 | if (end - begin > 2) 22 | int_to_perm(val % fac, ++begin, end); 23 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Algorithms 2 | Implementations of algorithms used for competitive programming, with a focus placed on readability, usability, conciseness, and performance (when important). 3 | 4 | Common macros/typedef used: 5 | ``` 6 | #define all(v) v.begin(), v.end() 7 | typedef long long ll; 8 | typedef unsigned long long ull; 9 | ``` 10 | 11 | Repo automatically generated from https://gist.github.com/Chillee. Some algorithms will have comments on the gists. 12 | 13 | Many of the best implementations here have/are being ported to https://github.com/kth-competitive-programming/kactl 14 | -------------------------------------------------------------------------------- /Random Snippets (Stuff that's not reusable but were painful to write that I wrote nicely and am happy with)/description.txt: -------------------------------------------------------------------------------- 1 | Random Snippets (Stuff that's not reusable but were painful to write that I wrote nicely and am happy with) 2 | -------------------------------------------------------------------------------- /Random Snippets (Stuff that's not reusable but were painful to write that I wrote nicely and am happy with)/merging two paths on tree.cpp: -------------------------------------------------------------------------------- 1 | pair> canMerge(array pts) { 2 | auto cmp = [&](int a, int b) { return make_pair(lca.depth[a], a) > make_pair(lca.depth[b], b); }; 3 | sort(pts.begin(), pts.end(), cmp); 4 | do { 5 | if (lca.dist(pts[0], pts[1]) + lca.dist(pts[1], pts[2]) + lca.dist(pts[2], pts[3]) == lca.dist(pts[0], pts[3])) 6 | return {true, {pts[0], pts[3]}}; 7 | } while (next_permutation(pts.begin() + 1, pts.end(), cmp)); 8 | return {false, {0, 0}}; 9 | } -------------------------------------------------------------------------------- /SOS DP (Sum over Subsets DP)/description.txt: -------------------------------------------------------------------------------- 1 | SOS DP (Sum over Subsets DP) 2 | -------------------------------------------------------------------------------- /SOS DP (Sum over Subsets DP)/sosdp.cpp: -------------------------------------------------------------------------------- 1 | int F[1 << MAXBITS]; 2 | for (int i = 0; i <= MAXBITS; ++i) { 3 | for (int mask = 0; mask < (1 << MAXBITS); ++mask) { 4 | if (mask & (1 << i)) { 5 | F[mask] = max(F[mask], F[mask ^ (1 << i)]); 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /Segment tree/2D BIT.cpp: -------------------------------------------------------------------------------- 1 | int N, M; 2 | int bit[MAXN][MAXN]; 3 | int sum(int x, int y) { 4 | int ret = 0; 5 | for (int i = x; i >= 0; i = (i & (i + 1)) - 1) 6 | for (int j = y; j >= 0; j = (j & (j + 1)) - 1) 7 | ret += bit[i][j]; 8 | return ret; 9 | } 10 | void add(int x, int y, int delta) { 11 | for (int i = x; i < N; i = i | (i + 1)) 12 | for (int j = y; j < M; j = j | (j + 1)) 13 | bit[i][j] += delta; 14 | } -------------------------------------------------------------------------------- /Segment tree/2D Seg.cpp: -------------------------------------------------------------------------------- 1 | struct seg { 2 | int seg[2 * MAXN][2 * MAXN]; 3 | void modify(int qr, int qc, int val) { 4 | qr += N, qc += M; 5 | seg[qr][qc] = val; 6 | for (int r = qr; r > 0; r >>= 1) { 7 | for (int c = qc; c > 0; c >>= 1) 8 | seg[r][c >> 1] = seg[r][c] + seg[r][c ^ 1]; 9 | seg[r >> 1][qc] = seg[r][qc] + seg[r ^ 1][qc]; 10 | } 11 | } 12 | int query2(int l, int r, int row) { 13 | int res = 0; 14 | for (l += M, r += M; l < r; l >>= 1, r >>= 1) { 15 | if (l & 1) 16 | res += seg[row][l++]; 17 | if (r & 1) 18 | res += seg[row][--r]; 19 | } 20 | return res; 21 | } 22 | int query(int u, int d, int l, int r) { 23 | int res = 0; 24 | for (u += N, d += N; u < d; u >>= 1, d >>= 1) { 25 | if (u & 1) 26 | res += query2(l, r, u++); 27 | if (d & 1) 28 | res += query2(l, r, --d); 29 | } 30 | return res; 31 | } 32 | }; -------------------------------------------------------------------------------- /Segment tree/abstract.cpp: -------------------------------------------------------------------------------- 1 | template struct Seg { 2 | const int N; 3 | vector seg; 4 | T unit; 5 | const function combine; 6 | Seg(int n, T arr[], T u, function cF) : N(n), unit(u), combine(cF), seg(N * 2) { 7 | for (int i = 0; i < N; i++) 8 | seg[i + N] = arr[i]; 9 | build(); 10 | } 11 | void build() { 12 | for (int i = N - 1; i > 0; --i) 13 | seg[i] = combine(seg[i << 1], seg[i << 1 | 1]); 14 | } 15 | 16 | void modify(int p, T value) { 17 | for (seg[p += N] = value; p > 0; p >>= 1) 18 | seg[p>>1] = combine(seg[p], seg[p ^ 1]); 19 | } 20 | 21 | T query(int l, int r) { 22 | T resl = unit; 23 | T resr = unit; 24 | for (l += N, r += N; l < r; l >>= 1, r >>= 1) { 25 | if (l & 1) 26 | resl = combine(resl, seg[l++]); 27 | if (r & 1) 28 | resr = combine(seg[--r], resr); 29 | } 30 | return combine(resl, resr); 31 | } 32 | }; -------------------------------------------------------------------------------- /Segment tree/description.txt: -------------------------------------------------------------------------------- 1 | Segment tree 2 | -------------------------------------------------------------------------------- /Segment tree/dynamic.cpp: -------------------------------------------------------------------------------- 1 | gp_hash_table seg; 2 | 3 | int get(int x) { return (seg.find(x) == seg.end()) ? 0 : seg[x]; } 4 | void modify(int p, int val) { 5 | for (seg[p += N] = val; p > 0; p >>= 1) { 6 | seg[p >> 1] = get(p) + get(p ^ 1); 7 | } 8 | } 9 | 10 | int query(int l, int r) { 11 | int res = 0; 12 | for (l += N, r += N; l < r; l >>= 1, r >>= 1) { 13 | if (l & 1) 14 | res += get(l++); 15 | if (r & 1) 16 | res += get(--r); 17 | } 18 | return res; 19 | } -------------------------------------------------------------------------------- /Segment tree/lazy propagation.cpp: -------------------------------------------------------------------------------- 1 | struct Tree { 2 | Tree *pl, *pr; 3 | int nl = 0, nr = 0, val = 0, lazy = 0; 4 | 5 | void updateVal() { val = pl->val + pr->val; } 6 | void propagate() { pl->apply(lazy), pr->apply(lazy), lazy = 0; } 7 | void apply(int x) { lazy += x, val += (nr - nl) * x; } 8 | 9 | Tree(int l, int r, int A[]) { 10 | nl = l, nr = r; 11 | if (nl + 1 == nr) { 12 | val = A[nl]; 13 | return; 14 | } 15 | pl = new Tree(nl, nl + nr >> 1, A); 16 | pr = new Tree(nl + nr >> 1, nr, A); 17 | updateVal(); 18 | } 19 | void modify(int l, int r, int x) { 20 | if (l <= nl && nr <= r) { 21 | apply(x); 22 | return; 23 | } 24 | if (l >= nr || nl >= r) 25 | return; 26 | propagate(); 27 | pl->modify(l, r, x); 28 | pr->modify(l, r, x); 29 | updateVal(); 30 | } 31 | int query(int l, int r) { 32 | if (l <= nl && r >= nr) 33 | return val; 34 | if (l >= nr || nl >= r) 35 | return 0; 36 | propagate(); 37 | return pl->query(l, r) + pr->query(l, r); 38 | } 39 | }; -------------------------------------------------------------------------------- /Segment tree/pointer.cpp: -------------------------------------------------------------------------------- 1 | struct Tree { 2 | Tree *pl, *pr; 3 | int nl = 0, nr = 0, val = 0; 4 | 5 | void updateVal() { val = pl->val + pr->val; } 6 | 7 | Tree(int l, int r, int A[]) { 8 | nl = l, nr = r; 9 | if (nl + 1 == nr) { 10 | val = A[nl]; 11 | return; 12 | } 13 | pl = new Tree(nl, nl + nr >> 1, A); 14 | pr = new Tree(nl + nr >> 1, nr, A); 15 | updateVal(); 16 | } 17 | void modify(int p, int x) { 18 | if (p < nl || nr <= p) { 19 | return; 20 | } 21 | if (nl + 1 == nr) { 22 | val = x; 23 | return; 24 | } 25 | pl->modify(p, x); 26 | pr->modify(p, x); 27 | updateVal(); 28 | } 29 | int query(int l, int r) { 30 | if (l <= nl && r >= nr) 31 | return val; 32 | if (l >= nr || nl >= r) 33 | return 0; 34 | return pl->query(l, r) + pr->query(l, r); 35 | } 36 | }; -------------------------------------------------------------------------------- /Segment tree/range modify point query.cpp: -------------------------------------------------------------------------------- 1 | int seg[2 * MAXN]; 2 | 3 | void modify(int l, int r, int val) { 4 | for (l += N, r += N; l < r; l >>= 1, r >>= 1) { 5 | if (l & 1) 6 | seg[l++] += val; 7 | if (r & 1) 8 | seg[--r] += val; 9 | } 10 | } 11 | 12 | int query(int p) { 13 | int res = 0; 14 | for (p += N; p > 0; p >>= 1) 15 | res += seg[p]; 16 | return res; 17 | } -------------------------------------------------------------------------------- /Segment tree/range query point modify (standard).cpp: -------------------------------------------------------------------------------- 1 | int seg[2 * MAXN]; 2 | void build() { 3 | for (int i = N - 1; i >= 0; i--) 4 | seg[i] = seg[i << 1] + seg[i << 1 | 1]; 5 | } 6 | 7 | void modify(int p, int val) { 8 | for (seg[p += N] = val; p > 0; p >>= 1) 9 | seg[p >> 1] = seg[p] + seg[p ^ 1]; 10 | } 11 | 12 | int query(int l, int r) { 13 | int res = 0; 14 | for (l += N, r += N; l < r; l >>= 1, r >>= 1) { 15 | if (l & 1) 16 | res += seg[l++]; 17 | if (r & 1) 18 | res += seg[--r]; 19 | } 20 | return res; 21 | } -------------------------------------------------------------------------------- /Suffix Array/description.txt: -------------------------------------------------------------------------------- 1 | Suffix Array 2 | -------------------------------------------------------------------------------- /Suffix Array/suffix_array.cpp: -------------------------------------------------------------------------------- 1 | struct SuffixArray { // sa[0] = n, sa[i] = i-th in sorted suffix array. O(n log n) 2 | #define rep(i, a, b) for (int i = a; i < (b); i++) 3 | vector sa, lcp; 4 | SuffixArray(string &s, int lim = 256) { 5 | int n = s.size() + 1, k = 0, a, b; 6 | vector x(all(s) + 1), y(n), ind(n), ws(max(n, lim)), rank(n); 7 | sa = lcp = y, iota(all(sa), 0); 8 | for (int j = 0, p = 0; p < n; j = max(1, j * 2), lim = p) { 9 | p = j, iota(all(y), n - j); 10 | rep(i, 0, n) if (sa[i] >= j) y[p++] = sa[i] - j; 11 | rep(i, 0, n) ind[i] = x[y[i]]; 12 | fill(all(ws), 0); 13 | rep(i, 0, n) ws[ind[i]]++; 14 | rep(i, 1, lim) ws[i] += ws[i - 1]; 15 | for (int i = n; i--;) sa[--ws[ind[i]]] = y[i]; 16 | swap(x, y), p = 1, x[sa[0]] = 0; 17 | rep(i, 1, n) a = sa[i - 1], b = sa[i], x[b] = (y[a] == y[b] && y[a + j] == y[b + j]) ? p - 1 : p++; 18 | } //lcp[0] = 0, lcp[i] = lcp(sa[i], sa[i-1]) 19 | rep(i, 1, n) rank[sa[i]] = i; 20 | for (int i = 0, j; i < n - 1; lcp[rank[i++]] = k) 21 | for (k &&k--, j = sa[rank[i] - 1]; s[i + k] == s[j + k]; k++); 22 | } 23 | #undef rep 24 | }; -------------------------------------------------------------------------------- /Treap/description.txt: -------------------------------------------------------------------------------- 1 | Treap 2 | -------------------------------------------------------------------------------- /Treap/treap.cpp: -------------------------------------------------------------------------------- 1 | auto seed = chrono::high_resolution_clock::now().time_since_epoch().count(); 2 | mt19937 rnd(seed); 3 | 4 | struct node { 5 | node *l = nullptr, *r = nullptr; 6 | int val, key = rnd(); 7 | int sz = 1; 8 | node(int value) : val(value) {} 9 | ~node() { delete l, delete r; } 10 | node *upd() { 11 | sz = 1 + (l ? l->sz : 0) + (r ? r->sz : 0); 12 | return this; 13 | } 14 | }; 15 | 16 | struct treap { 17 | node *root; 18 | treap() { root = nullptr; } 19 | void split(node *t, int val, node *&l, node *&r) { 20 | if (!t) { 21 | l = nullptr, r = nullptr; 22 | return; 23 | } else if (t->val < val) { 24 | split(t->r, val, t->r, r); 25 | l = t; 26 | } else { 27 | split(t->l, val, l, t->l); 28 | r = t; 29 | } 30 | t->upd(); 31 | } 32 | node *merge(node *l, node *r) { 33 | if (!l || !r) 34 | return (l ? l : r); 35 | if (l->key > r->key) { 36 | l->r = merge(l->r, r); 37 | return l->upd(); 38 | } else { 39 | r->l = merge(r->l, l); 40 | return r->upd(); 41 | } 42 | } 43 | bool find(node *t, int val) { 44 | if (!t) 45 | return false; 46 | if (t->val == val) 47 | return true; 48 | return find((t->val > val) ? t->l : t->r, val); 49 | } 50 | void insert(int val) { 51 | if (find(root, val)) 52 | return; 53 | node *l, *r; 54 | split(root, val, l, r); 55 | root = merge(l, merge(new node(val), r)); 56 | } 57 | void erase(int val) { 58 | if (!find(root, val)) 59 | return; 60 | node *l, *t, *r; 61 | split(root, val, l, t); 62 | split(t, val + 1, t, r); 63 | delete t; 64 | root = merge(l, r); 65 | } 66 | int size() { return root ? root->sz : 0; } 67 | int index(node *t, int i) { 68 | int lsz = t->l ? t->l->sz : 0; 69 | if (i == lsz) 70 | return t->val; 71 | if (i < lsz) 72 | return index(t->l, i); 73 | return index(t->r, i - lsz - 1); 74 | } 75 | int indexof(node *t, int x) { 76 | int lsz = t->l ? t->l->sz : 0; 77 | if (t->val == x) 78 | return lsz; 79 | if (t->val < x) 80 | return lsz + 1 + indexof(t->r, x); 81 | return indexof(t->l, x); 82 | } 83 | }; -------------------------------------------------------------------------------- /Tree Diameter: O(N)/description.txt: -------------------------------------------------------------------------------- 1 | Tree Diameter: O(N) 2 | -------------------------------------------------------------------------------- /Tree Diameter: O(N)/diameter.cpp: -------------------------------------------------------------------------------- 1 | int dfs(int cur, int prv = -1, int d = 0) { 2 | dist[cur] = d; 3 | int mx = cur; 4 | for (auto i : adj[cur]) { 5 | if (i == prv) 6 | continue; 7 | int res = dfs(i, cur, d + 1); 8 | if (dist[res] > dist[mx]) 9 | mx = res; 10 | } 11 | return mx; 12 | } 13 | cout<