├── .gitignore ├── README.md └── content ├── contest ├── .vimrc ├── r.sh ├── template.cpp └── template_big.cpp ├── data-structures ├── bit.cpp ├── bit2d.cpp ├── bit_multi.cpp ├── cht.cpp ├── implicit_segtree.cpp ├── implicit_treap.cpp ├── iterative_seg_tree.cpp ├── linear_cht.cpp ├── min_queue.cpp ├── persistent_bit_trie.cpp ├── persistent_lichao.cpp ├── persistent_seg_tree.cpp ├── rmq.cpp ├── seg_tree.cpp ├── seg_tree_beats.cpp ├── seg_tree_lazy.cpp ├── seg_tree_lazy_add_set.cpp ├── seg_tree_poly.cpp ├── slope_trick.cpp ├── treap_beats.cpp ├── trie_bit.cpp └── xor_base.cpp ├── experimental ├── generic_rmq.cpp └── generic_seg_tree.cpp ├── geometry ├── Emerson.cpp ├── circle.cpp ├── closest_pair.cpp ├── convex_hull.cpp ├── half_plane.cpp ├── in_polygon.cpp ├── intersecting_segments.cpp ├── point.cpp ├── polygon.cpp └── sum_minkowski.cpp ├── geometry2 ├── half_plane_intersection.cpp ├── minkowski.cpp └── point.cpp ├── graph ├── articulation_points.cpp ├── bipartite_matching.cpp ├── block_cut_tree.cpp ├── blossom.cpp ├── bridges.cpp ├── centroid_decomposition.cpp ├── dsu.cpp ├── euler_path.cpp ├── hld.cpp ├── lca.cpp ├── link_cut_tree.cpp ├── max_flow.cpp ├── mcmf.cpp ├── scc.cpp ├── twosat.cpp └── undirected_eulerian_path.cpp ├── math ├── FWHT.cpp ├── Lagrange.cpp ├── ceil_div.cpp ├── circular_fft.cpp ├── crt.cpp ├── diophantine.cpp ├── discrete_log.cpp ├── discrete_root.cpp ├── division_trick.cpp ├── ext_gcd.cpp ├── fft.cpp ├── fft2D.cpp ├── floor_div.cpp ├── floor_sum.cpp ├── gauss.cpp ├── gaussXor.cpp ├── linear_sieve.cpp ├── mobius.cpp ├── nck.cpp ├── ntt.cpp ├── online_gauss.cpp ├── pollardrho.cpp └── simplex.cpp ├── miscellaneous ├── dynamic_ds.cpp ├── hilbert_order.cpp └── rotate_matrix.cpp ├── primitives ├── frac.cpp ├── function.cpp ├── hash.cpp ├── matrix.cpp └── mint.cpp └── string ├── aho_corasick.cpp ├── hash.cpp ├── kmp.cpp ├── manacher.cpp ├── suffix_array.cpp ├── suffix_automaton.cpp ├── trie.cpp └── z_function.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | notebook.pdf 3 | .vscode -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Competitive Programming Notebook 2 | 3 | -------------------------------------------------------------------------------- /content/contest/.vimrc: -------------------------------------------------------------------------------- 1 | inoremap jk 2 | inoremap { {}O 3 | 4 | set number relativenumber noswapfile hlsearch ignorecase incsearch showcmd 5 | set tabstop=8 softtabstop=0 expandtab shiftwidth=4 smarttab autoindent 6 | 7 | autocmd filetype cpp nnoremap :w !g++ % -Wall -Wextra -Wshadow -Wconversion -Wlogical-op -Wshift-overflow=2 -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC -D_FORTIFY_SOURCE=2 -fsanitize=address -fsanitize=undefined -fno-sanitize-recover -fstack-protector -std=c++20 -o %:r && ./%:r 8 | autocmd filetype cpp nnoremap :w !g++ % (flags) -o %:r && ./%:r < ./in.txt 9 | 10 | syntax on 11 | syntax enable 12 | filetype plugin indent on 13 | 14 | -------------------------------------------------------------------------------- /content/contest/r.sh: -------------------------------------------------------------------------------- 1 | g++ -Wall -Wextra -Wshadow -Wconversion -Wlogical-op -Wshift-overflow=2 -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC -D_FORTIFY_SOURCE=2 -fsanitize=address -fsanitize=undefined -fno-sanitize-recover -fstack-protector -o $1 $1.cpp && ./$1 2 | -------------------------------------------------------------------------------- /content/contest/template.cpp: -------------------------------------------------------------------------------- 1 | #include "bits/stdc++.h" 2 | using namespace std; 3 | 4 | #define endl '\n' 5 | #define rep(i, a, b) for (int i = a; i < (b); i++) 6 | #define all(x) (x).begin(), (x).end() 7 | #define sz(x) (int)(x).size() 8 | typedef long long ll; 9 | 10 | int main() { 11 | cin.tie(0)->sync_with_stdio(0); 12 | } 13 | 14 | -------------------------------------------------------------------------------- /content/contest/template_big.cpp: -------------------------------------------------------------------------------- 1 | #include "bits/stdc++.h" 2 | using namespace std; 3 | //#pragma once 4 | //#pragma GCC optimize("O3,unroll-loops") 5 | //#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt") 6 | 7 | #define endl '\n' 8 | #define rep(i, a, b) for (int i = a; i < (b); i++) 9 | #define all(x) (x).begin(), (x).end() 10 | #define sz(x) (int)(x).size() 11 | #define sq(x) (x)*(x) 12 | template inline void chmin(T& a, U b) { if (a > b) a = b; } 13 | template inline void chmax(T& a, U b) { if (a < b) a = b; } 14 | mt19937 rng((int) chrono::steady_clock::now().time_since_epoch().count()); 15 | typedef long long ll; 16 | typedef long double ld; 17 | typedef __int128 i128; 18 | 19 | void solve_tc() { 20 | } 21 | 22 | int main() { 23 | cin.tie(0)->sync_with_stdio(0); 24 | int tc = 1; 25 | cin >> tc; 26 | while (tc--) solve_tc(); 27 | } 28 | 29 | -------------------------------------------------------------------------------- /content/data-structures/bit.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | template struct bit { 4 | int n; 5 | vector a; 6 | bit(int n) : n(n), a(n + 1) {} 7 | void add(int pos, T x) { 8 | for (; pos <= n; pos += (pos & -pos)) a[pos] += x; 9 | } 10 | T query(int pos) { 11 | T ans = 0; 12 | for (; pos > 0; pos -= (pos & -pos)) ans += a[pos]; 13 | return ans; 14 | } 15 | T query(int l, int r) { 16 | return query(r) - query(l - 1); 17 | } 18 | // min R such that a[1] + a[2] + ... + a[R] >= x, -1 if there's no valid R 19 | int min_right(T x) { 20 | int ans = -1, i = 31 - __builtin_clz(n), ac = 0; 21 | for (T cur = 0; i >= 0; i--) if (ac + (1 << i) <= n) { 22 | if (cur + a[(1 << i) + ac] >= x) ans = (1 << i) + ac; 23 | else ac += (1 << i), cur += a[ac]; 24 | } 25 | return ans; 26 | } 27 | // max R such that a[1] + a[2] + ... + a[R] <= x. -1 if there's no valid R 28 | int max_right(T x) { 29 | int i = 31 - __builtin_clz(n), ac = 0; 30 | for (T cur = 0; i >= 0; i--) { 31 | if (ac + (1 << i) <= n && cur + a[(1 << i) + ac] <= x) 32 | ac += (1 << i), cur += a[ac]; 33 | } 34 | return ac - (ac == 0); 35 | } 36 | }; 37 | 38 | -------------------------------------------------------------------------------- /content/data-structures/bit2d.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | template struct bit { 4 | int n; 5 | vector> a; 6 | bit (int n) : n(n), a(n + 1, vector(n + 1)) {} 7 | void add(int i, int j, T val) { 8 | for (; i <= n; i += i & -i) { 9 | for (int pos = j; pos <= n; pos += pos & -pos) { 10 | a[i][pos] += val; 11 | } 12 | } 13 | } 14 | T query(int i, int j) { 15 | T ans = 0; 16 | for (; i > 0; i -= i & -i) { 17 | for (int pos = j; pos > 0; pos -= pos & -pos) { 18 | ans += a[i][pos]; 19 | } 20 | } 21 | return ans; 22 | } 23 | }; 24 | 25 | -------------------------------------------------------------------------------- /content/data-structures/bit_multi.cpp: -------------------------------------------------------------------------------- 1 | // adapted from https://codeforces.com/blog/entry/64914 2 | #include "../contest/template.cpp" 3 | 4 | template struct bit { 5 | int val = 0; 6 | void update(int val) { this->val += val; } 7 | int query() { return val; } 8 | int pre() { return val; } 9 | }; 10 | 11 | template struct bit { 12 | bit b[N + 1]; 13 | template 14 | void update(int idx, Args... args) { 15 | for (; idx <= N; b[idx].update(args...), idx += idx & -idx); 16 | } 17 | template 18 | int query(int l, int r, Args... args) { 19 | int ans = 0; 20 | for (; r >= 1; ans += b[r].query(args...), r -= r & -r); 21 | for (--l; l >= 1; ans -= b[l].query(args...), l -= l & -l); 22 | return ans; 23 | } 24 | template 25 | int pre(int idx, Args... args) { 26 | int ans = 0; 27 | for (; idx > 0; ans += b[idx].pre(args...), idx -= idx & -idx); 28 | return ans; 29 | } 30 | }; 31 | 32 | -------------------------------------------------------------------------------- /content/data-structures/cht.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | struct Line { 4 | mutable ll k, m, p; 5 | bool operator<(const Line& o) const { return k < o.k; } 6 | bool operator<(ll x) const { return p < x; } 7 | }; 8 | 9 | // max queries 10 | struct LineContainer : multiset> { 11 | // (for doubles, use inf = 1/.0, div(a,b) = a/b) 12 | static const ll inf = LLONG_MAX; 13 | ll div(ll a, ll b) { // floored division 14 | return a / b - ((a ^ b) < 0 && a % b); } 15 | bool isect(iterator x, iterator y) { 16 | if (y == end()) return x->p = inf, 0; 17 | if (x->k == y->k) x->p = x->m > y->m ? inf : -inf; 18 | else x->p = div(y->m - x->m, x->k - y->k); 19 | return x->p >= y->p; 20 | } 21 | void add(ll k, ll m) { 22 | auto z = insert({k, m, 0}), y = z++, x = y; 23 | while (isect(y, z)) z = erase(z); 24 | if (x != begin() && isect(--x, y)) isect(x, y = erase(y)); 25 | while ((y = x) != begin() && (--x)->p >= y->p) 26 | isect(x, erase(y)); 27 | } 28 | ll query(ll x) { 29 | assert(!empty()); 30 | auto l = *lower_bound(x); 31 | return l.k * x + l.m; 32 | } 33 | // to make min queries, k = -k, m = -m, return -query(x) 34 | }; 35 | 36 | -------------------------------------------------------------------------------- /content/data-structures/implicit_segtree.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | struct Data { 4 | ll sum; 5 | Data() { sum = 0; } 6 | Data operator + (const Data &oth) const { 7 | Data ans; 8 | ans.sum = sum + oth.sum; 9 | return ans; 10 | } 11 | }; 12 | struct Vertex { 13 | int l, r; 14 | Data info; 15 | Vertex *lc = nullptr, *rc = nullptr; 16 | Vertex(int lb, int rb) : l(lb), r(rb) { 17 | info.sum = 0; 18 | } 19 | void extend() { 20 | if (!lc && l != r) { 21 | int mid = (l + r) / 2; 22 | lc = new Vertex(l, mid); 23 | rc = new Vertex(mid + 1, r); 24 | } 25 | } 26 | void update(int pos, int val) { 27 | if (l == r) { 28 | info.sum = val; 29 | } else { 30 | extend(); 31 | int mid = (l + r) / 2; 32 | if (pos <= mid) lc->update(pos, val); 33 | else rc->update(pos, val); 34 | info = lc->info + rc->info; 35 | } 36 | } 37 | Data query(int lq, int rq) { 38 | if (lq <= l && r <= rq) return info; 39 | if (l > rq || r < lq) return Data(); 40 | extend(); 41 | return lc->query(lq, rq) + rc->query(lq, rq); 42 | } 43 | }; 44 | 45 | -------------------------------------------------------------------------------- /content/data-structures/implicit_treap.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); 4 | 5 | template struct treap { 6 | struct node { 7 | int p, rev, cnt; 8 | T val; 9 | node *l, *r; 10 | node(T val_) : p(rng()), rev(0), cnt(1), l(nullptr), r(nullptr) { 11 | val = val_; 12 | } 13 | }; 14 | typedef node* pnode; 15 | pnode root = nullptr; 16 | 17 | int cnt(pnode t) { return t ? t->cnt : 0; } 18 | void recalc(pnode t) { 19 | if (t) { 20 | t->cnt = 1 + cnt(t->l) + cnt(t->r); 21 | } 22 | } 23 | void push(pnode t) { 24 | if (t && t->rev) { 25 | t->rev = 0; 26 | swap(t->l, t->r); 27 | if (t->l) t->l->rev ^= 1; 28 | if (t->r) t->r->rev ^= 1; 29 | } 30 | } 31 | void split(pnode t, pnode &l, pnode &r, int pos) { 32 | if (!t) return void(l = r = nullptr); 33 | push(t); 34 | if (cnt(t->l) < pos) split(t->r, t->r, r, pos - cnt(t->l) - 1), l = t; 35 | else split(t->l, l, t->l, pos), r = t; 36 | recalc(t); 37 | } 38 | void merge(pnode &t, pnode a, pnode b) { 39 | push(a), push(b); 40 | if (!a || !b) return void(t = a ? a : b); 41 | if (a->p > b->p) merge(a->r, a->r, b), t = a; 42 | else merge(b->l, a, b->l), t = b; 43 | recalc(t); 44 | } 45 | void insert(int pos, T val) { 46 | pnode a, b; 47 | split(root, a, b, pos); 48 | merge(a, a, new node(val)); 49 | merge(root, a, b); 50 | } 51 | void erase(pnode &t, int pos) { 52 | if (cnt(t->l) == pos) { 53 | pnode tmp = t; 54 | merge(t, t->l, t->r); 55 | delete tmp; 56 | } 57 | else if (cnt(t->l) < pos) erase(t->r, pos - cnt(t->l) - 1); 58 | else erase(t->l, pos); 59 | recalc(t); 60 | } 61 | void erase(int pos) { erase(root, pos); } 62 | void reverse(int l, int r) { 63 | if (l >= r) return; 64 | pnode a, b, c; 65 | split(root, a, b, l); 66 | split(b, b, c, r - l + 1); 67 | b->rev ^= 1; 68 | merge(root, a, b); 69 | merge(root, root, c); 70 | } 71 | void swap_ranges(int l1, int r1, int l2, int r2) { 72 | pnode a, b, c, d, e; 73 | split(root, a, b, l1); 74 | split(b, b, c, r1 - l1 + 1); 75 | split(c, c, d, l2 - r1 - 1); 76 | split(d, d, e, r2 - l2 + 1); 77 | merge(root, a, d); 78 | merge(root, root, c); 79 | merge(root, root, b); 80 | merge(root, root, e); 81 | } 82 | T get(int l, int r) { 83 | pnode a, b, c; 84 | split(root, a, b, l); 85 | split(b, b, c, r - l + 1); 86 | int ans = b->val; 87 | merge(root, a, b); 88 | merge(root, root, c); 89 | return ans; 90 | } 91 | treap(vector &a) { 92 | for (int i = 0; i < (int)a.size(); i++) insert(i, a[i]); 93 | } 94 | void print(pnode t) { 95 | if (!t) return; 96 | push(t); 97 | print(t->l); 98 | cout << t->val << " "; 99 | print(t->r); 100 | } 101 | void print() { print(root); cout << endl; } 102 | }; 103 | 104 | -------------------------------------------------------------------------------- /content/data-structures/iterative_seg_tree.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | template struct seg_tree { 4 | struct node { 5 | T x = LLONG_MIN; 6 | const node operator + (const node& o) const { 7 | node ans; 8 | ans.x = max(o.x, x); 9 | return ans; 10 | } 11 | }; 12 | int n; 13 | vector tree; 14 | seg_tree(int _n) : n(_n), tree(n * 2) {} 15 | void update(int i, T f) { 16 | i += n; 17 | tree[i].x = f; 18 | for (i >>= 1; i >= 1; i >>= 1) tree[i] = tree[i * 2] + tree[i * 2 + 1]; 19 | } 20 | T query(int a, int b) { 21 | node esq; 22 | node dir; 23 | for (a += n, b += n; a <= b; a >>= 1, b >>= 1) { 24 | if (a % 2) esq = esq + tree[a++]; 25 | if (b % 2 == 0) dir = tree[b--] + dir; 26 | } 27 | return (esq + dir).x; 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /content/data-structures/linear_cht.cpp: -------------------------------------------------------------------------------- 1 | // https://codeforces.com/contest/1083/problem/E 2 | #include "../contest/template.cpp" 3 | 4 | struct line { 5 | ll a, b; 6 | ll eval(ll x) { 7 | return a * x + b; 8 | } 9 | long double inter(const line &oth) const { 10 | return (long double) (-b + oth.b) / (a - oth.a); 11 | } 12 | }; 13 | 14 | // non-increasing slope, non-increasing queries, max queries 15 | struct cht { 16 | deque q; 17 | void add(ll a, ll b) { 18 | line cur = { a, b }; 19 | while (q.size() > 1) { 20 | if (q.back().a == a) { 21 | if (b <= q.back().b) return; 22 | q.pop_back(); 23 | continue; 24 | } 25 | if (cur.inter(q[q.size() - 1]) < cur.inter(q[q.size() - 2])) break; 26 | q.pop_back(); 27 | } 28 | q.push_back(cur); 29 | } 30 | ll query(ll x) { 31 | while (q.size() > 1 && q[0].eval(x) <= q[1].eval(x)) q.pop_front(); 32 | return q[0].eval(x); 33 | } 34 | }; 35 | 36 | -------------------------------------------------------------------------------- /content/data-structures/min_queue.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | template struct min_queue { 4 | int added = 0, removed = 0; 5 | deque> q; 6 | 7 | T min() { return q.front().first; } 8 | 9 | void add(T val) { 10 | // for maximum, switch to < 11 | while (!q.empty() && q.back().first > val) q.pop_back(); 12 | q.push_back({val, added}); 13 | added++; 14 | } 15 | 16 | void pop() { 17 | if (!q.empty() && q.front().second == removed) q.pop_front(); 18 | removed++; 19 | } 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /content/data-structures/persistent_bit_trie.cpp: -------------------------------------------------------------------------------- 1 | // tested on https://codeforces.com/group/XrhoJtxCjm/contest/422671/problem/H 2 | #include "../contest/template.cpp" 3 | 4 | struct trie { 5 | struct node { 6 | int ch[2], cnt; 7 | node() { 8 | ch[0] = ch[1] = -1; 9 | cnt = 0; 10 | } 11 | }; 12 | const static int ms = (500000) * 20, LG = 20; 13 | node buffer[ms]; 14 | int CNT = 1; 15 | vector vs = { 0 }; 16 | int get_cnt(int v) { 17 | return v == -1 ? 0 : buffer[v].cnt; 18 | } 19 | int get_ch(int v, int bit) { 20 | return v == -1 ? -1 : buffer[v].ch[bit]; 21 | } 22 | int insert(int v, int x, int bit) { 23 | int ans = CNT++; 24 | if (bit < 0) { 25 | buffer[ans].cnt = 1 + get_cnt(v); 26 | return ans; 27 | } 28 | int nxt = (x & (1 << bit)) > 0; 29 | buffer[ans].ch[nxt] = insert(get_ch(v, nxt), x, bit - 1); 30 | buffer[ans].ch[nxt ^ 1] = get_ch(v, nxt ^ 1); 31 | buffer[ans].cnt = get_cnt(buffer[ans].ch[0]) + get_cnt(buffer[ans].ch[1]); 32 | return ans; 33 | } 34 | void insert(int x) { 35 | vs.push_back(insert(vs.back(), x, LG)); 36 | } 37 | int xor_max(int vl, int vr, int x, int bit) { 38 | if (bit < 0) return 0; 39 | 40 | int nxt = (x & (1 << bit)) == 0; 41 | if (get_cnt(get_ch(vr, nxt)) - get_cnt(get_ch(vl, nxt)) > 0) { 42 | return (1 << bit) + xor_max(get_ch(vl, nxt), get_ch(vr, nxt), x, bit - 1); 43 | } 44 | return xor_max(get_ch(vl, nxt ^ 1), get_ch(vr, nxt ^ 1), x, bit - 1); 45 | } 46 | int xor_max(int l, int r, int x) { 47 | return xor_max(vs[l - 1], vs[r], x, LG); 48 | } 49 | 50 | void erase(int k) { 51 | while (k--) { 52 | vs.pop_back(); 53 | } 54 | } 55 | }; 56 | 57 | -------------------------------------------------------------------------------- /content/data-structures/persistent_lichao.cpp: -------------------------------------------------------------------------------- 1 | // tested on https://codeforces.com/group/XrhoJtxCjm/contest/422715/problem/K 2 | #include "../contest/template.cpp" 3 | 4 | const ll INF = 1e18; 5 | struct PersistentLiChaoTree { 6 | PersistentLiChaoTree() { 7 | tree.push_back({-1, -1, s, e, Line(0, -INF)}); 8 | } 9 | 10 | struct Line { 11 | int idx; 12 | ll a, b; 13 | Line(ll a, ll b, int idx = -1) : a(a), b(b), idx(idx) {} 14 | Line() {} 15 | ll f(ll x) { 16 | return a * x + b; 17 | } 18 | 19 | bool best(Line ot, ll x) { 20 | return f(x) > ot.f(x); 21 | } 22 | }; 23 | Line best(Line a, Line b, ll x) { 24 | return (a.best(b, x) ? a : b); 25 | }; 26 | 27 | struct Node { 28 | int l, r; 29 | ll xl, xr; 30 | Line line; 31 | Node(int l, int r, ll xl, ll xr, Line line) : l(l), r(r), xl(xl), xr(xr), line(line) {} 32 | }; 33 | 34 | struct Info { 35 | int l, r; 36 | ll a, b; 37 | }; 38 | 39 | vector tree; 40 | vector>> change; 41 | ll s = -2e9, e = 2e9; 42 | 43 | void add_line(Line new_line, int i = 0) { 44 | ll xl = tree[i].xl, xr = tree[i].xr; 45 | ll xm = (xl + xr) >> 1; 46 | 47 | change.back().push_back({i, {tree[i].l, tree[i].r, tree[i].line.a, tree[i].line.b}}); 48 | 49 | Line low = tree[i].line, high = new_line; 50 | if (low.best(high, xl)) swap(low, high); 51 | 52 | if (high.best(low, xr)) { 53 | tree[i].line = high; 54 | return; 55 | }else if (high.best(low, xm)) { 56 | tree[i].line = high; 57 | if (tree[i].r == -1) { 58 | tree[i].r = tree.size(); 59 | tree.push_back({-1, -1, xm + 1, xr, Line(0, -INF)}); 60 | } 61 | add_line(low, tree[i].r); 62 | }else { 63 | tree[i].line = low; 64 | if (tree[i].l == -1) { 65 | tree[i].l = tree.size(); 66 | tree.push_back({-1, -1, xl, xm, Line(0, -INF)}); 67 | } 68 | add_line(high, tree[i].l); 69 | } 70 | } 71 | 72 | Line query2(ll x, int i = 0) { 73 | if (i == -1) return Line(0,-INF); 74 | ll xl = tree[i].xl, xr = tree[i].xr; 75 | ll xm = (xl + xr) >> 1; 76 | if (x <= xm) return best(tree[i].line, query2(x, tree[i].l), x); 77 | else return best(tree[i].line, query2(x, tree[i].r), x); 78 | } 79 | ll query(ll x, int i = 0) { return query2(x, i).f(x); } 80 | 81 | void add_line(ll a, ll b) { 82 | change.push_back({}); 83 | add_line({a, b}, 0); 84 | } 85 | 86 | void delete_line() { 87 | for (auto &[i, info] : change.back()) { 88 | tree[i].l = info.l; 89 | tree[i].r = info.r; 90 | tree[i].line.a = info.a; 91 | tree[i].line.b = info.b; 92 | } 93 | change.pop_back(); 94 | } 95 | }; 96 | -------------------------------------------------------------------------------- /content/data-structures/persistent_seg_tree.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | // 1-indexed 3 | 4 | struct seg_tree { 5 | struct node { 6 | int x, l, r; 7 | node () : l(-1), r(-1), x(0) {} 8 | node (int val) : l(-1), r(-1), x(val) {} 9 | node operator + (const node &oth) const { 10 | return node(x + oth.x); 11 | } 12 | }; 13 | 14 | vector nodes; 15 | vector roots; 16 | int n; 17 | 18 | int create(int val) { 19 | nodes.push_back(node(val)); 20 | return (int)nodes.size() - 1; 21 | } 22 | int create(int l, int r) { 23 | nodes.push_back(nodes[l] + nodes[r]); 24 | nodes.back().l = l, nodes.back().r = r; 25 | return (int)nodes.size() - 1; 26 | } 27 | seg_tree(vector a) : n(a.size()) { 28 | roots.push_back(build(1, n, a)); 29 | } 30 | int build(int l, int r, vector &a) { 31 | if (l == r) return create(a[l - 1]); 32 | int mid = (l + r) / 2; 33 | return create(build(l, mid, a), build(mid + 1, r, a)); 34 | } 35 | int update(int l, int r, int pos, int val, int v) { 36 | if (l == r) return create(val + nodes[v].x); // add / set 37 | int mid = (l + r) / 2; 38 | if (pos <= mid) return create(update(l, mid, pos, val, nodes[v].l), nodes[v].r); 39 | return create(nodes[v].l, update(mid + 1, r, pos, val, nodes[v].r)); 40 | } 41 | node query(int l, int r, int lq, int rq, int v) { 42 | if (lq <= l && r <= rq) return nodes[v]; 43 | if (l > rq || r < lq) return node(); 44 | int mid = (l + r) / 2; 45 | return query(l, mid, lq, rq, nodes[v].l) + query(mid + 1, r, lq, rq, nodes[v].r); 46 | } 47 | void update(int pos, int val, int version = -1) { 48 | version = (version == -1 ? roots.back() : roots[version]); 49 | roots.push_back(update(1, n, pos, val, version)); 50 | } 51 | node query(int l, int r, int version) { return query(1, n, l, r, roots[version]); } 52 | }; 53 | 54 | 55 | -------------------------------------------------------------------------------- /content/data-structures/rmq.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | template struct rmq { 4 | vector> t; 5 | 6 | rmq() {} 7 | rmq(const vector &a) { 8 | int n = a.size(), lg = 31 - __builtin_clz(n); 9 | t = vector>(lg + 1, vector(n)); 10 | rep(i, 0, n) t[0][i] = a[i]; 11 | for (int i = 1; (1 << i) <= n; i++) for (int j = 0; j + (1 << i) <= n; j++) 12 | t[i][j] = min(t[i - 1][j], t[i - 1][j + (1 << (i - 1))]); 13 | } 14 | 15 | T query(int l, int r) { 16 | if (l > r) swap(l, r); 17 | int lg = 31 - __builtin_clz(r - l + 1); 18 | return min(t[lg][l], t[lg][r - (1 << lg) + 1]); 19 | } 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /content/data-structures/seg_tree.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | template struct seg_tree { 4 | struct node { 5 | T x; 6 | node() : x(0) {} 7 | node(T x) : x(x) {} 8 | node operator + (const node &o) const { 9 | return node(x + o.x); 10 | } 11 | }; 12 | int n; 13 | vector tree; 14 | seg_tree(int n) : n(n), tree(n * 4) {} 15 | 16 | inline int left(int id) { return (id << 1); } 17 | inline int right(int id) { return (id << 1) | 1; } 18 | 19 | void set(int id, int l, int r, int pos, T val) { 20 | if (l == r) tree[id] = node(val); 21 | else { 22 | int mid = (l + r) >> 1; 23 | if (pos <= mid) set(left(id), l, mid, pos, val); 24 | else set(right(id), mid + 1, r, pos, val); 25 | tree[id] = tree[left(id)] + tree[right(id)]; 26 | } 27 | } 28 | 29 | node query(int id, int l, int r, int lq, int rq) { 30 | if (l > rq || r < lq) return node(); 31 | if (lq <= l && r <= rq) return tree[id]; 32 | int mid = (l + r) >> 1; 33 | return query(left(id), l, mid, lq, rq) + query(right(id), mid + 1, r, lq, rq); 34 | } 35 | 36 | // min R such that f(a[L] + a[L + 1] + ... + a[R]) is true 37 | template 38 | int min_right(int L, F f) { 39 | int ans = -1; 40 | node cur; 41 | auto go = [&](auto &&self, int id, int l, int r) -> bool { 42 | if (r < L) return false; 43 | int mid = (l + r) / 2; 44 | if (L <= l) { 45 | auto new_cur = cur + tree[id]; 46 | if (!f(new_cur)) return (cur = new_cur), false; 47 | ans = r; 48 | if (l != r) { 49 | new_cur = cur + tree[left(id)]; 50 | if (!f(new_cur)) cur = new_cur, self(self, right(id), mid + 1, r); 51 | else self(self, left(id), l, mid); 52 | } 53 | return true; 54 | } 55 | if (self(self, left(id), l, mid)) return true; 56 | return self(self, right(id), mid + 1, r); 57 | }; 58 | go(go, 1, 0, n - 1); 59 | return ans; 60 | } 61 | 62 | // max L such that f(a[L] + a[L + 1] + ... + a[R]) is true 63 | template 64 | int max_left(int R, F f) { 65 | int ans = -1; 66 | node cur; 67 | auto go = [&](auto &&self, int id, int l, int r) -> bool { 68 | if (l > R) return false; 69 | int mid = (l + r) / 2; 70 | if (r <= R) { 71 | auto new_cur = tree[id] + cur; 72 | if (!f(new_cur)) return (cur = new_cur), false; 73 | ans = l; 74 | if (l != r) { 75 | new_cur = tree[right(id)] + cur; 76 | if (!f(new_cur)) cur = new_cur, self(self, left(id), l, mid); 77 | else self(self, right(id), mid + 1, r); 78 | } 79 | return true; 80 | } 81 | if (self(self, right(id), mid + 1, r)) return true; 82 | return self(self, left(id), l, mid); 83 | }; 84 | go(go, 1, 0, n - 1); 85 | return ans; 86 | } 87 | 88 | void set(int pos, T val) { set(1, 0, n - 1, pos, val); } 89 | node query(int l, int r) { return query(1, 0, n - 1, l, r); } 90 | }; 91 | 92 | -------------------------------------------------------------------------------- /content/data-structures/seg_tree_beats.cpp: -------------------------------------------------------------------------------- 1 | // tested on https://atcoder.jp/contests/abc256/tasks/abc256_h 2 | // O(Q * logN * logA) 3 | // update each a_i in [l, r] to val 4 | // update each a_i in [l, r] to floor(a_i / x) 5 | #include "../contest/template.cpp" 6 | 7 | template struct seg_tree { 8 | struct node { 9 | ll sum, al, eq; 10 | node() { 11 | sum = al = 0; 12 | eq = -1; 13 | } 14 | node(ll x) { 15 | sum = al = x; 16 | eq = 1; 17 | } 18 | node operator + (const node &o) const { 19 | node ans; 20 | if (eq == -1) { 21 | ans.sum = o.sum; 22 | ans.al = o.al; 23 | ans.eq = o.eq; 24 | } else if (o.eq == -1) { 25 | ans.sum = sum; 26 | ans.al = al; 27 | ans.eq = eq; 28 | } else { 29 | ans.sum = sum + o.sum; 30 | ans.al = al; 31 | ans.eq = eq && o.eq && al == o.al; 32 | } 33 | return ans; 34 | } 35 | }; 36 | struct lazy_node { 37 | ll set; 38 | lazy_node() : set(-1) {} 39 | }; 40 | 41 | int n; 42 | vector tree; 43 | vector lazy; 44 | 45 | seg_tree(vector a) { 46 | n = a.size(); 47 | tree.resize(n * 4); 48 | lazy.resize(n * 4); 49 | build(1, 0, n - 1, a); 50 | } 51 | 52 | inline int left(int id) { return (id << 1); } 53 | inline int right(int id) { return (id << 1) | 1; } 54 | 55 | void build(int id, int l, int r, const vector &a) { 56 | if (l == r) tree[id] = node(a[l]); 57 | else { 58 | int m = (l + r) >> 1; 59 | build(left(id), l, m, a); 60 | build(right(id), m + 1, r, a); 61 | tree[id] = tree[left(id)] + tree[right(id)]; 62 | } 63 | } 64 | 65 | inline void push(int id, int l, int r) { 66 | if (lazy[id].set == -1) return; 67 | 68 | tree[id].sum = (r - l + 1) * lazy[id].set; 69 | tree[id].al = lazy[id].set; 70 | if (l != r) { 71 | lazy[left(id)].set = lazy[id].set; 72 | lazy[right(id)].set = lazy[id].set; 73 | } 74 | lazy[id].set = -1; 75 | } 76 | 77 | void update(int id, int l, int r, int lq, int rq, T val) { 78 | push(id, l, r); 79 | if (l > rq || r < lq) return; 80 | if (lq <= l && r <= rq) { 81 | lazy[id].set = val; 82 | push(id, l, r); 83 | } else { 84 | int mid = (l + r) >> 1; 85 | update(left(id), l, mid, lq, rq, val); 86 | update(right(id), mid + 1, r, lq, rq, val); 87 | tree[id] = tree[left(id)] + tree[right(id)]; 88 | } 89 | } 90 | 91 | void update_div(int id, int l, int r, int lq, int rq, int x) { 92 | push(id, l, r); 93 | if (l > rq || r < lq) return; 94 | if (tree[id].eq && tree[id].al == 0) return; 95 | 96 | if (lq <= l && r <= rq && tree[id].eq) { 97 | lazy[id].set = tree[id].al / x; 98 | push(id, l, r); 99 | } else { 100 | int mid = (l + r) >> 1; 101 | update_div(left(id), l, mid, lq, rq, x); 102 | update_div(right(id), mid + 1, r, lq, rq, x); 103 | tree[id] = tree[left(id)] + tree[right(id)]; 104 | } 105 | } 106 | 107 | node query(int id, int l, int r, int lq, int rq) { 108 | push(id, l, r); 109 | if (l > rq || r < lq) return node(); 110 | if (lq <= l && r <= rq) return tree[id]; 111 | int mid = (l + r) >> 1; 112 | auto xx = query(left(id), l, mid, lq, rq) + query(right(id), mid + 1, r, lq, rq); 113 | return xx; 114 | } 115 | 116 | // update each a_i in [l, r] to val 117 | void update(int l, int r, T val) { update(1, 0, n - 1, l, r, val); } 118 | // update each a_i in [l, r] to floor(a_i / x) 119 | void update_div(int l, int r, int x) { update_div(1, 0, n - 1, l, r, x); } 120 | node query(int l, int r) { return query(1, 0, n - 1, l, r); } 121 | }; 122 | 123 | -------------------------------------------------------------------------------- /content/data-structures/seg_tree_lazy.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | const ll inf = 1e18; 4 | template struct seg_tree { 5 | struct node { 6 | T x; 7 | node() : x(-inf) {} 8 | node(T x) : x(x) {} 9 | node operator+(const node &o) const { 10 | return node(max(x, o.x)); 11 | } 12 | }; 13 | int n; 14 | vector tree; 15 | vector lazy; 16 | seg_tree(vector a) { 17 | n = a.size(); 18 | tree.resize(n * 4); 19 | lazy.resize(n * 4); 20 | build(1, 0, n - 1, a); 21 | } 22 | inline int left(int id) { return (id << 1); } 23 | inline int right(int id) { return (id << 1) | 1; } 24 | void build(int id, int l, int r, const vector &a) { 25 | if (l == r) tree[id] = node(a[l]); 26 | else { 27 | int m = (l + r) >> 1; 28 | build(left(id), l, m, a); 29 | build(right(id), m + 1, r, a); 30 | tree[id] = tree[left(id)] + tree[right(id)]; 31 | } 32 | } 33 | inline void push(int id, int l, int r) { 34 | if (lazy[id]) { 35 | tree[id].x += lazy[id]; 36 | if (l != r) { 37 | lazy[left(id)] += lazy[id]; 38 | lazy[right(id)] += lazy[id]; 39 | } 40 | lazy[id] = 0; 41 | } 42 | } 43 | void update(int id, int l, int r, int lq, int rq, T val) { 44 | push(id, l, r); 45 | if (l > rq || r < lq) return; 46 | if (lq <= l && r <= rq) { 47 | lazy[id] += val; 48 | push(id, l, r); 49 | } else { 50 | int mid = (l + r) >> 1; 51 | update(left(id), l, mid, lq, rq, val); 52 | update(right(id), mid + 1, r, lq, rq, val); 53 | tree[id] = tree[left(id)] + tree[right(id)]; 54 | } 55 | } 56 | node query(int id, int l, int r, int lq, int rq) { 57 | push(id, l, r); 58 | if (l > rq || r < lq) return node(); 59 | if (lq <= l && r <= rq) return tree[id]; 60 | int mid = (l + r) >> 1; 61 | return query(left(id), l, mid, lq, rq) + query(right(id), mid + 1, r, lq, rq); 62 | } 63 | void update(int l, int r, T val) { update(1, 0, n - 1, l, r, val); } 64 | node query(int l, int r) { return query(1, 0, n - 1, l, r); } 65 | }; 66 | 67 | -------------------------------------------------------------------------------- /content/data-structures/seg_tree_lazy_add_set.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | template struct seg_tree { 4 | struct node { 5 | T x; 6 | node() : x(0) {} 7 | node(T x) : x(x) {} 8 | node operator+(const node &o) const { 9 | return node(x + o.x); 10 | } 11 | }; 12 | struct lazy_node { 13 | T add, set; 14 | lazy_node() : add(0), set(0) {} 15 | }; 16 | int n; 17 | vector tree; 18 | vector lazy; 19 | seg_tree(vector a) { 20 | n = a.size(); 21 | tree.resize(n * 4); 22 | lazy.resize(n * 4); 23 | build(1, 0, n - 1, a); 24 | } 25 | inline int left(int id) { return (id << 1); } 26 | inline int right(int id) { return (id << 1) | 1; } 27 | void build(int id, int l, int r, const vector &a) { 28 | if (l == r) tree[id] = node(a[l]); 29 | else { 30 | int m = (l + r) >> 1; 31 | build(left(id), l, m, a); 32 | build(right(id), m + 1, r, a); 33 | tree[id] = tree[left(id)] + tree[right(id)]; 34 | } 35 | } 36 | inline void push(int id, int l, int r) { 37 | if (lazy[id].set) { 38 | tree[id].x = (r - l + 1) * lazy[id].set; 39 | if (l != r) { 40 | lazy[left(id)].add = 0; 41 | lazy[right(id)].add = 0; 42 | lazy[left(id)].set = lazy[id].set; 43 | lazy[right(id)].set = lazy[id].set; 44 | } 45 | lazy[id].set = 0; 46 | } 47 | if (lazy[id].add) { 48 | tree[id].x += (r - l + 1) * lazy[id].add; 49 | if (l != r) { 50 | lazy[left(id)].add += lazy[id].add; 51 | lazy[right(id)].add += lazy[id].add; 52 | } 53 | lazy[id].add = 0; 54 | } 55 | } 56 | template 57 | void update(int id, int l, int r, int lq, int rq, T val) { 58 | push(id, l, r); 59 | if (l > rq || r < lq) return; 60 | if (lq <= l && r <= rq) { 61 | if (ADD) lazy[id].add += val; 62 | else lazy[id].set = val, lazy[id].add = 0; 63 | push(id, l, r); 64 | } else { 65 | int mid = (l + r) >> 1; 66 | update(left(id), l, mid, lq, rq, val); 67 | update(right(id), mid + 1, r, lq, rq, val); 68 | tree[id] = tree[left(id)] + tree[right(id)]; 69 | } 70 | } 71 | node query(int id, int l, int r, int lq, int rq) { 72 | push(id, l, r); 73 | if (l > rq || r < lq) return node(); 74 | if (lq <= l && r <= rq) return tree[id]; 75 | int mid = (l + r) >> 1; 76 | return query(left(id), l, mid, lq, rq) + query(right(id), mid + 1, r, lq, rq); 77 | } 78 | template 79 | void update(int l, int r, T val) { update(1, 0, n - 1, l, r, val); } 80 | node query(int l, int r) { return query(1, 0, n - 1, l, r); } 81 | }; 82 | 83 | -------------------------------------------------------------------------------- /content/data-structures/seg_tree_poly.cpp: -------------------------------------------------------------------------------- 1 | #include "../primitives/mint.cpp" 2 | 3 | // polynomial's degree + 1 4 | const int K = 4; 5 | Int d2 = Int(1) / 2, d4 = Int(1) / 4, d6 = Int(1) / 6; 6 | 7 | // f[i](x) = 0^i + 1^i + ... + x^i 8 | function f[] = { 9 | [](ll x){ return Int(x) + 1; }, 10 | [](ll x){ return Int(x) * (x + 1) * d2; }, 11 | [](ll x){ return Int(x) * (x + 1) * (2 * x + 1) * d6; }, 12 | [](ll x){ return Int(x) * x * (x + 1) * (x + 1) * d4; } 13 | }; 14 | 15 | using T = array; 16 | // updates polynomial's coefficients from f(x) to f(x + h) 17 | T shift_idx(T a, ll h) { 18 | Int h2 = Int(h)*h, h3 = h2*h; 19 | return { 20 | a[0] + a[1]*h + a[2]*h2 + a[3] * h3, 21 | a[1] + a[2]*2*h + a[3]*3*h2, 22 | a[2] + a[3]*3*h, 23 | a[3] 24 | }; 25 | } 26 | 27 | struct seg_tree { 28 | int n; 29 | vector tree; 30 | vector lazy; 31 | 32 | seg_tree(vector a) { 33 | n = a.size(); 34 | tree.resize(n * 4); 35 | lazy.resize(n * 4); 36 | build(1, 0, n - 1, a); 37 | } 38 | 39 | inline int left(int id) { return (id << 1); } 40 | inline int right(int id) { return (id << 1) | 1; } 41 | 42 | void build(int id, int l, int r, const vector &a) { 43 | if (l == r) tree[id] = a[l]; 44 | else { 45 | int m = (l + r) >> 1; 46 | build(left(id), l, m, a); 47 | build(right(id), m + 1, r, a); 48 | tree[id] = tree[left(id)] + tree[right(id)]; 49 | } 50 | } 51 | 52 | inline void push(int id, int l, int r) { 53 | if (lazy[id] == T{}) return; 54 | rep(i, 0, K) tree[id] += f[i](r - l) * lazy[id][i]; 55 | 56 | if (l != r) { 57 | int mid = (l + r) / 2; 58 | rep(i, 0, K) lazy[left(id)][i] += lazy[id][i]; 59 | auto nxt = shift_idx(lazy[id], mid - l + 1); 60 | rep(i, 0, K) lazy[right(id)][i] += nxt[i]; 61 | } 62 | rep(i, 0, K) lazy[id][i] = 0; 63 | } 64 | 65 | // add f(i - l) to each i in [l, r] 66 | void update(int id, int l, int r, int lq, int rq, T val) { 67 | push(id, l, r); 68 | if (l > rq || r < lq) return; 69 | if (lq <= l && r <= rq) { 70 | rep(i, 0, K) lazy[id][i] += val[i]; 71 | push(id, l, r); 72 | } else { 73 | int mid = (l + r) >> 1; 74 | update(left(id), l, mid, lq, rq, val); 75 | auto nxt = shift_idx(val, max(0ll, mid - max(l, lq) + 1ll)); 76 | update(right(id), mid + 1, r, lq, rq, nxt); 77 | tree[id] = tree[left(id)] + tree[right(id)]; 78 | } 79 | } 80 | 81 | Int query(int id, int l, int r, int lq, int rq) { 82 | push(id, l, r); 83 | if (l > rq || r < lq) return 0; 84 | if (lq <= l && r <= rq) return tree[id]; 85 | int mid = (l + r) >> 1; 86 | return query(left(id), l, mid, lq, rq) + query(right(id), mid + 1, r, lq, rq); 87 | } 88 | 89 | void update(int l, int r, T val) { update(1, 0, n - 1, l, r, val); } 90 | Int query(int l, int r) { return query(1, 0, n - 1, l, r); } 91 | }; 92 | 93 | -------------------------------------------------------------------------------- /content/data-structures/slope_trick.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | template 4 | struct SlopeTrick { 5 | const T INF = numeric_limits::max() / 3; 6 | 7 | T min_f; 8 | priority_queue, less<> > L; 9 | priority_queue, greater<> > R; 10 | T add_l, add_r; 11 | 12 | private: 13 | void push_R(const T &a) { R.push(a - add_r); } 14 | 15 | T top_R() const { 16 | if (R.empty()) 17 | return INF; 18 | else 19 | return R.top() + add_r; 20 | } 21 | 22 | T pop_R() { 23 | T val = top_R(); 24 | if (not R.empty()) R.pop(); 25 | return val; 26 | } 27 | 28 | void push_L(const T &a) { L.push(a - add_l); } 29 | 30 | T top_L() const { 31 | if (L.empty()) 32 | return -INF; 33 | else 34 | return L.top() + add_l; 35 | } 36 | 37 | T pop_L() { 38 | T val = top_L(); 39 | if (not L.empty()) L.pop(); 40 | return val; 41 | } 42 | 43 | size_t size() { return L.size() + R.size(); } 44 | 45 | public: 46 | SlopeTrick() : min_f(0), add_l(0), add_r(0) {} 47 | 48 | struct Query { 49 | T lx, rx, min_f; 50 | }; 51 | 52 | // return min f(x) 53 | Query query() const { return (Query){top_L(), top_R(), min_f}; } 54 | 55 | // f(x) += a 56 | void add_all(const T &a) { min_f += a; } 57 | 58 | // add \_ 59 | // f(x) += max(a - x, 0) 60 | void add_a_minus_x(const T &a) { 61 | min_f += max(T(0), a - top_R()); 62 | push_R(a); 63 | push_L(pop_R()); 64 | } 65 | 66 | // add _/ 67 | // f(x) += max(x - a, 0) 68 | void add_x_minus_a(const T &a) { 69 | min_f += max(T(0), top_L() - a); 70 | push_L(a); 71 | push_R(pop_L()); 72 | } 73 | 74 | // add \/ 75 | // f(x) += abs(x - a) 76 | void add_abs(const T &a) { 77 | add_a_minus_x(a); 78 | add_x_minus_a(a); 79 | } 80 | 81 | // \/ -> \_ 82 | // f_{new} (x) = min f(y) (y <= x) 83 | void clear_right() { 84 | while (not R.empty()) R.pop(); 85 | } 86 | 87 | // \/ -> _/ 88 | // f_{new} (x) = min f(y) (y >= x) 89 | void clear_left() { 90 | while (not L.empty()) L.pop(); 91 | } 92 | 93 | // \/ -> \_/ 94 | // f_{new} (x) = min f(y) (x-b <= y <= x-a) 95 | void shift(const T &a, const T &b) { 96 | assert(a <= b); 97 | add_l += a; 98 | add_r += b; 99 | } 100 | 101 | // \/. -> .\/ 102 | // f_{new} (x) = f(x - a) 103 | void shift(const T &a) { shift(a, a); } 104 | 105 | // L, R 106 | T get(const T &x) { 107 | T ret = min_f; 108 | while (not L.empty()) { 109 | ret += max(T(0), pop_L() - x); 110 | } 111 | while (not R.empty()) { 112 | ret += max(T(0), x - pop_R()); 113 | } 114 | return ret; 115 | } 116 | 117 | void merge(SlopeTrick &st) { 118 | if (st.size() > size()) { 119 | swap(st.L, L); 120 | swap(st.R, R); 121 | swap(st.add_l, add_l); 122 | swap(st.add_r, add_r); 123 | swap(st.min_f, min_f); 124 | } 125 | while (not st.R.empty()) { 126 | add_x_minus_a(st.pop_R()); 127 | } 128 | while (not st.L.empty()) { 129 | add_a_minus_x(st.pop_L()); 130 | } 131 | min_f += st.min_f; 132 | } 133 | }; 134 | -------------------------------------------------------------------------------- /content/data-structures/treap_beats.cpp: -------------------------------------------------------------------------------- 1 | struct treap { 2 | struct node { 3 | ll val, ma1, ma2, cnt, sum, lazy; 4 | int rnk, siz, l, r; 5 | node(ll &_val) { 6 | val = sum = ma1 = _val; 7 | ma2 = -1; 8 | siz = 1; 9 | cnt = 1; 10 | rnk = rng(); 11 | l = r = -1; 12 | lazy = 0; 13 | } 14 | 15 | void chmin(ll x) { 16 | if(ma1 <= x) return; 17 | sum -= (ma1 - x) * cnt; 18 | ma1 = x; 19 | val = min(val, x); 20 | } 21 | 22 | void soma(ll x) { 23 | if(ma2 != -1) ma2 += x; 24 | ma1 += x; 25 | sum += siz * x; 26 | lazy += x; 27 | val += x; 28 | } 29 | }; 30 | 31 | vector cur; 32 | inline int g_siz(int x) { 33 | return (x == -1 ? 0 : cur[x].siz); 34 | } 35 | 36 | void prop(int x) { 37 | if(cur[x].l != -1) { 38 | cur[cur[x].l].soma(cur[x].lazy); 39 | cur[cur[x].l].chmin(cur[x].ma1); 40 | } 41 | if(cur[x].r != -1){ 42 | cur[cur[x].r].soma(cur[x].lazy); 43 | cur[cur[x].r].chmin(cur[x].ma1); 44 | } 45 | cur[x].lazy = 0; 46 | } 47 | 48 | void calc(int x) { 49 | cur[x].siz = 1; 50 | cur[x].sum = cur[x].ma1 = cur[x].val; 51 | cur[x].ma2 = -1; 52 | cur[x].cnt = 1; 53 | if(cur[x].l != -1) { 54 | int l = cur[x].l; 55 | cur[x].siz += cur[l].siz; 56 | cur[x].sum += cur[l].sum; 57 | 58 | if(cur[l].ma1 == cur[x].ma1) { 59 | cur[x].cnt += cur[l].cnt; 60 | }else if(cur[l].ma1 > cur[x].ma1) { 61 | cur[x].cnt = cur[l].cnt; 62 | swap(cur[x].ma1, cur[x].ma2); 63 | cur[x].ma1 = cur[l].ma1; 64 | }else if(cur[l].ma1 > cur[x].ma2) { 65 | cur[x].ma2 = cur[l].ma1; 66 | } 67 | if(cur[l].ma2 > cur[x].ma2) cur[x].ma2 = cur[l].ma2; 68 | } 69 | 70 | if(cur[x].r != -1) { 71 | int r = cur[x].r; 72 | cur[x].siz += cur[r].siz; 73 | cur[x].sum += cur[r].sum; 74 | 75 | if(cur[r].ma1 == cur[x].ma1) { 76 | cur[x].cnt += cur[r].cnt; 77 | }else if(cur[r].ma1 > cur[x].ma1) { 78 | cur[x].cnt = cur[r].cnt; 79 | swap(cur[x].ma1, cur[x].ma2); 80 | cur[x].ma1 = cur[r].ma1; 81 | }else if(cur[r].ma1 > cur[x].ma2) { 82 | cur[x].ma2 = cur[r].ma1; 83 | } 84 | if(cur[r].ma2 > cur[x].ma2) cur[x].ma2 = cur[r].ma2; 85 | } 86 | } 87 | 88 | int root = -1; 89 | void push(ll x) { 90 | cur.push_back(node(x)); 91 | root = merge(root, sz(cur) - 1); 92 | } 93 | 94 | int merge(int a, int b) { 95 | if(b == -1) return a; 96 | if(a == -1) return b; 97 | prop(a), prop(b); 98 | if(cur[a].rnk > cur[b].rnk) { 99 | cur[a].r = merge(cur[a].r, b); 100 | calc(a); 101 | return a; 102 | } else { 103 | cur[b].l = merge(a, cur[b].l); 104 | calc(b); 105 | return b; 106 | } 107 | } 108 | 109 | void split(int a, int cnt, int &l, int &r) { 110 | if(a == -1) { 111 | l = -1, r = -1; 112 | return; 113 | } 114 | prop(a); 115 | if(g_siz(cur[a].l) >= cnt) { 116 | split(cur[a].l, cnt, l, r); 117 | cur[a].l = r; 118 | calc(a); 119 | r = a; 120 | } else { 121 | split(cur[a].r, cnt - g_siz(cur[a].l) - 1, l, r); 122 | cur[a].r = l; 123 | calc(a); 124 | l = a; 125 | } 126 | } 127 | 128 | void swap_ranges(int l1, int r1, int l2, int r2) { 129 | int p1, p2, p3, p4, p5; 130 | split(root, l1, p1, p2); 131 | split(p2, r1 - l1 + 1, p2, p3); 132 | split(p3, l2 - r1 - 1, p3, p4); 133 | split(p4, r2 - l2 + 1, p4, p5); 134 | 135 | int r = merge(p1, p4); 136 | r = merge(r, p3); 137 | r = merge(r, p2); 138 | r = merge(r, p5); 139 | } 140 | 141 | void dale(int a, ll x) { 142 | if(a == -1) return; 143 | prop(a); 144 | if(cur[a].ma2 >= x) { 145 | dale(cur[a].l, x); 146 | dale(cur[a].r, x); 147 | if(cur[a].val > x) cur[a].val = x; 148 | calc(a); 149 | }else if(cur[a].ma1 > x) { 150 | cur[a].chmin(x); 151 | } 152 | } 153 | 154 | void chmin(int l, int r, ll h) { 155 | int p1, p2, p3; 156 | split(root, l, p1, p2); 157 | split(p2, r - l + 1, p2, p3); 158 | dale(p2, h); 159 | merge(merge(p1, p2), p3); 160 | } 161 | 162 | void sum(int l, int r, ll h) { 163 | int p1, p2, p3; 164 | split(root, l, p1, p2); 165 | split(p2, r - l + 1, p2, p3); 166 | cur[p2].soma(h); 167 | prop(p2); 168 | calc(p2); 169 | merge(merge(p1,p2), p3); 170 | } 171 | 172 | void print(int x) { 173 | if(x == -1) return; 174 | print(cur[x].l); 175 | cout << cur[x].val << " "; 176 | print(cur[x].r); 177 | }; 178 | 179 | inline void print() {print(root);} 180 | }; 181 | -------------------------------------------------------------------------------- /content/data-structures/trie_bit.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | const int LG = 29; 4 | struct trie { 5 | trie *ch[2]; 6 | 7 | trie() { ch[0] = ch[1] = nullptr; } 8 | void insert(int x, int bit = LG) { 9 | if (bit < 0) return; 10 | 11 | int nxt = (x & (1 << bit)) > 0; 12 | if (!ch[nxt]) ch[nxt] = new trie(); 13 | ch[nxt]->insert(x, bit - 1); 14 | } 15 | int xor_min(int x, int bit = LG) { 16 | if (bit < 0) return 0; 17 | 18 | int nxt = (x & (1 << bit)) > 0; 19 | if (ch[nxt]) return ch[nxt]->xor_min(x, bit - 1); 20 | return (1 << bit) + ch[nxt ^ 1]->xor_min(x, bit - 1); 21 | } 22 | int xor_max(int x, int bit = LG) { 23 | if (bit < 0) return 0; 24 | 25 | int nxt = (x & (1 << bit)) > 0; 26 | if (ch[nxt ^ 1]) return (1 << bit) + ch[nxt ^ 1]->xor_max(x, bit - 1); 27 | return ch[nxt]->xor_max(x, bit - 1); 28 | } 29 | void get_all(vector &v, int bit = LG, int x = 0) { 30 | if (bit < 0) { 31 | v.push_back(x); 32 | return; 33 | } 34 | if (ch[0]) ch[0]->get_all(v, bit - 1, x); 35 | if (ch[1]) ch[1]->get_all(v, bit - 1, x | (1 << bit)); 36 | } 37 | }; 38 | 39 | -------------------------------------------------------------------------------- /content/data-structures/xor_base.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | struct xor_base { 4 | const static int B = 60; 5 | ll b[B], size = 0, free = 0; 6 | xor_base() { memset(b, 0, sizeof b); } 7 | void insert(ll x) { 8 | for (int i = B - 1; i >= 0; i--) { 9 | if (x & (1ll << i)) { 10 | if (!b[i]) { 11 | size++; 12 | b[i] = x; 13 | return; 14 | } 15 | x ^= b[i]; 16 | } 17 | } 18 | free++; 19 | } 20 | ll kth(ll k) { 21 | ll ans = 0, n = (1ll << size); 22 | for (int i = B - 1; i >= 0; i--) { 23 | if (!b[i]) continue; 24 | 25 | if ((k <= n / 2) ^ ((ans & (1ll << i)) == 0)) ans ^= b[i]; 26 | if (k > n / 2) k -= n / 2; 27 | n /= 2; 28 | } 29 | return ans; 30 | } 31 | bool contains(ll x) { 32 | for (int i = B - 1; i >= 0; i--) { 33 | if (x & (1ll << i)) { 34 | if (!b[i]) { 35 | return false; 36 | } 37 | x ^= b[i]; 38 | } 39 | } 40 | return true; 41 | } 42 | }; 43 | 44 | -------------------------------------------------------------------------------- /content/experimental/generic_rmq.cpp: -------------------------------------------------------------------------------- 1 | #include "bits/stdc++.h" 2 | using namespace std; 3 | 4 | template struct rmq { 5 | vector> t; 6 | 7 | rmq(const vector &a) { 8 | int n = a.size(), lg = 31 - __builtin_clz(n); 9 | t = vector>(lg + 1, vector(n)); 10 | for (int i = 0; i < n; i++) t[0][i] = a[i]; 11 | for (int i = 1; (1 << i) <= n; i++) { 12 | for (int j = 0; j + (1 << i) <= n; j++) { 13 | t[i][j] = op(t[i - 1][j], t[i - 1][j + (1 << (i - 1))]); 14 | } 15 | } 16 | } 17 | 18 | T query(int l, int r) { 19 | if (l > r) swap(l, r); 20 | int lg = 31 - __builtin_clz(r - l + 1); 21 | return op(t[lg][l], t[lg][r - (1 << lg) + 1]); 22 | } 23 | }; 24 | 25 | int main() { 26 | rmq a({4, 7, 9}); 27 | cout << a.query(1, 2) << endl; // 7 28 | } 29 | 30 | -------------------------------------------------------------------------------- /content/experimental/generic_seg_tree.cpp: -------------------------------------------------------------------------------- 1 | #include "bits/stdc++.h" 2 | using namespace std; 3 | 4 | #define endl '\n' 5 | typedef long long ll; 6 | 7 | template struct seg_tree { 8 | int n; 9 | vector tree; 10 | seg_tree(int n_) : n(n_), tree(n * 4) {} 11 | 12 | inline int left(int id) { return (id << 1); } 13 | inline int right(int id) { return (id << 1) | 1; } 14 | 15 | void update(int id, int l, int r, int pos, T val) { 16 | if (l == r) tree[id] = node(val); 17 | else { 18 | int mid = (l + r) >> 1; 19 | if (pos <= mid) update(left(id), l, mid, pos, val); 20 | else update(right(id), mid + 1, r, pos, val); 21 | tree[id] = op(tree[left(id)], tree[right(id)]); 22 | } 23 | } 24 | 25 | node query(int id, int l, int r, int lq, int rq) { 26 | if (l > rq || r < lq) return node(); 27 | if (lq <= l && r <= rq) return tree[id]; 28 | int mid = (l + r) >> 1; 29 | return op(query(left(id), l, mid, lq, rq), query(right(id), mid + 1, r, lq, rq)); 30 | } 31 | 32 | void update(int pos, T val) { update(1, 0, n - 1, pos, val); } 33 | node query(int l, int r) { return query(1, 0, n - 1, l, r); } 34 | }; 35 | 36 | void solvetask() { 37 | int n; cin >> n; 38 | struct node { 39 | int x; 40 | node() : x(0) {} 41 | node(int val) : x(val) {} 42 | }; 43 | seg_tree s(n); 46 | } 47 | 48 | int main() { 49 | ios_base::sync_with_stdio(0); cin.tie(0); 50 | int t = 1; 51 | while(t--) solvetask(); 52 | } 53 | 54 | -------------------------------------------------------------------------------- /content/geometry/Emerson.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | typedef double T; 5 | 6 | T EPS = 1e-9; 7 | #define INF T(1e18) 8 | 9 | int cmp(T x, T y = 0) { return (x <= y + EPS) ? (x + EPS < y) ? -1 : 0 : 1; } 10 | 11 | struct point { 12 | T x, y; 13 | int id; 14 | point(T x_ = 0, T y_ = 0, int id_ = -1): x(x_), y(y_), id(id_) {} 15 | point operator + (const point& b) const { return point(x + b.x, y + b.y, id); } 16 | point operator - (const point& b) const { return point(x - b.x, y - b.y, id); } 17 | point operator * (T c) { return point(x*c, y*c, id); } 18 | point operator / (T c) { return point(x/c, y/c, id); } 19 | bool operator < (const point& b) const { return tie(x, y) < tie(b.x, b.y); } 20 | bool operator == (const point& b) const { return tie(x, y) == tie(b.x, b.y); } 21 | }; 22 | 23 | typedef pair segm; 24 | typedef vector polygon; 25 | 26 | inline T abs(point a) { return sqrt(a.x * a.x + a.y * a.y);} 27 | inline T escalar(point a, point b) { return a.x * b.x + a.y * b.y;} 28 | inline T vetorial(point a, point b) { return a.x * b.y - a.y * b.x;} 29 | 30 | /** Counter-clockwise (o is the pivot)**/ 31 | int ccw(point p, point q, point o) {return cmp(vetorial(p - o, q - o));} 32 | 33 | /** o is the pivot **/ 34 | T angle(point p, point q, point o) { 35 | point u = p - o, v = q - o; 36 | return abs(atan2(vetorial(u, v), escalar(u, v))); 37 | } 38 | 39 | /** CCW rotate around origin **/ 40 | point rot(point p, double a) { 41 | return {p.x*cos(a) - p.y*sin(a), p.x*sin(a) + p.y*cos(a)}; 42 | } 43 | 44 | /** Rotate 90 degrees around the origin, CCW **/ 45 | point perp(point p) {return {-p.y, p.x};} 46 | 47 | T polygon_area(vector &p) { 48 | if(p.size() <= 2) return 0; 49 | T area = vetorial(p.back(), p[0]); 50 | for(int i = 1; i < (int)p.size(); i++) area += vetorial(p[i-1], p[i]); 51 | return abs(area) / 2; 52 | } 53 | 54 | /** Center of mass of a polygon with uniform mass distribution **/ 55 | point polygon_centroid(vector &poly) { 56 | point ret = (poly.back() + poly[0]) * vetorial(poly.back(), poly[0]); 57 | for(int i = 1; i < (int)poly.size(); i++) 58 | ret = ret + (poly[i-1] + poly[i]) * vetorial(poly[i-1], poly[i]); 59 | ret = ret / (6 * polygon_area(poly)); 60 | return ret; 61 | } 62 | 63 | long long areaTriangle(const point &a, const point &b, const point &c) { 64 | return (a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y)); 65 | } 66 | 67 | //Check if point is inside of a convex polygon in O(log(n)) 68 | bool inConvexPoly(const vector < point > &convPoly, point p) { 69 | long long start = 1, last = (int) convPoly.size() - 1; 70 | 71 | while (last - start > 1) { 72 | long long mid = (start + last) / 2; 73 | if (areaTriangle(convPoly[0], convPoly[mid], p) < 0) last = mid; 74 | else start = mid; 75 | } 76 | 77 | long long r0 = abs(areaTriangle(convPoly[0], convPoly[start], convPoly[last])); 78 | long long r1 = abs(areaTriangle(convPoly[0], convPoly[start], p)); 79 | long long r2 = abs(areaTriangle(convPoly[0], convPoly[last], p)); 80 | long long r3 = abs(areaTriangle(convPoly[start], convPoly[last], p)); 81 | 82 | // if you need strictly inside 83 | long long r4 = areaTriangle(convPoly[0], convPoly[1], p); 84 | long long r5 = areaTriangle(convPoly[0], convPoly[convPoly.size() - 1], p); 85 | 86 | // if you need strictly inside, add '&& r3 != 0 && r4 != 0 && r5 != 0' to return 87 | return r0 == (r1 + r2 + r3); 88 | } 89 | 90 | struct line { 91 | T a, b, c; 92 | line(T a_, T b_, T c_): a(a_), b(b_), c(c_) { 93 | T tmp = sqrt(a * a + b * b); 94 | a /= tmp, b /= tmp, c /= tmp; 95 | } 96 | line(point p1, point p2): 97 | a(p1.y - p2.y), 98 | b(p2.x - p1.x), 99 | c(p1.x*p2.y - p2.x*p1.y) { 100 | T tmp = sqrt(a * a + b * b); 101 | a /= tmp, b /= tmp, c /= tmp; 102 | } 103 | }; 104 | 105 | inline T point_line(point a, point l1, point l2) { 106 | return abs(vetorial(l2 - l1, a - l1)) / abs(l2 - l1); 107 | } 108 | 109 | inline T point_line(point a, line l) { 110 | return abs(l.a*a.x + l.b*a.y + l.c) / sqrt(l.a*l.a + l.b*l.b); 111 | } 112 | 113 | bool parallel(line a, line b) { 114 | return abs(a.b * b.a - a.a * b.b) < EPS; 115 | } 116 | 117 | T distLines(line a, line b) { 118 | if(!parallel(a, b)) return 0; 119 | if(cmp(a.a) == 0) return point_line(point(0, -a.c/a.b), b); 120 | return point_line(point(-a.c/a.a, 0), b); 121 | } 122 | 123 | point intersection(line a, line b) { 124 | point ret; 125 | ret.x = (b.c * a.b - a.c * b.b) / (b.b * a.a - a.b * b.a); 126 | ret.y = (a.c * b.a - b.c * a.a) / (b.b * a.a - a.b * b.a); 127 | return ret; 128 | } 129 | 130 | bool equal_lines(line a, line b) { 131 | if(!parallel(a,b)) return false; 132 | return abs(distLines(a,b)) < EPS; 133 | } 134 | 135 | line perpendicular(line a, point b) { 136 | T la, lb, lc; 137 | la = a.b; 138 | lb = -a.a; 139 | lc = -la * b.x - lb * b.y; 140 | return line(la, lb, lc); 141 | } 142 | 143 | inline T point_segment(segm s, point a) { 144 | if(escalar(s.second - s.first, a - s.first) < 0) return abs(a - s.first); 145 | if(escalar(s.first - s.second, a - s.second) < 0) return abs(a - s.second); 146 | if(cmp(abs(s.first - s.second))) return point_line(a, s.first, s.second); 147 | return abs(s.first - a); 148 | } 149 | 150 | /** proper intersection of segments (strictly inside) **/ 151 | bool properInter(point a, point b, point c, point d, point &out) { 152 | T oa = ccw(d, a, c), ob = ccw(d, b, c), oc = ccw(b, c, a), od = ccw(b, d, a); 153 | // Proper intersection exists iff opposite signs 154 | if (oa*ob < 0 && oc*od < 0) { 155 | out = intersection({a, b}, {c, d}); 156 | return true; 157 | } 158 | return false; 159 | } 160 | 161 | bool onSegment(point a, point b, point p) { 162 | return ccw(b, p, a) == 0 && cmp(escalar(a-p, b-p)) <= 0; 163 | } 164 | 165 | set segment_intersection(point a, point b, point c, point d) { 166 | point out; 167 | if (properInter(a, b, c, d, out)) return {out}; 168 | set s; 169 | if (onSegment(c, d, a)) s.insert(a); 170 | if (onSegment(c, d, b)) s.insert(b); 171 | if (onSegment(a, b, c)) s.insert(c); 172 | if (onSegment(a, b, d)) s.insert(d); 173 | return s; 174 | } 175 | 176 | T segSeg(point a, point b, point c, point d) { 177 | point dummy; 178 | if (properInter(a, b, c, d, dummy)) return 0; 179 | return min({point_segment({a, b}, c), point_segment({a, b}, d), 180 | point_segment({c, d}, a), point_segment({c, d}, b)}); 181 | } 182 | 183 | struct circle { 184 | point center; T rad; 185 | circle(point c, T r): center(c), rad(r) {} 186 | circle(point p1, point p2) { 187 | center = (p1 + p2) / 2; 188 | rad = abs(p2 - p1) / 2; 189 | } 190 | circle(point p1, point p2, point p3) { 191 | line l12 (p1, p2); 192 | line l23 (p2, p3); 193 | assert(!equal_lines(l12, l23)); 194 | point p12 = (p1 + p2) / 2; 195 | point p23 = (p2 + p3) / 2; 196 | center = intersection(perpendicular(l12, p12), perpendicular(l23, p23)); 197 | rad = abs(center - p1); 198 | } 199 | bool circle_intersection(circle c, pair &out) { 200 | double d = abs(c.center-center), co = (d*d+rad*rad-c.rad*c.rad)/(2*d*rad); 201 | if (abs(co) > 1) return false; 202 | double alpha = acos(co); point r = (c.center - center) / d * rad; 203 | out = {center + rot(r, -alpha), center + rot(r, alpha)}; 204 | return true; 205 | } 206 | }; 207 | 208 | circle mec_solve1(vector &p, int i, int j) { 209 | circle c(p[i], p[j]); 210 | for(int k = 0; k < j; k++) 211 | if(cmp(abs(c.center - p[k]), c.rad) == 1) 212 | c = circle(p[i], p[j], p[k]); 213 | return c; 214 | } 215 | 216 | circle mec_solve2(vector &p, int i) { 217 | circle c(p[0], p[i]); 218 | for(int j = 1; j < i; j++) 219 | if(cmp(abs(c.center - p[j]), c.rad) == 1) 220 | c = mec_solve1(p, i, j); 221 | return c; 222 | } 223 | 224 | circle mec_solve3(vector &p) { 225 | circle c(p[0], p[1]); 226 | for(int i = 2; i < (int)p.size(); i++) 227 | if(cmp(abs(c.center - p[i]), c.rad) == 1) 228 | c = mec_solve2(p, i); 229 | return c; 230 | } 231 | 232 | circle minimum_enclosing_circle(vector p) { 233 | if(p.size() == 1) return circle{p[0], 0}; 234 | random_shuffle(p.begin(), p.end()); 235 | return mec_solve3(p); 236 | } 237 | 238 | circle mec(vector ps) { 239 | shuffle(ps.begin(), ps.end(), mt19937(chrono::steady_clock::now().time_since_epoch().count())); 240 | double EPS = 1 + 1e-8; 241 | circle c(ps[0], 0); 242 | for (int i = 0; i < (int)ps.size(); i++) if (abs(c.center - ps[i]) > c.rad * EPS) { 243 | c = circle(ps[i], 0); 244 | for (int j = 0; j < i; j++) if (abs(c.center - ps[j]) > c.rad * EPS) { 245 | c = circle(ps[i], ps[j]); 246 | for (int k = 0; k < j; k++) 247 | if (abs(c.center - ps[k]) > c.rad * EPS) 248 | c = circle(ps[i], ps[j], ps[k]); 249 | } 250 | } 251 | return c; 252 | } 253 | 254 | vector tangents(circle c1, point p2) { // todo: 4 tangentes 255 | point d = p2 - c1.center; 256 | double dr = c1.rad, d2 = escalar(d, d), h2 = d2-dr*dr; 257 | assert(cmp(h2) >= 0 && cmp(d2) != 0); 258 | vector ret({c1.center + (d*dr + perp(d)*sqrt(h2))/d2*dr}); 259 | if(cmp(h2)) ret.push_back(c1.center + (d*dr - perp(d)*sqrt(h2))/d2*dr); 260 | return ret; 261 | } 262 | 263 | /// distance from a to b avoiding circle c. assume a and b are already outside c 264 | T distAvoidCircle(point a, point b, circle c) { 265 | if(point_segment({a, b}, c.center) < c.rad) { 266 | auto tg1 = tangents(c, a), tg2 = tangents(c, b); 267 | T ret = DBL_MAX; 268 | for(point ta : tg1) for(point tb : tg2) 269 | ret = min(ret, abs(ta - a) + abs(angle(ta, c.center, tb))*c.rad + abs(b - tb)); 270 | return ret; 271 | } 272 | else return abs(b - a); 273 | } 274 | 275 | namespace convex_hull { /// careful equal points. for collinear use > and <. 276 | pair, vector> ulHull(const vector& P) { 277 | vector p(P.size()), u, l; iota(p.begin(), p.end(), 0); 278 | sort(p.begin(), p.end(), [&P](int a, int b) { return P[a] < P[b]; }); 279 | for(int i : p) { 280 | #define ADDP(C, cmp)\ 281 | while (C.size() > 1 && ccw(P[C.back()], P[i], P[C.end()[-2]]) cmp 0)\ 282 | C.pop_back();\ 283 | C.push_back(i); 284 | ADDP(u, >=); ADDP(l, <=); 285 | } 286 | return {u,l}; 287 | } 288 | vector hullInd(const vector& P) { 289 | vector u, l; tie(u,l) = ulHull(P); 290 | if (l.size() <= 1) return l; 291 | if (P[l[0]] == P[l[1]]) return {0}; 292 | l.insert(l.end(), rbegin(u)+1, rend(u)-1); 293 | return l; 294 | } 295 | vector hull(const vector& P) { 296 | vector v = hullInd(P); 297 | vector res; 298 | for(int i : v) res.push_back(P[i]); 299 | return res; 300 | } 301 | } 302 | 303 | ///Pick a very tight EPS (like 1e-16, use long double if needed) 304 | vector > voronoi(vector p) { 305 | int n = (int)p.size(); 306 | vector > diagram, ans(p.size() + 4, vector(2)); 307 | vector inv, hull; 308 | p.resize(p.size() + 4); 309 | for(int i = 0; i < n; i++) { 310 | EPS = 1e-15; 311 | diagram.push_back(vector()); 312 | 313 | p[n].x = 2*(-INF) - p[i].x; p[n].y = p[i].y; 314 | p[n+1].x = p[i].x; p[n+1].y = 2*INF - p[i].y; 315 | p[n+2].x = 2*INF - p[i].x; p[n+2].y = p[i].y; 316 | p[n+3].x = p[i].x; p[n+3].y = 2*(-INF) - p[i].y; 317 | 318 | inv.clear(); 319 | for(int j = 0; j < n + 4; j++) { 320 | if(j == i) continue; 321 | T tmp = escalar(p[j] - p[i], p[j] - p[i]); 322 | inv.push_back(point((p[j].x - p[i].x)/tmp, (p[j].y - p[i].y)/tmp, j)); 323 | } 324 | 325 | hull = convex_hull::hull(inv); 326 | hull.push_back(hull[0]); 327 | EPS = 1e-9; 328 | 329 | for(int j = 0; j < (int)hull.size(); j++) { 330 | assert(hull[j].id != -1); 331 | ans[j][0].x = (p[i].x + p[hull[j].id].x) / 2; 332 | ans[j][0].y = (p[i].y + p[hull[j].id].y) / 2; 333 | ans[j][1].x = ans[j][0].x - (p[hull[j].id].y - p[i].y); 334 | ans[j][1].y = ans[j][0].y + (p[hull[j].id].x - p[i].x); 335 | 336 | if(j) { 337 | line r(ans[j-1][0], ans[j-1][1]), s(ans[j][0], ans[j][1]); 338 | if(parallel(r, s)) continue; 339 | point b = intersection(r, s); 340 | diagram[i].push_back(b); 341 | } 342 | } 343 | } 344 | 345 | return diagram; 346 | } 347 | 348 | /// 0 - Border / 1 - Outside / -1 - Inside 349 | int point_inside_polygon(point p, vector &poly) { 350 | int n = (int)poly.size(), windingNumber = 0; 351 | for(int i = 0; i < n; i++) { 352 | if(abs(p - poly[i]) < EPS) return 0; 353 | int j = (i + 1) % n; 354 | if(cmp(poly[i].y, p.y) == 0 && cmp(poly[j].y, p.y) == 0) { 355 | if(cmp(min(poly[i].x, poly[j].x), p.x) <= 0 && 356 | cmp(p.x, max(poly[i].x, poly[j].x)) <= 0) return 0; 357 | } else { 358 | bool below = (cmp(poly[i].y, p.y) == -1); 359 | if(below != (cmp(poly[j].y, p.y) == -1)) { 360 | int orientation = ccw(p, poly[j], poly[i]); 361 | if(orientation == 0) return 0; 362 | if(below == (orientation > 0)) windingNumber += below ? 1 : -1; 363 | } 364 | } 365 | } 366 | return (windingNumber == 0) ? 1 : -1; 367 | } 368 | 369 | // https://www.dropbox.com/sh/mkyxabccsf6k80u/AABYol6e4tgbrmnUNnqhf6DRa/Geometria?dl=0&subfolder_nav_tracking=1 370 | namespace halfplane { 371 | pair has_intersection(vector> v){ 372 | random_shuffle(v.begin(), v.end()); 373 | point p; 374 | for(int i = 0; i < (int)v.size(); i++) if(ccw(v[i].second, p, v[i].first) != 1) { 375 | point dir = (v[i].second - v[i].first)/abs(v[i].second - v[i].first); 376 | point l = v[i].first - dir*1e15; 377 | point r = v[i].first + dir*1e15; 378 | if(r < l) swap(l, r); 379 | for(int j = 0; j < i; j++) { 380 | if(ccw(v[i].first - v[i].second, v[j].first - v[j].second, point())==0){ 381 | if(ccw(v[j].second, p, v[j].first) == 1) 382 | continue; 383 | return {false, point()}; 384 | } 385 | if(ccw(v[j].second, l, v[j].first) != 1) 386 | l = max(l, intersection({v[i].first, v[i].second}, {v[j].first, v[j].second})); 387 | if(ccw(v[j].second, r, v[j].first) != 1) 388 | r = min(r, intersection({v[i].first, v[i].second}, {v[j].first, v[j].second})); 389 | if(!(l < r)) return {false, point()}; 390 | } 391 | p = r; 392 | } 393 | return {true, p}; 394 | } 395 | int halfplane(line l) { 396 | return cmp(l.b) > 0 || (cmp(l.b) == 0 && cmp(l.a) > 0); 397 | } 398 | bool cmpL(line& l1, line& l2) { 399 | if(halfplane(l1) != halfplane(l2)) 400 | return halfplane(l1) < halfplane(l2); 401 | point n1(l1.a, l1.b), n2(l2.a, l2.b); 402 | if(cmp(vetorial(n1, n2))) return cmp(vetorial(n1, n2)) < 0; 403 | return cmp(l1.c, l2.c) < 0; 404 | } 405 | bool strict(point p, line& l) { 406 | T val = l.a * p.x + l.b * p.y + l.c; 407 | return cmp(val) > 0; 408 | } 409 | vector intersect(vector v) { 410 | v.push_back({1, 0, INF}); v.push_back({0, 1, INF}); 411 | v.push_back({-1, 0, INF}); v.push_back({0, -1, INF}); 412 | sort(v.begin(), v.end(), cmpL); 413 | deque d; 414 | int s = 0; 415 | for (int i = 0; i < (int)v.size(); ++i) { 416 | if (i && cmp(v[i].a, v[i-1].a) == 0 && cmp(v[i].b, v[i-1].b) == 0) { 417 | continue; 418 | } 419 | while (s >= 2 && !strict(intersection(d[s-1], d[s-2]), v[i])) { 420 | d.pop_back(); 421 | --s; 422 | } 423 | while (s >= 2 && !strict(intersection(d[0], d[1]), v[i])) { 424 | d.pop_front(); 425 | --s; 426 | } 427 | if (s < 2 || strict(intersection(v[i], d[s - 1]), d[0])) { 428 | d.push_back(v[i]); 429 | ++s; 430 | } 431 | if (s >= 2) { 432 | point n1 = {d[s-2].a, d[s-2].b}; 433 | point n2 = {d[s-1].a, d[s-1].b}; 434 | if (cmp(vetorial(n1, n2)) > 0) return {}; 435 | } 436 | } 437 | if (s <= 2) return {}; 438 | vector ret; 439 | for (int i = 0, n = (int)d.size(); i < n; ++i) 440 | ret.push_back(intersection(d[i], d[(i+1)%n])); 441 | return ret; 442 | } 443 | } 444 | 445 | namespace delaunay { // use T as long long 446 | typedef struct Quad* Q; 447 | typedef long long ll; 448 | typedef __int128_t lll; // (can be ll if coords are < 2e4) 449 | point arb(INF, INF); // not equal to any other point 450 | struct Quad { 451 | bool mark; 452 | Q o, rot; 453 | point p; 454 | point F() { return r()->p; } 455 | Q r() { return rot->rot; } 456 | Q prev() { return rot->o->rot; } 457 | Q next() { return r()->prev(); } 458 | }; 459 | // test if p is in the circumcircle 460 | bool circ(point p, point a, point b, point c) { 461 | ll ar = vetorial(b-a, c-a); 462 | assert(ar); 463 | if (ar < 0) swap(a, b); 464 | lll p2 = escalar(p, p), A = escalar(a, a) - p2, 465 | B = escalar(b, b) - p2, C = escalar(c, c) - p2; 466 | return vetorial(a-p, b-p) * C + vetorial(b-p, c-p) * A + vetorial(c-p, a-p) * B > 0; 467 | } 468 | Q makeEdge(point orig, point dest) { 469 | Q q[] = {new Quad{0, nullptr, nullptr, orig}, new Quad{0, nullptr, nullptr, arb}, 470 | new Quad{0, nullptr, nullptr, dest}, new Quad{0, nullptr, nullptr, arb}}; 471 | for (int i = 0; i < 4; ++i) q[i]->o = q[-i & 3], q[i]->rot = q[(i + 1) & 3]; 472 | return *q; 473 | } 474 | void splice(Q a, Q b) { 475 | swap(a->o->rot->o, b->o->rot->o); 476 | swap(a->o, b->o); 477 | } 478 | Q connect(Q a, Q b) { 479 | Q q = makeEdge(a->F(), b->p); 480 | splice(q, a->next()); 481 | splice(q->r(), b); 482 | return q; 483 | } 484 | pair rec(const vector& s) { 485 | if (s.size() <= 3) { 486 | Q a = makeEdge(s[0], s[1]), b = makeEdge(s[1], s.back()); 487 | if (s.size() == 2) return {a, a->r()}; 488 | splice(a->r(), b); 489 | auto side = vetorial(s[1]-s[0], s[2]-s[0]); 490 | Q c = side ? connect(b, a) : 0; 491 | return {side < 0 ? c -> r() : a, side < 0 ? c : b -> r()}; 492 | } 493 | #define H(e) e->F(), e->p 494 | #define valid(e)(vetorial((base->F())-(e->F()), (base->p)-(e->F())) > 0) 495 | Q A, B, ra, rb; 496 | int half = (int)s.size() / 2; 497 | tie(ra, A) = rec({s.begin(), s.end() - half}); 498 | tie(B, rb) = rec({s.size() - half + s.begin(), s.end()}); 499 | while ((vetorial((A->F())-(B->p), (A->p)-(B->p)) < 0 && (A = A->next())) || 500 | (vetorial((B->F())-(A->p), (B->p)-(A->p)) > 0 && (B = B->r()->o))); 501 | Q base = connect(B->r(), A); 502 | if (A->p == ra->p) ra = base->r(); 503 | if (B->p == rb->p) rb = base; 504 | #define DEL(e, init, dir)\ 505 | Q e = init->dir; if (valid(e))\ 506 | while (circ(e->dir->F(), H(base), e->F())) {\ 507 | Q t = e->dir;\ 508 | splice(e, e->prev());\ 509 | splice(e->r(), e->r()->prev());\ 510 | e = t;\ 511 | } 512 | for (;;) { 513 | DEL(LC, base->r(), o); 514 | DEL(RC, base, prev()); 515 | if (!valid(LC) && !valid(RC)) break; 516 | if (!valid(LC) || (valid(RC) && circ(H(RC), H(LC)))) 517 | base = connect(RC, base->r()); 518 | else base = connect(base->r(), LC->r()); 519 | } 520 | return {ra, rb}; 521 | } 522 | vector> triangulate(vector pts) { 523 | sort(pts.begin(), pts.end()); 524 | assert(unique(pts.begin(), pts.end()) == pts.end()); 525 | if (pts.size() < 2) return {}; 526 | Q e = rec(pts).first; 527 | vector q = {e}; 528 | int qi = 0; 529 | while (vetorial((e->F())-(e->o->F()), (e->p)-(e->o->F())) < 0) e = e->o; 530 | #define ADD {\ 531 | Q c = e;\ 532 | do {\ 533 | c->mark = 1;\ 534 | pts.push_back(c->p);\ 535 | q.push_back(c->r());\ 536 | c = c->next();\ 537 | } while (c != e);\ 538 | } 539 | ADD; 540 | pts.clear(); 541 | while (qi < q.size()) if (!(e = q[qi++])->mark) ADD; 542 | vector> ret; 543 | for (int i = 0; i < (int)pts.size() / 3; ++i) 544 | ret.push_back({pts[3*i], pts[3*i+1], pts[3*i+2]}); 545 | return ret; 546 | } 547 | } 548 | 549 | pair closest_pair_of_points(vector v) { 550 | pair> bes; bes.first = INF; 551 | set S; int ind = 0; 552 | sort(v.begin(), v.end()); 553 | for(int i = 0; i < (int)v.size(); i++) { 554 | if (i && v[i] == v[i-1]) return {v[i], v[i]}; 555 | for (; v[i].x - v[ind].x >= bes.first; ++ind) 556 | S.erase({v[ind].y, v[ind].x}); 557 | for (auto it = S.upper_bound({v[i].y-bes.first, INF}); it != S.end() && it->x < v[i].y+bes.first; ++it) { 558 | point t = {it->y, it->x}; 559 | bes = min(bes, {abs(t-v[i]), {t, v[i]}}); 560 | } 561 | S.insert(point{v[i].y, v[i].x}); 562 | } 563 | return bes.second; 564 | } 565 | 566 | /// convex polygon 567 | T maxDist2(const vector& poly) { 568 | int n = poly.size(); 569 | T res = 0; 570 | for (int i = 0, j = n < 2 ? 0 : 1; i < j; ++i) 571 | for (;; j = (j+1)%n) { 572 | res = max(res, escalar(poly[i] - poly[j], poly[i] - poly[j])); 573 | if (ccw(poly[i+1] - poly[i], poly[(j+1)%n] - poly[j], point()) <= 0) break; 574 | } 575 | return res; 576 | } 577 | 578 | point pivot; 579 | bool comp(point a, point b){ // radial sort 580 | a = a - pivot; b = b - pivot; 581 | if((a.x > 0 || (a.x==0 && a.y>0) ) && (b.x < 0 || (b.x==0 && b.y<0))) return 1; 582 | if((b.x > 0 || (b.x==0 && b.y>0) ) && (a.x < 0 || (a.x==0 && a.y<0))) return 0; 583 | T R = vetorial(a, b); 584 | if(R) return R > 0; 585 | return escalar(a, a) < escalar(b, b); 586 | } 587 | 588 | polygon minkowski_sum(polygon a, polygon b){ 589 | if(a.empty() || b.empty()) return polygon(0); 590 | // SORT 591 | for(auto& v : {&a, &b}) { 592 | pivot = *min_element(v->begin(), v->end()); 593 | sort(v->begin(), v->end(), comp); 594 | v->resize(unique(v->begin(), v->end()) - v->begin()); 595 | } 596 | pivot = {0, 0}; 597 | 598 | int pa = 0, pb = 0, sa = (int)a.size(), sb = (int)b.size(); 599 | if(min(sa, sb) < 2) { 600 | polygon ret(0); 601 | for(int i = 0; i < sa; i++) 602 | for(int j = 0; j < sb; j++) 603 | ret.push_back(a[i] + b[j]); 604 | return ret; 605 | } 606 | polygon ret; 607 | ret.push_back(a[0]+b[0]); 608 | while(pa < sa || pb < sb){ 609 | point p = ret.back(); 610 | if(pb == sb || (pa < sa && comp(a[(pa+1)%sa]-a[pa],b[(pb+1)%sb]-b[pb]))) 611 | p = p + (a[(pa+1)%sa]-a[pa]), pa++; 612 | else p = p + (b[(pb+1)%sb]-b[pb]), pb++; 613 | while(ret.size() > 1 && !ccw(ret[ret.size()-1], p, ret[ret.size()-2])) 614 | ret.pop_back(); 615 | ret.push_back(p); 616 | } 617 | ret.pop_back(); 618 | return ret; 619 | } 620 | 621 | /// be careful 3+ collinear points 622 | void radial_sweep_180_line(vector p, int idx) { 623 | swap(p[idx], p[0]); point piv = p[0]; for(point &pp : p) pp = pp - piv; 624 | 625 | sort(p.begin() + 1, p.end(), [&](point &a, point &b) { 626 | int ua = (a.x > 0 or (a.x == 0 and a.y >= 0)), ub = (b.x > 0 or (b.x == 0 and b.y >= 0)); 627 | if(ua != ub) return ua < ub; 628 | T R = vetorial(a, b); 629 | return R ? R > 0 : escalar(a, a) < escalar(b, b); 630 | }); 631 | 632 | auto tmp = p; 633 | p.insert(p.end(), tmp.begin() + 1, tmp.end()); 634 | 635 | // center is p[0] 636 | for(int i = (int)tmp.size(), j = 1; i < (int)p.size(); i++) { 637 | while(j < i && ccw(p[i], p[j], p[0]) >= 0) j++; 638 | /// [j, i) clockwise 639 | } 640 | } 641 | 642 | ld circle_intersection_area(ld x1, ld y1, ld r1, ld x2, ld y2, ld r2) { 643 | ld d = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)); 644 | 645 | if(d >= r1+r2) return 0; 646 | if (d+r1 <= r2) return pi*r1*r1; 647 | if(d+r2 <= r1) return pi*r2*r2; 648 | 649 | ld ang1 = 2*acos( (r2*r2 - r1*r1 - d*d)/(-2*r1*d) ); 650 | ld ang2 = 2*acos( (r1*r1 - r2*r2 - d*d)/(-2*r2*d) ); 651 | 652 | ld areaarco1 = ang1*r1*r1/2.0; 653 | ld areatri1 = r1*r1*sin(ang1)/2.0; 654 | 655 | ld areaarco2 = ang2*r2*r2/2.0; 656 | ld areatri2 = r2*r2*sin(ang2)/2.0; 657 | 658 | return areaarco1 - areatri1 + areaarco2 - areatri2; 659 | } 660 | 661 | 662 | int main() { 663 | } 664 | -------------------------------------------------------------------------------- /content/geometry/circle.cpp: -------------------------------------------------------------------------------- 1 | #include "./point.cpp" 2 | 3 | struct circle{ 4 | pt center; long double r; 5 | circle (pt c = pt(0, 0), long double rr = 0) : center(c), r(rr) {} 6 | bool intersect(circle o){ 7 | pt v = center - o.center; 8 | return v.dist() <= r + o.r && v.dist() >= fabs(r - o.r); 9 | } 10 | vector intersection(circle o){ 11 | vector ans; 12 | long double d = (center-o.center).dist(), R = o.r, x, y; 13 | if (d > r + R || d < fabs(r - R)) return ans; 14 | x = (d*d - R*R + r*r)/(2*d*r); 15 | y = r*sqrt(1 - x*x); 16 | pt middle = center + (o.center - center)*( (r*x) / d); 17 | pt vdif = (o.center - center).r90cw()*(y / d); 18 | ans.push_back(middle + vdif); ans.push_back(middle - vdif); 19 | return ans; 20 | } 21 | }; 22 | 23 | //radius of the circle going through points A, B and C 24 | double ccRadius(const pt& A, const pt& B, const pt& C) { 25 | return (B-A).dist()*(C-B).dist()*(A-C).dist()/ 26 | abs((B-A).cross(C-A))/2; 27 | } 28 | 29 | pt ccCenter(const pt& A, const pt& B, const pt& C) { 30 | pt b = C-A, c = B-A; 31 | return A + (b*c.dist2()-c*b.dist2()).perp()/b.cross(c)/2; 32 | } 33 | 34 | /*Returns the area of the intersection of a circle with a ccw polygon. 35 | O(n)*/ 36 | #define arg(p, q) atan2(p.cross(q), p.dot(q)) 37 | double circleptoly(pt c, double r, vector ps) { 38 | auto tri = [&](pt p, pt q) { 39 | auto r2 = r * r / 2; 40 | pt d = q - p; 41 | auto a = d.dot(p)/d.dist2(), b = (p.dist2()-r*r)/d.dist2(); 42 | auto det = a * a - b; 43 | if (det <= 0) return arg(p, q) * r2; 44 | auto s = max((ld).0, -a-sqrt(det)), t = min((ld)1., -a+sqrt(det)); 45 | if (t < 0 || 1 <= s) return arg(p, q) * r2; 46 | pt u = p + d * s, v = p + d * t; 47 | return arg(p,u) * r2 + u.cross(v)/2 + arg(v,q) * r2; 48 | }; 49 | auto sum = 0.0; 50 | rep(i,0,sz(ps)) 51 | sum += tri(ps[i] - c, ps[(i + 1) % sz(ps)] - c); 52 | return sum; 53 | } 54 | 55 | /* Finds the external tangents of two circles, or internal if r2 is negated. 56 | Can return 0, 1, or 2 tangents -- 0 if one circle contains the other (or overlaps it, in the internal case, or if the circles are the same); 57 | 1 if the circles are tangent to each other (in which case .first = .second and the tangent line 58 | is perpendicular to the line between the centers). 59 | .first and .second give the tangency points at circle 1 and 2 respectively. 60 | To find the tangents of a circle with a point set r2 to 0. */ 61 | vector> tangents(pt c1, double r1, pt c2, double r2) { 62 | pt d = c2 - c1; 63 | double dr = r1 - r2, d2 = d.dist2(), h2 = d2 - dr * dr; 64 | if (d2 == 0 || h2 < 0) return {}; 65 | vector> out; 66 | for (double sign : {-1, 1}) { 67 | pt v = (d * dr + d.perp() * sqrt(h2) * sign) / d2; 68 | out.push_back({c1 + v * r1, c2 + v * r2}); 69 | } 70 | if (h2 == 0) out.pop_back(); 71 | return out; 72 | } 73 | 74 | // Computes the minimum circle that encloses a set of points. O(N) 75 | pair mec(vector ps) { 76 | shuffle(all(ps), mt19937(time(0))); 77 | pt o = ps[0]; 78 | double r = 0, EPS = 1 + 1e-8; 79 | rep(i,0,sz(ps)) if ((o - ps[i]).dist() > r * EPS) { 80 | o = ps[i], r = 0; 81 | rep(j,0,i) if ((o - ps[j]).dist() > r * EPS) { 82 | o = (ps[i] + ps[j]) / 2; 83 | r = (o - ps[i]).dist(); 84 | rep(k,0,j) if ((o - ps[k]).dist() > r * EPS) { 85 | o = ccCenter(ps[i], ps[j], ps[k]); 86 | r = (o - ps[i]).dist(); 87 | } 88 | } 89 | } 90 | return {o, r}; 91 | } -------------------------------------------------------------------------------- /content/geometry/closest_pair.cpp: -------------------------------------------------------------------------------- 1 | //https://codeforces.com/blog/entry/58747 2 | #include "./point.cpp" 3 | 4 | pair closest(vector v) { 5 | assert(sz(v) > 1); 6 | set S; //change LLONG_MAX if is double 7 | sort(all(v), [](pt a, pt b) { return a.y < b.y; }); 8 | pair> ret{DBL_MAX, {pt(), pt()}}; 9 | int j = 0; 10 | for (pt p : v) { 11 | pt d{1.0 + (ll)sqrt(ret.first), 0}; 12 | while (v[j].y <= p.y - d.x) S.erase(v[j++]); 13 | auto lo = S.lower_bound(p - d), hi = S.upper_bound(p + d); 14 | for (; lo != hi; ++lo) 15 | ret = min(ret, {(*lo - p).dist2(), {*lo, p}}); 16 | S.insert(p); 17 | } 18 | return ret.second; 19 | } 20 | -------------------------------------------------------------------------------- /content/geometry/convex_hull.cpp: -------------------------------------------------------------------------------- 1 | #include "./point.cpp" 2 | //convexhull sem coolinear 3 | vector convexHull(vector pts) { 4 | if (sz(pts) <= 1) return pts; 5 | sort(all(pts)); 6 | vector h(sz(pts)+1); //h(2*sz(pts)+2) pra ter colinear 7 | int s = 0, t = 0; 8 | for (int it = 2; it--; s = --t, reverse(all(pts))) 9 | for (pt p : pts) { // troca por > 0,coolinear 10 | while (t >= s + 2 && h[t-2].cross(h[t-1], p) <= 0) t--; 11 | h[t++] = p; 12 | } 13 | return {h.begin(), h.begin() + t - (t == 2 && h[0] == h[1])}; 14 | } 15 | 16 | /*Returns the two points with max distance on a convex hull 17 | (ccw,no duplicate/collinear points) O(N)*/ 18 | array hullDiameter(vector S) { 19 | int n = sz(S), j = n < 2 ? 0 : 1; 20 | pair> res({0, {S[0], S[0]}}); 21 | rep(i,0,j) 22 | for (;; j = (j + 1) % n) { 23 | res = max(res, {(S[i] - S[j]).dist2(), {S[i], S[j]}}); 24 | if ((S[(j + 1) % n] - S[j]).cross(S[i + 1] - S[i]) >= 0) 25 | break; 26 | } 27 | return res.second; 28 | } 29 | -------------------------------------------------------------------------------- /content/geometry/half_plane.cpp: -------------------------------------------------------------------------------- 1 | #include "./point.cpp" 2 | 3 | #define pb push_back 4 | const double EPS = 1e-6, INF = 1e9; 5 | const double PI = acos(-1); 6 | 7 | pt lineIntersectSeg(pt p, pt q, pt A, pt B) { 8 | double c = (A-B).cross(p-q); 9 | double a = A.cross(B); 10 | double b = p.cross(q); 11 | return ((p-q)*(a/c)) - ((A-B)*(b/c)); 12 | } 13 | 14 | bool parallel(pt a, pt b) { 15 | return fabs(a.cross(b)) < EPS; 16 | } 17 | 18 | typedef vector polygon; 19 | typedef pair halfplane; 20 | pt dir(halfplane h) { 21 | return h.second - h.first; 22 | } 23 | bool belongs(halfplane h, pt a) { 24 | return dir(h).cross(a - h.first) > EPS; 25 | } 26 | 27 | bool hpcomp(halfplane ha, halfplane hb) { 28 | pt a = dir(ha), b = dir(hb); 29 | if (parallel(a, b) && a.dot(b) > EPS) 30 | return b.cross(ha.first - hb.first) < -EPS; 31 | if (b.y*a.y > EPS) return a.cross(b) > EPS; 32 | else if (fabs(b.y) < EPS && b.x > EPS) return false; 33 | else if (fabs(a.y) < EPS && a.x > EPS) return true; 34 | else return b.y < a.y; 35 | } 36 | 37 | //clockwise {(i+1),(i)} 38 | polygon intersect(vector H, double W = INF) { // 39 | H.pb(halfplane(pt(-W,-W), pt(W,-W)));//-1,-1 | 1,-1 40 | H.pb(halfplane(pt(W,-W), pt(W,W))); // 1,-1 | 1, 1 41 | H.pb(halfplane(pt(W,W), pt(-W,W))); // 1, 1 |-1, 1 42 | H.pb(halfplane(pt(-W,W), pt(-W,-W)));//-1, 1 |-1,-1 43 | sort(all(H), hpcomp); 44 | int i = 0; 45 | while(parallel(dir(H[0]), dir(H[i]))) i++; 46 | deque P; 47 | deque S; 48 | S.pb(H[i-1]); 49 | for(;i 0 61 | while(!belongs(S.back(), P.front()) || 62 | !belongs(S.front(), P.back())) { 63 | while(!belongs(S.back(), P.front())) 64 | P.pop_front(), S.pop_front(); 65 | while(!belongs(S.front(), P.back())) 66 | P.pop_back(), S.pop_back(); 67 | } 68 | 69 | P.pb(lineIntersectSeg(S.front().first, 70 | S.front().second, S.back().first, S.back().second)); 71 | return polygon(all(P)); 72 | } 73 | -------------------------------------------------------------------------------- /content/geometry/in_polygon.cpp: -------------------------------------------------------------------------------- 1 | // https://victorlecomte.com/cp-geo.pdf 2 | #include "./point.cpp" 3 | 4 | bool in_polygon(vector &a, pt p, bool strict = true) { 5 | int ans = 0, n = a.size(); 6 | for (int i = 0; i < n; i++) { 7 | int j = (i + 1) % n; 8 | if (onSegment(a[i], a[j], p)) return !strict; 9 | ans ^= ((p.y < a[i].y) - (p.y < a[j].y)) * p.cross(a[i], a[j]) > 0; 10 | } 11 | return ans; 12 | } 13 | -------------------------------------------------------------------------------- /content/geometry/intersecting_segments.cpp: -------------------------------------------------------------------------------- 1 | // tested on timus 1469 2 | // need point and onSegment (kactl) 3 | 4 | bool segInter(point a, point b, point c, point d) { 5 | auto oa = c.cross(d, a), ob = c.cross(d, b), 6 | oc = a.cross(b, c), od = a.cross(b, d); 7 | if (sgn(oa) * sgn(ob) < 0 && sgn(oc) * sgn(od) < 0) return true; 8 | if (onSegment(c, d, a)) return true; 9 | if (onSegment(c, d, b)) return true; 10 | if (onSegment(a, b, c)) return true; 11 | if (onSegment(a, b, d)) return true; 12 | return false; 13 | } 14 | 15 | const double eps = 1e-9; 16 | struct seg { 17 | point a, b; 18 | int idx; 19 | double get_y(double x) const { 20 | if (a.x == b.x) return a.y; 21 | return a.y + (b.y - a.y) * (x - a.x) / (b.x - a.x); 22 | } 23 | bool operator < (const seg &other) const { 24 | ll x = max(a.x, other.a.x); 25 | return get_y(x) < other.get_y(x) - eps; 26 | } 27 | }; 28 | 29 | struct event { 30 | ll x, type, idx; 31 | bool operator < (const event &other) const { 32 | if (x == other.x) return type < other.type; 33 | return x < other.x; 34 | } 35 | }; 36 | 37 | pair solve(vector a) { 38 | int n = sz(a); 39 | vector evs; 40 | rep(i, 0, n) { 41 | if (a[i].a.x > a[i].b.x || (a[i].a.x == a[i].b.x && 42 | a[i].a.y > a[i].b.y)) swap(a[i].a, a[i].b); 43 | evs.push_back({a[i].a.x, 0, i}); 44 | evs.push_back({a[i].b.x, 1, i}); 45 | } 46 | sort(all(evs)); 47 | 48 | auto intersect = [&](int i, int j) { 49 | return segInter(a[i].a, a[i].b, a[j].a, a[j].b); 50 | }; 51 | 52 | set s; 53 | for (auto [x, type, i] : evs) { 54 | if (type) { 55 | auto it = s.find(a[i]); 56 | if (it != s.begin()) { 57 | auto prv = prev(it); 58 | auto nxt = next(it); 59 | if (nxt != s.end() && intersect(prv->idx, nxt->idx)) { 60 | return { prv->idx, nxt->idx }; 61 | } 62 | } 63 | s.erase(it); 64 | } else { 65 | auto it = s.lower_bound(a[i]); 66 | if (it != s.end() && intersect(i, it->idx)) { 67 | return { i, it->idx }; 68 | } 69 | if (it != s.begin() && intersect(i, prev(it)->idx)) { 70 | return { i, prev(it)->idx }; 71 | } 72 | s.insert(a[i]); 73 | } 74 | } 75 | return { -1, -1 }; 76 | } 77 | 78 | -------------------------------------------------------------------------------- /content/geometry/point.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | using ld = long double; 4 | using ll = long long; 5 | 6 | const double eps = 1e-7; 7 | bool eq(ld a, ld b = 0) { 8 | return abs(a - b) <= eps; 9 | } 10 | 11 | struct pt { 12 | using T = ld; 13 | 14 | T x, y; 15 | explicit pt(T x=0, T y=0) : x(x), y(y) {} 16 | bool operator < (pt p) const { return tie(x,y) < tie(p.x,p.y); } 17 | bool operator == (pt p) const { return tie(x,y)==tie(p.x,p.y); } 18 | pt operator + (pt p) const { return pt(x+p.x, y+p.y); } 19 | pt operator - (pt p) const { return pt(x-p.x, y-p.y); } 20 | pt operator * (T d) const { return pt(x*d, y*d); } 21 | pt operator / (T d) const { return pt(x/d, y/d); } 22 | T dot(pt p) const { return x*p.x + y*p.y; } 23 | T cross(pt p) const { return x*p.y - y*p.x; } 24 | T cross(pt &a, pt &b) const { return (a-*this).cross(b-*this); } 25 | T dist2() const { return x*x + y*y; } 26 | double dist() const { return sqrt((double)dist2()); } 27 | double angle() const { return atan2(y, x); } 28 | pt unit() const { return *this/dist(); } // makes dist()=1 29 | pt perp() const { return pt(-y, x); } // rotates +90 degrees 30 | pt normal() const { return perp().unit(); } 31 | // friend ostream& operator << (ostream &os, pt p) { 32 | // return os << "(" << p.x << ", " << p.y << ")";} 33 | T ori(pt a, pt b) const { T f = cross(a, b); return (f < 0 ? -1 : (f > 0 ? 1 : 0)); } 34 | pt r90cw(){ return pt(y, -x);} // rotate 90 degrees clock wise 35 | pt r90ccw(){ return pt(-y, x);} // rotate 90 degrees counter clock wise 36 | }; 37 | 38 | bool onSegment(pt &s, pt &e, pt &p) { 39 | return p.cross(s, e) == 0 && (s - p).dot(e - p) <= 0; 40 | } 41 | int sgn(ll x) { return (x > 0) - (x < 0); } 42 | 43 | double areaPoly(vector &poly) { 44 | assert(3<=sz(poly)); 45 | ld area=poly.back().cross(poly[0]); 46 | for(int i=0;i vector seg_int(T a, T b, T c, T d) { 67 | auto oa = c.cross(d, a), ob = c.cross(d, b), 68 | oc = a.cross(b, c), od = a.cross(b, d); 69 | if (sgn(oa) * sgn(ob) < 0 && sgn(oc) * sgn(od) < 0) 70 | return {(a * ob - b * oa) / (ob - oa)}; 71 | set s; 72 | if (onSegment(c, d, a)) s.insert(a); 73 | if (onSegment(c, d, b)) s.insert(b); 74 | if (onSegment(a, b, c)) s.insert(c); 75 | if (onSegment(a, b, d)) s.insert(d); 76 | return {s.begin(), s.end()}; 77 | } 78 | 79 | struct line { // reta 80 | pt p, q; 81 | double a,b,c; 82 | line() {} 83 | line(pt p_, pt q_) : p(p_), q(q_) {} 84 | line(double a=0,double b=0, double c=0): a(a),b(b),c(c){} 85 | }; 86 | 87 | line bisector(pt o, pt a, pt b) { //bissetriz de AOB, p 88 | a = a - o, b = b - o; // (a*b) k (b*a) 89 | pt k = a * b.dist() + b * a.dist() + o; // \ o / k/=k.dist() 90 | //reta Ax+By+C=0 91 | double A=k.y-o.y, B = o.x-k.x, C = -A*o.x - B*o.y; 92 | return line(A,B,C); 93 | } 94 | 95 | ld sarea(pt p, pt q, pt r) { // area com sinal 96 | return ((q-p).cross(r-q))/2; 97 | } 98 | 99 | bool ccw(pt p, pt q, pt r) { // se p, q, r sao ccw 100 | return sarea(p, q, r) > eps; 101 | } 102 | 103 | bool isinseg(pt p, line r) { // se p pertence ao seg de r 104 | pt a = r.p - p, b = r.q - p; 105 | return eq(a.cross(b), 0) and a.dot(b) < eps; 106 | } 107 | 108 | bool interseg(line r, line s) { // se o seg de r intersecta o seg de s 109 | if (isinseg(r.p, s) or isinseg(r.q, s) 110 | or isinseg(s.p, r) or isinseg(s.q, r)) return 1; 111 | 112 | return ccw(r.p, r.q, s.p) != ccw(r.p, r.q, s.q) and 113 | ccw(s.p, s.q, r.p) != ccw(s.p, s.q, r.q); 114 | } 115 | 116 | pair segProj(pt l, pt r, pt p) { 117 | if((l-r).dot(p-r) < 0) return {(p-r).dist(), r}; 118 | if((r-l).dot(p-l) < 0) return {(p-l).dist(), l}; 119 | ld dis = (r-l).cross(p-l)/(l-r).dist(); 120 | 121 | pt v = (r-l) / (r-l).dist(); 122 | pt best = l + v * (r-l).dot(p-l) / (l-r).dist(); 123 | 124 | pair ans = {dis, best}; 125 | return ans; 126 | } 127 | //ponto no poligno v, mais proximo de p 128 | pt closest(vector &v, pt p) { 129 | int n=sz(v); 130 | ld inf = 1e18; 131 | pair best={inf, p}; 132 | rep(i,0,n) { 133 | pair cur = segProj(v[i],v[(i+1)%n], p); 134 | if(cur.first < best.first) 135 | best = cur; 136 | } 137 | return best.second; 138 | } 139 | -------------------------------------------------------------------------------- /content/geometry/polygon.cpp: -------------------------------------------------------------------------------- 1 | #include "./point.cpp" 2 | 3 | struct polygon { 4 | int n; 5 | vector pol; 6 | polygon(vector poly) : pol(poly) { 7 | n = sz(pol); 8 | } 9 | 10 | bool inside(pt p, bool strict = true) { //check if point p is inside O(log(n)) 11 | int a = 1, b = n - 1, r = !strict; 12 | if (n < 3) return r && onSegment(pol[0], pol.back(), p); 13 | if (sgn(pol[0].cross(pol[a], pol[b])) > 0) swap(a, b); 14 | if (sgn(pol[0].cross(pol[a], p)) >= r || sgn(pol[0].cross(pol[b], p)) <= -r) 15 | return false; 16 | while (abs(a - b) > 1) { 17 | int c = (a + b) / 2; 18 | (sgn(pol[0].cross(pol[c], p)) > 0 ? b : a) = c; 19 | } 20 | return sgn(pol[a].cross(pol[b], p)) < r; 21 | } 22 | pt polygonCenter(const vector& v) { 23 | pt res(0, 0); double A = 0; 24 | for (int i = 0, j = sz(v) - 1; i < sz(v); j = i++) { 25 | res = res + (v[i] + v[j]) * v[j].cross(v[i]); 26 | A += v[j].cross(v[i]); 27 | } 28 | return res / A / 3; 29 | } 30 | }; 31 | 32 | // Returns a vector with the vertices of a polygon with everything to the left of the line going 33 | // from s to e cut away. 34 | pair lineInter(pt s1, pt e1, pt s2, pt e2) { 35 | auto d = (e1 - s1).cross(e2 - s2); 36 | if (d == 0) // if parallel 37 | return {-(s1.cross(e1, s2) == 0), pt(0, 0)}; 38 | auto p = s2.cross(e1, e2), q = s2.cross(e2, s1); 39 | return {1, (s1 * p + e1 * q) / d}; 40 | } 41 | 42 | vector polygonCut(const vector& poly, pt s, pt e) { 43 | vector res; 44 | rep(i,0,sz(poly)) { 45 | pt cur = poly[i], prev = i ? poly[i-1] : poly.back(); 46 | bool side = s.cross(e, cur) < 0; 47 | if (side != (s.cross(e, prev) < 0)) 48 | res.push_back(lineInter(s, e, cur, prev).second); 49 | if (side) 50 | res.push_back(cur); 51 | } 52 | return res; 53 | } 54 | 55 | // area of the union of $n$ polygons (not necessarily convex) 56 | // O(N^2), N = number of points 57 | int sideOf(pt s, pt e, pt p) { return sgn(s.cross(e, p)); } 58 | int sideOf(const pt& s, const pt& e, const pt& p, double eps) { 59 | auto a = (e-s).cross(p-s); double l = (e-s).dist()*eps; 60 | return (a > l) - (a < -l); 61 | } 62 | double rat(pt a, pt b) { return sgn(b.x) ? a.x/b.x : a.y/b.y; } 63 | double polyUnion(vector>& poly) { 64 | double ret = 0; 65 | rep(i,0,sz(poly)) rep(v,0,sz(poly[i])) { 66 | pt A = poly[i][v], B = poly[i][(v + 1) % sz(poly[i])]; 67 | vector> segs = {{0, 0}, {1, 0}}; 68 | rep(j,0,sz(poly)) if (i != j) { 69 | rep(u,0,sz(poly[j])) { 70 | pt C = poly[j][u], D = poly[j][(u + 1) % sz(poly[j])]; 71 | int sc = sideOf(A, B, C), sd = sideOf(A, B, D); 72 | if (sc != sd) { 73 | double sa = C.cross(D, A), sb = C.cross(D, B); 74 | if (min(sc, sd) < 0) 75 | segs.emplace_back(sa / (sa - sb), sgn(sc - sd)); 76 | } else if (!sc && !sd && j0){ 77 | segs.emplace_back(rat(C - A, B - A), 1); 78 | segs.emplace_back(rat(D - A, B - A), -1); 79 | } 80 | } 81 | } 82 | sort(all(segs)); 83 | for (auto& s : segs) s.first = min(max(s.first, 0.0), 1.0); 84 | double sum = 0; 85 | int cnt = segs[0].second; 86 | rep(j,1,sz(segs)) { 87 | if (!cnt) sum += segs[j].first - segs[j - 1].first; 88 | cnt += segs[j].second; 89 | } 90 | ret += A.cross(B) * sum; 91 | } 92 | return ret / 2; 93 | } -------------------------------------------------------------------------------- /content/geometry/sum_minkowski.cpp: -------------------------------------------------------------------------------- 1 | #include "./point.cpp" 2 | 3 | void reorder_polygon(vector & P){ 4 | size_t pos = 0; 5 | for(size_t i = 1; i < P.size(); i++){ 6 | if(P[i].y < P[pos].y || (P[i].y == P[pos].y && P[i].x < P[pos].x)) 7 | pos = i; 8 | } 9 | rotate(P.begin(), P.begin() + pos, P.end()); 10 | } 11 | 12 | vector minkowski(vector P, vector Q){ 13 | reorder_polygon(P); // the first vertex must be the lowest 14 | reorder_polygon(Q); // we must ensure cyclic indexing 15 | P.push_back(P[0]); 16 | P.push_back(P[1]); 17 | Q.push_back(Q[0]); 18 | Q.push_back(Q[1]); 19 | 20 | vector result; 21 | size_t i = 0, j = 0; 22 | while(i < P.size() - 2 || j < Q.size() - 2){ 23 | result.push_back(P[i] + Q[j]); 24 | auto cross = (P[i + 1] - P[i]).cross(Q[j + 1] - Q[j]); 25 | if(cross >= 0 && i < P.size() - 2) 26 | ++i; 27 | if(cross <= 0 && j < Q.size() - 2) 28 | ++j; 29 | } 30 | return result; 31 | } 32 | -------------------------------------------------------------------------------- /content/geometry2/half_plane_intersection.cpp: -------------------------------------------------------------------------------- 1 | #include "point.cpp" 2 | 3 | typedef Point P; 4 | const double EPS = 1e-9; 5 | 6 | P lineIntersectSeg(P p, P q, P A, P B) { 7 | double c = (A-B).cross(p-q); 8 | double a = A.cross(B); 9 | double b = p.cross(q); 10 | return ((p-q)*(a/c)) - ((A-B)*(b/c)); 11 | } 12 | 13 | bool parallel(P a, P b) { 14 | return fabs(a.cross(b)) < EPS; 15 | } 16 | 17 | struct line { 18 | P a, b; 19 | }; 20 | 21 | P dir(line h) { 22 | return h.b - h.a; 23 | } 24 | bool belongs(line h, P a) { 25 | return dir(h).cross(a - h.a) > -EPS; 26 | } 27 | 28 | vector

intersect(vector H, double W) { 29 | vector

box = { {-W, -W}, {W, -W}, {W, W}, {-W, W} }; 30 | rep(i, 0, 4) H.push_back({box[i], box[(i+1)%4]}); 31 | sort(all(H), [](const line &ha, const line &hb) { 32 | P a = dir(ha), b = dir(hb); 33 | if (parallel(a, b) && a.dot(b) > EPS) 34 | return b.cross(ha.a - hb.a) < -EPS; 35 | if (b.y*a.y > EPS) return a.cross(b) > EPS; 36 | if (fabs(b.y) < EPS && b.x > EPS) return false; 37 | if (fabs(a.y) < EPS && a.x > EPS) return true; 38 | return b.y < a.y; 39 | }); 40 | int i = 0; 41 | while(parallel(dir(H[0]), dir(H[i]))) i++; 42 | deque

pts; 43 | deque S = { H[i - 1] }; 44 | for (; i < sz(H); i++) { 45 | while(sz(pts) && !belongs(H[i], pts.back())) 46 | pts.pop_back(), S.pop_back(); 47 | P df = dir(S.front()), di = dir(H[i]); 48 | if (pts.empty() && df.cross(di) < EPS) 49 | return vector

(); 50 | pts.push_back(lineIntersectSeg(H[i].a, H[i].b, 51 | S.back().a, S.back().b)); 52 | S.push_back(H[i]); 53 | } 54 | #define EXIST (sz(pts) && sz(S)) 55 | 56 | while(EXIST && (!belongs(S.back(), pts.front()) || 57 | !belongs(S.front(), pts.back()))) { 58 | while(EXIST && !belongs(S.back(), pts.front())) 59 | pts.pop_front(), S.pop_front(); 60 | while(EXIST && !belongs(S.front(), pts.back())) 61 | pts.pop_back(), S.pop_back(); 62 | } 63 | 64 | if(sz(S)) pts.push_back(lineIntersectSeg(S.front().a, 65 | S.front().b, S.back().a, S.back().b)); 66 | return vector

(all(pts)); 67 | } 68 | 69 | -------------------------------------------------------------------------------- /content/geometry2/minkowski.cpp: -------------------------------------------------------------------------------- 1 | #include "point.cpp" 2 | 3 | typedef Point P; 4 | 5 | void reorder_polygon(vector

&pts){ 6 | int pos = 0; 7 | for(int i = 1; i < pts.size(); i++){ 8 | if(pts[i].y < pts[pos].y || (pts[i].y == pts[pos].y && pts[i].x < pts[pos].x)) 9 | pos = i; 10 | } 11 | rotate(pts.begin(), pts.begin() + pos, pts.end()); 12 | } 13 | 14 | vector

minkowski(vector

a, vector

b){ 15 | reorder_polygon(a); 16 | reorder_polygon(b); 17 | a.push_back(a[0]); 18 | a.push_back(a[1]); 19 | b.push_back(b[0]); 20 | b.push_back(b[1]); 21 | vector

result; 22 | int i = 0, j = 0; 23 | while(i < a.size() - 2 || j < b.size() - 2){ 24 | result.push_back(a[i] + b[j]); 25 | auto cross = (a[i + 1] - a[i]).cross(b[j + 1] - b[j]); 26 | if(cross >= 0 && i < a.size() - 2) 27 | ++i; 28 | if(cross <= 0 && j < b.size() - 2) 29 | ++j; 30 | } 31 | return result; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /content/geometry2/point.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | template int sgn(T x) { return (x > 0) - (x < 0); } 4 | template 5 | struct Point { 6 | typedef Point P; 7 | T x, y; 8 | Point(T x=0, T y=0) : x(x), y(y) {} 9 | bool operator<(P p) const { return tie(x,y) < tie(p.x,p.y); } 10 | bool operator==(P p) const { return tie(x,y)==tie(p.x,p.y); } 11 | P operator+(P p) const { return P(x+p.x, y+p.y); } 12 | P operator-(P p) const { return P(x-p.x, y-p.y); } 13 | P operator*(T d) const { return P(x*d, y*d); } 14 | P operator/(T d) const { return P(x/d, y/d); } 15 | T dot(P p) const { return x*p.x + y*p.y; } 16 | T cross(P p) const { return x*p.y - y*p.x; } 17 | T cross(P a, P b) const { return (a-*this).cross(b-*this); } 18 | T dist2() const { return x*x + y*y; } 19 | double dist() const { return sqrt((double)dist2()); } 20 | // angle to x-axis in interval [-pi, pi] 21 | double angle() const { return atan2(y, x); } 22 | P unit() const { return *this/dist(); } // makes dist()=1 23 | P perp() const { return P(-y, x); } // rotates +90 degrees 24 | P normal() const { return perp().unit(); } 25 | // returns point rotated 'a' radians ccw around the origin 26 | P rotate(double a) const { 27 | return P(x*cos(a)-y*sin(a),x*sin(a)+y*cos(a)); } 28 | friend ostream& operator<<(ostream& os, P p) { 29 | return os << "(" << p.x << "," << p.y << ")"; } 30 | template 31 | Point(const Point& p) : x(static_cast(p.x)), y(static_cast(p.y)) {} 32 | }; 33 | 34 | -------------------------------------------------------------------------------- /content/graph/articulation_points.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | int n; // number of nodes 4 | vector> adj; // adjacency list of graph 5 | 6 | vector visited; 7 | vector tin, low; 8 | int timer; 9 | 10 | void dfs(int v, int p = -1) { 11 | visited[v] = true; 12 | tin[v] = low[v] = timer++; 13 | int children = 0; 14 | for (int to : adj[v]) { 15 | if (to == p) continue; 16 | if (visited[to]) low[v] = min(low[v], tin[to]); 17 | else { 18 | dfs(to, v); 19 | low[v] = min(low[v], low[to]); 20 | if (low[to] >= tin[v] && p != -1) { 21 | // v eh um ponto de articulacao 22 | } 23 | ++children; 24 | } 25 | } 26 | if(p == -1 && children > 1) { 27 | // v eh um ponto de articulacao 28 | } 29 | } 30 | 31 | void find_cutpoints() { 32 | timer = 0; 33 | visited.assign(n, false); 34 | tin.assign(n, -1); 35 | low.assign(n, -1); 36 | rep(i, 0, n) if (!visited[i]) dfs(i); 37 | } 38 | 39 | -------------------------------------------------------------------------------- /content/graph/bipartite_matching.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | mt19937 rng((int) chrono::steady_clock::now().time_since_epoch().count()); 4 | struct bip_match { 5 | int n, m; 6 | vector> g; 7 | // ma[i] = quem eh o match de i (-1 se nao tem) 8 | vector dist, nxt, ma, mb; 9 | 10 | bip_match(int n_, int m_) : n(n_), m(m_), g(n), 11 | dist(n), nxt(n), ma(n, -1), mb(m, -1) {} 12 | 13 | // 0 indexado 14 | void add(int a, int b) { g[a].push_back(b); } 15 | 16 | bool dfs(int i) { 17 | for (int &id = nxt[i]; id < sz(g[i]); id++) { 18 | int j = g[i][id]; 19 | if (mb[j] == -1 or (dist[mb[j]] == dist[i] + 1 and dfs(mb[j]))) { 20 | ma[i] = j, mb[j] = i; 21 | return true; 22 | } 23 | } 24 | return false; 25 | } 26 | bool bfs() { 27 | rep(i, 0, n) dist[i] = n; 28 | queue q; 29 | rep(i, 0, n) if (ma[i] == -1) { 30 | dist[i] = 0; 31 | q.push(i); 32 | } 33 | bool rep = 0; 34 | while (q.size()) { 35 | int i = q.front(); q.pop(); 36 | for (int j : g[i]) { 37 | if (mb[j] == -1) rep = 1; 38 | else if (dist[mb[j]] > dist[i] + 1) { 39 | dist[mb[j]] = dist[i] + 1; 40 | q.push(mb[j]); 41 | } 42 | } 43 | } 44 | return rep; 45 | } 46 | int solve() { 47 | int ret = 0; 48 | for (auto& i : g) shuffle(i.begin(), i.end(), rng); 49 | while (bfs()) { 50 | rep(i, 0, n) nxt[i] = 0; 51 | rep(i, 0, n) if (ma[i] == -1 and dfs(i)) ret++; 52 | } 53 | return ret; 54 | } 55 | }; 56 | 57 | -------------------------------------------------------------------------------- /content/graph/block_cut_tree.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | vector> block_cut(vector> g, vector &is_cut, vector &at) { 4 | int n = sz(g); 5 | is_cut.resize(n); 6 | 7 | vector st, tin(n), low(n); 8 | vector> comps; 9 | 10 | int t = 0; 11 | auto dfs = [&](auto &self, int v, int p) -> void { 12 | tin[v] = low[v] = ++t; 13 | st.push_back(v); 14 | for (int ch : g[v]) if (ch != p) { 15 | if (tin[ch]) { 16 | low[v] = min(low[v], tin[ch]); 17 | } else { 18 | self(self, ch, v); 19 | low[v] = min(low[v], low[ch]); 20 | if (low[ch] >= tin[v]) { 21 | is_cut[v] |= tin[v] > 1 || tin[ch] > 2; 22 | comps.push_back({v}); 23 | while (comps.back().back() != ch) { 24 | comps.back().push_back(st.back()); 25 | st.pop_back(); 26 | } 27 | } 28 | } 29 | } 30 | }; 31 | dfs(dfs, 0, -1); 32 | 33 | at.resize(n); 34 | vector> adj; 35 | rep(v, 0, n) if (is_cut[v]) { 36 | at[v] = sz(adj); 37 | adj.push_back({}); 38 | } 39 | for (auto comp : comps) { 40 | int id = sz(adj); 41 | adj.push_back({}); 42 | for (int v : comp) { 43 | if (!is_cut[v]) at[v] = id; 44 | else { 45 | adj[at[v]].push_back(id); 46 | adj[id].push_back(at[v]); 47 | } 48 | } 49 | } 50 | if (!sz(adj)) adj.push_back({}); 51 | return adj; 52 | } 53 | 54 | -------------------------------------------------------------------------------- /content/graph/blossom.cpp: -------------------------------------------------------------------------------- 1 | const int MAX = 550; // O(N^3) 2 | vector g[MAX]; // 0 indexado 3 | int match[MAX]; // match[i] = com quem i esta matchzado ou -1 4 | int n, pai[MAX], base[MAX], vis[MAX]; 5 | queue q; // Se for bipartido, nao precisa da funcao 6 | // 'contract', e roda em O(nm) 7 | 8 | void contract(int u, int v, bool first = 1) { 9 | static vector bloss; 10 | static int l; 11 | if (first) { 12 | bloss = vector(n, 0); 13 | vector teve(n, 0); 14 | int k = u; l = v; 15 | while (1) { 16 | teve[k = base[k]] = 1; 17 | if (match[k] == -1) break; 18 | k = pai[match[k]]; 19 | } 20 | while (!teve[l = base[l]]) l = pai[match[l]]; 21 | } 22 | while (base[u] != l) { 23 | bloss[base[u]] = bloss[base[match[u]]] = 1; 24 | pai[u] = v; 25 | v = match[u]; 26 | u = pai[match[u]]; 27 | } 28 | if (!first) return; 29 | contract(v, u, 0); 30 | for (int i = 0; i < n; i++) if (bloss[base[i]]) { 31 | base[i] = l; 32 | if (!vis[i]) q.push(i); 33 | vis[i] = 1; 34 | } 35 | } 36 | 37 | int getpath(int s) { 38 | for (int i = 0; i < n; i++) base[i] = i, pai[i] = -1, vis[i] = 0; 39 | vis[s] = 1; q = queue(); q.push(s); 40 | while (q.size()) { 41 | int u = q.front(); q.pop(); 42 | for (int i : g[u]) { 43 | if (base[i] == base[u] or match[u] == i) continue; 44 | if (i == s or (match[i] != -1 and pai[match[i]] != -1)) 45 | contract(u, i); 46 | else if (pai[i] == -1) { 47 | pai[i] = u; 48 | if (match[i] == -1) return i; 49 | i = match[i]; 50 | vis[i] = 1; q.push(i); 51 | } 52 | } 53 | } 54 | return -1; 55 | } 56 | 57 | int blossom() { 58 | int ans = 0; 59 | memset(match, -1, sizeof(match)); 60 | for (int i = 0; i < n; i++) if (match[i] == -1) 61 | for (int j : g[i]) if (match[j] == -1) { 62 | match[i] = j; 63 | match[j] = i; 64 | ans++; 65 | break; 66 | } 67 | for (int i = 0; i < n; i++) if (match[i] == -1) { 68 | int j = getpath(i); 69 | if (j == -1) continue; 70 | ans++; 71 | while (j != -1) { 72 | int p = pai[j], pp = match[p]; 73 | match[p] = j; 74 | match[j] = p; 75 | j = pp; 76 | } 77 | } 78 | return ans; // tamanho do Matching 79 | //for (int i = 0; i < n; i++) imprimir as arestas 80 | // if (match[i] != -1 and i < match[i]) { 81 | // cout << i << " " << match[i] << endl; 82 | //} 83 | } -------------------------------------------------------------------------------- /content/graph/bridges.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | const int N = 3e5 + 10; 4 | int n, m, tin[N], low[N], e[N][2], is_bridge[N]; 5 | vector adj[N]; 6 | 7 | int timer; 8 | void dfs(int v, int p = -1) { 9 | tin[v] = low[v] = timer++; 10 | for (int i : adj[v]) { 11 | int to = e[i][0] ^ e[i][1] ^ v; 12 | if (to == p) continue; 13 | if (tin[to]) { 14 | low[v] = min(low[v], tin[to]); 15 | } else { 16 | dfs(to, v); 17 | low[v] = min(low[v], low[to]); 18 | if (low[to] > tin[v]) { 19 | is_bridge[i] = 1; 20 | } 21 | } 22 | } 23 | } 24 | 25 | void find_bridges() { 26 | timer = 1; 27 | rep(i, 0, n) { 28 | tin[i] = low[i] = 0; 29 | } 30 | rep(i, 0, n) if (!tin[i]) dfs(i); 31 | } 32 | 33 | -------------------------------------------------------------------------------- /content/graph/centroid_decomposition.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | vector centroid_dec(vector> &adj) { 4 | int n = adj.size(); 5 | vector p(n), vis(n), siz(n); 6 | 7 | auto build_sz = [&](auto self, int v, int pr) -> int { 8 | siz[v] = 1; 9 | for (int ch : adj[v]) { 10 | if (!vis[ch] && ch != pr) siz[v] += self(self, ch, v); 11 | } 12 | return siz[v]; 13 | }; 14 | 15 | auto find_cent = [&](auto self, int v, int pr, int size) -> int { 16 | for (int ch : adj[v]) { 17 | if (!vis[ch] && ch != pr && siz[ch] > size / 2) 18 | return self(self, ch, v, size); 19 | } 20 | return v; 21 | }; 22 | 23 | auto build_cent = [&](auto self, int v, int pr) -> void { 24 | build_sz(build_sz, v, -1); 25 | int c = find_cent(find_cent, v, -1, siz[v]); 26 | p[c] = pr; 27 | vis[c] = true; 28 | for (int ch : adj[c]) { 29 | if (!vis[ch]) self(self, ch, c); 30 | } 31 | }; 32 | 33 | build_cent(build_cent, n - 1, -1); 34 | 35 | return p; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /content/graph/dsu.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | struct dsu { 4 | vector p, rnk; 5 | dsu(int n) : p(n), rnk(n, 1) { iota(all(p), 0); } 6 | int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); } 7 | bool join(int a, int b) { 8 | a = find(a); b = find(b); 9 | if (a == b) return false; 10 | if (rnk[a] < rnk[b]) swap(a, b); 11 | p[b] = a; 12 | rnk[a] += rnk[b]; 13 | return true; 14 | } 15 | bool same(int a, int b) { return find(a) == find(b); } 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /content/graph/euler_path.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | template struct euler_path { 4 | vector> adj, anc; 5 | vector idxs, siz, dep; 6 | vector bit, vals; 7 | int n; 8 | const int lg = 18; 9 | euler_path(vector> _adj) { 10 | adj = _adj; 11 | n = sz(adj); 12 | idxs.resize(n); 13 | siz.resize(n); 14 | bit.resize(n); 15 | vals.resize(n); 16 | anc = vector>(n, vector(lg)); 17 | dep.resize(n); 18 | dfs(1); //tree root 19 | } 20 | int time = 0; 21 | void dfs(int v, int p = 0) { 22 | idxs[v] = time++; 23 | siz[v] = 1; 24 | anc[v][0] = p; 25 | dep[v] = dep[p] + 1; 26 | rep(j, 1, lg) { 27 | anc[v][j] = anc[anc[v][j - 1]][j - 1]; 28 | } 29 | 30 | for (auto ch: adj[v]) if (ch != p) { 31 | dfs(ch, v); 32 | siz[v] += siz[ch]; 33 | } 34 | } 35 | int lca(int x,int y) { 36 | if (dep[x] < dep[y]) swap(x,y); 37 | for (int i = lg - 1; i >= 0; i--) if (dep[anc[x][i]] >= dep[y]) x = anc[x][i]; 38 | if (x == y) return x; 39 | 40 | for (int i = lg - 1; i >= 0; i--) if (anc[x][i] != anc[y][i]) x = anc[x][i], y = anc[y][i]; 41 | return anc[x][0]; 42 | } 43 | ll sum(int x) { 44 | ll s = 0; 45 | for (int i = x; i >= 0; i = (i & (i + 1)) - 1) s += bit[i]; 46 | return s; 47 | } 48 | void add(int x, ll delta) { 49 | for (int i = x; i < n; i = i | (i + 1)) bit[i] += delta; 50 | } 51 | void inc_vertex(int i, ll x) { 52 | vals[i] += x; 53 | add(idxs[i], x); 54 | if(siz[i] + idxs[i] < n) add(idxs[i] + siz[i], -x); 55 | } 56 | void update_vertex(int i, ll x) { 57 | inc_vertex(i, x - vals[i]); 58 | } 59 | ll query(int u) { 60 | return sum(idxs[u]); 61 | } 62 | ll query(int u, int v) { 63 | int lc = lca(u, v); 64 | return query(u) + query(v) - 2 * query(lc) + vals[lc] * (EDGES == false); 65 | } 66 | }; 67 | 68 | -------------------------------------------------------------------------------- /content/graph/hld.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | template struct seg_tree { 4 | struct node { 5 | T x = 0; 6 | const node operator + (const node& o) const { 7 | node ans; 8 | ans.x = max(o.x, x); 9 | return ans; 10 | } 11 | }; 12 | 13 | int n; 14 | vector tree; 15 | seg_tree(int n) : n(n), tree(n * 2) {} 16 | void update(ll i, T f){ 17 | i += n; 18 | tree[i].x = f; 19 | for(i >>= 1; i >= 1; i >>= 1) tree[i] = tree[i * 2] + tree[i * 2 + 1]; 20 | } 21 | T query(ll a, ll b){ 22 | node esq, dir; 23 | for(a += n, b += n; a <= b; a >>= 1, b >>= 1){ 24 | if(a % 2) esq = esq + tree[a++]; 25 | if(b % 2 == 0) dir = tree[b--] + dir; 26 | } 27 | return (esq + dir).x; 28 | } 29 | }; 30 | 31 | template struct hld { 32 | int n, cnt = 0; 33 | vector> adj; 34 | vector pr, siz, dep, tp, idx; 35 | seg_tree tree; 36 | hld(vector> adj) 37 | : n(sz(adj)), adj(adj), pr(n, -1), siz(n, 1), dep(n), 38 | tp(n), idx(n), tree(n) { 39 | dfs_sz(0); 40 | dfs(0); 41 | } 42 | void dfs_sz(int v) { 43 | if (pr[v] != -1) adj[v].erase(find(all(adj[v]), pr[v])); 44 | for (int &ch : adj[v]) { 45 | pr[ch] = v, dep[ch] = dep[v] + 1; 46 | dfs_sz(ch); 47 | siz[v] += siz[ch]; 48 | if (siz[ch] > siz[adj[v][0]]) swap(ch, adj[v][0]); 49 | } 50 | } 51 | void dfs(int v) { 52 | idx[v] = cnt++; 53 | for (int ch : adj[v]) { 54 | tp[ch] = (ch == adj[v][0] ? tp[v] : ch); 55 | dfs(ch); 56 | } 57 | } 58 | template void process(int u, int v, B op) { 59 | for (; tp[u] != tp[v]; v = pr[tp[v]]) { 60 | if (dep[tp[u]] > dep[tp[v]]) swap(u, v); 61 | op(idx[tp[v]], idx[v]); 62 | } 63 | if (dep[u] > dep[v]) swap(u, v); 64 | op(idx[u] + EDGES, idx[v]); 65 | } 66 | /* requires lazy segment tree 67 | void update_path(int u, int v, int val) { 68 | process(u, v, [&](int l, int r) { tree.update(l, r, val); }); 69 | } 70 | */ 71 | void update_vertex(int v, int val) { 72 | tree.update(idx[v], val); 73 | } 74 | int query(int u, int v) { 75 | int ans = 0; 76 | process(u, v, [&](int l, int r) { ans = max(ans, tree.query(l, r)); }); 77 | return ans; 78 | } 79 | int query_subtree(int v) { 80 | return tree.query(idx[v] + EDGES, idx[v] + siz[v] - 1); 81 | } 82 | }; 83 | -------------------------------------------------------------------------------- /content/graph/lca.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | struct lca { 4 | vector> adj, anc; 5 | vector dep, in, out; 6 | int n, lg, t; 7 | lca(int n) : n(n), adj(n + 1), dep(n + 1), in(n + 1), out(n + 1) { 8 | lg = 32 - __builtin_clz(n); 9 | anc = vector>(n + 1, vector(lg)); 10 | } 11 | void add_edge(int u, int v) { 12 | adj[u].push_back(v); 13 | adj[v].push_back(u); 14 | } 15 | void dfs(int v, int p = -1, int d = 1) { 16 | dep[v] = d; 17 | in[v] = t++; 18 | rep(i, 1, lg) anc[v][i] = anc[anc[v][i - 1]][i - 1]; 19 | for (int ch : adj[v]) if (ch != p) { 20 | anc[ch][0] = v; 21 | dfs(ch, v, d + 1); 22 | } 23 | out[v] = t++; 24 | } 25 | bool is_anc(int a, int b){ 26 | return (in[a] <= in[b]) && (out[a] >= out[b]); 27 | } 28 | int get_lca(int a, int b) { 29 | if(is_anc(a, b)) return a; 30 | if(is_anc(b, a)) return b; 31 | for (int i = lg - 1; i >= 0; i--) { 32 | if (!is_anc(anc[a][i], b) && in[anc[a][i]] != out[anc[a][i]]){ 33 | a = anc[a][i]; 34 | } 35 | } 36 | return anc[a][0]; 37 | } 38 | int dist(int a, int b) { 39 | return dep[a] + dep[b] - 2 * dep[get_lca(a, b)]; 40 | } 41 | int jump(int v, int k) { 42 | for (int i = lg - 1; i >= 0; i--) { 43 | if ((1 << i) <= k) { 44 | v = anc[v][i]; 45 | k -= (1 << i); 46 | } 47 | } 48 | return v; 49 | } 50 | }; 51 | -------------------------------------------------------------------------------- /content/graph/link_cut_tree.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | struct SplayTree { 4 | struct Node { 5 | int p = 0, ch[2] = {0, 0}; 6 | ll self = 0, path = 0; // Path aggregates 7 | ll sub = 0, vir = 0; // Subtree aggregates 8 | bool flip = 0; // Lazy tags 9 | }; 10 | vector t; 11 | SplayTree(int n) : t(n + 1) {} 12 | 13 | void push(int v) { 14 | if(!v || !t[v].flip) return; 15 | auto &[l, r] = t[v].ch; 16 | t[l].flip ^= 1, t[r].flip ^= 1; 17 | swap(l, r), t[v].flip = 0; 18 | } 19 | 20 | void pull(int v) { 21 | auto [l, r] = t[v].ch; push(l), push(r); 22 | t[v].path = t[l].path + t[v].self + t[r].path; 23 | t[v].sub = t[v].vir + t[l].sub + t[v].self + t[r].sub; 24 | } 25 | 26 | void set(int u, int d, int v) { 27 | t[u].ch[d] = v, t[v].p = u, pull(u); 28 | } 29 | 30 | void splay(int v) { 31 | auto dir = [&](int x) { 32 | int u = t[x].p; 33 | return t[u].ch[0] == x ? 0 : t[u].ch[1] == x ? 1 : -1; 34 | }; 35 | auto rotate = [&](int x) { 36 | int y = t[x].p, z = t[y].p, dx = dir(x), dy = dir(y); 37 | set(y, dx, t[x].ch[!dx]), set(x, !dx, y); 38 | if(~dy) set(z, dy, x); 39 | t[x].p = z; 40 | }; 41 | for(push(v); ~dir(v); ) { 42 | int y = t[v].p, z = t[y].p; 43 | push(z), push(y), push(v); 44 | int dv = dir(v), dy = dir(y); 45 | if(~dy) rotate(dv == dy ? y : v); 46 | rotate(v); 47 | } 48 | } 49 | }; 50 | 51 | struct LinkCut : SplayTree { // One-indexed 52 | LinkCut(int n) : SplayTree(n) {} 53 | 54 | int access(int v) { 55 | int u = v, x = 0; 56 | for(; u; x = u, u = t[u].p) { 57 | splay(u); 58 | int &ox = t[u].ch[1]; 59 | t[u].vir += t[ox].sub; 60 | t[u].vir -= t[x].sub; 61 | ox = x, pull(u); 62 | } 63 | return splay(v), x; 64 | } 65 | 66 | void reroot(int v) { 67 | access(v), t[v].flip ^= 1, push(v); 68 | } 69 | 70 | void link(int u, int v) { 71 | reroot(u), access(v); 72 | t[v].vir += t[u].sub; 73 | t[u].p = v, pull(v); 74 | } 75 | 76 | void cut(int u, int v) { 77 | reroot(u), access(v); 78 | t[v].ch[0] = t[u].p = 0, pull(v); 79 | } 80 | 81 | // Rooted tree LCA. Returns 0 if u and v are not connected. 82 | int lca(int u, int v) { 83 | if(u == v) return u; 84 | access(u); int ret = access(v); 85 | return t[u].p ? ret : 0; 86 | } 87 | 88 | // Query subtree of u where v is outside the subtree. 89 | ll getSub(int u, int v) { 90 | reroot(v), access(u); 91 | return t[u].vir + t[u].self; 92 | } 93 | 94 | ll getPath(int u, int v) { 95 | reroot(u), access(v); 96 | return t[v].path; 97 | } 98 | 99 | // Add val in vertex u 100 | void update(int u, ll val) { 101 | access(u), t[u].self += val, pull(u); 102 | } 103 | 104 | // Finds the root of the tree containing node v 105 | int find_root(int v) { 106 | access(v); 107 | for (; t[v].ch[0]; v = t[v].ch[0]); 108 | access(v); 109 | return v; 110 | } 111 | }; 112 | -------------------------------------------------------------------------------- /content/graph/max_flow.cpp: -------------------------------------------------------------------------------- 1 | // https://cp-algorithms.com/graph/dinic.html#implementation 2 | #include "../contest/template.cpp" 3 | 4 | struct FlowEdge { 5 | int v, u; 6 | ll cap, flow = 0; 7 | FlowEdge(int v, int u, ll cap) : v(v), u(u), cap(cap) {} 8 | }; 9 | 10 | struct Dinic { 11 | const ll flow_inf = 1e18; 12 | vector edges; 13 | vector> adj; 14 | int n, m = 0, s, t; 15 | vector level, ptr; 16 | queue q; 17 | 18 | Dinic(int n, int s, int t) : adj(n), n(n), s(s), t(t), level(n), ptr(n) {} 19 | 20 | void add_edge(int v, int u, ll cap) { 21 | edges.emplace_back(v, u, cap); 22 | edges.emplace_back(u, v, 0); 23 | adj[v].push_back(m); 24 | adj[u].push_back(m + 1); 25 | m += 2; 26 | } 27 | 28 | bool bfs() { 29 | while (!q.empty()) { 30 | int v = q.front(); 31 | q.pop(); 32 | for (int id : adj[v]) { 33 | if (edges[id].cap - edges[id].flow < 1) continue; 34 | if (level[edges[id].u] != -1) continue; 35 | level[edges[id].u] = level[v] + 1; 36 | q.push(edges[id].u); 37 | } 38 | } 39 | return level[t] != -1; 40 | } 41 | 42 | ll dfs(int v, ll pushed) { 43 | if (pushed == 0) return 0; 44 | if (v == t) return pushed; 45 | for (int& cid = ptr[v]; cid < sz(adj[v]); cid++) { 46 | int id = adj[v][cid]; 47 | int u = edges[id].u; 48 | if (level[v] + 1 != level[u] || edges[id].cap - edges[id].flow < 1) 49 | continue; 50 | ll tr = dfs(u, min(pushed, edges[id].cap - edges[id].flow)); 51 | if (tr == 0) continue; 52 | edges[id].flow += tr; 53 | edges[id ^ 1].flow -= tr; 54 | return tr; 55 | } 56 | return 0; 57 | } 58 | 59 | ll flow() { 60 | ll f = 0; 61 | while (true) { 62 | fill(all(level), -1); 63 | level[s] = 0; 64 | q.push(s); 65 | if (!bfs()) break; 66 | fill(all(ptr), 0); 67 | while (ll pushed = dfs(s, flow_inf)) { 68 | f += pushed; 69 | } 70 | } 71 | return f; 72 | } 73 | }; 74 | 75 | -------------------------------------------------------------------------------- /content/graph/mcmf.cpp: -------------------------------------------------------------------------------- 1 | // MinCostMaxFlow 2 | // 3 | // min_cost_flow(s, t, f) computa o par (fluxo, custo) 4 | // com max(fluxo) <= f que tenha min(custo) 5 | // min_cost_flow(s, t) -> Fluxo maximo de custo minimo de s pra t 6 | // Se for um dag, da pra substituir o SPFA por uma DP pra nao 7 | // pagar O(nm) no comeco 8 | // Se nao tiver aresta com custo negativo, nao precisa do SPFA 9 | // 10 | // O(nm + f * m log n) 11 | 12 | template struct mcmf { 13 | struct edge { 14 | int to, rev, flow, cap; // para, id da reversa, fluxo, capacidade 15 | bool res; // se eh reversa 16 | T cost; // custo da unidade de fluxo 17 | edge() : to(0), rev(0), flow(0), cap(0), cost(0), res(false) {} 18 | edge(int to_, int rev_, int flow_, int cap_, T cost_, bool res_) 19 | : to(to_), rev(rev_), flow(flow_), cap(cap_), res(res_), cost(cost_) {} 20 | }; 21 | 22 | vector> g; 23 | vector par_idx, par; 24 | T inf; 25 | vector dist; 26 | 27 | mcmf(int n) : g(n), par_idx(n), par(n), inf(numeric_limits::max()/3) {} 28 | 29 | void add(int u, int v, int w, T cost) { // de u pra v com cap w e custo cost 30 | edge a = edge(v, g[v].size(), 0, w, cost, false); 31 | edge b = edge(u, g[u].size(), 0, 0, -cost, true); 32 | 33 | g[u].push_back(a); 34 | g[v].push_back(b); 35 | } 36 | 37 | //Usar esse spfa se o grafo for uma DAG. nm + f * m log n -> n + m + f * m log n 38 | // vector spfa(int s) { 39 | // vector in(g.size(), 0); 40 | // queue q; 41 | 42 | // rep(i,0,sz(g)){ 43 | // rep(j,0,sz(g[i])){ 44 | // auto [to, rev, flow, cap, res, cost] = g[i][j]; 45 | // if(flow < cap) in[to]++; 46 | // } 47 | // } 48 | 49 | // rep(i,0,sz(g)){ 50 | // if(in[i] == 0) q.push(i); 51 | // } 52 | 53 | // dist = vector(g.size(), inf); 54 | // dist[s] = 0; 55 | 56 | // while (!q.empty()) { 57 | // int v = q.front(); 58 | // q.pop(); 59 | 60 | // rep(i,0,sz(g[v])) { 61 | // auto [to, rev, flow, cap, res, cost] = g[v][i]; 62 | // if (flow < cap) { 63 | // dist[to] = min(dist[to], dist[v] + cost); 64 | // if(--in[to] == 0) q.push(to); 65 | // } 66 | // } 67 | // } 68 | // return dist; 69 | // } 70 | 71 | vector spfa(int s) { // nao precisa se nao tiver custo negativo 72 | deque q; 73 | vector is_inside(g.size(), 0); 74 | dist = vector(g.size(), inf); 75 | 76 | dist[s] = 0; 77 | q.push_back(s); 78 | is_inside[s] = true; 79 | 80 | while (!q.empty()) { 81 | int v = q.front(); 82 | q.pop_front(); 83 | is_inside[v] = false; 84 | 85 | for (int i = 0; i < g[v].size(); i++) { 86 | auto [to, rev, flow, cap, res, cost] = g[v][i]; 87 | if (flow < cap and dist[v] + cost < dist[to]) { 88 | dist[to] = dist[v] + cost; 89 | 90 | if (is_inside[to]) continue; 91 | if (!q.empty() and dist[to] > dist[q.front()]) q.push_back(to); 92 | else q.push_front(to); 93 | is_inside[to] = true; 94 | } 95 | } 96 | } 97 | return dist; 98 | } 99 | 100 | bool dijkstra(int s, int t, vector& pot) { 101 | priority_queue, vector>, greater<>> q; 102 | dist = vector(g.size(), inf); 103 | dist[s] = 0; 104 | q.emplace(0, s); 105 | while (q.size()) { 106 | auto [d, v] = q.top(); 107 | q.pop(); 108 | if (dist[v] < d) continue; 109 | for (int i = 0; i < g[v].size(); i++) { 110 | auto [to, rev, flow, cap, res, cost] = g[v][i]; 111 | cost += pot[v] - pot[to]; 112 | if (flow < cap and dist[v] + cost < dist[to]) { 113 | dist[to] = dist[v] + cost; 114 | q.emplace(dist[to], to); 115 | par_idx[to] = i, par[to] = v; 116 | } 117 | } 118 | } 119 | return dist[t] < inf; 120 | } 121 | 122 | pair min_cost_flow(int s, int t, int flow = INF) { 123 | vector pot(g.size(), 0); 124 | pot = spfa(s); // mudar algoritmo de caminho minimo aqui 125 | 126 | int f = 0; 127 | T ret = 0; 128 | while (f < flow and dijkstra(s, t, pot)) { 129 | for (int i = 0; i < g.size(); i++) 130 | if (dist[i] < inf) pot[i] += dist[i]; 131 | 132 | int mn_flow = flow - f, u = t; 133 | while (u != s){ 134 | mn_flow = min(mn_flow, 135 | g[par[u]][par_idx[u]].cap - g[par[u]][par_idx[u]].flow); 136 | u = par[u]; 137 | } 138 | 139 | ret += pot[t] * mn_flow; 140 | 141 | u = t; 142 | while (u != s) { 143 | g[par[u]][par_idx[u]].flow += mn_flow; 144 | g[u][g[par[u]][par_idx[u]].rev].flow -= mn_flow; 145 | u = par[u]; 146 | } 147 | 148 | f += mn_flow; 149 | } 150 | 151 | return make_pair(f, ret); 152 | } 153 | 154 | // Opcional: retorna as arestas originais por onde passa flow = cap 155 | vector> recover() { 156 | vector> used; 157 | for (int i = 0; i < g.size(); i++) for (edge e : g[i]) 158 | if(e.flow == e.cap && !e.res) used.push_back({i, e.to}); 159 | return used; 160 | } 161 | }; -------------------------------------------------------------------------------- /content/graph/scc.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | vector> adj, adj_rev; 4 | vector used; 5 | vector order, component; 6 | 7 | void dfs1(int v) { 8 | used[v] = true; 9 | for (auto u : adj[v]) if (!used[u]) dfs1(u); 10 | order.push_back(v); 11 | } 12 | void dfs2(int v) { 13 | used[v] = true; 14 | component.push_back(v); 15 | for (auto u : adj_rev[v]) if (!used[u]) dfs2(u); 16 | } 17 | 18 | void solve(int n, int m) { 19 | adj.resize(n); 20 | adj_rev.resize(n); 21 | while (m--) { 22 | int a, b; cin >> a >> b; 23 | adj[a].push_back(b); 24 | adj_rev[b].push_back(a); 25 | } 26 | used.assign(n, false); 27 | for (int i = 0; i < n; i++) if (!used[i]) dfs1(i); 28 | used.assign(n, false); 29 | reverse(order.begin(), order.end()); 30 | 31 | vector roots(n, 0), root_nodes; 32 | vector> adj_scc(n); 33 | for (auto v : order) if (!used[v]) { 34 | dfs2(v); 35 | int root = component.front(); 36 | for (auto u : component) roots[u] = root; 37 | root_nodes.push_back(root); 38 | component.clear(); 39 | } 40 | for (int v = 0; v < n; v++) for (auto u : adj[v]) { 41 | int root_v = roots[v], root_u = roots[u]; 42 | if (root_u != root_v) 43 | adj_scc[root_v].push_back(root_u); 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /content/graph/twosat.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | struct twosat { 4 | int n, cur_comp = 0; 5 | vector> adj, adjr; 6 | vector order, comp, val; 7 | twosat(int n) : n(n), adj(n), adjr(n), comp(n) {} 8 | 9 | void add(int a, int sa, int b, int sb) { // sa = se a esta negado 10 | int pa = (2 * a) ^ sa, pb = (2 * b) ^ sb; 11 | 12 | adj[pa ^ 1].push_back(pb); 13 | adj[pb ^ 1].push_back(pa); 14 | adjr[pb].push_back(pa ^ 1); 15 | adjr[pa].push_back(pb ^ 1); 16 | } 17 | void dfs1(int v) { 18 | comp[v] = 1; 19 | for (int ch : adj[v]) if (!comp[ch]) dfs1(ch); 20 | order.push_back(v); 21 | } 22 | void dfs2(int v) { 23 | comp[v] = cur_comp; 24 | for (int ch : adjr[v]) if (!comp[ch]) dfs2(ch); 25 | } 26 | bool solve() { 27 | for (int i = 0; i < n; i++) if (!comp[i]) dfs1(i); 28 | reverse(order.begin(), order.end()); 29 | comp = vector(n); 30 | for (int v : order) if (!comp[v]) { 31 | cur_comp++; 32 | dfs2(v); 33 | } 34 | val = vector(n / 2, -1); 35 | for (int i = 0; i < n; i += 2) { 36 | if (comp[i] == comp[i ^ 1]) return false; 37 | val[i / 2] = comp[i] > comp[i ^ 1]; 38 | } 39 | return true; 40 | } 41 | }; 42 | 43 | -------------------------------------------------------------------------------- /content/graph/undirected_eulerian_path.cpp: -------------------------------------------------------------------------------- 1 | // https://cses.fi/problemset/task/1691/ 2 | #include "../contest/template.cpp" 3 | 4 | #define endl '\n' 5 | 6 | void solve() { 7 | ios_base::sync_with_stdio(0); cin.tie(0); 8 | 9 | int n, m; cin >> n >> m; 10 | vector> adj(n + 1); 11 | vector> e(m); 12 | for (int i = 0; i < m; i++) { 13 | int u, v; cin >> u >> v; 14 | adj[u].push_back(i); 15 | adj[v].push_back(i); 16 | e[i] = { u, v }; 17 | } 18 | for (int i = 1; i <= n; i++) { 19 | if (adj[i].size() % 2 == 1) { 20 | cout << "IMPOSSIBLE" << endl; 21 | return; 22 | } 23 | } 24 | vector ans, vis(m); 25 | auto dfs = [&](auto self, int v) -> void { 26 | while (adj[v].size() > 0) { 27 | int i = adj[v].back(); 28 | adj[v].pop_back(); 29 | if (!vis[i]) { 30 | vis[i] = 1; 31 | self(self, e[i][e[i][0] == v]); 32 | } 33 | } 34 | ans.push_back(v); 35 | }; 36 | dfs(dfs, 1); 37 | if (ans.size() != m + 1) cout << "IMPOSSIBLE" << endl; 38 | else { 39 | for (int x : ans) cout << x << " "; 40 | cout << endl; 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /content/math/FWHT.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | // Fast Walsh Hadamard Transform 4 | // 5 | // FWHT<'|'>(f) eh SOS DP 6 | // FWHT<'&'>(f) eh soma de superset DP 7 | // Se chamar com ^, usar tamanho potencia de 2!! 8 | // 9 | // O(n log(n)) 10 | 11 | template vector FWHT(vector f, bool inv = false) { 12 | int n = f.size(); 13 | for (int k = 0; (n-1)>>k; k++) for (int i = 0; i < n; i++) if (i>>k&1) { 14 | int j = i^(1< vl conv(vl a, vl b) { 24 | a = FWHT(a), b = FWHT(b); 25 | rep(i, 0, sz(a)) a[i] *= b[i]; 26 | a = FWHT(a, 1); 27 | return a; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /content/math/Lagrange.cpp: -------------------------------------------------------------------------------- 1 | #include "../primitives/mint.cpp" 2 | 3 | // dados (i, y(i)) para 0 <= i < n, retorna y(x) 4 | // em que y é um polinômio de grau n - 1 5 | Int evaluate_interpolation(ll x, vector y) { 6 | int n = y.size(); 7 | 8 | vector sulf(n+1, 1), fat(n, 1), ifat(n); 9 | for (int i = n-1; i >= 0; i--) sulf[i] = sulf[i+1] * (x - i); 10 | for (int i = 1; i < n; i++) fat[i] = fat[i-1] * i; 11 | ifat[n-1] = (Int)1/fat[n-1]; 12 | for (int i = n-2; i >= 0; i--) ifat[i] = ifat[i+1] * (i + 1); 13 | 14 | Int pref = 1, ans = 0; 15 | for (int i = 0; i < n; pref *= (x - i++)) { 16 | Int num = pref * sulf[i+1]; 17 | 18 | Int den = ifat[i] * ifat[n-1 - i]; 19 | if ((n-1 - i)%2) den *= -1; 20 | 21 | ans += y[i] * num * den; 22 | } 23 | return ans; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /content/math/ceil_div.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | ll ceil_div(ll x, ll y) { 3 | assert(y != 0); 4 | if (y < 0) { 5 | y = -y; 6 | x = -x; 7 | } 8 | if (x <= 0) return x / y; 9 | return (x - 1) / y + 1; 10 | } 11 | -------------------------------------------------------------------------------- /content/math/circular_fft.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | #include "fft.cpp" 3 | 4 | // res[i] = somatorio a[j] * b[(i - j + n) % n] 5 | void circularConv(vector &a, vector &b, vector &res) { 6 | assert(sz(a) == sz(b)); 7 | int n = a.size(); 8 | res = conv(a, b); 9 | rep(i, n, sz(res)) res[i%n] = (res[i%n]+res[i]); 10 | res.resize(n); 11 | } 12 | 13 | -------------------------------------------------------------------------------- /content/math/crt.cpp: -------------------------------------------------------------------------------- 1 | #include "ext_gcd.cpp" 2 | 3 | // encontra a solução para o sistema 4 | // x == a mod m 5 | // x == b mod n 6 | // 7 | // uma solução existe se e somente se 8 | // gcd(n, m) dividir a - b 9 | // 10 | // a solução é única módulo lcm(n, m) 11 | // 12 | ll crt(ll a, ll m, ll b, ll n) { 13 | if (n > m) swap(a, b), swap(m, n); 14 | ll x, y, g = ext_gcd(m, n, x, y); 15 | if((a - b) % g != 0) return -1; 16 | x = (b - a) % n * x % n / g * m + a; 17 | return x < 0 ? x + m*n/g : x; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /content/math/diophantine.cpp: -------------------------------------------------------------------------------- 1 | #include "./ext_gcd.cpp" 2 | 3 | bool find_any_solution(ll a, ll b, ll c, ll &x0, ll &y0, ll &g) { 4 | g = ext_gcd(abs(a), abs(b), x0, y0); 5 | if (c % g) { 6 | return false; 7 | } 8 | 9 | x0 *= c / g; 10 | y0 *= c / g; 11 | if (a < 0) x0 = -x0; 12 | if (b < 0) y0 = -y0; 13 | return true; 14 | } 15 | -------------------------------------------------------------------------------- /content/math/discrete_log.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | // menor x tal que a ^ x = b (mod m) 4 | int solve(int a, int b, int m) { 5 | a %= m, b %= m; 6 | int k = 1, add = 0, g; 7 | while((g = gcd(a, m)) > 1) { 8 | if (b == k) return add; 9 | if (b % g) return -1; 10 | b /= g, m /= g, add++; 11 | k = (k * 1ll * a / g) % m; 12 | } 13 | int n = sqrt(m) + 1, an = 1; 14 | rep(i, 0, n) an = (an * 1ll * a) % m; 15 | unordered_map vals; 16 | for (int q = 0, cur = b; q <= n; q++) { 17 | vals[cur] = q; 18 | cur = (cur * 1ll * a) % m; 19 | } 20 | for (int p = 1, cur = k; p <= n; p++) { 21 | cur = (cur * 1ll * an) % m; 22 | if (vals.count(cur)) { 23 | int ans = n * p - vals[cur] + add; 24 | return ans; 25 | } 26 | } 27 | return -1; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /content/math/discrete_root.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | int powmod(int a, int b, int p) { 4 | int res = 1; 5 | while (b > 0) { 6 | if (b & 1) res = res * a % p; 7 | a = a * a % p; 8 | b >>= 1; 9 | } 10 | return res; 11 | } 12 | 13 | // Finds the primitive root modulo p 14 | int generator(int p) { 15 | vector fact; 16 | int phi = p-1, n = phi; 17 | for (int i = 2; i * i <= n; ++i) { 18 | if (n % i == 0) { 19 | fact.push_back(i); 20 | while (n % i == 0) 21 | n /= i; 22 | } 23 | } 24 | if (n > 1) 25 | fact.push_back(n); 26 | 27 | for (int res = 2; res <= p; ++res) { 28 | bool ok = true; 29 | for (int factor : fact) { 30 | if (powmod(res, phi / factor, p) == 1) { 31 | ok = false; 32 | break; 33 | } 34 | } 35 | if (ok) return res; 36 | } 37 | return -1; 38 | } 39 | 40 | // This program finds all numbers x such that x^k = a (mod n) 41 | int main() { 42 | int n, k, a; 43 | scanf("%d %d %d", &n, &k, &a); 44 | if (a == 0) { 45 | puts("1\n0"); 46 | return 0; 47 | } 48 | 49 | int g = generator(n); 50 | 51 | // Baby-step giant-step discrete logarithm algorithm 52 | int sq = (int) sqrt (n + .0) + 1; 53 | vector> dec(sq); 54 | for (int i = 1; i <= sq; ++i) 55 | dec[i-1] = {powmod(g, i * sq * k % (n - 1), n), i}; 56 | sort(dec.begin(), dec.end()); 57 | int any_ans = -1; 58 | for (int i = 0; i < sq; ++i) { 59 | int my = powmod(g, i * k % (n - 1), n) * a % n; 60 | auto it = lower_bound(dec.begin(), dec.end(), make_pair(my, 0)); 61 | if (it != dec.end() && it->first == my) { 62 | any_ans = it->second * sq - i; 63 | break; 64 | } 65 | } 66 | if (any_ans == -1) { 67 | puts("0"); 68 | return 0; 69 | } 70 | 71 | // Print all possible answers 72 | int delta = (n-1) / gcd(k, n-1); 73 | vector ans; 74 | for (int cur = any_ans % delta; cur < n-1; cur += delta) 75 | ans.push_back(powmod(g, cur, n)); 76 | sort(ans.begin(), ans.end()); 77 | printf("%d\n", ans.size()); 78 | for (int answer : ans) 79 | printf("%d ", answer); 80 | } 81 | 82 | -------------------------------------------------------------------------------- /content/math/division_trick.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | // Division Trick 4 | // 5 | // Gera o conjunto n/i, pra todo i, em O(sqrt(n)) 6 | // copiei do github do tfg50 7 | void division_trick(ll n){ 8 | for(int l = 1, r; l <= n; l = r + 1) r = n / (n / l); 9 | // n / i has the same value for l <= i <= r 10 | } 11 | -------------------------------------------------------------------------------- /content/math/ext_gcd.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | // dados a e b, retorna g = gcd(a, b) 4 | // a * x + b * y = g 5 | // 6 | // para a e M coprimos, podemos encontrar a^-1 mod M da seguinte forma: 7 | // a * x + M * y = 1 8 | // aplicando mod M nos dois lados: 9 | // a * x == 1 (mod M) 10 | // então, basta chamar ext_gcd(a, M, x, y) 11 | // se g != 1, não tem inverso 12 | // se g = 1, o inverso é (x%M + M) % M 13 | // 14 | // se a e M nao forem coprimos, temos que dividir ambos a e M pelo gcd(a, M) 15 | // isso acontece pq resolver inv == a^-1 (mod M), eh equivalente a encontrar 16 | // inv = a^-1 17 | // solução para 18 | 19 | ll ext_gcd(ll a, ll b, ll &x, ll &y) { 20 | if (!b) return x = 1, y = 0, a; 21 | ll d = ext_gcd(b, a % b, y, x); 22 | return y -= a/b * x, d; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /content/math/fft.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | typedef complex C; 4 | typedef vector vd; 5 | typedef vector vi; 6 | void fft(vector& a) { 7 | int n = sz(a), L = 31 - __builtin_clz(n); 8 | static vector> R(2, 1); 9 | static vector rt(2, 1); // (^ 10% faster if double) 10 | for (static int k = 2; k < n; k *= 2) { 11 | R.resize(n); rt.resize(n); 12 | auto x = polar(1.0L, acos(-1.0L) / k); 13 | rep(i,k,2*k) rt[i] = R[i] = i&1 ? R[i/2] * x : R[i/2]; 14 | } 15 | vi rev(n); 16 | rep(i,0,n) rev[i] = (rev[i / 2] | (i & 1) << L) / 2; 17 | rep(i,0,n) if (i < rev[i]) swap(a[i], a[rev[i]]); 18 | for (int k = 1; k < n; k *= 2) 19 | for (int i = 0; i < n; i += 2 * k) rep(j,0,k) { 20 | // C z = rt[j+k] * a[i+j+k]; // (25% faster if hand-rolled) /// include-line 21 | auto x = (double *)&rt[j+k], y = (double *)&a[i+j+k]; /// exclude-line 22 | C z(x[0]*y[0] - x[1]*y[1], x[0]*y[1] + x[1]*y[0]); /// exclude-line 23 | a[i + j + k] = a[i + j] - z; 24 | a[i + j] += z; 25 | } 26 | } 27 | 28 | vd conv(const vd& a, const vd& b) { 29 | if (a.empty() || b.empty()) return {}; 30 | vd res(sz(a) + sz(b) - 1); 31 | int L = 32 - __builtin_clz(sz(res)), n = 1 << L; 32 | vector in(n), out(n); 33 | copy(all(a), begin(in)); 34 | rep(i,0,sz(b)) in[i].imag(b[i]); 35 | fft(in); 36 | for (C& x : in) x *= x; 37 | rep(i,0,n) out[i] = in[-i & (n - 1)] - conj(in[i]); 38 | fft(out); 39 | rep(i,0,sz(res)) res[i] = imag(out[i]) / (4 * n); 40 | return res; 41 | } 42 | 43 | -------------------------------------------------------------------------------- /content/math/fft2D.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | using cd = complex; 4 | const double PI = acos(-1); 5 | 6 | void fft(vector & a, bool invert) { 7 | int n = a.size(); 8 | 9 | for (int i = 1, j = 0; i < n; i++) { 10 | int bit = n >> 1; 11 | for (; j & bit; bit >>= 1) 12 | j ^= bit; 13 | j ^= bit; 14 | 15 | if (i < j) 16 | swap(a[i], a[j]); 17 | } 18 | 19 | for (int len = 2; len <= n; len <<= 1) { 20 | double ang = 2 * PI / len * (invert ? -1 : 1); 21 | cd wlen(cos(ang), sin(ang)); 22 | for (int i = 0; i < n; i += len) { 23 | cd w(1); 24 | for (int j = 0; j < len / 2; j++) { 25 | cd u = a[i+j], v = a[i+j+len/2] * w; 26 | a[i+j] = u + v; 27 | a[i+j+len/2] = u - v; 28 | w *= wlen; 29 | } 30 | } 31 | } 32 | 33 | if (invert) { 34 | for (cd & x : a) 35 | x /= n; 36 | } 37 | } 38 | 39 | void fft2D(vector> &a, bool invert){ 40 | int n = sz(a), m = sz(a[0]); 41 | 42 | if(!invert) for(int i = 0; i < n; i++) fft(a[i], invert); 43 | 44 | for(int j = 0; j < m; j++){ 45 | vector col; 46 | for(int i = 0; i < n; i++){ 47 | col.push_back(a[i][j]); 48 | } 49 | fft(col, invert); 50 | for(int i = 0; i < n; i++){ 51 | a[i][j] = col[i]; 52 | } 53 | } 54 | 55 | if(invert) for(int i = 0; i < n; i++) fft(a[i], invert); 56 | } 57 | 58 | vector> conv2D(vector> a, vector> b) { 59 | int n = 1; 60 | while (n < sz(a) + sz(b)) 61 | n <<= 1; 62 | int m = 1; 63 | while (m < sz(a[0]) + sz(b[0])) m <<= 1; 64 | a.resize(n); 65 | b.resize(n); 66 | 67 | rep(i,0,n){ 68 | a[i].resize(m); 69 | b[i].resize(m); 70 | } 71 | 72 | fft2D(a, false); 73 | fft2D(b, false); 74 | for (int i = 0; i < n; i++) for(int j = 0; j < m; j++) 75 | a[i][j] *= b[i][j]; 76 | 77 | fft2D(a, true); 78 | 79 | return a; 80 | } 81 | -------------------------------------------------------------------------------- /content/math/floor_div.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | ll floor_div(ll x, ll y) { 4 | assert(y != 0); 5 | if (y < 0) { 6 | y = -y; 7 | x = -x; 8 | } 9 | if (x >= 0) return x / y; 10 | return (x + 1) / y - 1; 11 | } 12 | -------------------------------------------------------------------------------- /content/math/floor_sum.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | // soma de floor((a * x + b) / m) 4 | // para x inteiro em [0, n) 5 | ll floor_sum(ll n, ll m, ll a, ll b) { 6 | ll a1 = a / m; 7 | ll a2 = a % m; 8 | ll ans = n * (n - 1) / 2 * a1; 9 | if (a2 == 0) { 10 | return ans + (b / m) * n; 11 | } 12 | ll b1 = b / m; 13 | ll b2 = b % m; 14 | ll y = (a2 * n + b2) / m; 15 | ans += n * (y + b1) - floor_sum(y, a2, m, m + a2 - b2 - 1); 16 | return ans; 17 | } 18 | 19 | -------------------------------------------------------------------------------- /content/math/gauss.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | const ld eps = 1e-6; 4 | template 5 | pair> gauss(vector> a, vector b){ 6 | int n = sz(a), m = sz(a[0]); 7 | rep(i,0,n) a[i].push_back(b[i]); 8 | 9 | vector pivot(m, -1); 10 | int f = 0; 11 | rep(i,0,m){ 12 | rep(j,f,n){ 13 | if(fabs(a[j][i]) < eps) continue; 14 | 15 | swap(a[j], a[f]); 16 | T div = a[f][i]; 17 | for(auto &x: a[f]) x /= div; 18 | pivot[i] = f++; 19 | break; 20 | } 21 | 22 | if(pivot[i] == -1) continue; 23 | rep(j,0,n){ 24 | if(j == f - 1) continue; 25 | T div = a[j][i]; 26 | rep(k,0,m + 1) a[j][k] -= a[f - 1][k] * div; 27 | } 28 | } 29 | 30 | vector ans(m); 31 | rep(i,0,m){ 32 | if(pivot[i] == -1) continue; 33 | ans[i] = a[pivot[i]].back(); 34 | } 35 | 36 | rep(i,0,n){ 37 | T res = 0; 38 | rep(j,0,m){ 39 | res += a[i][j] * ans[j]; 40 | } 41 | if(fabs(res - a[i].back()) > eps){ 42 | return {0, {}}; 43 | } 44 | } 45 | 46 | if(f == m) return {1, ans}; 47 | return {2, ans}; 48 | } 49 | -------------------------------------------------------------------------------- /content/math/gaussXor.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | const int N = 103; 4 | pair> gaussXor(vector> a, vector b){ 5 | int n = sz(a), m = N - 1; 6 | rep(i,0,n) a[i][N - 1] = b[i]; 7 | 8 | vector pivot(m, -1); 9 | int f = 0; 10 | rep(i,0,m){ 11 | rep(j,f,n){ 12 | if(!a[j][i]) continue; 13 | 14 | swap(a[j], a[f]); 15 | pivot[i] = f++; 16 | break; 17 | } 18 | 19 | if(pivot[i] == -1) continue; 20 | rep(j,0,n){ 21 | if(j == f - 1 || !a[j][i]) continue; 22 | a[j] ^= a[f - 1]; 23 | } 24 | } 25 | vector ans(m); 26 | for(int i = m - 1; i >= 0; i--){ 27 | if(pivot[i] == -1) continue; 28 | ans[i] = a[pivot[i]][N - 1]; 29 | } 30 | 31 | rep(i,0,n){ 32 | bool res = 0; 33 | rep(j,0,m){ 34 | res ^= (a[i][j] & ans[j]); 35 | } 36 | if(res != a[i][N - 1]){ 37 | return {0, {}}; 38 | } 39 | } 40 | if(f == m) return {1, ans}; 41 | return {2, ans}; 42 | } 43 | -------------------------------------------------------------------------------- /content/math/linear_sieve.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | const int MAX = 1e7; 4 | int lp[MAX + 1]; 5 | vector pr; 6 | 7 | void linear_sieve() { 8 | rep(i, 2, MAX + 1) { 9 | if (lp[i] == 0) { 10 | lp[i] = i; 11 | pr.push_back(i); 12 | } 13 | for (int j = 0; i * pr[j] <= MAX; j++) { 14 | lp[i * pr[j]] = pr[j]; 15 | if (pr[j] == lp[i]) break; 16 | } 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /content/math/mobius.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | const int MAX = 1e6+10; 4 | 5 | bool prime[MAX]; 6 | int mobius[MAX]; 7 | 8 | void build_mobius(){ 9 | memset(mobius, -1, sizeof mobius); 10 | mobius[1] = 1; 11 | rep(i,2,MAX) prime[i] = 1; 12 | 13 | for(ll i = 2; i < MAX; i++){ 14 | if(!prime[i]) continue; 15 | for(ll j = i; j < MAX; j += i){ 16 | mobius[j] *= -1; 17 | prime[j] = false; 18 | } 19 | prime[i] = 1; 20 | 21 | for(ll j = 1; i * i * j < MAX; j++){ 22 | mobius[i * i * j] = 0; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /content/math/nck.cpp: -------------------------------------------------------------------------------- 1 | #include "../primitives/mint.cpp" 2 | 3 | const ll N = 2e5 + 1, mod = 1e9 + 7; 4 | Int fn[N], fd[N], iv[N]; 5 | 6 | void initnck() { 7 | iv[1] = fn[1] = fd[1] = fn[0] = fd[0] = 1; 8 | rep(i, 2, N) { 9 | iv[i] = Int() - iv[mod % i] * (mod / i); 10 | fn[i] = fn[i - 1] * i; 11 | fd[i] = fd[i - 1] * iv[i]; 12 | } 13 | } 14 | 15 | Int nck(int n, int k) { 16 | return fn[n] * fd[n - k] * fd[k]; 17 | } 18 | 19 | -------------------------------------------------------------------------------- /content/math/ntt.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "fft.cpp" 4 | 5 | typedef vector vl; 6 | template vl convMod(const vl &a, const vl &b) { 7 | if (a.empty() || b.empty()) return {}; 8 | vl res(sz(a) + sz(b) - 1); 9 | int B=32-__builtin_clz(sz(res)), n=1< L(n), R(n), outs(n), outl(n); 11 | rep(i,0,sz(a)) L[i] = C((int)a[i] / cut, (int)a[i] % cut); 12 | rep(i,0,sz(b)) R[i] = C((int)b[i] / cut, (int)b[i] % cut); 13 | fft(L), fft(R); 14 | rep(i,0,n) { 15 | int j = -i & (n - 1); 16 | outl[j] = (L[i] + conj(L[j])) * R[i] / (2.0 * n); 17 | outs[j] = (L[i] - conj(L[j])) * R[i] / (2.0 * n) / 1i; 18 | } 19 | fft(outl), fft(outs); 20 | rep(i,0,sz(res)) { 21 | ll av = ll(real(outl[i])+.5), cv = ll(imag(outs[i])+.5); 22 | ll bv = ll(imag(outl[i])+.5) + ll(real(outs[i])+.5); 23 | res[i] = ((av % M * cut + bv) % M * cut + cv) % M; 24 | } 25 | return res; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /content/math/online_gauss.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct online_gauss { 3 | bitset gauss[N]; 4 | 5 | void add(bitset x){ 6 | for(int b = N - 1; b >= 0; b--){ 7 | if(!gauss[b][b] && x[b]){ 8 | gauss[b] = x; 9 | break; 10 | }else if(x[b]) x ^= gauss[b]; 11 | } 12 | } 13 | 14 | //if MIN = 0, max xor starting with x 15 | //if MIN = 1, min xor starting with x 16 | bitset query(bitset x, bool MIN=0){ 17 | for(int b = N - 1; b >= 0; b--) 18 | if(x[b] == MIN) x ^= gauss[b]; 19 | return x; 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /content/math/pollardrho.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | // Pollard's Rho Alg 4 | // 5 | // Usa o algoritmo de deteccao de ciclo de Floyd 6 | // com uma otimizacao na qual o gcd eh acumulado 7 | // A fatoracao nao sai necessariamente ordenada 8 | // O algoritmo rho encontra um fator de n, 9 | // e funciona muito bem quando n possui um fator pequeno 10 | // 11 | // Complexidades (considerando mul constante): 12 | // rho - esperado O(n^(1/4)) no pior caso 13 | // fact - esperado menos que O(n^(1/4) log(n)) no pior caso 14 | 15 | ll mul(ll a, ll b, ll m) { 16 | ll ret = a*b - ll((long double)1/m*a*b+0.5)*m; 17 | return ret < 0 ? ret+m : ret; 18 | } 19 | 20 | ll pow(ll x, ll y, ll m) { 21 | if (!y) return 1; 22 | ll ans = pow(mul(x, x, m), y/2, m); 23 | return y%2 ? mul(x, ans, m) : ans; 24 | } 25 | 26 | bool prime(ll n) { 27 | if (n < 2) return 0; 28 | if (n <= 3) return 1; 29 | if (n % 2 == 0) return 0; 30 | 31 | ll r = __builtin_ctzll(n - 1), d = n >> r; 32 | for (int a : {2, 325, 9375, 28178, 450775, 9780504, 1795265022}) { 33 | ll x = pow(a, d, n); 34 | if (x == 1 or x == n - 1 or a % n == 0) continue; 35 | 36 | for (int j = 0; j < r - 1; j++) { 37 | x = mul(x, x, n); 38 | if (x == n - 1) break; 39 | } 40 | if (x != n - 1) return 0; 41 | } 42 | return 1; 43 | } 44 | 45 | ll rho(ll n) { 46 | if (n == 1 or prime(n)) return n; 47 | auto f = [n](ll x) {return mul(x, x, n) + 1;}; 48 | 49 | ll x = 0, y = 0, t = 30, prd = 2, x0 = 1, q; 50 | while (t % 40 != 0 or gcd(prd, n) == 1) { 51 | if (x==y) x = ++x0, y = f(x); 52 | q = mul(prd, abs(x-y), n); 53 | if (q != 0) prd = q; 54 | x = f(x), y = f(f(y)), t++; 55 | } 56 | return gcd(prd, n); 57 | } 58 | 59 | vector fact(ll n) { 60 | if (n == 1) return {}; 61 | if (prime(n)) return {n}; 62 | ll d = rho(n); 63 | vector l = fact(d), r = fact(n / d); 64 | l.insert(l.end(), r.begin(), r.end()); 65 | return l; 66 | } 67 | 68 | vector get_divs(ll n) { 69 | vector facts = fact(n); 70 | map mp; 71 | for(auto e: facts) mp[e]++; 72 | sort(all(facts)); 73 | facts.resize(unique(all(facts)) - facts.begin()); 74 | vector f(sz(facts)); 75 | rep(i,0,sz(f)) f[i] = mp[facts[i]]; 76 | 77 | vl divs; 78 | auto go = [&](auto self, int i, ll cur) -> void { 79 | if(i == sz(facts)) { 80 | divs.push_back(cur); 81 | return; 82 | } 83 | 84 | rep(j,0, f[i] + 1) { 85 | self(self, i + 1, cur); 86 | cur *= facts[i]; 87 | } 88 | }; 89 | 90 | go(go, 0, 1); 91 | return divs; 92 | } 93 | -------------------------------------------------------------------------------- /content/math/simplex.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | //O(2^N) pior caso, O(N^3) caso médio 4 | //A = coeficientes subjects 5 | //B = resultados subjects 6 | //C = função a ser maximizada 7 | //x >= 0 8 | 9 | //Retorno: 10 | //pair 11 | //{-1e18, {}} sem solução 12 | //{1e18, {}} solução pode ser arbritariamente boa 13 | 14 | //Exemplo: 15 | //10.x1 + 8.x2 + x3 16 | //subject to 17 | //3.x1 + 3.x2 + 2.x3 <= 30 18 | //6.x1 + 3.x2 <= 48 19 | 20 | //Uso: 21 | //Subjects, resultados, função a ser maximizada 22 | //auto ans = Simplex::simplex({{3, 3, 2}, {6, 3, 0}}, {30, 48}, {10, 8, 1}); 23 | const double eps = 1e-7; 24 | namespace Simplex { 25 | vector> T; 26 | int n, m; 27 | vector X, Y; 28 | 29 | void pivot(int x, int y) { 30 | swap(X[y], Y[x-1]); 31 | for (int i = 0; i <= m; i++) if (i != y) T[x][i] /= T[x][y]; 32 | T[x][y] = 1/T[x][y]; 33 | for (int i = 0; i <= n; i++) if (i != x and abs(T[i][y]) > eps) { 34 | for (int j = 0; j <= m; j++) if (j != y) T[i][j] -= T[i][y] * T[x][j]; 35 | T[i][y] = -T[i][y] * T[x][y]; 36 | } 37 | } 38 | 39 | // Retorna o par (valor maximo, vetor solucao) 40 | pair> simplex( 41 | vector> A, vector b, vector c) { 42 | n = b.size(), m = c.size(); 43 | T = vector>(n + 1, vector(m + 1)); 44 | X = vector(m); 45 | Y = vector(n); 46 | for (int i = 0; i < m; i++) X[i] = i; 47 | for (int i = 0; i < n; i++) Y[i] = i+m; 48 | for (int i = 0; i < m; i++) T[0][i] = -c[i]; 49 | for (int i = 0; i < n; i++) { 50 | for (int j = 0; j < m; j++) T[i+1][j] = A[i][j]; 51 | T[i+1][m] = b[i]; 52 | } 53 | while (true) { 54 | int x = -1, y = -1; 55 | double mn = -eps; 56 | for (int i = 1; i <= n; i++) if (T[i][m] < mn) mn = T[i][m], x = i; 57 | if (x < 0) break; 58 | for (int i = 0; i < m; i++) if (T[x][i] < -eps) { y = i; break; } 59 | 60 | if (y < 0) return {-1e18, {}}; // sem solucao para Ax <= b 61 | pivot(x, y); 62 | } 63 | while (true) { 64 | int x = -1, y = -1; 65 | double mn = -eps; 66 | for (int i = 0; i < m; i++) if (T[0][i] < mn) mn = T[0][i], y = i; 67 | if (y < 0) break; 68 | mn = 1e200; 69 | for (int i = 1; i <= n; i++) if (T[i][y] > eps and T[i][m] / T[i][y] < mn) 70 | mn = T[i][m] / T[i][y], x = i; 71 | 72 | if (x < 0) return {1e18, {}}; // c^T x eh ilimitado 73 | pivot(x, y); 74 | } 75 | vector r(m); 76 | for(int i = 0; i < n; i++) if (Y[i] < m) r[Y[i]] = T[i+1][m]; 77 | return {T[0][m], r}; 78 | } 79 | }; -------------------------------------------------------------------------------- /content/miscellaneous/dynamic_ds.cpp: -------------------------------------------------------------------------------- 1 | #include"../contest/template.cpp" 2 | 3 | template struct dynamic_ds { 4 | vector a = { ds() }; 5 | vector> at = { {} }; 6 | dynamic_ds() {} 7 | void insert(const T &val) { 8 | at[0].push_back(val); 9 | rep(i, 0, sz(a)) { 10 | if (sz(at[i]) > (1 << i)) { 11 | if (i == sz(a) - 1) { 12 | at.push_back({}); 13 | a.push_back(ds()); 14 | } 15 | for (T x : at[i]) { 16 | at[i + 1].push_back(x); 17 | } 18 | at[i].clear(); 19 | a[i] = ds(); 20 | continue; 21 | } 22 | a[i] = ds(); 23 | for (T x : at[i]) { 24 | a[i].insert(x); 25 | } 26 | a[i].build(); 27 | break; 28 | } 29 | } 30 | ll query(const T &val) { 31 | ll ans = 0; 32 | rep(i, 0, sz(a)) ans += a[i].query(val); 33 | return ans; 34 | } 35 | }; 36 | 37 | -------------------------------------------------------------------------------- /content/miscellaneous/hilbert_order.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | inline ll hilbert_order(int x, int y) { 4 | int bit = 20; 5 | ll res = 0; 6 | for (int n = 1 << bit, s = n >> 1; s; s >>= 1) { 7 | int rotate_x = (x & s) ? 1 : 0; 8 | int rotate_y = (y & s) ? 1 : 0; 9 | res += ((rotate_x) ^ (rotate_y * 3LL)) * s * s; 10 | if (rotate_x) continue; 11 | if (rotate_y) { 12 | x = n - 1 - x; 13 | y = n - 1 - y; 14 | } 15 | swap(x, y); 16 | } 17 | return res; 18 | } 19 | 20 | struct query { 21 | int l, r, idx; 22 | ll ord; 23 | void init() { 24 | ord = hilbert_order(l, r); 25 | } 26 | bool operator < (const query &other) const { 27 | return ord < other.ord; 28 | } 29 | }; 30 | 31 | -------------------------------------------------------------------------------- /content/miscellaneous/rotate_matrix.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | vector> rotate_ccw(const vector> &a) { 4 | int n = sz(a), m = sz(a[0]); 5 | vector b(m, vector(n)); 6 | rep(i, 0, n) rep(j, 0, m) { 7 | b[m - j - 1][i] = a[i][j]; 8 | } 9 | return b; 10 | } 11 | 12 | vector> rotate_cw(const vector> &a) { 13 | int n = sz(a), m = sz(a[0]); 14 | vector b(m, vector(n)); 15 | rep(i, 0, n) rep(j, 0, m) { 16 | b[j][n - i - 1] = a[i][j]; 17 | } 18 | return b; 19 | } 20 | 21 | -------------------------------------------------------------------------------- /content/primitives/frac.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | struct frac { 4 | ll num, den; 5 | frac() : num(0), den(1) {} 6 | frac(ll x) : num(x), den(1) {} 7 | frac(ll x, ll y) : num(x), den(y) {norm();} 8 | void norm() { 9 | if (den < 0) num = -num, den = -den; 10 | ll g = __gcd(abs(num), den); 11 | num /= g, den /= g; 12 | } 13 | frac& operator += (frac o) { 14 | num = num * o.den + o.num * den, den = den * o.den; 15 | norm(); 16 | return *this; 17 | } 18 | frac& operator -= (frac o) { 19 | num = num * o.den - o.num * den, den = den * o.den; 20 | norm(); 21 | return *this; 22 | } 23 | frac& operator *= (frac o) { 24 | num = num * o.num, den = den * o.den; 25 | norm(); 26 | return *this; 27 | } 28 | frac& operator /= (frac o) { 29 | num = num * o.den, den = den * o.num; 30 | norm(); 31 | return *this; 32 | } 33 | bool operator < (frac o) const { return num * o.den < den * o.num; } 34 | bool operator > (frac o) const { return num * o.den > den * o.num; } 35 | bool operator == (frac o) const { return num * o.den == den * o.num; } 36 | bool operator <= (frac o) const { return num * o.den <= den * o.num; } 37 | frac operator + (frac o) const { return frac(*this) += o; } 38 | frac operator - (frac o) const { return frac(*this) -= o; } 39 | frac operator * (frac o) const { return frac(*this) *= o; } 40 | frac operator / (frac o) const { return frac(*this) /= o; } 41 | string tos() { return to_string(num) + "/" + to_string(den); } 42 | }; 43 | 44 | -------------------------------------------------------------------------------- /content/primitives/function.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | struct F { 4 | ll a; 5 | ll b; 6 | 7 | F() = default; 8 | F(ll v) : b{v} {} 9 | F(ll a, ll b) : a{a}, b{b} {} 10 | 11 | ll operator()(ll x) { 12 | return (a * x + b); 13 | } 14 | 15 | //F(g(x)) 16 | const F operator() (F g){ 17 | F ans; 18 | ans.a = a * g.a; 19 | ans.b = (b + a * g.b); 20 | return ans; 21 | } 22 | 23 | //F(x) + g(x) 24 | const F operator+ (F g){ 25 | F ans; 26 | ans.a = (a + g.a); 27 | ans.b = (b + g.b); 28 | 29 | return ans; 30 | } 31 | }; -------------------------------------------------------------------------------- /content/primitives/hash.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | const int MOD_COUNT = 3; 4 | const ll BASE[] = { 104000711, 104000717, 1000000007 }; 5 | 6 | struct hsh { 7 | int a[MOD_COUNT]; 8 | hsh() { 9 | for (int i = 0; i < MOD_COUNT; i++) a[i] = 1; 10 | } 11 | bool operator < (const hsh &o) const { 12 | for (int i = 0; i < MOD_COUNT; i++) { 13 | if (a[i] < o.a[i]) return true; 14 | if (a[i] > o.a[i]) return false; 15 | } 16 | return false; 17 | } 18 | bool operator == (const hsh &o) const { 19 | for (int i = 0; i < MOD_COUNT; i++) if (a[i] != o.a[i]) return false; 20 | return true; 21 | } 22 | }; 23 | 24 | -------------------------------------------------------------------------------- /content/primitives/matrix.cpp: -------------------------------------------------------------------------------- 1 | // matrix fib; 2 | // fib.a = {{ {{1, 1}}, {{1, 0}} }}; 3 | 4 | #include "../contest/template.cpp" 5 | 6 | template struct matrix { 7 | array, N> a{}; 8 | matrix operator * (const matrix &o) const { 9 | matrix ans; 10 | rep(i, 0, N) rep(j, 0, N) rep(k, 0, N) 11 | ans.a[i][j] += a[i][k] * o.a[k][j]; 12 | return ans; 13 | } 14 | matrix operator ^ (ll e) const { 15 | matrix ans, self(*this); 16 | rep(i, 0, N) ans.a[i][i] = 1; 17 | while (e > 0) { 18 | if (e & 1) ans = ans * self; 19 | self = self * self; 20 | e >>= 1; 21 | } 22 | return ans; 23 | } 24 | vector operator * (const vector &o) const { 25 | vector ans(N); 26 | rep(i, 0, N) rep(j, 0, N) ans[i] += a[i][j] * o[j]; 27 | return ans; 28 | } 29 | array& operator[](int i) { 30 | return a[i]; 31 | } 32 | }; 33 | 34 | -------------------------------------------------------------------------------- /content/primitives/mint.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | template 4 | struct mint { 5 | int x; 6 | mint() : x(0) {} 7 | mint(ll _x) { _x %= mod; if (_x < 0) _x += mod; x = _x; } 8 | mint& operator += (mint o) { x += o.x; if (x >= mod) x -= mod; return *this; } 9 | mint& operator -= (mint o) { x -= o.x; if (x < 0) x += mod; return *this; } 10 | mint& operator *= (mint o) { x = (ll)x * o.x % mod; return *this; } 11 | mint& operator /= (mint o) { 12 | ll a = o.x, b = mod, u = 1, v = 0; 13 | while (b > 0) { 14 | ll t = a / b; 15 | a -= t * b; swap(a, b); 16 | u -= t * v; swap(u, v); 17 | } 18 | if (u < 0) u += mod; 19 | return *this *= u; 20 | } 21 | mint& operator ^= (ll e) { 22 | ll b = x; x = 1; 23 | while (e > 0) { 24 | if (e & 1ll) x = x * b % mod; 25 | b = b * b % mod, e >>= 1ll; 26 | } 27 | return *this; 28 | } 29 | mint operator + (mint o) const { return mint(*this) += o; } 30 | mint operator - (mint o) const { return mint(*this) -= o; } 31 | mint operator * (mint o) const { return mint(*this) *= o; } 32 | mint operator / (mint o) const { return mint(*this) /= o; } 33 | mint operator ^ (ll o) const { return mint(*this) ^= o; } 34 | bool operator < (mint o) const { return x < o.x; } 35 | bool operator == (mint o) const { return x == o.x; } 36 | bool operator != (mint o) const { return x != o.x; } 37 | }; 38 | 39 | template 40 | U& operator >> (U& is, mint& number) { 41 | ll x; 42 | is >> x; 43 | number = mint(x); 44 | return is; 45 | } 46 | 47 | template 48 | U& operator << (U& os, mint& number){ 49 | os << number.x; 50 | return os; 51 | } 52 | 53 | using Int = mint<(int)1e9 + 7>; 54 | -------------------------------------------------------------------------------- /content/string/aho_corasick.cpp: -------------------------------------------------------------------------------- 1 | // aho.build() 2 | // aho.solve(s) 3 | #include "../contest/template.cpp" 4 | 5 | struct aho_corasick { 6 | enum { N = (int)5e5 + 10, K = 26, first = 'a' }; 7 | struct node { 8 | int ch[K], cnt, link, p; 9 | vector id; 10 | node() { 11 | memset(ch, -1, sizeof ch); 12 | cnt = link = p = 0; 13 | } 14 | } a[N]; 15 | vector adj[N]; 16 | int pt = 0, ans[N]; 17 | void insert(const string &s, int id) { 18 | int cur = 0; 19 | for (char c : s) { 20 | int x = c - first; 21 | if (a[cur].ch[x] == -1) { 22 | pt++; 23 | a[pt].p = cur; 24 | a[cur].ch[x] = pt; 25 | } 26 | cur = a[cur].ch[x]; 27 | } 28 | a[cur].id.push_back(id); 29 | } 30 | void build() { 31 | queue> q; 32 | for (q.emplace(0, 0); !q.empty(); q.pop()) { 33 | auto [v, c] = q.front(); 34 | if (a[v].p) { 35 | int &link = a[v].link; 36 | 37 | link = a[a[v].p].link; 38 | while (link && a[link].ch[c] == -1) { 39 | link = a[link].link; 40 | } 41 | if (a[link].ch[c] != -1) link = a[link].ch[c]; 42 | } 43 | if (v) adj[a[v].link].push_back(v); 44 | 45 | rep(i, 0, K) if (a[v].ch[i] != -1) { 46 | q.push({a[v].ch[i], i}); 47 | } 48 | } 49 | } 50 | 51 | void solve(const string &s) { 52 | memset(ans, 0, sizeof ans); 53 | int cur = 0; 54 | for (char c : s) { 55 | int x = c - first; 56 | while (cur && a[cur].ch[x] == -1) { 57 | cur = a[cur].link; 58 | } 59 | if (a[cur].ch[x] != -1) { 60 | cur = a[cur].ch[x]; 61 | } 62 | a[cur].cnt++; 63 | } 64 | dfs(0); 65 | } 66 | 67 | int dfs(int v) { 68 | for (int ch : adj[v]) a[v].cnt += dfs(ch); 69 | for (int id : a[v].id) ans[id] = a[v].cnt; 70 | return a[v].cnt; 71 | } 72 | }; 73 | 74 | -------------------------------------------------------------------------------- /content/string/hash.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | mt19937 rng((int) chrono::steady_clock::now().time_since_epoch().count()); 4 | const int NN = 2e5 + 1, K = 2, P = uniform_int_distribution(256, 1e9)(rng); // l > |sigma|, r < min(mod) 5 | const ll MOD[] = {1000893493, 1013782387}; 6 | ll ph[NN][K], hh[NN][K], IT; // LEMBRAR DE CHAMAR pre()!!!!!!!!!! 7 | void pre() { rep(i, 0, NN) rep(j, 0, K) ph[i][j] = i ? ph[i - 1][j] * P % MOD[j] : 1; } 8 | 9 | struct hsh { 10 | int L; 11 | hsh() {} 12 | hsh(const string &s) { 13 | L = IT, IT += sz(s); 14 | rep(i, 0, sz(s)) rep(j, 0, K) { 15 | hh[L + i][j] = ((i > 0 ? hh[L + i - 1][j] * P : 0) + s[i]) % MOD[j]; 16 | } 17 | } 18 | array operator()(int l, int r) { 19 | array ans; 20 | rep(j, 0, K) { 21 | ans[j] = hh[L + r][j] - (l > 0 ? hh[L + l - 1][j] * ph[r - l + 1][j] % MOD[j] : 0); 22 | if (ans[j] < 0) ans[j] += MOD[j]; 23 | } 24 | // return ans[0] | (ans[1] << 31); // for K = 2 25 | return ans; 26 | } 27 | }; 28 | 29 | -------------------------------------------------------------------------------- /content/string/kmp.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | vector kmp(const string &s) { 4 | int n = s.size(); 5 | vector p(n); 6 | rep(i, 1, n) { 7 | int j = p[i - 1]; 8 | while (j > 0 && s[i] != s[j]) j = p[j - 1]; 9 | if (s[i] == s[j]) j++; 10 | p[i] = j; 11 | } 12 | return p; 13 | } 14 | 15 | -------------------------------------------------------------------------------- /content/string/manacher.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | vector manacher(const string &s) { 4 | string t = "$#"; 5 | rep(i, 0, sz(s)) { 6 | t += s[i]; 7 | t += '#'; 8 | } 9 | t += '@'; 10 | vector a(t.size() + 1), only_odd(s.size()); 11 | for (int i = 2, c = 1, r = 1; i < t.size()-1; i++){ 12 | int m = 2 * c - i; 13 | if (i < r) a[i] = min(r - i, a[m]); 14 | while (t[i - a[i] - 1] == t[i + a[i] + 1]) a[i]++; 15 | if (i + a[i] > r) { 16 | c = i; 17 | r = i + a[i]; 18 | } 19 | } 20 | for (int i = 2, p = 0; i < t.size() - 1; i += 2) only_odd[p++] = a[i]; 21 | return a; 22 | } 23 | 24 | -------------------------------------------------------------------------------- /content/string/suffix_array.cpp: -------------------------------------------------------------------------------- 1 | #include "../data-structures/rmq.cpp" 2 | 3 | struct suffix_array { 4 | // lcp[i] = lcp(sa[i], sa[i - 1]) 5 | vector sa, lcp, rnk; 6 | rmq RMQ; 7 | //Se usar basic_string, não colocar algum valor = 0 8 | suffix_array(string& s, int lim=256) { // or basic_string 9 | int n = sz(s) + 1, k = 0, a, b; 10 | vector x(all(s)+1), y(n), ws(max(n, lim)); 11 | rnk.resize(n); 12 | sa = lcp = y, iota(all(sa), 0); 13 | for (int j = 0, p = 0; p < n; j = max(1, j * 2), lim = p) { 14 | p = j, iota(all(y), n - j); 15 | rep(i,0,n) if (sa[i] >= j) y[p++] = sa[i] - j; 16 | fill(all(ws), 0); 17 | rep(i,0,n) ws[x[i]]++; 18 | rep(i,1,lim) ws[i] += ws[i - 1]; 19 | for (int i = n; i--;) sa[--ws[x[y[i]]]] = y[i]; 20 | swap(x, y), p = 1, x[sa[0]] = 0; 21 | rep(i,1,n) a = sa[i - 1], b = sa[i], x[b] = 22 | (y[a] == y[b] && y[a + j] == y[b + j]) ? p - 1 : p++; 23 | } 24 | rep(i,1,n) rnk[sa[i]] = i; 25 | for (int i = 0, j; i < n - 1; lcp[rnk[i++]] = k) 26 | for (k && k--, j = sa[rnk[i] - 1]; s[i + k] == s[j + k]; k++); 27 | RMQ = rmq(lcp); 28 | } 29 | // l e r sao posicoes no suffix array 30 | int query(int l, int r) { 31 | if (l == r) return sz(sa) - sa[l] - 1; 32 | return RMQ.query(min(l, r) + 1, max(l, r)); 33 | } 34 | int compare(int l1, int r1, int l2, int r2) { 35 | int len1 = r1 - l1 + 1, len2 = r2 - l2 + 1; 36 | int len = min({query(rnk[l1], rnk[l2]), len1, len2}); 37 | if (len1 == len2 && len == len1) return 0; 38 | if (len == len1) return -1; 39 | if (len == len2) return 1; 40 | return rnk[l1] < rnk[l2] ? -1 : 1; 41 | } 42 | }; 43 | 44 | -------------------------------------------------------------------------------- /content/string/suffix_automaton.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | using namespace std; 3 | 4 | struct suffix_automaton { 5 | enum { N = (int)5e5 + 10, K = 26, first = 'a' }; 6 | struct node { 7 | int link = -1, len = 0, to[K]; 8 | node() { 9 | memset(to, -1, sizeof to); 10 | } 11 | }; 12 | 13 | int pt = 1, last = 0; 14 | int cnt[2 * N], d[2 * N]; // only necessary to count occurrences 15 | ll paths[2 * N]; // only necessary for kth 16 | node st[2 * N]; 17 | 18 | suffix_automaton() {} 19 | void build(const string &s) { 20 | for (auto c : s) add(c - first); 21 | memset(paths, -1, sizeof paths); 22 | } 23 | void add(int c) { 24 | int cur = pt++; 25 | st[cur].len = st[last].len + 1; 26 | cnt[cur] = 1; 27 | int p = last; 28 | while (p != -1 && st[p].to[c] == -1) { 29 | st[p].to[c] = cur; 30 | p = st[p].link; 31 | } 32 | if (p == -1) { 33 | st[cur].link = 0; 34 | } else { 35 | int q = st[p].to[c]; 36 | if (st[p].len + 1 == st[q].len) { 37 | st[cur].link = q; 38 | } else { 39 | int clone = pt++; 40 | cnt[clone] = 0; 41 | rep(i, 0, K) st[clone].to[i] = st[q].to[i]; 42 | st[clone].link = st[q].link; 43 | st[clone].len = st[p].len + 1; 44 | while (p != -1 && st[p].to[c] == q) { 45 | st[p].to[c] = clone; 46 | p = st[p].link; 47 | } 48 | st[q].link = st[cur].link = clone; 49 | } 50 | } 51 | last = cur; 52 | } 53 | ll unique_substrs() { 54 | ll ans = 0; 55 | rep(i, 1, pt) ans += st[i].len - st[st[i].link].len; 56 | return ans; 57 | } 58 | bool contains(const string &s) { 59 | return get(s) != -1; 60 | } 61 | // must call pre_cnt()!! 62 | int occurrences(const string &s) { 63 | int pos = get(s); 64 | return pos == -1 ? 0 : cnt[pos]; 65 | } 66 | string kth(ll k) { 67 | dfs(0); 68 | int v = 0, prv = -1; 69 | string ans = ""; 70 | while (k > 0) { 71 | assert(v != prv); 72 | prv = v; 73 | rep(i, 0, K) if (st[v].to[i] != -1) { 74 | if (paths[st[v].to[i]] < k) { 75 | k -= paths[st[v].to[i]]; 76 | } else { 77 | k--; 78 | ans += i + first; 79 | v = st[v].to[i]; 80 | break; 81 | } 82 | } 83 | } 84 | return ans; 85 | } 86 | int get(const string &s) { 87 | int v = 0; 88 | for (char c : s) { 89 | int x = c - first; 90 | if (st[v].to[x] == -1) return -1; 91 | v = st[v].to[x]; 92 | } 93 | return v; 94 | } 95 | ll dfs(int v) { 96 | if (paths[v] != -1) return paths[v]; 97 | paths[v] = 1; 98 | rep(i, 0, K) if (st[v].to[i] != -1) { 99 | paths[v] += dfs(st[v].to[i]); 100 | } 101 | return paths[v]; 102 | } 103 | void pre_cnt() { 104 | memset(d, 0, sizeof d); 105 | rep(i, 1, pt) d[st[i].link]++; 106 | queue q; 107 | rep(i, 1, pt) if (d[i] == 0) { 108 | q.push(i); 109 | } 110 | while (!q.empty()) { 111 | int v = q.front(); q.pop(); 112 | if (v == 0) continue; 113 | cnt[st[v].link] += cnt[v]; 114 | if (d[st[v].link]-- == 1) q.push(st[v].link); 115 | } 116 | } 117 | } sa; 118 | 119 | -------------------------------------------------------------------------------- /content/string/trie.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | const int N = 1e6 + 10; 4 | struct trie { 5 | trie() {} 6 | struct node { 7 | bool end; 8 | int ch[26]; 9 | node() { memset(ch, -1, sizeof ch), end = false; } 10 | }; 11 | node a[N]; 12 | int head = 0; 13 | void insert(const string &s) { 14 | int cur = 0; 15 | rep(i, 0, sz(s)) { 16 | if (a[cur].ch[s[i] - 'a'] == -1) a[cur].ch[s[i] - 'a'] = ++head; 17 | cur = a[cur].ch[s[i] - 'a']; 18 | } 19 | a[cur].end = true; 20 | } 21 | } tr; 22 | 23 | -------------------------------------------------------------------------------- /content/string/z_function.cpp: -------------------------------------------------------------------------------- 1 | #include "../contest/template.cpp" 2 | 3 | vector z_function(string s) { 4 | int n = sz(s); 5 | vector z(n); 6 | int x = 0, y = 0; 7 | rep(i, 1, n) { 8 | z[i] = max(0,min(z[i-x],y-i+1)); 9 | while (i+z[i] < n && s[z[i]] == s[i+z[i]]) { 10 | x = i; y = i+z[i]; z[i]++; 11 | } 12 | } 13 | return z; 14 | } 15 | --------------------------------------------------------------------------------