├── .gitignore ├── README.md ├── data ├── bstnode.cpp ├── disjointsparsetable.cpp ├── dsu.cpp ├── fenwick.cpp ├── fenwick2d.cpp ├── fenwicknode.cpp ├── hashmap.cpp ├── linkcut.cpp ├── pbds.cpp ├── queue.cpp ├── segtree.cpp ├── sparsetable.cpp ├── splay.cpp └── treap.cpp ├── flows ├── blossom.cpp ├── dinic-edge-ids.cpp ├── dinic-old.cpp ├── dinic.cpp ├── fastflow-other.cpp ├── fastflow.cpp ├── flow_decomposition.cpp ├── flow_graph.cpp ├── gomory_hu-old.cpp ├── gomory_hu.cpp ├── hungarian-arrays.cpp ├── hungarian.cpp ├── matching.cpp ├── mcmf-slow.cpp ├── mcmf.cpp └── mincut.cpp ├── generate_snippets.py ├── geometry └── point.cpp ├── graph ├── bicone.cpp ├── biconv.cpp ├── bridges.cpp ├── centroid.cpp ├── cutpoints.cpp ├── cycles.cpp ├── dfs_digraph_useless.cpp ├── dfs_forest.cpp ├── dfs_undigraph.cpp ├── digraph.cpp ├── dijkstra-set.cpp ├── dijkstra.cpp ├── dominators.cpp ├── eulerian.cpp ├── forest.cpp ├── graph.cpp ├── hld_forest.cpp ├── hld_forest_old.cpp ├── lca_forest.cpp ├── mst.cpp ├── scc.cpp ├── topsort.cpp ├── tree_dp.cpp ├── twosat.cpp └── undigraph.cpp ├── keybindings.json ├── misc ├── debug.cpp ├── fastinput.cpp ├── fastoutput.cpp ├── lis.cpp ├── pragma.cpp ├── radix.cpp └── rng.cpp ├── numeric ├── bm.cpp ├── extgcd.cpp ├── factorizer.cpp ├── fft.cpp ├── fwht.cpp ├── gauss.cpp ├── matrix.cpp ├── mint.cpp ├── ntt.cpp ├── poly.cpp ├── primitive.cpp ├── simplex.cpp └── sparsematrix.cpp ├── segtree ├── dynamic_fenwick.cpp ├── dynamic_lazy.cpp ├── dynamic_simple.cpp ├── info.cpp ├── layout.cpp ├── lazy.cpp ├── simple.cpp └── tag.cpp ├── settings.json ├── string ├── duval.cpp ├── duval_prefixes.cpp ├── hash61.cpp ├── kmp.cpp ├── manacher.cpp ├── suffix_array.cpp └── z.cpp └── template ├── hc.cpp ├── multithreaded.cpp ├── multithreaded2.cpp ├── q1.cpp └── qt.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | cpp.json 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # algo -------------------------------------------------------------------------------- /data/bstnode.cpp: -------------------------------------------------------------------------------- 1 | class node { 2 | public: 3 | int id; 4 | node* l; 5 | node* r; 6 | node* p; 7 | bool rev; 8 | int sz; 9 | // declare extra variables: 10 | 11 | 12 | node(int _id) { 13 | id = _id; 14 | l = r = p = nullptr; 15 | rev = false; 16 | sz = 1; 17 | // init extra variables: 18 | 19 | } 20 | 21 | // push everything else: 22 | void push_stuff() { 23 | 24 | } 25 | 26 | void unsafe_reverse() { 27 | push_stuff(); // !! edu 112 28 | rev ^= 1; 29 | swap(l, r); 30 | pull(); 31 | } 32 | 33 | // apply changes: 34 | void unsafe_apply() { 35 | 36 | } 37 | 38 | void push() { 39 | if (rev) { 40 | if (l != nullptr) { 41 | l->unsafe_reverse(); 42 | } 43 | if (r != nullptr) { 44 | r->unsafe_reverse(); 45 | } 46 | rev = 0; 47 | } 48 | push_stuff(); 49 | } 50 | 51 | void pull() { 52 | sz = 1; 53 | // now init from self: 54 | 55 | if (l != nullptr) { 56 | l->p = this; 57 | sz += l->sz; 58 | // now pull from l: 59 | 60 | } 61 | if (r != nullptr) { 62 | r->p = this; 63 | sz += r->sz; 64 | // now pull from r: 65 | 66 | } 67 | } 68 | }; 69 | 70 | void debug_node(node* v, string pref = "") { 71 | #ifdef LOCAL 72 | if (v != nullptr) { 73 | debug_node(v->r, pref + " "); 74 | cerr << pref << "-" << " " << v->id << '\n'; 75 | debug_node(v->l, pref + " "); 76 | } else { 77 | cerr << pref << "-" << " " << "nullptr" << '\n'; 78 | } 79 | #endif 80 | } 81 | -------------------------------------------------------------------------------- /data/disjointsparsetable.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class DisjointSparseTable { 3 | public: 4 | int n; 5 | vector> mat; 6 | F func; 7 | 8 | DisjointSparseTable(const vector& a, const F& f) : n(int(a.size())), func(f) { 9 | mat.push_back(a); 10 | for (int p = 1; (1 << p) < n; p++) { 11 | mat.emplace_back(n); 12 | for (int mid = 1 << p; mid < n; mid += 1 << (p + 1)) { 13 | mat[p][mid - 1] = a[mid - 1]; 14 | for (int j = mid - 2; j >= mid - (1 << p); j--) { 15 | mat[p][j] = func(a[j], mat[p][j + 1]); 16 | } 17 | mat[p][mid] = a[mid]; 18 | for (int j = mid + 1; j < min(n, mid + (1 << p)); j++) { 19 | mat[p][j] = func(mat[p][j - 1], a[j]); 20 | } 21 | } 22 | } 23 | } 24 | 25 | T Query(int l, int r) const { 26 | assert(0 <= l && l < r && r <= n); 27 | if (r - l == 1) { 28 | return mat[0][l]; 29 | } 30 | int p = bit_width(unsigned(l ^ (r - 1))) - 1; 31 | return func(mat[p][l], mat[p][r - 1]); 32 | } 33 | }; -------------------------------------------------------------------------------- /data/dsu.cpp: -------------------------------------------------------------------------------- 1 | class dsu { 2 | public: 3 | vector p; 4 | int n; 5 | 6 | dsu(int _n) : n(_n) { 7 | p.resize(n); 8 | iota(p.begin(), p.end(), 0); 9 | } 10 | 11 | inline int get(int x) { 12 | return (x == p[x] ? x : (p[x] = get(p[x]))); 13 | } 14 | 15 | inline bool unite(int x, int y) { 16 | x = get(x); 17 | y = get(y); 18 | if (x != y) { 19 | p[x] = y; 20 | return true; 21 | } 22 | return false; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /data/fenwick.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class FenwickTree { 3 | public: 4 | vector fenw; 5 | int n; 6 | int pw; 7 | 8 | FenwickTree() : n(0) {} 9 | FenwickTree(int n_) : n(n_) { 10 | fenw.resize(n); 11 | pw = bit_floor(unsigned(n)); 12 | } 13 | 14 | void Modify(int x, T v) { 15 | assert(0 <= x && x <= n); 16 | while (x < n) { 17 | fenw[x] += v; 18 | x |= x + 1; 19 | } 20 | } 21 | 22 | T Query(int x) { 23 | assert(0 <= x && x <= n); 24 | T v{}; 25 | while (x > 0) { 26 | v += fenw[x - 1]; 27 | x &= x - 1; 28 | } 29 | return v; 30 | } 31 | 32 | // Returns the length of the longest prefix with sum <= c 33 | int MaxPrefix(T c) { 34 | T v{}; 35 | int at = 0; 36 | for (int len = pw; len > 0; len >>= 1) { 37 | if (at + len <= n) { 38 | auto nv = v; 39 | nv += fenw[at + len - 1]; 40 | if (!(c < nv)) { 41 | v = nv; 42 | at += len; 43 | } 44 | } 45 | } 46 | assert(0 <= at && at <= n); 47 | return at; 48 | } 49 | }; 50 | -------------------------------------------------------------------------------- /data/fenwick2d.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class FenwickTree2D { 3 | public: 4 | vector> fenw; 5 | int n, m; 6 | 7 | FenwickTree2D() : n(0), m(0) {} 8 | FenwickTree2D(int n_, int m_) : n(n_), m(m_) { 9 | fenw.resize(n); 10 | for (int i = 0; i < n; i++) { 11 | fenw[i].resize(m); 12 | } 13 | } 14 | 15 | void Modify(int i, int j, T v) { 16 | assert(0 <= i && i < n && 0 <= j && j < m); 17 | int x = i; 18 | while (x < n) { 19 | int y = j; 20 | while (y < m) { 21 | fenw[x][y] += v; 22 | y |= y + 1; 23 | } 24 | x |= x + 1; 25 | } 26 | } 27 | 28 | T Query(int i, int j) { 29 | assert(0 <= i && i <= n && 0 <= j && j <= m); 30 | T v{}; 31 | int x = i; 32 | while (x > 0) { 33 | int y = j; 34 | while (y > 0) { 35 | v += fenw[x - 1][y - 1]; 36 | y &= y - 1; 37 | } 38 | x &= x - 1; 39 | } 40 | return v; 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /data/fenwicknode.cpp: -------------------------------------------------------------------------------- 1 | struct FenwickTreeNode { 2 | ${0}... a = ...; 3 | 4 | inline void operator += (FenwickTreeNode &other) { 5 | a = ...(a, other.a); 6 | } 7 | 8 | inline bool operator < (FenwickTreeNode &other) { 9 | return a < other.a; 10 | } 11 | }; 12 | 13 | -------------------------------------------------------------------------------- /data/hashmap.cpp: -------------------------------------------------------------------------------- 1 | // #include 2 | #include 3 | 4 | struct splitmix64_hash { 5 | static uint64_t splitmix64(uint64_t x) { 6 | // http://xorshift.di.unimi.it/splitmix64.c 7 | x += 0x9e3779b97f4a7c15; 8 | x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9; 9 | x = (x ^ (x >> 27)) * 0x94d049bb133111eb; 10 | return x ^ (x >> 31); 11 | } 12 | 13 | size_t operator()(uint64_t x) const { 14 | static const uint64_t FIXED_RANDOM = std::chrono::steady_clock::now().time_since_epoch().count(); 15 | return splitmix64(x + FIXED_RANDOM); 16 | } 17 | }; 18 | 19 | template 20 | using HashMap = __gnu_pbds::gp_hash_table; 21 | 22 | template 23 | using HashSet = HashMap; -------------------------------------------------------------------------------- /data/linkcut.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class link_cut_tree { 3 | public: 4 | int n; 5 | vector nodes; 6 | 7 | link_cut_tree(int _n) : n(_n) { 8 | nodes.resize(n); 9 | for (int i = 0; i < n; i++) { 10 | nodes[i] = new node(i); 11 | } 12 | } 13 | 14 | int add_node() { 15 | int id = (int) nodes.size(); 16 | nodes.push_back(new node(id)); 17 | return id; 18 | } 19 | 20 | void expose(node* v) { 21 | node* r = nullptr; 22 | node* u = v; 23 | while (u != nullptr) { 24 | splay(u); 25 | u->push(); 26 | u->r = r; 27 | u->pull(); 28 | r = u; 29 | u = u->p; 30 | } 31 | splay(v); 32 | assert(v->p == nullptr); 33 | } 34 | 35 | int get_root(int i) { 36 | node* v = nodes[i]; 37 | expose(v); 38 | return get_leftmost(v)->id; 39 | } 40 | 41 | bool link(int i, int j) { // for rooted: (x, parent[x]) 42 | if (i == j) { 43 | return false; 44 | } 45 | node* v = nodes[i]; 46 | node* u = nodes[j]; 47 | if (rooted) { 48 | splay(v); 49 | if (v->p != nullptr || v->l != nullptr) { 50 | return false; // not a root 51 | } 52 | } else { 53 | make_root(i); 54 | } 55 | expose(u); 56 | if (v->p != nullptr) { 57 | return false; 58 | } 59 | v->p = u; 60 | return true; 61 | } 62 | 63 | bool cut(int i, int j) { // for rooted: (x, parent[x]) 64 | if (i == j) { 65 | return false; 66 | } 67 | node* v = nodes[i]; 68 | node* u = nodes[j]; 69 | expose(u); 70 | splay(v); 71 | if (v->p != u) { 72 | if (rooted) { 73 | return false; 74 | } 75 | swap(u, v); 76 | expose(u); 77 | splay(v); 78 | if (v->p != u) { 79 | return false; 80 | } 81 | } 82 | v->p = nullptr; 83 | return true; 84 | } 85 | 86 | bool cut(int i) { // only for rooted 87 | assert(rooted); 88 | node* v = nodes[i]; 89 | expose(v); 90 | v->push(); 91 | if (v->l == nullptr) { 92 | return false; // already a root 93 | } 94 | v->l->p = nullptr; 95 | v->l = nullptr; 96 | v->pull(); 97 | return true; 98 | } 99 | 100 | bool connected(int i, int j) { 101 | if (i == j) { 102 | return true; 103 | } 104 | node* v = nodes[i]; 105 | node* u = nodes[j]; 106 | expose(v); 107 | expose(u); 108 | return v->p != nullptr; 109 | } 110 | 111 | int lca(int i, int j) { 112 | if (i == j) { 113 | return i; 114 | } 115 | node* v = nodes[i]; 116 | node* u = nodes[j]; 117 | expose(v); 118 | expose(u); 119 | if (v->p == nullptr) { 120 | return -1; 121 | } 122 | splay(v); 123 | if (v->p == nullptr) { 124 | return v->id; 125 | } 126 | return v->p->id; 127 | } 128 | 129 | bool is_ancestor(int i, int j) { 130 | if (i == j) { 131 | return true; 132 | } 133 | node* v = nodes[i]; 134 | node* u = nodes[j]; 135 | expose(u); 136 | splay(v); 137 | return v->p == nullptr && u->p != nullptr; 138 | } 139 | 140 | void make_root(int i) { 141 | assert(!rooted); 142 | node* v = nodes[i]; 143 | expose(v); 144 | reverse(v); 145 | } 146 | 147 | node* get_path_from_root(int i) { 148 | node* v = nodes[i]; 149 | expose(v); 150 | return v; 151 | } 152 | 153 | template 154 | void apply(int i, T... args) { 155 | node* v = nodes[i]; 156 | splay_tree::apply(v, args...); 157 | } 158 | }; 159 | -------------------------------------------------------------------------------- /data/pbds.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template > 4 | using ordered_map = __gnu_pbds::tree< 5 | K, V, Comp, 6 | __gnu_pbds::rb_tree_tag, 7 | __gnu_pbds::tree_order_statistics_node_update 8 | >; 9 | 10 | template > 11 | using ordered_set = ordered_map; 12 | 13 | // Supports 14 | // auto iterator = ordered_set().find_by_order(idx); // (0-indexed) 15 | // int num_strictly_smaller = ordered_set().order_of_key(key); 16 | -------------------------------------------------------------------------------- /data/queue.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class Queue { 3 | public: 4 | vector pref; 5 | vector> suf; 6 | F func; 7 | 8 | Queue(const F& f) : func(f) {} 9 | 10 | bool Empty() { return pref.empty() && suf.empty(); } 11 | int Size() { return int(pref.size()) + int(suf.size()); } 12 | void Clear() { pref.clear(); suf.clear(); } 13 | 14 | void Push(T t) { 15 | if (suf.empty()) { 16 | suf.emplace_back(t, t); 17 | } else { 18 | suf.emplace_back(t, func(suf.back().second, t)); 19 | } 20 | } 21 | 22 | void Pop() { 23 | if (!pref.empty()) { 24 | pref.pop_back(); 25 | return; 26 | } 27 | assert(!suf.empty()); 28 | if (suf.size() > 1) { 29 | pref.resize(suf.size() - 1); 30 | pref[0] = suf.back().first; 31 | for (int i = 1; i < int(pref.size()); i++) { 32 | pref[i] = func(suf[int(suf.size()) - 1 - i].first, pref[i - 1]); 33 | } 34 | } 35 | suf.clear(); 36 | } 37 | 38 | T Get() { 39 | assert(!Empty()); 40 | if (pref.empty()) { 41 | return suf.back().second; 42 | } 43 | if (suf.empty()) { 44 | return pref.back(); 45 | } 46 | return func(pref.back(), suf.back().second); 47 | } 48 | }; 49 | 50 | template 51 | Queue MakeQueue(const F& f) { 52 | return Queue(f); 53 | } 54 | -------------------------------------------------------------------------------- /data/segtree.cpp: -------------------------------------------------------------------------------- 1 | class segtree { 2 | public: 3 | struct node { 4 | // don't forget to set default value (used for leaves) 5 | // not necessarily neutral element! 6 | ... a = ...; 7 | 8 | void apply(int l, int r, ... v) { 9 | ... 10 | } 11 | }; 12 | 13 | node unite(const node &a, const node &b) const { 14 | node res; 15 | ... 16 | return res; 17 | } 18 | 19 | inline void push(int x, int l, int r) { 20 | int y = (l + r) >> 1; 21 | int z = x + ((y - l + 1) << 1); 22 | // push from x into (x + 1) and z 23 | ... 24 | /* 25 | if (tree[x].add != 0) { 26 | tree[x + 1].apply(l, y, tree[x].add); 27 | tree[z].apply(y + 1, r, tree[x].add); 28 | tree[x].add = 0; 29 | } 30 | */ 31 | } 32 | 33 | inline void pull(int x, int z) { 34 | tree[x] = unite(tree[x + 1], tree[z]); 35 | } 36 | 37 | int n; 38 | vector tree; 39 | 40 | void build(int x, int l, int r) { 41 | if (l == r) { 42 | return; 43 | } 44 | int y = (l + r) >> 1; 45 | int z = x + ((y - l + 1) << 1); 46 | build(x + 1, l, y); 47 | build(z, y + 1, r); 48 | pull(x, z); 49 | } 50 | 51 | template 52 | void build(int x, int l, int r, const vector &v) { 53 | if (l == r) { 54 | tree[x].apply(l, r, v[l]); 55 | return; 56 | } 57 | int y = (l + r) >> 1; 58 | int z = x + ((y - l + 1) << 1); 59 | build(x + 1, l, y, v); 60 | build(z, y + 1, r, v); 61 | pull(x, z); 62 | } 63 | 64 | node get(int x, int l, int r, int ll, int rr) { 65 | if (ll <= l && r <= rr) { 66 | return tree[x]; 67 | } 68 | int y = (l + r) >> 1; 69 | int z = x + ((y - l + 1) << 1); 70 | push(x, l, r); 71 | node res{}; 72 | if (rr <= y) { 73 | res = get(x + 1, l, y, ll, rr); 74 | } else { 75 | if (ll > y) { 76 | res = get(z, y + 1, r, ll, rr); 77 | } else { 78 | res = unite(get(x + 1, l, y, ll, rr), get(z, y + 1, r, ll, rr)); 79 | } 80 | } 81 | pull(x, z); 82 | return res; 83 | } 84 | 85 | template 86 | void modify(int x, int l, int r, int ll, int rr, const M&... v) { 87 | if (ll <= l && r <= rr) { 88 | tree[x].apply(l, r, v...); 89 | return; 90 | } 91 | int y = (l + r) >> 1; 92 | int z = x + ((y - l + 1) << 1); 93 | push(x, l, r); 94 | if (ll <= y) { 95 | modify(x + 1, l, y, ll, rr, v...); 96 | } 97 | if (rr > y) { 98 | modify(z, y + 1, r, ll, rr, v...); 99 | } 100 | pull(x, z); 101 | } 102 | 103 | int find_first_knowingly(int x, int l, int r, const function &f) { 104 | if (l == r) { 105 | return l; 106 | } 107 | push(x, l, r); 108 | int y = (l + r) >> 1; 109 | int z = x + ((y - l + 1) << 1); 110 | int res; 111 | if (f(tree[x + 1])) { 112 | res = find_first_knowingly(x + 1, l, y, f); 113 | } else { 114 | res = find_first_knowingly(z, y + 1, r, f); 115 | } 116 | pull(x, z); 117 | return res; 118 | } 119 | 120 | int find_first(int x, int l, int r, int ll, int rr, const function &f) { 121 | if (ll <= l && r <= rr) { 122 | if (!f(tree[x])) { 123 | return -1; 124 | } 125 | return find_first_knowingly(x, l, r, f); 126 | } 127 | push(x, l, r); 128 | int y = (l + r) >> 1; 129 | int z = x + ((y - l + 1) << 1); 130 | int res = -1; 131 | if (ll <= y) { 132 | res = find_first(x + 1, l, y, ll, rr, f); 133 | } 134 | if (rr > y && res == -1) { 135 | res = find_first(z, y + 1, r, ll, rr, f); 136 | } 137 | pull(x, z); 138 | return res; 139 | } 140 | 141 | int find_last_knowingly(int x, int l, int r, const function &f) { 142 | if (l == r) { 143 | return l; 144 | } 145 | push(x, l, r); 146 | int y = (l + r) >> 1; 147 | int z = x + ((y - l + 1) << 1); 148 | int res; 149 | if (f(tree[z])) { 150 | res = find_last_knowingly(z, y + 1, r, f); 151 | } else { 152 | res = find_last_knowingly(x + 1, l, y, f); 153 | } 154 | pull(x, z); 155 | return res; 156 | } 157 | 158 | int find_last(int x, int l, int r, int ll, int rr, const function &f) { 159 | if (ll <= l && r <= rr) { 160 | if (!f(tree[x])) { 161 | return -1; 162 | } 163 | return find_last_knowingly(x, l, r, f); 164 | } 165 | push(x, l, r); 166 | int y = (l + r) >> 1; 167 | int z = x + ((y - l + 1) << 1); 168 | int res = -1; 169 | if (rr > y) { 170 | res = find_last(z, y + 1, r, ll, rr, f); 171 | } 172 | if (ll <= y && res == -1) { 173 | res = find_last(x + 1, l, y, ll, rr, f); 174 | } 175 | pull(x, z); 176 | return res; 177 | } 178 | 179 | segtree(int _n) : n(_n) { 180 | assert(n > 0); 181 | tree.resize(2 * n - 1); 182 | build(0, 0, n - 1); 183 | } 184 | 185 | template 186 | segtree(const vector &v) { 187 | n = v.size(); 188 | assert(n > 0); 189 | tree.resize(2 * n - 1); 190 | build(0, 0, n - 1, v); 191 | } 192 | 193 | node get(int ll, int rr) { 194 | assert(0 <= ll && ll <= rr && rr <= n - 1); 195 | return get(0, 0, n - 1, ll, rr); 196 | } 197 | 198 | node get(int p) { 199 | assert(0 <= p && p <= n - 1); 200 | return get(0, 0, n - 1, p, p); 201 | } 202 | 203 | template 204 | void modify(int ll, int rr, const M&... v) { 205 | assert(0 <= ll && ll <= rr && rr <= n - 1); 206 | modify(0, 0, n - 1, ll, rr, v...); 207 | } 208 | 209 | // find_first and find_last call all FALSE elements 210 | // to the left (right) of the sought position exactly once 211 | 212 | int find_first(int ll, int rr, const function &f) { 213 | assert(0 <= ll && ll <= rr && rr <= n - 1); 214 | return find_first(0, 0, n - 1, ll, rr, f); 215 | } 216 | 217 | int find_last(int ll, int rr, const function &f) { 218 | assert(0 <= ll && ll <= rr && rr <= n - 1); 219 | return find_last(0, 0, n - 1, ll, rr, f); 220 | } 221 | }; 222 | -------------------------------------------------------------------------------- /data/sparsetable.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class SparseTable { 3 | public: 4 | int n; 5 | vector> mat; 6 | F func; 7 | 8 | SparseTable(const vector& a, const F& f) : func(f) { 9 | n = static_cast(a.size()); 10 | int max_log = 32 - __builtin_clz(n); 11 | mat.resize(max_log); 12 | mat[0] = a; 13 | for (int j = 1; j < max_log; j++) { 14 | mat[j].resize(n - (1 << j) + 1); 15 | for (int i = 0; i <= n - (1 << j); i++) { 16 | mat[j][i] = func(mat[j - 1][i], mat[j - 1][i + (1 << (j - 1))]); 17 | } 18 | } 19 | } 20 | 21 | T get(int from, int to) const { 22 | assert(0 <= from && from <= to && to <= n - 1); 23 | int lg = 32 - __builtin_clz(to - from + 1) - 1; 24 | return func(mat[lg][from], mat[lg][to - (1 << lg) + 1]); 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /data/splay.cpp: -------------------------------------------------------------------------------- 1 | namespace splay_tree { 2 | 3 | bool is_bst_root(node* v) { 4 | if (v == nullptr) { 5 | return false; 6 | } 7 | return (v->p == nullptr || (v->p->l != v && v->p->r != v)); 8 | } 9 | 10 | void rotate(node* v) { 11 | node* u = v->p; 12 | assert(u != nullptr); 13 | u->push(); 14 | v->push(); 15 | v->p = u->p; 16 | if (v->p != nullptr) { 17 | if (v->p->l == u) { 18 | v->p->l = v; 19 | } 20 | if (v->p->r == u) { 21 | v->p->r = v; 22 | } 23 | } 24 | if (v == u->l) { 25 | u->l = v->r; 26 | v->r = u; 27 | } else { 28 | u->r = v->l; 29 | v->l = u; 30 | } 31 | u->pull(); 32 | v->pull(); 33 | } 34 | 35 | void splay(node* v) { 36 | if (v == nullptr) { 37 | return; 38 | } 39 | while (!is_bst_root(v)) { 40 | node* u = v->p; 41 | if (!is_bst_root(u)) { 42 | if ((u->l == v) ^ (u->p->l == u)) { 43 | rotate(v); 44 | } else { 45 | rotate(u); 46 | } 47 | } 48 | rotate(v); 49 | } 50 | } 51 | 52 | pair find(node* v, const function &go_to) { 53 | // go_to returns: 0 -- found; -1 -- go left; 1 -- go right 54 | // find returns the last vertex on the descent and its go_to 55 | if (v == nullptr) { 56 | return {nullptr, 0}; 57 | } 58 | splay(v); 59 | int dir; 60 | while (true) { 61 | v->push(); 62 | dir = go_to(v); 63 | if (dir == 0) { 64 | break; 65 | } 66 | node* u = (dir == -1 ? v->l : v->r); 67 | if (u == nullptr) { 68 | break; 69 | } 70 | v = u; 71 | } 72 | splay(v); 73 | return {v, dir}; 74 | } 75 | 76 | node* get_leftmost(node* v) { 77 | return find(v, [&](node*) { return -1; }).first; 78 | } 79 | 80 | node* get_rightmost(node* v) { 81 | return find(v, [&](node*) { return 1; }).first; 82 | } 83 | 84 | node* get_kth(node* v, int k) { // 0-indexed 85 | pair p = find(v, [&](node* u) { 86 | if (u->l != nullptr) { 87 | if (u->l->sz > k) { 88 | return -1; 89 | } 90 | k -= u->l->sz; 91 | } 92 | if (k == 0) { 93 | return 0; 94 | } 95 | k--; 96 | return 1; 97 | }); 98 | return (p.second == 0 ? p.first : nullptr); 99 | } 100 | 101 | int get_position(node* v) { // 0-indexed 102 | splay(v); 103 | return (v->l != nullptr ? v->l->sz : 0); 104 | } 105 | 106 | node* get_bst_root(node* v) { 107 | splay(v); 108 | return v; 109 | } 110 | 111 | pair split(node* v, const function &is_right) { 112 | if (v == nullptr) { 113 | return {nullptr, nullptr}; 114 | } 115 | pair p = find(v, [&](node* u) { return is_right(u) ? -1 : 1; }); 116 | v = p.first; 117 | v->push(); 118 | if (p.second == -1) { 119 | node* u = v->l; 120 | if (u == nullptr) { 121 | return {nullptr, v}; 122 | } 123 | v->l = nullptr; 124 | u->p = v->p; 125 | u = get_rightmost(u); 126 | v->p = u; 127 | v->pull(); 128 | return {u, v}; 129 | } else { 130 | node* u = v->r; 131 | if (u == nullptr) { 132 | return {v, nullptr}; 133 | } 134 | v->r = nullptr; 135 | v->pull(); 136 | return {v, u}; 137 | } 138 | } 139 | 140 | pair split_leftmost_k(node* v, int k) { 141 | return split(v, [&](node* u) { 142 | int left_and_me = (u->l != nullptr ? u->l->sz : 0) + 1; 143 | if (k >= left_and_me) { 144 | k -= left_and_me; 145 | return false; 146 | } 147 | return true; 148 | }); 149 | } 150 | 151 | node* merge(node* v, node* u) { 152 | if (v == nullptr) { 153 | return u; 154 | } 155 | if (u == nullptr) { 156 | return v; 157 | } 158 | v = get_rightmost(v); 159 | assert(v->r == nullptr); 160 | splay(u); 161 | v->push(); 162 | v->r = u; 163 | v->pull(); 164 | return v; 165 | } 166 | 167 | int count_left(node* v, const function &is_right) { 168 | if (v == nullptr) { 169 | return 0; 170 | } 171 | pair p = find(v, [&](node* u) { return is_right(u) ? -1 : 1; }); 172 | node* u = p.first; 173 | return (u->l != nullptr ? u->l->sz : 0) + (p.second == 1); 174 | } 175 | 176 | node* add(node* r, node* v, const function &go_left) { 177 | pair p = split(r, go_left); 178 | return merge(p.first, merge(v, p.second)); 179 | } 180 | 181 | node* remove(node* v) { // returns the new root 182 | splay(v); 183 | v->push(); 184 | node* x = v->l; 185 | node* y = v->r; 186 | v->l = v->r = nullptr; 187 | node* z = merge(x, y); 188 | if (z != nullptr) { 189 | z->p = v->p; 190 | } 191 | v->p = nullptr; 192 | v->push(); 193 | v->pull(); // now v might be reusable... 194 | return z; 195 | } 196 | 197 | node* next(node* v) { 198 | splay(v); 199 | v->push(); 200 | if (v->r == nullptr) { 201 | return nullptr; 202 | } 203 | v = v->r; 204 | while (v->l != nullptr) { 205 | v->push(); 206 | v = v->l; 207 | } 208 | splay(v); 209 | return v; 210 | } 211 | 212 | node* prev(node* v) { 213 | splay(v); 214 | v->push(); 215 | if (v->l == nullptr) { 216 | return nullptr; 217 | } 218 | v = v->l; 219 | while (v->r != nullptr) { 220 | v->push(); 221 | v = v->r; 222 | } 223 | splay(v); 224 | return v; 225 | } 226 | 227 | int get_size(node* v) { 228 | splay(v); 229 | return (v != nullptr ? v->sz : 0); 230 | } 231 | 232 | template 233 | void do_apply(node* v, T... args) { 234 | splay(v); 235 | v->unsafe_apply(args...); 236 | } 237 | 238 | void reverse(node* v) { 239 | splay(v); 240 | v->unsafe_reverse(); 241 | } 242 | 243 | } // namespace splay_tree 244 | 245 | using namespace splay_tree; 246 | -------------------------------------------------------------------------------- /data/treap.cpp: -------------------------------------------------------------------------------- 1 | namespace treap { 2 | 3 | pair find(node* v, const function &go_to) { 4 | // go_to returns: 0 -- found; -1 -- go left; 1 -- go right 5 | // find returns the last vertex on the descent and its go_to 6 | if (v == nullptr) { 7 | return {nullptr, 0}; 8 | } 9 | int dir; 10 | while (true) { 11 | v->push(); 12 | dir = go_to(v); 13 | if (dir == 0) { 14 | break; 15 | } 16 | node* u = (dir == -1 ? v->l : v->r); 17 | if (u == nullptr) { 18 | break; 19 | } 20 | v = u; 21 | } 22 | return {v, dir}; 23 | } 24 | 25 | node* get_leftmost(node* v) { 26 | return find(v, [&](node*) { return -1; }).first; 27 | } 28 | 29 | node* get_rightmost(node* v) { 30 | return find(v, [&](node*) { return 1; }).first; 31 | } 32 | 33 | node* get_kth(node* v, int k) { // 0-indexed 34 | pair p = find(v, [&](node* u) { 35 | if (u->l != nullptr) { 36 | if (u->l->sz > k) { 37 | return -1; 38 | } 39 | k -= u->l->sz; 40 | } 41 | if (k == 0) { 42 | return 0; 43 | } 44 | k--; 45 | return 1; 46 | }); 47 | return (p.second == 0 ? p.first : nullptr); 48 | } 49 | 50 | int get_position(node* v) { // 0-indexed 51 | int k = (v->l != nullptr ? v->l->sz : 0); 52 | while (v->p != nullptr) { 53 | if (v == v->p->r) { 54 | k++; 55 | if (v->p->l != nullptr) { 56 | k += v->p->l->sz; 57 | } 58 | } 59 | v = v->p; 60 | } 61 | return k; 62 | } 63 | 64 | node* get_bst_root(node* v) { 65 | while (v->p != nullptr) { 66 | v = v->p; 67 | } 68 | return v; 69 | } 70 | 71 | pair split(node* v, const function &is_right) { 72 | if (v == nullptr) { 73 | return {nullptr, nullptr}; 74 | } 75 | v->push(); 76 | if (is_right(v)) { 77 | pair p = split(v->l, is_right); 78 | if (p.first != nullptr) { 79 | p.first->p = nullptr; 80 | } 81 | v->l = p.second; 82 | v->pull(); 83 | return {p.first, v}; 84 | } else { 85 | pair p = split(v->r, is_right); 86 | v->r = p.first; 87 | if (p.second != nullptr) { 88 | p.second->p = nullptr; 89 | } 90 | v->pull(); 91 | return {v, p.second}; 92 | } 93 | } 94 | 95 | pair split_leftmost_k(node* v, int k) { 96 | return split(v, [&](node* u) { 97 | int left_and_me = (u->l != nullptr ? u->l->sz : 0) + 1; 98 | if (k >= left_and_me) { 99 | k -= left_and_me; 100 | return false; 101 | } 102 | return true; 103 | }); 104 | } 105 | 106 | node* merge(node* v, node* u) { 107 | if (v == nullptr) { 108 | return u; 109 | } 110 | if (u == nullptr) { 111 | return v; 112 | } 113 | if (v->P > u->P) { 114 | // if (rng() % (v->sz + u->sz) < (unsigned int) v->sz) { 115 | v->push(); 116 | v->r = merge(v->r, u); 117 | v->pull(); 118 | return v; 119 | } else { 120 | u->push(); 121 | u->l = merge(v, u->l); 122 | u->pull(); 123 | return u; 124 | } 125 | } 126 | 127 | int count_left(node* v, const function &is_right) { 128 | if (v == nullptr) { 129 | return 0; 130 | } 131 | v->push(); 132 | if (is_right(v)) { 133 | return count_left(v->l, is_right); 134 | } 135 | return (v->l != nullptr ? v->l->sz : 0) + 1 + count_left(v->r, is_right); 136 | } 137 | 138 | node* add(node* r, node* v, const function &go_left) { 139 | pair p = split(r, go_left); 140 | return merge(p.first, merge(v, p.second)); 141 | } 142 | 143 | node* remove(node* v) { // returns the new root 144 | v->push(); 145 | node* x = v->l; 146 | node* y = v->r; 147 | node* p = v->p; 148 | v->l = v->r = v->p = nullptr; 149 | v->push(); 150 | v->pull(); // now v might be reusable... 151 | node* z = merge(x, y); 152 | if (p == nullptr) { 153 | if (z != nullptr) { 154 | z->p = nullptr; 155 | } 156 | return z; 157 | } 158 | if (p->l == v) { 159 | p->l = z; 160 | } 161 | if (p->r == v) { 162 | p->r = z; 163 | } 164 | while (true) { 165 | p->push(); 166 | p->pull(); 167 | if (p->p == nullptr) { 168 | break; 169 | } 170 | p = p->p; 171 | } 172 | return p; 173 | } 174 | 175 | node* next(node* v) { 176 | if (v->r == nullptr) { 177 | while (v->p != nullptr && v->p->r == v) { 178 | v = v->p; 179 | } 180 | return v->p; 181 | } 182 | v->push(); 183 | v = v->r; 184 | while (v->l != nullptr) { 185 | v->push(); 186 | v = v->l; 187 | } 188 | return v; 189 | } 190 | 191 | node* prev(node* v) { 192 | if (v->l == nullptr) { 193 | while (v->p != nullptr && v->p->l == v) { 194 | v = v->p; 195 | } 196 | return v->p; 197 | } 198 | v->push(); 199 | v = v->l; 200 | while (v->r != nullptr) { 201 | v->push(); 202 | v = v->r; 203 | } 204 | return v; 205 | } 206 | 207 | int get_size(node* v) { 208 | return (v != nullptr ? v->sz : 0); 209 | } 210 | 211 | template 212 | void apply(node* v, T... args) { 213 | v->unsafe_apply(args...); 214 | } 215 | 216 | void reverse(node* v) { 217 | v->unsafe_reverse(); 218 | } 219 | 220 | } // namespace treap 221 | 222 | using namespace treap; 223 | -------------------------------------------------------------------------------- /flows/blossom.cpp: -------------------------------------------------------------------------------- 1 | template 2 | vector find_max_unweighted_matching(const undigraph& g) { 3 | vector mate(g.n, -1); 4 | vector label(g.n); 5 | vector parent(g.n); 6 | vector orig(g.n); 7 | queue q; 8 | vector aux(g.n, -1); 9 | int aux_time = -1; 10 | auto lca = [&](int x, int y) { 11 | aux_time++; 12 | while (true) { 13 | if (x != -1) { 14 | if (aux[x] == aux_time) { 15 | return x; 16 | } 17 | aux[x] = aux_time; 18 | if (mate[x] == -1) { 19 | x = -1; 20 | } else { 21 | x = orig[parent[mate[x]]]; 22 | } 23 | } 24 | swap(x, y); 25 | } 26 | }; 27 | auto blossom = [&](int v, int w, int a) { 28 | while (orig[v] != a) { 29 | parent[v] = w; 30 | w = mate[v]; 31 | if (label[w] == 1) { 32 | label[w] = 0; 33 | q.push(w); 34 | } 35 | orig[v] = orig[w] = a; 36 | v = parent[w]; 37 | } 38 | }; 39 | auto augment = [&](int v) { 40 | while (v != -1) { 41 | int pv = parent[v]; 42 | int nv = mate[pv]; 43 | mate[v] = pv; 44 | mate[pv] = v; 45 | v = nv; 46 | } 47 | }; 48 | auto bfs = [&](int root) { 49 | fill(label.begin(), label.end(), -1); 50 | iota(orig.begin(), orig.end(), 0); 51 | while (!q.empty()) { 52 | q.pop(); 53 | } 54 | q.push(root); 55 | label[root] = 0; 56 | while (!q.empty()) { 57 | int v = q.front(); 58 | q.pop(); 59 | for (int id : g.g[v]) { 60 | auto &e = g.edges[id]; 61 | int x = e.from ^ e.to ^ v; 62 | if (label[x] == -1) { 63 | label[x] = 1; 64 | parent[x] = v; 65 | if (mate[x] == -1) { 66 | augment(x); 67 | return true; 68 | } 69 | label[mate[x]] = 0; 70 | q.push(mate[x]); 71 | continue; 72 | } 73 | if (label[x] == 0 && orig[v] != orig[x]) { 74 | int a = lca(orig[v], orig[x]); 75 | blossom(x, v, a); 76 | blossom(v, x, a); 77 | } 78 | } 79 | } 80 | return false; 81 | }; 82 | auto greedy = [&]() { 83 | vector order(g.n); 84 | iota(order.begin(), order.end(), 0); 85 | shuffle(order.begin(), order.end(), mt19937(787788)); 86 | for (int i : order) { 87 | if (mate[i] == -1) { 88 | for (int id : g.g[i]) { 89 | auto &e = g.edges[id]; 90 | int to = e.from ^ e.to ^ i; 91 | if (i != to && mate[to] == -1) { 92 | mate[i] = to; 93 | mate[to] = i; 94 | break; 95 | } 96 | } 97 | } 98 | } 99 | }; 100 | greedy(); 101 | for (int i = 0; i < g.n; i++) { 102 | if (mate[i] == -1) { 103 | bfs(i); 104 | } 105 | } 106 | return mate; 107 | } 108 | -------------------------------------------------------------------------------- /flows/dinic-edge-ids.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class flow_graph { 3 | public: 4 | static constexpr T eps = (T) 1e-9; 5 | 6 | struct edge { 7 | int from; 8 | int to; 9 | T c; 10 | T f; 11 | }; 12 | 13 | vector> g; 14 | vector edges; 15 | int n; 16 | int st, fin; 17 | T flow; 18 | 19 | vector ptr; 20 | vector d; 21 | vector q; 22 | 23 | flow_graph(int _n, int _st, int _fin) : n(_n), st(_st), fin(_fin) { 24 | assert(0 <= st && st < n && 0 <= fin && fin < n && st != fin); 25 | g.resize(n); 26 | ptr.resize(n); 27 | d.resize(n); 28 | q.resize(n); 29 | flow = 0; 30 | } 31 | 32 | void clear_flow() { 33 | for (const edge &e : edges) { 34 | e.f = 0; 35 | } 36 | flow = 0; 37 | } 38 | 39 | void add(int from, int to, T forward_cap, T backward_cap) { 40 | assert(0 <= from && from < n && 0 <= to && to < n); 41 | g[from].push_back((int) edges.size()); 42 | edges.push_back({from, to, forward_cap, 0}); 43 | g[to].push_back((int) edges.size()); 44 | edges.push_back({to, from, backward_cap, 0}); 45 | } 46 | 47 | bool expath() { 48 | fill(d.begin(), d.end(), -1); 49 | q[0] = fin; 50 | d[fin] = 0; 51 | int beg = 0, end = 1; 52 | while (beg < end) { 53 | int i = q[beg++]; 54 | for (int id : g[i]) { 55 | const edge &e = edges[id]; 56 | const edge &back = edges[id ^ 1]; 57 | if (back.c - back.f > eps && d[e.to] == -1) { 58 | d[e.to] = d[i] + 1; 59 | if (e.to == st) { 60 | return true; 61 | } 62 | q[end++] = e.to; 63 | } 64 | } 65 | } 66 | return false; 67 | } 68 | 69 | T dfs(int v, T w) { 70 | if (v == fin) { 71 | return w; 72 | } 73 | int &j = ptr[v]; 74 | while (j >= 0) { 75 | int id = g[v][j]; 76 | const edge &e = edges[id]; 77 | if (e.c - e.f > eps && d[e.to] == d[v] - 1) { 78 | T t = dfs(e.to, min(e.c - e.f, w)); 79 | if (t > eps) { 80 | edges[id].f += t; 81 | edges[id ^ 1].f -= t; 82 | return t; 83 | } 84 | } 85 | j--; 86 | } 87 | return 0; 88 | } 89 | 90 | T max_flow() { 91 | while (expath()) { 92 | for (int i = 0; i < n; i++) { 93 | ptr[i] = (int) g[i].size() - 1; 94 | } 95 | T big_add = 0; 96 | while (true) { 97 | T add = dfs(st, numeric_limits::max()); 98 | if (add <= eps) { 99 | break; 100 | } 101 | big_add += add; 102 | } 103 | if (big_add <= eps) { 104 | break; 105 | } 106 | flow += big_add; 107 | } 108 | return flow; 109 | } 110 | 111 | vector min_cut() { 112 | max_flow(); 113 | vector ret(n); 114 | for (int i = 0; i < n; i++) { 115 | ret[i] = (d[i] != -1); 116 | } 117 | return ret; 118 | } 119 | 120 | // Maximum flow / minimum cut, Dinic's algorithm 121 | // Usage: 122 | // 1) flow_graph g(n, start, finish); [T == int / int64_t / double] 123 | // 2) g.add(from, to, forward_cap, backward_cap); 124 | // 3) cout << g.max_flow() << endl; 125 | // 4) vector cut = g.min_cut(); 126 | // for (auto &e : g.edges) 127 | // if (cut[e.from] != cut[e.to]) ; // edge e = (e.from -> e.to) is cut 128 | }; 129 | -------------------------------------------------------------------------------- /flows/dinic-old.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class flow_graph { 3 | public: 4 | static constexpr T eps = (T) 1e-9; 5 | 6 | struct edge { 7 | int to; 8 | T c; 9 | T f; 10 | int rev; 11 | }; 12 | 13 | vector> g; 14 | vector ptr; 15 | vector d; 16 | vector q; 17 | int n; 18 | int st, fin; 19 | T flow; 20 | 21 | flow_graph(int _n, int _st, int _fin) : n(_n), st(_st), fin(_fin) { 22 | assert(0 <= st && st < n && 0 <= fin && fin < n && st != fin); 23 | g.resize(n); 24 | ptr.resize(n); 25 | d.resize(n); 26 | q.resize(n); 27 | flow = 0; 28 | } 29 | 30 | void clear_flow() { 31 | for (int i = 0; i < n; i++) { 32 | for (edge &e : g[i]) { 33 | e.f = 0; 34 | } 35 | } 36 | flow = 0; 37 | } 38 | 39 | void add(int from, int to, T forward_cap, T backward_cap) { 40 | assert(0 <= from && from < n && 0 <= to && to < n); 41 | int from_size = g[from].size(); 42 | int to_size = g[to].size(); 43 | g[from].push_back({to, forward_cap, 0, to_size}); 44 | g[to].push_back({from, backward_cap, 0, from_size}); 45 | } 46 | 47 | bool expath() { 48 | fill(d.begin(), d.end(), -1); 49 | q[0] = fin; 50 | d[fin] = 0; 51 | int beg = 0, end = 1; 52 | while (beg < end) { 53 | int i = q[beg++]; 54 | for (const edge &e : g[i]) { 55 | const edge &back = g[e.to][e.rev]; 56 | if (back.c - back.f > eps && d[e.to] == -1) { 57 | d[e.to] = d[i] + 1; 58 | if (e.to == st) { 59 | return true; 60 | } 61 | q[end++] = e.to; 62 | } 63 | } 64 | } 65 | return false; 66 | } 67 | 68 | T dfs(int v, T w) { 69 | if (v == fin) { 70 | return w; 71 | } 72 | int &j = ptr[v]; 73 | while (j >= 0) { 74 | const edge &e = g[v][j]; 75 | if (e.c - e.f > eps && d[e.to] == d[v] - 1) { 76 | T t = dfs(e.to, min(e.c - e.f, w)); 77 | if (t > eps) { 78 | g[v][j].f += t; 79 | g[e.to][e.rev].f -= t; 80 | return t; 81 | } 82 | } 83 | j--; 84 | } 85 | return 0; 86 | } 87 | 88 | T max_flow() { 89 | while (expath()) { 90 | for (int i = 0; i < n; i++) { 91 | ptr[i] = (int) g[i].size() - 1; 92 | } 93 | T big_add = 0; 94 | while (true) { 95 | T add = dfs(st, numeric_limits::max()); 96 | if (add <= eps) { 97 | break; 98 | } 99 | big_add += add; 100 | } 101 | if (big_add <= eps) { 102 | break; 103 | } 104 | flow += big_add; 105 | } 106 | return flow; 107 | } 108 | 109 | vector min_cut() { 110 | max_flow(); 111 | vector ret(n); 112 | for (int i = 0; i < n; i++) { 113 | ret[i] = (d[i] != -1); 114 | } 115 | return ret; 116 | } 117 | }; 118 | -------------------------------------------------------------------------------- /flows/dinic.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class dinic { 3 | public: 4 | flow_graph &g; 5 | 6 | vector ptr; 7 | vector d; 8 | vector q; 9 | 10 | dinic(flow_graph &_g) : g(_g) { 11 | ptr.resize(g.n); 12 | d.resize(g.n); 13 | q.resize(g.n); 14 | } 15 | 16 | bool expath() { 17 | fill(d.begin(), d.end(), -1); 18 | q[0] = g.fin; 19 | d[g.fin] = 0; 20 | int beg = 0, end = 1; 21 | while (beg < end) { 22 | int i = q[beg++]; 23 | for (int id : g.g[i]) { 24 | const auto &e = g.edges[id]; 25 | const auto &back = g.edges[id ^ 1]; 26 | if (back.c - back.f > g.eps && d[e.to] == -1) { 27 | d[e.to] = d[i] + 1; 28 | if (e.to == g.st) { 29 | return true; 30 | } 31 | q[end++] = e.to; 32 | } 33 | } 34 | } 35 | return false; 36 | } 37 | 38 | T dfs(int v, T w) { 39 | if (v == g.fin) { 40 | return w; 41 | } 42 | int &j = ptr[v]; 43 | while (j >= 0) { 44 | int id = g.g[v][j]; 45 | const auto &e = g.edges[id]; 46 | if (e.c - e.f > g.eps && d[e.to] == d[v] - 1) { 47 | T t = dfs(e.to, min(e.c - e.f, w)); 48 | if (t > g.eps) { 49 | g.edges[id].f += t; 50 | g.edges[id ^ 1].f -= t; 51 | return t; 52 | } 53 | } 54 | j--; 55 | } 56 | return 0; 57 | } 58 | 59 | T max_flow() { 60 | while (expath()) { 61 | for (int i = 0; i < g.n; i++) { 62 | ptr[i] = (int) g.g[i].size() - 1; 63 | } 64 | T big_add = 0; 65 | while (true) { 66 | T add = dfs(g.st, numeric_limits::max()); 67 | if (add <= g.eps) { 68 | break; 69 | } 70 | big_add += add; 71 | } 72 | if (big_add <= g.eps) { 73 | break; 74 | } 75 | g.flow += big_add; 76 | } 77 | return g.flow; 78 | } 79 | 80 | vector min_cut() { 81 | max_flow(); 82 | vector ret(g.n); 83 | for (int i = 0; i < g.n; i++) { 84 | ret[i] = (d[i] != -1); 85 | } 86 | return ret; 87 | } 88 | }; 89 | -------------------------------------------------------------------------------- /flows/fastflow-other.cpp: -------------------------------------------------------------------------------- 1 | // https://pastebin.com/exQM152L 2 | 3 | // Doesn't walk through the whole path during augment at the cost of bigger constant 4 | // Not recommended to use with double 5 | 6 | template 7 | class flow_graph { 8 | public: 9 | static constexpr T eps = (T) 1e-9; 10 | 11 | struct edge { 12 | int to; 13 | T c; 14 | T f; 15 | int rev; 16 | }; 17 | 18 | vector> g; 19 | vector ptr; 20 | vector d; 21 | vector q; 22 | vector cnt_on_layer; 23 | vector prev_edge; 24 | vector to_push; 25 | vector pushed; 26 | vector smallest; 27 | bool can_reach_sink; 28 | 29 | int n; 30 | int st, fin; 31 | T flow; 32 | 33 | flow_graph(int _n, int _st, int _fin) : n(_n), st(_st), fin(_fin) { 34 | assert(0 <= st && st < n && 0 <= fin && fin < n && st != fin); 35 | g.resize(n); 36 | ptr.resize(n); 37 | d.resize(n); 38 | q.resize(n); 39 | cnt_on_layer.resize(n + 1); 40 | prev_edge.resize(n); 41 | to_push.resize(n); 42 | pushed.resize(n); 43 | smallest.resize(n); 44 | flow = 0; 45 | } 46 | 47 | void clear_flow() { 48 | for (int i = 0; i < n; i++) { 49 | for (edge &e : g[i]) { 50 | e.f = 0; 51 | } 52 | } 53 | flow = 0; 54 | } 55 | 56 | void add(int from, int to, T forward_cap, T backward_cap) { 57 | assert(0 <= from && from < n && 0 <= to && to < n); 58 | int from_size = g[from].size(); 59 | int to_size = g[to].size(); 60 | g[from].push_back({to, forward_cap, 0, to_size}); 61 | g[to].push_back({from, backward_cap, 0, from_size}); 62 | } 63 | 64 | bool expath() { 65 | fill(d.begin(), d.end(), n); 66 | q[0] = fin; 67 | d[fin] = 0; 68 | fill(cnt_on_layer.begin(), cnt_on_layer.end(), 0); 69 | cnt_on_layer[n] = n - 1; 70 | cnt_on_layer[0] = 1; 71 | int beg = 0, end = 1; 72 | while (beg < end) { 73 | int i = q[beg++]; 74 | for (const edge &e : g[i]) { 75 | const edge &back = g[e.to][e.rev]; 76 | if (back.c - back.f > eps && d[e.to] == n) { 77 | cnt_on_layer[d[e.to]]--; 78 | d[e.to] = d[i] + 1; 79 | cnt_on_layer[d[e.to]]++; 80 | q[end++] = e.to; 81 | } 82 | } 83 | } 84 | return (d[st] != n); 85 | } 86 | 87 | void rollback(int &v) { 88 | edge &e = g[v][prev_edge[v]]; 89 | if (pushed[v]) { 90 | edge &back = g[e.to][e.rev]; 91 | back.f += pushed[v]; 92 | e.f -= pushed[v]; 93 | pushed[e.to] += pushed[v]; 94 | to_push[e.to] -= pushed[v]; 95 | pushed[v] = 0; 96 | } 97 | v = e.to; 98 | } 99 | 100 | void augment(int &v) { 101 | pushed[v] += to_push[v]; 102 | to_push[v] = 0; 103 | int new_v = smallest[v]; 104 | while (v != new_v) { 105 | rollback(v); 106 | } 107 | } 108 | 109 | void retreat(int &v) { 110 | int new_dist = n - 1; 111 | for (const edge &e : g[v]) { 112 | if (e.c - e.f > eps && d[e.to] < new_dist) { 113 | new_dist = d[e.to]; 114 | } 115 | } 116 | cnt_on_layer[d[v]]--; 117 | if (cnt_on_layer[d[v]] == 0) { 118 | if (new_dist + 1 > d[v]) { 119 | can_reach_sink = false; 120 | } 121 | } 122 | d[v] = new_dist + 1; 123 | cnt_on_layer[d[v]]++; 124 | if (v != st) { 125 | rollback(v); 126 | } 127 | } 128 | 129 | T max_flow() { 130 | can_reach_sink = true; 131 | for (int i = 0; i < n; i++) { 132 | ptr[i] = (int) g[i].size() - 1; 133 | } 134 | if (expath()) { 135 | int v = st; 136 | to_push[v] = numeric_limits::max(); 137 | smallest[v] = v; 138 | while (d[st] < n) { 139 | while (ptr[v] >= 0) { 140 | const edge &e = g[v][ptr[v]]; 141 | if (e.c - e.f > eps && d[e.to] == d[v] - 1) { 142 | prev_edge[e.to] = e.rev; 143 | to_push[e.to] = to_push[v]; 144 | smallest[e.to] = smallest[v]; 145 | if (e.c - e.f < to_push[e.to]) { 146 | to_push[e.to] = e.c - e.f; 147 | smallest[e.to] = v; 148 | } 149 | v = e.to; 150 | if (v == fin) { 151 | augment(v); 152 | } 153 | break; 154 | } 155 | ptr[v]--; 156 | } 157 | if (ptr[v] < 0) { 158 | ptr[v] = (int) g[v].size() - 1; 159 | retreat(v); 160 | if (!can_reach_sink) { 161 | break; 162 | } 163 | } 164 | } 165 | while (v != st) { 166 | rollback(v); 167 | } 168 | flow += pushed[st]; 169 | pushed[st] = 0; 170 | } 171 | return flow; 172 | } 173 | 174 | vector min_cut() { 175 | max_flow(); 176 | assert(!expath()); 177 | vector ret(n); 178 | for (int i = 0; i < n; i++) { 179 | ret[i] = (d[i] != n); 180 | } 181 | return ret; 182 | } 183 | }; 184 | -------------------------------------------------------------------------------- /flows/fastflow.cpp: -------------------------------------------------------------------------------- 1 | // https://pastebin.com/exQM152L 2 | 3 | template 4 | class flow_graph { 5 | public: 6 | static constexpr T eps = (T) 1e-9; 7 | 8 | struct edge { 9 | int to; 10 | T c; 11 | T f; 12 | int rev; 13 | }; 14 | 15 | vector> g; 16 | vector ptr; 17 | vector d; 18 | vector q; 19 | vector cnt_on_layer; 20 | vector prev_edge; 21 | bool can_reach_sink; 22 | 23 | int n; 24 | int st, fin; 25 | T flow; 26 | 27 | flow_graph(int _n, int _st, int _fin) : n(_n), st(_st), fin(_fin) { 28 | assert(0 <= st && st < n && 0 <= fin && fin < n && st != fin); 29 | g.resize(n); 30 | ptr.resize(n); 31 | d.resize(n); 32 | q.resize(n); 33 | cnt_on_layer.resize(n + 1); 34 | prev_edge.resize(n); 35 | flow = 0; 36 | } 37 | 38 | void clear_flow() { 39 | for (int i = 0; i < n; i++) { 40 | for (edge &e : g[i]) { 41 | e.f = 0; 42 | } 43 | } 44 | flow = 0; 45 | } 46 | 47 | void add(int from, int to, T forward_cap, T backward_cap) { 48 | assert(0 <= from && from < n && 0 <= to && to < n); 49 | int from_size = g[from].size(); 50 | int to_size = g[to].size(); 51 | g[from].push_back({to, forward_cap, 0, to_size}); 52 | g[to].push_back({from, backward_cap, 0, from_size}); 53 | } 54 | 55 | bool expath() { 56 | fill(d.begin(), d.end(), n); 57 | q[0] = fin; 58 | d[fin] = 0; 59 | fill(cnt_on_layer.begin(), cnt_on_layer.end(), 0); 60 | cnt_on_layer[n] = n - 1; 61 | cnt_on_layer[0] = 1; 62 | int beg = 0, end = 1; 63 | while (beg < end) { 64 | int i = q[beg++]; 65 | for (const edge &e : g[i]) { 66 | const edge &back = g[e.to][e.rev]; 67 | if (back.c - back.f > eps && d[e.to] == n) { 68 | cnt_on_layer[d[e.to]]--; 69 | d[e.to] = d[i] + 1; 70 | cnt_on_layer[d[e.to]]++; 71 | q[end++] = e.to; 72 | } 73 | } 74 | } 75 | return (d[st] != n); 76 | } 77 | 78 | T augment(int &v) { 79 | T cur = numeric_limits::max(); 80 | int i = fin; 81 | while (i != st) { 82 | const edge &e = g[i][prev_edge[i]]; 83 | const edge &back = g[e.to][e.rev]; 84 | cur = min(cur, back.c - back.f); 85 | i = e.to; 86 | } 87 | i = fin; 88 | while (i != st) { 89 | edge &e = g[i][prev_edge[i]]; 90 | edge &back = g[e.to][e.rev]; 91 | back.f += cur; 92 | e.f -= cur; 93 | i = e.to; 94 | if (back.c - back.f <= eps) { 95 | v = i; 96 | } 97 | } 98 | return cur; 99 | } 100 | 101 | int retreat(int v) { 102 | int new_dist = n - 1; 103 | for (const edge &e : g[v]) { 104 | if (e.c - e.f > eps && d[e.to] < new_dist) { 105 | new_dist = d[e.to]; 106 | } 107 | } 108 | cnt_on_layer[d[v]]--; 109 | if (cnt_on_layer[d[v]] == 0) { 110 | if (new_dist + 1 > d[v]) { 111 | can_reach_sink = false; 112 | } 113 | } 114 | d[v] = new_dist + 1; 115 | cnt_on_layer[d[v]]++; 116 | if (v != st) { 117 | v = g[v][prev_edge[v]].to; 118 | } 119 | return v; 120 | } 121 | 122 | T max_flow() { 123 | can_reach_sink = true; 124 | for (int i = 0; i < n; i++) { 125 | ptr[i] = (int) g[i].size() - 1; 126 | } 127 | if (expath()) { 128 | int v = st; 129 | while (d[st] < n) { 130 | while (ptr[v] >= 0) { 131 | const edge &e = g[v][ptr[v]]; 132 | if (e.c - e.f > eps && d[e.to] == d[v] - 1) { 133 | prev_edge[e.to] = e.rev; 134 | v = e.to; 135 | if (v == fin) { 136 | flow += augment(v); 137 | } 138 | break; 139 | } 140 | ptr[v]--; 141 | } 142 | if (ptr[v] < 0) { 143 | ptr[v] = (int) g[v].size() - 1; 144 | v = retreat(v); 145 | if (!can_reach_sink) { 146 | break; 147 | } 148 | } 149 | } 150 | } 151 | return flow; 152 | } 153 | 154 | vector min_cut() { 155 | max_flow(); 156 | assert(!expath()); 157 | vector ret(n); 158 | for (int i = 0; i < n; i++) { 159 | ret[i] = (d[i] != n); 160 | } 161 | return ret; 162 | } 163 | }; 164 | -------------------------------------------------------------------------------- /flows/flow_decomposition.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class flow_decomposition { 3 | public: 4 | const flow_graph &g; 5 | 6 | vector> paths; 7 | vector path_flows; 8 | vector> cycles; 9 | vector cycle_flows; 10 | 11 | flow_decomposition(const flow_graph &_g) : g(_g) { 12 | } 13 | 14 | void decompose() { 15 | vector fs(g.edges.size()); 16 | for (int i = 0; i < (int) g.edges.size(); i++) { 17 | fs[i] = g.edges[i].f; 18 | } 19 | paths.clear(); 20 | path_flows.clear(); 21 | cycles.clear(); 22 | cycle_flows.clear(); 23 | vector ptr(g.n); 24 | for (int i = 0; i < g.n; i++) { 25 | ptr[i] = (int) g.g[i].size() - 1; 26 | } 27 | vector was(g.n, -1); 28 | int start = g.st; 29 | for (int iter = 0; ; iter++) { 30 | bool found_start = false; 31 | while (true) { 32 | if (ptr[start] >= 0) { 33 | int id = g.g[start][ptr[start]]; 34 | if (fs[id] > g.eps) { 35 | found_start = true; 36 | break; 37 | } 38 | ptr[start]--; 39 | continue; 40 | } 41 | start = (start + 1) % g.n; 42 | if (start == g.st) { 43 | break; 44 | } 45 | } 46 | if (!found_start) { 47 | break; 48 | } 49 | vector path; 50 | bool is_cycle = false; 51 | int v = start; 52 | while (true) { 53 | if (v == g.fin) { 54 | break; 55 | } 56 | if (was[v] == iter) { 57 | bool found = false; 58 | for (int i = 0; i < (int) path.size(); i++) { 59 | int id = path[i]; 60 | auto &e = g.edges[id]; 61 | if (e.from == v) { 62 | path.erase(path.begin(), path.begin() + i); 63 | found = true; 64 | break; 65 | } 66 | } 67 | assert(found); 68 | is_cycle = true; 69 | break; 70 | } 71 | was[v] = iter; 72 | bool found = false; 73 | while (ptr[v] >= 0) { 74 | int id = g.g[v][ptr[v]]; 75 | if (fs[id] > g.eps) { 76 | path.push_back(id); 77 | v = g.edges[id].to; 78 | found = true; 79 | break; 80 | } 81 | ptr[v]--; 82 | } 83 | assert(found); 84 | } 85 | T path_flow = numeric_limits::max(); 86 | for (int id : path) { 87 | path_flow = min(path_flow, fs[id]); 88 | } 89 | for (int id : path) { 90 | fs[id] -= path_flow; 91 | fs[id ^ 1] += path_flow; 92 | } 93 | if (is_cycle) { 94 | cycles.push_back(path); 95 | cycle_flows.push_back(path_flow); 96 | } else { 97 | paths.push_back(path); 98 | path_flows.push_back(path_flow); 99 | } 100 | } 101 | for (const T& f : fs) { 102 | assert(-g.eps <= f && f <= g.eps); 103 | } 104 | } 105 | }; 106 | -------------------------------------------------------------------------------- /flows/flow_graph.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class flow_graph { 3 | public: 4 | static constexpr T eps = (T) 1e-9; 5 | 6 | struct edge { 7 | int from; 8 | int to; 9 | T c; 10 | T f; 11 | }; 12 | 13 | vector> g; 14 | vector edges; 15 | int n; 16 | int st; 17 | int fin; 18 | T flow; 19 | 20 | flow_graph(int _n, int _st, int _fin) : n(_n), st(_st), fin(_fin) { 21 | assert(0 <= st && st < n && 0 <= fin && fin < n && st != fin); 22 | g.resize(n); 23 | flow = 0; 24 | } 25 | 26 | void clear_flow() { 27 | for (const edge &e : edges) { 28 | e.f = 0; 29 | } 30 | flow = 0; 31 | } 32 | 33 | int add(int from, int to, T forward_cap, T backward_cap) { 34 | assert(0 <= from && from < n && 0 <= to && to < n); 35 | int id = (int) edges.size(); 36 | g[from].push_back(id); 37 | edges.push_back({from, to, forward_cap, 0}); 38 | g[to].push_back(id + 1); 39 | edges.push_back({to, from, backward_cap, 0}); 40 | return id; 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /flows/gomory_hu-old.cpp: -------------------------------------------------------------------------------- 1 | template 2 | forest gomory_hu(const undigraph &g) { 3 | int n = g.n; 4 | if (n == 1) { 5 | return forest(n); 6 | } 7 | flow_graph fg(n, 0, 1); 8 | for (auto &e : g.edges) { 9 | fg.add(e.from, e.to, e.cost, e.cost); 10 | } 11 | vector> dist(n, vector(n, numeric_limits::max())); 12 | function)> dfs = [&g, &n, &fg, &dist, &dfs](vector group) { 13 | int sz = group.size(); 14 | if (sz == 1) { 15 | return; 16 | } 17 | fg.clear_flow(); 18 | fg.st = group[0]; 19 | fg.fin = group[1]; 20 | T flow = fg.max_flow(); 21 | vector cut = fg.min_cut(); 22 | for (int i = 0; i < n; i++) { 23 | for (int j = i + 1; j < n; j++) { 24 | if (cut[i] != cut[j]) { 25 | dist[i][j] = min(dist[i][j], flow); 26 | } 27 | } 28 | } 29 | vector new_groups[2]; 30 | for (int v : group) { 31 | new_groups[(int) cut[v]].push_back(v); 32 | } 33 | for (int id = 0; id < 2; id++) { 34 | dfs(new_groups[id]); 35 | } 36 | }; 37 | vector group(n); 38 | iota(group.begin(), group.end(), 0); 39 | dfs(group); 40 | undigraph mg(n); 41 | for (int i = 0; i < n; i++) { 42 | for (int j = i + 1; j < n; j++) { 43 | mg.add(i, j, -dist[i][j]); 44 | } 45 | } 46 | T foo; 47 | vector ids = mst(mg, foo); 48 | forest ret(n); 49 | for (int id : ids) { 50 | auto &e = mg.edges[id]; 51 | ret.add(e.from, e.to, -e.cost); 52 | } 53 | return ret; 54 | // don't be lazy next time! 55 | // implement a proper gomory-hu tree 56 | } 57 | -------------------------------------------------------------------------------- /flows/gomory_hu.cpp: -------------------------------------------------------------------------------- 1 | template 2 | forest gomory_hu(const undigraph& g) { 3 | int n = g.n; 4 | flow_graph fg(n, 0, 1); 5 | for (auto& e : g.edges) { 6 | fg.add(e.from, e.to, e.cost, e.cost); 7 | } 8 | forest ret(n); 9 | vector pr(n, 0); 10 | for (int i = 1; i < n; i++) { 11 | fg.clear_flow(); 12 | fg.st = i; 13 | fg.fin = pr[i]; 14 | T flow = fg.max_flow(); 15 | vector cut = fg.min_cut(); 16 | for (int j = i + 1; j < n; j++) { 17 | if (cut[j] == cut[i] && pr[j] == pr[i]) { 18 | pr[j] = i; 19 | } 20 | } 21 | ret.add(i, pr[i], flow); 22 | } 23 | return ret; 24 | // can be optimized by compressing components 25 | } 26 | -------------------------------------------------------------------------------- /flows/hungarian-arrays.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class hungarian { 3 | public: 4 | static const int MAX_N = ... + 1; 5 | 6 | int n; 7 | int m; 8 | T a[MAX_N][MAX_N]; 9 | T u[MAX_N]; 10 | T v[MAX_N]; 11 | int pa[MAX_N]; 12 | int pb[MAX_N]; 13 | int way[MAX_N]; 14 | T minv[MAX_N]; 15 | bool used[MAX_N]; 16 | T inf; 17 | 18 | hungarian(int _n, int _m) : n(_n), m(_m) { 19 | assert(n <= m); 20 | T zero = T{}; 21 | fill(u, u + n + 1, zero); 22 | fill(v, v + m + 1, zero); 23 | fill(pa, pa + n + 1, -1); 24 | fill(pb, pb + m + 1, -1); 25 | inf = numeric_limits::max(); 26 | } 27 | 28 | inline void add_row(int i) { 29 | fill(minv, minv + m + 1, inf); 30 | fill(used, used + m + 1, false); 31 | pb[m] = i; 32 | pa[i] = m; 33 | int j0 = m; 34 | do { 35 | used[j0] = true; 36 | int i0 = pb[j0]; 37 | T delta = inf; 38 | int j1 = -1; 39 | for (int j = 0; j < m; j++) { 40 | if (!used[j]) { 41 | T cur = a[i0][j] - u[i0] - v[j]; 42 | if (cur < minv[j]) { 43 | minv[j] = cur; 44 | way[j] = j0; 45 | } 46 | if (minv[j] < delta) { 47 | delta = minv[j]; 48 | j1 = j; 49 | } 50 | } 51 | } 52 | for (int j = 0; j <= m; j++) { 53 | if (used[j]) { 54 | u[pb[j]] += delta; 55 | v[j] -= delta; 56 | } else { 57 | minv[j] -= delta; 58 | } 59 | } 60 | j0 = j1; 61 | } while (pb[j0] != -1); 62 | do { 63 | int j1 = way[j0]; 64 | pb[j0] = pb[j1]; 65 | pa[pb[j0]] = j0; 66 | j0 = j1; 67 | } while (j0 != m); 68 | } 69 | 70 | inline T current_score() { 71 | return -v[m]; 72 | } 73 | 74 | inline T solve() { 75 | for (int i = 0; i < n; i++) { 76 | add_row(i); 77 | } 78 | return current_score(); 79 | } 80 | }; 81 | -------------------------------------------------------------------------------- /flows/hungarian.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class hungarian { 3 | public: 4 | int n; 5 | int m; 6 | vector> a; 7 | vector u; 8 | vector v; 9 | vector pa; 10 | vector pb; 11 | vector way; 12 | vector minv; 13 | vector used; 14 | T inf; 15 | 16 | hungarian(int _n, int _m) : n(_n), m(_m) { 17 | assert(n <= m); 18 | a = vector>(n, vector(m)); 19 | u = vector(n + 1); 20 | v = vector(m + 1); 21 | pa = vector(n + 1, -1); 22 | pb = vector(m + 1, -1); 23 | way = vector(m, -1); 24 | minv = vector(m); 25 | used = vector(m + 1); 26 | inf = numeric_limits::max(); 27 | } 28 | 29 | inline void add_row(int i) { 30 | fill(minv.begin(), minv.end(), inf); 31 | fill(used.begin(), used.end(), false); 32 | pb[m] = i; 33 | pa[i] = m; 34 | int j0 = m; 35 | do { 36 | used[j0] = true; 37 | int i0 = pb[j0]; 38 | T delta = inf; 39 | int j1 = -1; 40 | for (int j = 0; j < m; j++) { 41 | if (!used[j]) { 42 | T cur = a[i0][j] - u[i0] - v[j]; 43 | if (cur < minv[j]) { 44 | minv[j] = cur; 45 | way[j] = j0; 46 | } 47 | if (minv[j] < delta) { 48 | delta = minv[j]; 49 | j1 = j; 50 | } 51 | } 52 | } 53 | for (int j = 0; j <= m; j++) { 54 | if (used[j]) { 55 | u[pb[j]] += delta; 56 | v[j] -= delta; 57 | } else { 58 | minv[j] -= delta; 59 | } 60 | } 61 | j0 = j1; 62 | } while (pb[j0] != -1); 63 | do { 64 | int j1 = way[j0]; 65 | pb[j0] = pb[j1]; 66 | pa[pb[j0]] = j0; 67 | j0 = j1; 68 | } while (j0 != m); 69 | } 70 | 71 | inline T current_score() { 72 | return -v[m]; 73 | } 74 | 75 | inline T solve() { 76 | for (int i = 0; i < n; i++) { 77 | add_row(i); 78 | } 79 | return current_score(); 80 | } 81 | }; 82 | -------------------------------------------------------------------------------- /flows/matching.cpp: -------------------------------------------------------------------------------- 1 | class matching { 2 | public: 3 | vector> g; 4 | vector pa; 5 | vector pb; 6 | vector was; 7 | int n, m; 8 | int res; 9 | int iter; 10 | 11 | matching(int _n, int _m) : n(_n), m(_m) { 12 | assert(0 <= n && 0 <= m); 13 | pa = vector(n, -1); 14 | pb = vector(m, -1); 15 | was = vector(n, 0); 16 | g.resize(n); 17 | res = 0; 18 | iter = 0; 19 | } 20 | 21 | void add(int from, int to) { 22 | assert(0 <= from && from < n && 0 <= to && to < m); 23 | g[from].push_back(to); 24 | } 25 | 26 | bool dfs(int v) { 27 | was[v] = iter; 28 | for (int u : g[v]) { 29 | if (pb[u] == -1) { 30 | pa[v] = u; 31 | pb[u] = v; 32 | return true; 33 | } 34 | } 35 | for (int u : g[v]) { 36 | if (was[pb[u]] != iter && dfs(pb[u])) { 37 | pa[v] = u; 38 | pb[u] = v; 39 | return true; 40 | } 41 | } 42 | return false; 43 | } 44 | 45 | int solve() { 46 | mt19937_64 rng(uint32_t(chrono::steady_clock::now().time_since_epoch().count())); 47 | for (int i = 0; i < n; i++) { 48 | ranges::shuffle(g[i], rng); 49 | } 50 | while (true) { 51 | iter++; 52 | int add = 0; 53 | for (int i = 0; i < n; i++) { 54 | if (pa[i] == -1 && dfs(i)) { 55 | add++; 56 | } 57 | } 58 | if (add == 0) { 59 | break; 60 | } 61 | res += add; 62 | } 63 | return res; 64 | } 65 | 66 | int run_one(int v) { 67 | if (pa[v] != -1) { 68 | return 0; 69 | } 70 | iter++; 71 | return (int) dfs(v); 72 | } 73 | }; 74 | -------------------------------------------------------------------------------- /flows/mcmf-slow.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class mcmf { 3 | public: 4 | static constexpr T eps = (T) 1e-9; 5 | 6 | struct edge { 7 | int from; 8 | int to; 9 | T c; 10 | T f; 11 | C cost; 12 | }; 13 | 14 | vector> g; 15 | vector edges; 16 | vector d; 17 | vector q; 18 | vector in_queue; 19 | vector pe; 20 | int n; 21 | int st, fin; 22 | T flow; 23 | C cost; 24 | 25 | mcmf(int _n, int _st, int _fin) : n(_n), st(_st), fin(_fin) { 26 | assert(0 <= st && st < n && 0 <= fin && fin < n && st != fin); 27 | g.resize(n); 28 | d.resize(n); 29 | in_queue.resize(n); 30 | pe.resize(n); 31 | flow = 0; 32 | cost = 0; 33 | } 34 | 35 | void clear_flow() { 36 | for (const edge &e : edges) { 37 | e.f = 0; 38 | } 39 | flow = 0; 40 | } 41 | 42 | void add(int from, int to, T forward_cap, T backward_cap, C cost) { 43 | assert(0 <= from && from < n && 0 <= to && to < n); 44 | g[from].push_back((int) edges.size()); 45 | edges.push_back({from, to, forward_cap, 0, cost}); 46 | g[to].push_back((int) edges.size()); 47 | edges.push_back({to, from, backward_cap, 0, -cost}); 48 | } 49 | 50 | bool expath() { 51 | fill(d.begin(), d.end(), numeric_limits::max()); 52 | q.clear(); 53 | q.push_back(st); 54 | d[st] = 0; 55 | in_queue[st] = true; 56 | int beg = 0; 57 | bool found = false; 58 | while (beg < (int) q.size()) { 59 | int i = q[beg++]; 60 | if (i == fin) { 61 | found = true; 62 | } 63 | in_queue[i] = false; 64 | for (int id : g[i]) { 65 | const edge &e = edges[id]; 66 | if (e.c - e.f > eps && d[i] + e.cost < d[e.to]) { 67 | d[e.to] = d[i] + e.cost; 68 | pe[e.to] = id; 69 | if (!in_queue[e.to]) { 70 | q.push_back(e.to); 71 | in_queue[e.to] = true; 72 | } 73 | } 74 | } 75 | } 76 | if (found) { 77 | T push = numeric_limits::max(); 78 | int v = fin; 79 | while (v != st) { 80 | const edge &e = edges[pe[v]]; 81 | push = min(push, e.c - e.f); 82 | v = e.from; 83 | } 84 | v = fin; 85 | while (v != st) { 86 | edge &e = edges[pe[v]]; 87 | e.f += push; 88 | edge &back = edges[pe[v] ^ 1]; 89 | back.f -= push; 90 | v = e.from; 91 | } 92 | flow += push; 93 | cost += push * d[fin]; 94 | } 95 | return found; 96 | } 97 | 98 | pair max_flow_min_cost() { 99 | while (expath()) {} 100 | return {flow, cost}; 101 | } 102 | }; 103 | -------------------------------------------------------------------------------- /flows/mcmf.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | class MCMF { 5 | public: 6 | static constexpr T eps = (T) 1e-9; 7 | 8 | struct edge { 9 | int from; 10 | int to; 11 | T c; 12 | T f; 13 | C cost; 14 | }; 15 | 16 | int n; 17 | vector> g; 18 | vector edges; 19 | vector d; 20 | vector pot; 21 | __gnu_pbds::priority_queue> q; 22 | vector its; 23 | vector pe; 24 | const C INF_C = numeric_limits::max() / 2; 25 | 26 | explicit MCMF(int n_) : n(n_), g(n), d(n), pot(n, 0), its(n), pe(n) {} 27 | 28 | int add(int from, int to, T forward_cap, T backward_cap, C edge_cost) { 29 | assert(0 <= from && from < n && 0 <= to && to < n); 30 | assert(forward_cap >= 0 && backward_cap >= 0); 31 | int id = static_cast(edges.size()); 32 | g[from].push_back(id); 33 | edges.push_back({from, to, forward_cap, 0, edge_cost}); 34 | g[to].push_back(id + 1); 35 | edges.push_back({to, from, backward_cap, 0, -edge_cost}); 36 | return id; 37 | } 38 | 39 | void expath(int st) { 40 | fill(d.begin(), d.end(), INF_C); 41 | q.clear(); 42 | fill(its.begin(), its.end(), q.end()); 43 | its[st] = q.push({pot[st], st}); 44 | d[st] = 0; 45 | while (!q.empty()) { 46 | int i = q.top().second; 47 | q.pop(); 48 | its[i] = q.end(); 49 | for (int id : g[i]) { 50 | const edge &e = edges[id]; 51 | int j = e.to; 52 | if (e.c - e.f > eps && d[i] + e.cost < d[j]) { 53 | d[j] = d[i] + e.cost; 54 | pe[j] = id; 55 | if (its[j] == q.end()) { 56 | its[j] = q.push({pot[j] - d[j], j}); 57 | } else { 58 | q.modify(its[j], {pot[j] - d[j], j}); 59 | } 60 | } 61 | } 62 | } 63 | swap(d, pot); 64 | } 65 | 66 | pair max_flow_min_cost(int st, int fin) { 67 | T flow = 0; 68 | C cost = 0; 69 | bool ok = true; 70 | for (auto& e : edges) { 71 | if (e.c - e.f > eps && e.cost + pot[e.from] - pot[e.to] < 0) { 72 | ok = false; 73 | break; 74 | } 75 | } 76 | if (ok) { 77 | expath(st); 78 | } else { 79 | vector deg(n, 0); 80 | for (int i = 0; i < n; i++) { 81 | for (int eid : g[i]) { 82 | auto& e = edges[eid]; 83 | if (e.c - e.f > eps) { 84 | deg[e.to] += 1; 85 | } 86 | } 87 | } 88 | vector que; 89 | for (int i = 0; i < n; i++) { 90 | if (deg[i] == 0) { 91 | que.push_back(i); 92 | } 93 | } 94 | for (int b = 0; b < (int) que.size(); b++) { 95 | for (int eid : g[que[b]]) { 96 | auto& e = edges[eid]; 97 | if (e.c - e.f > eps) { 98 | deg[e.to] -= 1; 99 | if (deg[e.to] == 0) { 100 | que.push_back(e.to); 101 | } 102 | } 103 | } 104 | } 105 | fill(pot.begin(), pot.end(), INF_C); 106 | pot[st] = 0; 107 | if (static_cast(que.size()) == n) { 108 | for (int v : que) { 109 | if (pot[v] < INF_C) { 110 | for (int eid : g[v]) { 111 | auto& e = edges[eid]; 112 | if (e.c - e.f > eps) { 113 | if (pot[v] + e.cost < pot[e.to]) { 114 | pot[e.to] = pot[v] + e.cost; 115 | pe[e.to] = eid; 116 | } 117 | } 118 | } 119 | } 120 | } 121 | } else { 122 | que.assign(1, st); 123 | vector in_queue(n, false); 124 | in_queue[st] = true; 125 | for (int b = 0; b < (int) que.size(); b++) { 126 | int i = que[b]; 127 | in_queue[i] = false; 128 | for (int id : g[i]) { 129 | const edge &e = edges[id]; 130 | if (e.c - e.f > eps && pot[i] + e.cost < pot[e.to]) { 131 | pot[e.to] = pot[i] + e.cost; 132 | pe[e.to] = id; 133 | if (!in_queue[e.to]) { 134 | que.push_back(e.to); 135 | in_queue[e.to] = true; 136 | } 137 | } 138 | } 139 | } 140 | } 141 | } 142 | while (pot[fin] < INF_C) { 143 | T push = numeric_limits::max(); 144 | int v = fin; 145 | while (v != st) { 146 | const edge &e = edges[pe[v]]; 147 | push = min(push, e.c - e.f); 148 | v = e.from; 149 | } 150 | v = fin; 151 | while (v != st) { 152 | edge &e = edges[pe[v]]; 153 | e.f += push; 154 | edge &back = edges[pe[v] ^ 1]; 155 | back.f -= push; 156 | v = e.from; 157 | } 158 | flow += push; 159 | cost += push * pot[fin]; 160 | expath(st); 161 | } 162 | return {flow, cost}; 163 | } 164 | }; 165 | -------------------------------------------------------------------------------- /flows/mincut.cpp: -------------------------------------------------------------------------------- 1 | template 2 | pair> MinCut(vector> g) { 3 | int n = static_cast(g.size()); 4 | for (int i = 0; i < n; i++) { 5 | assert(static_cast(g[i].size()) == n); 6 | } 7 | for (int i = 0; i < n; i++) { 8 | for (int j = i + 1; j < n; j++) { 9 | assert(g[i][j] == g[j][i]); 10 | } 11 | } 12 | vector> v(n, vector(n)); 13 | for (int i = 0; i < n; i++) { 14 | v[i][i] = true; 15 | } 16 | vector w(n); 17 | vector exists(n, true); 18 | vector in_a(n); 19 | T best_cost = numeric_limits::max(); 20 | vector best_cut; 21 | for (int ph = 0; ph < n - 1; ph++) { 22 | fill(in_a.begin(), in_a.end(), false); 23 | fill(w.begin(), w.end(), T(0)); 24 | int prev = -1; 25 | for (int it = 0; it < n - ph; it++) { 26 | int sel = -1; 27 | for (int i = 0; i < n; i++) { 28 | if (exists[i] && !in_a[i] && (sel == -1 || w[i] > w[sel])) { 29 | sel = i; 30 | } 31 | } 32 | if (it == n - ph - 1) { 33 | if (w[sel] < best_cost) { 34 | best_cost = w[sel]; 35 | best_cut = v[sel]; 36 | } 37 | for (int i = 0; i < n; i++) { 38 | v[prev][i] = v[prev][i] | v[sel][i]; 39 | g[prev][i] += g[sel][i]; 40 | g[i][prev] += g[i][sel]; 41 | } 42 | exists[sel] = false; 43 | break; 44 | } 45 | in_a[sel] = true; 46 | for (int i = 0; i < n; i++) { 47 | w[i] += g[sel][i]; 48 | } 49 | prev = sel; 50 | } 51 | } 52 | return make_pair(best_cost, best_cut); 53 | } 54 | -------------------------------------------------------------------------------- /generate_snippets.py: -------------------------------------------------------------------------------- 1 | # Generates cpp.json with snippets for VSCode 2 | 3 | import os 4 | import json 5 | import sys 6 | 7 | snippets = {} 8 | 9 | for subdir in os.walk('.'): 10 | if subdir[0] == '.' or '.git' in subdir[0]: 11 | continue 12 | for filename in subdir[2]: 13 | name, extension = filename.split('.') 14 | if extension != 'cpp': 15 | continue 16 | 17 | if name in snippets: 18 | print(f'error: duplicate snippet {name}', file=sys.stderr) 19 | exit(0) 20 | 21 | path = subdir[0] + '/' + filename 22 | with open(path, 'r') as f: 23 | snippet = { 24 | "prefix": name, 25 | "body": [line.rstrip() for line in f.readlines()], 26 | "description": name 27 | } 28 | snippets[name] = snippet 29 | 30 | print(f'generated snippet {name}', file=sys.stderr) 31 | 32 | with open('cpp.json', 'w') as f: 33 | f.write(json.dumps(snippets, indent=2)) 34 | 35 | print('done', file=sys.stderr) 36 | -------------------------------------------------------------------------------- /geometry/point.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct TPoint { 3 | T x; 4 | T y; 5 | int id; 6 | 7 | TPoint() : x(0), y(0), id(-1) {} 8 | TPoint(const T& x_, const T& y_) : x(x_), y(y_), id(-1) {} 9 | TPoint(const T& x_, const T& y_, int id_) : x(x_), y(y_), id(id_) {} 10 | 11 | static constexpr T eps = static_cast(1e-9); 12 | 13 | inline TPoint operator+(const TPoint& rhs) const { return TPoint(x + rhs.x, y + rhs.y); } 14 | inline TPoint operator-(const TPoint& rhs) const { return TPoint(x - rhs.x, y - rhs.y); } 15 | inline TPoint operator*(const T& rhs) const { return TPoint(x * rhs, y * rhs); } 16 | inline TPoint operator/(const T& rhs) const { return TPoint(x / rhs, y / rhs); } 17 | 18 | friend T smul(const TPoint& a, const TPoint& b) { 19 | return a.x * b.x + a.y * b.y; 20 | } 21 | 22 | friend T vmul(const TPoint& a, const TPoint& b) { 23 | return a.x * b.y - a.y * b.x; 24 | } 25 | 26 | inline T abs2() const { 27 | return x * x + y * y; 28 | } 29 | 30 | inline bool operator<(const TPoint& rhs) const { 31 | return (y < rhs.y || (y == rhs.y && x < rhs.x)); 32 | } 33 | 34 | inline bool is_upper() const { 35 | return (y > eps || (abs(y) <= eps && x > eps)); 36 | } 37 | 38 | inline int cmp_polar(const TPoint& rhs) const { 39 | assert(abs(x) > eps || abs(y) > eps); 40 | assert(abs(rhs.x) > eps || abs(rhs.y) > eps); 41 | bool a = is_upper(); 42 | bool b = rhs.is_upper(); 43 | if (a != b) { 44 | return (a ? -1 : 1); 45 | } 46 | auto v = x * rhs.y - y * rhs.x; 47 | return (v > eps ? -1 : (v < -eps ? 1 : 0)); 48 | } 49 | }; 50 | 51 | using Point = TPoint; 52 | //using Point = TPoint; 53 | 54 | template 55 | string to_string(const TPoint& p) { 56 | return "(" + to_string(p.x) + ", " + to_string(p.y) + ")"; 57 | } 58 | -------------------------------------------------------------------------------- /graph/bicone.cpp: -------------------------------------------------------------------------------- 1 | template 2 | vector find_bicone(dfs_undigraph &g, int &cnt) { 3 | g.dfs_all(); 4 | vector vertex_comp(g.n); 5 | cnt = 0; 6 | for (int i : g.order) { 7 | if (g.pv[i] == -1 || g.min_depth[i] == g.depth[i]) { 8 | vertex_comp[i] = cnt++; 9 | } else { 10 | vertex_comp[i] = vertex_comp[g.pv[i]]; 11 | } 12 | } 13 | return vertex_comp; 14 | } 15 | -------------------------------------------------------------------------------- /graph/biconv.cpp: -------------------------------------------------------------------------------- 1 | template 2 | vector find_biconv(dfs_undigraph &g, int &cnt) { 3 | g.dfs_all(); 4 | vector vertex_comp(g.n); 5 | cnt = 0; 6 | for (int i : g.order) { 7 | if (g.pv[i] == -1) { 8 | vertex_comp[i] = -1; 9 | continue; 10 | } 11 | if (g.min_depth[i] >= g.depth[g.pv[i]]) { 12 | vertex_comp[i] = cnt++; 13 | } else { 14 | vertex_comp[i] = vertex_comp[g.pv[i]]; 15 | } 16 | } 17 | vector edge_comp(g.edges.size(), -1); 18 | for (int id = 0; id < (int) g.edges.size(); id++) { 19 | int x = g.edges[id].from; 20 | int y = g.edges[id].to; 21 | int z = (g.depth[x] > g.depth[y] ? x : y); 22 | edge_comp[id] = vertex_comp[z]; 23 | } 24 | return edge_comp; 25 | } 26 | -------------------------------------------------------------------------------- /graph/bridges.cpp: -------------------------------------------------------------------------------- 1 | template 2 | vector find_bridges(dfs_undigraph &g) { 3 | g.dfs_all(); 4 | vector bridge(g.edges.size(), false); 5 | for (int i = 0; i < g.n; i++) { 6 | if (g.pv[i] != -1 && g.min_depth[i] == g.depth[i]) { 7 | bridge[g.pe[i]] = true; 8 | } 9 | } 10 | return bridge; 11 | } 12 | -------------------------------------------------------------------------------- /graph/centroid.cpp: -------------------------------------------------------------------------------- 1 | template 2 | vector centroid_decomposition(const forest& g) { 3 | int n = g.n; 4 | vector alive(n, true); 5 | vector res; 6 | res.reserve(n); 7 | vector sz(n); 8 | auto Dfs = [&](auto&& self, int v, int pr) -> void { 9 | sz[v] = 1; 10 | for (int eid : g.g[v]) { 11 | auto& e = g.edges[eid]; 12 | int u = e.from ^ e.to ^ v; 13 | if (u != pr && alive[u]) { 14 | self(self, u, v); 15 | sz[v] += sz[u]; 16 | } 17 | } 18 | }; 19 | auto Build = [&](auto&& self, int v) -> void { 20 | Dfs(Dfs, v, -1); 21 | int c = v; 22 | int pr = -1; 23 | while (true) { 24 | int nxt = -1; 25 | for (int eid : g.g[c]) { 26 | auto& e = g.edges[eid]; 27 | int u = e.from ^ e.to ^ c; 28 | if (u != pr && alive[u] && 2 * sz[u] > sz[v]) { 29 | nxt = u; 30 | break; 31 | } 32 | } 33 | if (nxt == -1) { 34 | break; 35 | } 36 | pr = c; 37 | c = nxt; 38 | } 39 | res.push_back(c); 40 | alive[c] = false; 41 | for (int eid : g.g[c]) { 42 | auto& e = g.edges[eid]; 43 | int u = e.from ^ e.to ^ c; 44 | if (alive[u]) { 45 | self(self, u); 46 | } 47 | } 48 | }; 49 | for (int i = 0; i < n; i++) { 50 | if (alive[i]) { 51 | Build(Build, i); 52 | } 53 | } 54 | return res; 55 | } 56 | 57 | // Usage example: 58 | 59 | // auto seq = centroid_decomposition(g); 60 | // vector alive(n, true); 61 | // for (int c : seq) { 62 | // alive[c] = false; 63 | // vector go; 64 | // for (int eid : g.g[c]) { 65 | // auto& e = g.edges[eid]; 66 | // int u = e.from ^ e.to ^ c; 67 | // if (alive[u]) { 68 | // go.push_back(u); 69 | // } 70 | // } 71 | // vector> p; 72 | // for (int r : go) { 73 | // vector> pp; 74 | // auto Dfs = [&](auto&& self, int v, int pr, int mn, int mx) -> void { 75 | // ans += Mint(mn) * mx; 76 | // pp.emplace_back(mn, mx); 77 | // p.emplace_back(mn, mx); 78 | // for (int eid : g.g[v]) { 79 | // auto& e = g.edges[eid]; 80 | // int u = e.from ^ e.to ^ v; 81 | // if (u != pr && alive[u]) { 82 | // self(self, u, v, min(mn, a[u]), max(mx, a[u])); 83 | // } 84 | // } 85 | // }; 86 | // Dfs(Dfs, r, c, min(a[r], a[c]), max(a[r], a[c])); 87 | // ans -= Solve(pp); 88 | // } 89 | // ans += Solve(p); 90 | // } 91 | 92 | // Another usage example: 93 | 94 | // auto seq = centroid_decomposition(g); 95 | // vector> fenw; 96 | // vector> fenw_depth; 97 | // vector>> fenw_data(n); 98 | // vector fenw_coeff; 99 | // int cnt = 0; 100 | // vector alive(n, true); 101 | // vector parent(n, -1); 102 | // for (int c : seq) { 103 | // alive[c] = false; 104 | // vector go; 105 | // for (int eid : g.g[c]) { 106 | // auto& e = g.edges[eid]; 107 | // int u = e.from ^ e.to ^ c; 108 | // if (alive[u]) { 109 | // go.push_back(u); 110 | // parent[u] = c; 111 | // } 112 | // } 113 | // vector> p; 114 | // p.emplace_back(0, c); 115 | // for (int r : go) { 116 | // vector> pp; 117 | // auto Dfs = [&](auto&& self, int v, int pr, int depth) -> void { 118 | // p.emplace_back(depth, v); 119 | // pp.emplace_back(depth, v); 120 | // for (int eid : g.g[v]) { 121 | // auto& e = g.edges[eid]; 122 | // int u = e.from ^ e.to ^ v; 123 | // if (u != pr && alive[u]) { 124 | // self(self, u, v, depth + 1); 125 | // } 126 | // } 127 | // }; 128 | // Dfs(Dfs, r, c, 1); 129 | // ranges::sort(pp); 130 | // fenw.push_back(FenwickTree(int(pp.size()))); 131 | // fenw_depth.emplace_back(); 132 | // fenw_coeff.push_back(-1); 133 | // for (int i = 0; i < int(pp.size()); i++) { 134 | // auto [depth, v] = pp[i]; 135 | // fenw_data[v].push_back({cnt, i, depth}); 136 | // fenw_depth[cnt].push_back(depth); 137 | // fenw[cnt].Modify(i, a[v]); 138 | // } 139 | // cnt += 1; 140 | // } 141 | // ranges::sort(p); 142 | // fenw.push_back(FenwickTree(int(p.size()))); 143 | // fenw_depth.emplace_back(); 144 | // fenw_coeff.push_back(+1); 145 | // for (int i = 0; i < int(p.size()); i++) { 146 | // auto [depth, v] = p[i]; 147 | // fenw_data[v].push_back({cnt, i, depth}); 148 | // fenw_depth[cnt].push_back(depth); 149 | // fenw[cnt].Modify(i, a[v]); 150 | // } 151 | // cnt += 1; 152 | // } 153 | // while (q--) { 154 | // int op, v; 155 | // cin >> op >> v; 156 | // if (op == 0) { 157 | // int x; 158 | // cin >> x; 159 | // for (auto& [id, i, depth] : fenw_data[v]) { 160 | // fenw[id].Modify(i, x); 161 | // } 162 | // } else { 163 | // int l, r; 164 | // cin >> l >> r; 165 | // int64_t ans = 0; 166 | // for (auto& [id, i, depth] : fenw_data[v]) { 167 | // int from = max(0, l - depth); 168 | // int to = max(0, r - depth); 169 | // if (from < to) { 170 | // int from_pos = int(ranges::lower_bound(fenw_depth[id], from) - fenw_depth[id].begin()); 171 | // int to_pos = int(ranges::lower_bound(fenw_depth[id], to) - fenw_depth[id].begin()); 172 | // ans += fenw_coeff[id] * (fenw[id].Query(to_pos) - fenw[id].Query(from_pos)); 173 | // } 174 | // } 175 | // cout << ans << '\n'; 176 | // } 177 | // } 178 | -------------------------------------------------------------------------------- /graph/cutpoints.cpp: -------------------------------------------------------------------------------- 1 | template 2 | vector find_cutpoints(dfs_undigraph &g) { 3 | g.dfs_all(); 4 | vector cutpoint(g.n, false); 5 | for (int i = 0; i < g.n; i++) { 6 | if (g.pv[i] != -1 && g.min_depth[i] >= g.depth[g.pv[i]]) { 7 | cutpoint[g.pv[i]] = true; 8 | } 9 | } 10 | vector children(g.n, 0); 11 | for (int i = 0; i < g.n; i++) { 12 | if (g.pv[i] != -1) { 13 | children[g.pv[i]]++; 14 | } 15 | } 16 | for (int i = 0; i < g.n; i++) { 17 | if (g.pv[i] == -1 && children[i] < 2) { 18 | cutpoint[i] = false; 19 | } 20 | } 21 | return cutpoint; 22 | } 23 | -------------------------------------------------------------------------------- /graph/cycles.cpp: -------------------------------------------------------------------------------- 1 | template 2 | vector> find_cycles(const graph &g, int bound_cnt = 1 << 30, int bound_size = 1 << 30) { 3 | vector was(g.n, -1); 4 | vector st; 5 | vector> cycles; 6 | int total_size = 0; 7 | function dfs = [&](int v, int pe) { 8 | if ((int) cycles.size() >= bound_cnt || total_size >= bound_size) { 9 | return; 10 | } 11 | was[v] = (int) st.size(); 12 | for (int id : g.g[v]) { 13 | if (id == pe) { 14 | continue; 15 | } 16 | auto &e = g.edges[id]; 17 | int to = e.from ^ e.to ^ v; 18 | if (was[to] >= 0) { 19 | vector cycle(1, id); 20 | for (int j = was[to]; j < (int) st.size(); j++) { 21 | cycle.push_back(st[j]); 22 | } 23 | cycles.push_back(cycle); 24 | total_size += (int) cycle.size(); 25 | if ((int) cycles.size() >= bound_cnt || total_size >= bound_size) { 26 | was[v] = -2; 27 | return; 28 | } 29 | continue; 30 | } 31 | if (was[to] == -1) { 32 | st.push_back(id); 33 | dfs(to, id); 34 | st.pop_back(); 35 | } 36 | } 37 | was[v] = -2; 38 | }; 39 | for (int i = 0; i < g.n; i++) { 40 | if (was[i] == -1) { 41 | dfs(i, -1); 42 | } 43 | } 44 | return cycles; 45 | // cycles are given by edge ids, all cycles are simple 46 | // breaks after getting bound_cnt cycles or total_size >= bound_size 47 | // digraph: finds at least one cycle in every connected component (if not broken) 48 | // undigraph: finds cycle basis 49 | } 50 | 51 | template 52 | vector edges_to_vertices(const graph &g, const vector &edge_cycle) { 53 | int sz = (int) edge_cycle.size(); 54 | vector vertex_cycle; 55 | if (sz <= 2) { 56 | vertex_cycle.push_back(g.edges[edge_cycle[0]].from); 57 | if (sz == 2) { 58 | vertex_cycle.push_back(g.edges[edge_cycle[0]].to); 59 | } 60 | } else { 61 | for (int i = 0; i < sz; i++) { 62 | int j = (i + 1) % sz; 63 | auto &e = g.edges[edge_cycle[i]]; 64 | auto &other = g.edges[edge_cycle[j]]; 65 | if (other.from == e.from || other.to == e.from) { 66 | vertex_cycle.push_back(e.to); 67 | } else { 68 | vertex_cycle.push_back(e.from); 69 | } 70 | } 71 | } 72 | return vertex_cycle; 73 | // only for simple cycles! 74 | } 75 | -------------------------------------------------------------------------------- /graph/dfs_digraph_useless.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class dfs_digraph : public digraph { 3 | public: 4 | using digraph::edges; 5 | using digraph::g; 6 | using digraph::n; 7 | 8 | vector pv; 9 | vector pe; 10 | vector order; 11 | vector pos; 12 | vector end; 13 | vector sz; 14 | vector root; 15 | vector depth; 16 | vector dist; 17 | 18 | dfs_digraph(int _n) : digraph(_n) { 19 | } 20 | 21 | void clear() { 22 | pv.clear(); 23 | pe.clear(); 24 | order.clear(); 25 | pos.clear(); 26 | end.clear(); 27 | sz.clear(); 28 | root.clear(); 29 | depth.clear(); 30 | dist.clear(); 31 | } 32 | 33 | void init() { 34 | pv = vector(n, -1); 35 | pe = vector(n, -1); 36 | order.clear(); 37 | pos = vector(n, -1); 38 | end = vector(n, -1); 39 | sz = vector(n, 0); 40 | root = vector(n, -1); 41 | depth = vector(n, -1); 42 | dist = vector(n); 43 | } 44 | 45 | private: 46 | void do_dfs(int v) { 47 | pos[v] = (int) order.size(); 48 | order.push_back(v); 49 | sz[v] = 1; 50 | for (int id : g[v]) { 51 | if (id == pe[v]) { 52 | continue; 53 | } 54 | auto &e = edges[id]; 55 | int to = e.from ^ e.to ^ v; 56 | // well, this is controversial... 57 | if (depth[to] != -1) { 58 | continue; 59 | } 60 | depth[to] = depth[v] + 1; 61 | dist[to] = dist[v] + e.cost; 62 | pv[to] = v; 63 | pe[to] = id; 64 | root[to] = (root[v] != -1 ? root[v] : to); 65 | do_dfs(to); 66 | sz[v] += sz[to]; 67 | } 68 | end[v] = (int) order.size() - 1; 69 | } 70 | 71 | void do_dfs_from(int v) { 72 | depth[v] = 0; 73 | dist[v] = T{}; 74 | root[v] = v; 75 | pv[v] = pe[v] = -1; 76 | do_dfs(v); 77 | } 78 | 79 | public: 80 | int dfs_one_unsafe(int v) { 81 | // run init() before this 82 | // then run this with the required v's 83 | do_dfs_from(v); 84 | return v; 85 | } 86 | 87 | int dfs(int v) { 88 | init(); 89 | do_dfs_from(v); 90 | // assert((int) order.size() == n); 91 | return v; 92 | } 93 | 94 | void dfs_many(const vector &roots) { 95 | init(); 96 | for (int v : roots) { 97 | if (depth[v] == -1) { 98 | do_dfs_from(v); 99 | } 100 | } 101 | // assert((int) order.size() == n); 102 | } 103 | 104 | vector dfs_all() { 105 | init(); 106 | vector roots; 107 | for (int v = 0; v < n; v++) { 108 | if (depth[v] == -1) { 109 | roots.push_back(v); 110 | do_dfs_from(v); 111 | } 112 | } 113 | assert((int) order.size() == n); 114 | return roots; 115 | } 116 | }; 117 | -------------------------------------------------------------------------------- /graph/dfs_forest.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class dfs_forest : public forest { 3 | public: 4 | using forest::edges; 5 | using forest::g; 6 | using forest::n; 7 | 8 | vector pv; 9 | vector pe; 10 | vector order; 11 | vector pos; 12 | vector end; 13 | vector sz; 14 | vector root; 15 | vector depth; 16 | vector dist; 17 | 18 | dfs_forest(int _n) : forest(_n) { 19 | } 20 | 21 | void init() { 22 | pv = vector(n, -1); 23 | pe = vector(n, -1); 24 | order.clear(); 25 | pos = vector(n, -1); 26 | end = vector(n, -1); 27 | sz = vector(n, 0); 28 | root = vector(n, -1); 29 | depth = vector(n, -1); 30 | dist = vector(n); 31 | } 32 | 33 | void clear() { 34 | pv.clear(); 35 | pe.clear(); 36 | order.clear(); 37 | pos.clear(); 38 | end.clear(); 39 | sz.clear(); 40 | root.clear(); 41 | depth.clear(); 42 | dist.clear(); 43 | } 44 | 45 | private: 46 | void do_dfs(int v) { 47 | pos[v] = (int) order.size(); 48 | order.push_back(v); 49 | sz[v] = 1; 50 | for (int id : g[v]) { 51 | if (id == pe[v]) { 52 | continue; 53 | } 54 | auto &e = edges[id]; 55 | int to = e.from ^ e.to ^ v; 56 | depth[to] = depth[v] + 1; 57 | dist[to] = dist[v] + e.cost; 58 | pv[to] = v; 59 | pe[to] = id; 60 | root[to] = (root[v] != -1 ? root[v] : to); 61 | do_dfs(to); 62 | sz[v] += sz[to]; 63 | } 64 | end[v] = (int) order.size() - 1; 65 | } 66 | 67 | void do_dfs_from(int v) { 68 | depth[v] = 0; 69 | dist[v] = T{}; 70 | root[v] = v; 71 | pv[v] = pe[v] = -1; 72 | do_dfs(v); 73 | } 74 | 75 | public: 76 | void dfs(int v, bool clear_order = true) { 77 | if (pv.empty()) { 78 | init(); 79 | } else { 80 | if (clear_order) { 81 | order.clear(); 82 | } 83 | } 84 | do_dfs_from(v); 85 | } 86 | 87 | void dfs_all() { 88 | init(); 89 | for (int v = 0; v < n; v++) { 90 | if (depth[v] == -1) { 91 | do_dfs_from(v); 92 | } 93 | } 94 | assert((int) order.size() == n); 95 | } 96 | }; 97 | -------------------------------------------------------------------------------- /graph/dfs_undigraph.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class dfs_undigraph : public undigraph { 3 | public: 4 | using undigraph::edges; 5 | using undigraph::g; 6 | using undigraph::n; 7 | 8 | vector pv; 9 | vector pe; 10 | vector order; 11 | vector pos; 12 | vector end; 13 | vector sz; 14 | vector root; 15 | vector depth; 16 | vector min_depth; 17 | vector dist; 18 | vector was; 19 | int attempt; 20 | 21 | dfs_undigraph(int _n) : undigraph(_n) { 22 | } 23 | 24 | void init() { 25 | pv = vector(n, -1); 26 | pe = vector(n, -1); 27 | order.clear(); 28 | pos = vector(n, -1); 29 | end = vector(n, -1); 30 | sz = vector(n, 0); 31 | root = vector(n, -1); 32 | depth = vector(n, -1); 33 | min_depth = vector(n, -1); 34 | dist = vector(n); 35 | was = vector(n, -1); 36 | attempt = 0; 37 | } 38 | 39 | void clear() { 40 | pv.clear(); 41 | pe.clear(); 42 | order.clear(); 43 | pos.clear(); 44 | end.clear(); 45 | sz.clear(); 46 | root.clear(); 47 | depth.clear(); 48 | min_depth.clear(); 49 | dist.clear(); 50 | was.clear(); 51 | } 52 | 53 | private: 54 | void do_dfs(int v) { 55 | was[v] = attempt; 56 | pos[v] = (int) order.size(); 57 | order.push_back(v); 58 | sz[v] = 1; 59 | min_depth[v] = depth[v]; 60 | for (int id : g[v]) { 61 | if (id == pe[v]) { 62 | continue; 63 | } 64 | auto &e = edges[id]; 65 | int to = e.from ^ e.to ^ v; 66 | if (was[to] == attempt) { 67 | min_depth[v] = min(min_depth[v], depth[to]); 68 | continue; 69 | } 70 | depth[to] = depth[v] + 1; 71 | dist[to] = dist[v] + e.cost; 72 | pv[to] = v; 73 | pe[to] = id; 74 | root[to] = (root[v] != -1 ? root[v] : to); 75 | do_dfs(to); 76 | sz[v] += sz[to]; 77 | min_depth[v] = min(min_depth[v], min_depth[to]); 78 | } 79 | end[v] = (int) order.size() - 1; 80 | } 81 | 82 | void do_dfs_from(int v) { 83 | ++attempt; 84 | depth[v] = 0; 85 | dist[v] = T{}; 86 | root[v] = v; 87 | pv[v] = pe[v] = -1; 88 | do_dfs(v); 89 | } 90 | 91 | public: 92 | void dfs(int v, bool clear_order = true) { 93 | if (pv.empty()) { 94 | init(); 95 | } else { 96 | if (clear_order) { 97 | order.clear(); 98 | } 99 | } 100 | do_dfs_from(v); 101 | } 102 | 103 | void dfs_all() { 104 | init(); 105 | for (int v = 0; v < n; v++) { 106 | if (depth[v] == -1) { 107 | do_dfs_from(v); 108 | } 109 | } 110 | assert((int) order.size() == n); 111 | } 112 | }; 113 | -------------------------------------------------------------------------------- /graph/digraph.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class digraph : public graph { 3 | public: 4 | using graph::edges; 5 | using graph::g; 6 | using graph::n; 7 | 8 | digraph(int _n) : graph(_n) { 9 | } 10 | 11 | int add(int from, int to, T cost = 1) { 12 | assert(0 <= from && from < n && 0 <= to && to < n); 13 | int id = (int) edges.size(); 14 | g[from].push_back(id); 15 | edges.push_back({from, to, cost}); 16 | return id; 17 | } 18 | 19 | digraph reverse() const { 20 | digraph rev(n); 21 | for (auto &e : edges) { 22 | rev.add(e.to, e.from, e.cost); 23 | } 24 | return rev; 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /graph/dijkstra-set.cpp: -------------------------------------------------------------------------------- 1 | template 2 | vector dijkstra(const graph &g, int start) { 3 | assert(0 <= start && start < g.n); 4 | vector dist(g.n, numeric_limits::max()); 5 | dist[start] = 0; 6 | set> s; 7 | s.emplace(dist[start], start); 8 | while (!s.empty()) { 9 | int i = s.begin()->second; 10 | s.erase(s.begin()); 11 | for (int id : g.g[i]) { 12 | auto &e = g.edges[id]; 13 | int to = e.from ^ e.to ^ i; 14 | if (dist[i] + e.cost < dist[to]) { 15 | s.erase({dist[to], to}); 16 | dist[to] = dist[i] + e.cost; 17 | s.emplace(dist[to], to); 18 | } 19 | } 20 | } 21 | return dist; 22 | // returns numeric_limits::max() if there's no path 23 | } 24 | -------------------------------------------------------------------------------- /graph/dijkstra.cpp: -------------------------------------------------------------------------------- 1 | template 2 | vector dijkstra(const graph &g, int start) { 3 | assert(0 <= start && start < g.n); 4 | vector dist(g.n, numeric_limits::max()); 5 | priority_queue, vector>, greater<>> s; 6 | dist[start] = 0; 7 | s.emplace(dist[start], start); 8 | while (!s.empty()) { 9 | auto [expected, i] = s.top(); 10 | s.pop(); 11 | if (dist[i] != expected) { 12 | continue; 13 | } 14 | for (int id : g.g[i]) { 15 | auto &e = g.edges[id]; 16 | int to = e.from ^ e.to ^ i; 17 | if (dist[i] + e.cost < dist[to]) { 18 | dist[to] = dist[i] + e.cost; 19 | s.emplace(dist[to], to); 20 | } 21 | } 22 | } 23 | return dist; 24 | // returns numeric_limits::max() if there's no path 25 | } 26 | -------------------------------------------------------------------------------- /graph/dominators.cpp: -------------------------------------------------------------------------------- 1 | template 2 | vector find_dominators(const digraph &g, int root) { 3 | int n = g.n; 4 | vector pos(n, -1); 5 | vector order; 6 | vector parent(n, -1); 7 | function dfs = [&g, &pos, &order, &parent, &dfs](int v) { 8 | pos[v] = (int) order.size(); 9 | order.push_back(v); 10 | for (int id : g.g[v]) { 11 | auto &e = g.edges[id]; 12 | int u = e.to; 13 | if (pos[u] == -1) { 14 | parent[u] = v; 15 | dfs(u); 16 | } 17 | } 18 | }; 19 | dfs(root); 20 | vector p(n), best(n); 21 | iota(p.begin(), p.end(), 0); 22 | iota(best.begin(), best.end(), 0); 23 | vector sdom = pos; 24 | function find_best = [&p, &best, &sdom, &find_best](int x) { 25 | if (p[x] != x) { 26 | int u = find_best(p[x]); 27 | if (sdom[u] < sdom[best[x]]) { 28 | best[x] = u; 29 | } 30 | p[x] = p[p[x]]; 31 | } 32 | if (sdom[best[p[x]]] < sdom[best[x]]) { 33 | best[x] = best[p[x]]; 34 | } 35 | return best[x]; 36 | }; 37 | digraph g_rev = g.reverse(); 38 | vector idom(n, -1); 39 | vector link(n, 0); 40 | vector> bucket(n); 41 | for (int it = (int) order.size() - 1; it >= 0; it--) { 42 | int w = order[it]; 43 | for (int id : g_rev.g[w]) { 44 | auto &e = g_rev.edges[id]; 45 | int u = e.to; 46 | if (pos[u] != -1) { 47 | sdom[w] = min(sdom[w], sdom[find_best(u)]); 48 | } 49 | } 50 | idom[w] = order[sdom[w]]; 51 | for (int u : bucket[w]) { 52 | link[u] = find_best(u); 53 | } 54 | for (int id : g.g[w]) { 55 | auto &e = g.edges[id]; 56 | int u = e.to; 57 | if (parent[u] == w) { 58 | p[u] = w; 59 | } 60 | } 61 | bucket[order[sdom[w]]].push_back(w); 62 | } 63 | for (int it = 1; it < (int) order.size(); it++) { 64 | int w = order[it]; 65 | idom[w] = idom[link[w]]; 66 | } 67 | return idom; 68 | // idom[i] -- immediate dominator for vertex i 69 | } 70 | -------------------------------------------------------------------------------- /graph/eulerian.cpp: -------------------------------------------------------------------------------- 1 | template 2 | vector find_eulerian_path(const graph &g, int &root) { 3 | // in_deg and out_deg are fake for undigraph! 4 | vector in_deg(g.n, 0); 5 | vector out_deg(g.n, 0); 6 | int cnt_edges = 0; 7 | for (int id = 0; id < (int) g.edges.size(); id++) { 8 | cnt_edges++; 9 | auto &e = g.edges[id]; 10 | out_deg[e.from]++; 11 | in_deg[e.to]++; 12 | } 13 | root = -1; 14 | int odd = 0; 15 | for (int i = 0; i < g.n; i++) { 16 | if ((in_deg[i] + out_deg[i]) % 2 == 1) { 17 | odd++; 18 | if (root == -1 || out_deg[i] - in_deg[i] > out_deg[root] - in_deg[root]) { 19 | root = i; 20 | } 21 | } 22 | } 23 | if (odd > 2) { 24 | root = -1; 25 | return vector(); 26 | } 27 | if (root == -1) { 28 | root = 0; 29 | while (root < g.n && in_deg[root] + out_deg[root] == 0) { 30 | root++; 31 | } 32 | if (root == g.n) { 33 | // an empty path 34 | root = 0; 35 | return vector(); 36 | } 37 | } 38 | vector used(g.edges.size(), false); 39 | vector ptr(g.n, 0); 40 | vector balance(g.n, 0); 41 | vector res(cnt_edges); 42 | int stack_ptr = 0; 43 | int write_ptr = cnt_edges; 44 | int v = root; 45 | while (true) { 46 | bool found = false; 47 | while (ptr[v] < (int) g.g[v].size()) { 48 | int id = g.g[v][ptr[v]++]; 49 | if (used[id]) { 50 | continue; 51 | } 52 | used[id] = true; 53 | res[stack_ptr++] = id; 54 | auto &e = g.edges[id]; 55 | balance[v]++; 56 | v ^= e.from ^ e.to; 57 | balance[v]--; 58 | found = true; 59 | break; 60 | } 61 | if (!found) { 62 | if (stack_ptr == 0) { 63 | break; 64 | } 65 | int id = res[--stack_ptr]; 66 | res[--write_ptr] = id; 67 | auto &e = g.edges[id]; 68 | v ^= e.from ^ e.to; 69 | } 70 | } 71 | int disbalance = 0; 72 | for (int i = 0; i < g.n; i++) { 73 | disbalance += abs(balance[i]); 74 | } 75 | if (write_ptr != 0 || disbalance > 2) { 76 | root = -1; 77 | return vector(); 78 | } 79 | return res; 80 | // returns edge ids in the path (or the cycle if it exists) 81 | // root == -1 if there is no path 82 | // (or res.empty(), but this is also true when there are no edges) 83 | } 84 | -------------------------------------------------------------------------------- /graph/forest.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class forest : public graph { 3 | public: 4 | using graph::edges; 5 | using graph::g; 6 | using graph::n; 7 | 8 | forest(int _n) : graph(_n) { 9 | } 10 | 11 | int add(int from, int to, T cost = 1) { 12 | assert(0 <= from && from < n && 0 <= to && to < n); 13 | int id = (int) edges.size(); 14 | assert(id < n - 1); 15 | g[from].push_back(id); 16 | g[to].push_back(id); 17 | edges.push_back({from, to, cost}); 18 | return id; 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /graph/graph.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class graph { 3 | public: 4 | struct edge { 5 | int from; 6 | int to; 7 | T cost; 8 | }; 9 | 10 | vector edges; 11 | vector> g; 12 | int n; 13 | 14 | graph(int _n) : n(_n) { 15 | g.resize(n); 16 | } 17 | 18 | virtual int add(int from, int to, T cost) = 0; 19 | }; 20 | -------------------------------------------------------------------------------- /graph/hld_forest.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class hld_forest : public dfs_forest { 3 | public: 4 | using dfs_forest::edges; 5 | using dfs_forest::g; 6 | using dfs_forest::n; 7 | using dfs_forest::pv; 8 | using dfs_forest::sz; 9 | using dfs_forest::root; 10 | using dfs_forest::pos; 11 | using dfs_forest::end; 12 | using dfs_forest::order; 13 | using dfs_forest::depth; 14 | using dfs_forest::dfs; 15 | using dfs_forest::dfs_all; 16 | 17 | vector head; 18 | vector visited; 19 | 20 | hld_forest(int _n) : dfs_forest(_n) { 21 | visited.resize(n); 22 | } 23 | 24 | void build_hld(const vector &vs) { 25 | for (int tries = 0; tries < 2; tries++) { 26 | if (vs.empty()) { 27 | dfs_all(); 28 | } else { 29 | order.clear(); 30 | for (int v : vs) { 31 | dfs(v, false); 32 | } 33 | assert((int) order.size() == n); 34 | } 35 | if (tries == 1) { 36 | break; 37 | } 38 | for (int i = 0; i < n; i++) { 39 | if (g[i].empty()) { 40 | continue; 41 | } 42 | int best = -1, bid = 0; 43 | for (int j = 0; j < (int) g[i].size(); j++) { 44 | int id = g[i][j]; 45 | int v = edges[id].from ^ edges[id].to ^ i; 46 | if (pv[v] != i) { 47 | continue; 48 | } 49 | if (sz[v] > best) { 50 | best = sz[v]; 51 | bid = j; 52 | } 53 | } 54 | swap(g[i][0], g[i][bid]); 55 | } 56 | } 57 | head.resize(n); 58 | for (int i = 0; i < n; i++) { 59 | head[i] = i; 60 | } 61 | for (int i = 0; i < n - 1; i++) { 62 | int x = order[i]; 63 | int y = order[i + 1]; 64 | if (pv[y] == x) { 65 | head[y] = head[x]; 66 | } 67 | } 68 | } 69 | 70 | void build_hld(int v) { 71 | build_hld(vector(1, v)); 72 | } 73 | 74 | void build_hld_all() { 75 | build_hld(vector()); 76 | } 77 | 78 | bool apply_on_path(int x, int y, bool with_lca, function f) { 79 | // f(x, y, up): up -- whether this part of the path goes up 80 | assert(!head.empty()); 81 | int z = lca(x, y); 82 | if (z == -1) { 83 | return false; 84 | } 85 | { 86 | int v = x; 87 | while (v != z) { 88 | if (depth[head[v]] <= depth[z]) { 89 | f(pos[z] + 1, pos[v], true); 90 | break; 91 | } 92 | f(pos[head[v]], pos[v], true); 93 | v = pv[head[v]]; 94 | } 95 | } 96 | if (with_lca) { 97 | f(pos[z], pos[z], false); 98 | } 99 | { 100 | int v = y; 101 | int cnt_visited = 0; 102 | while (v != z) { 103 | if (depth[head[v]] <= depth[z]) { 104 | f(pos[z] + 1, pos[v], false); 105 | break; 106 | } 107 | visited[cnt_visited++] = v; 108 | v = pv[head[v]]; 109 | } 110 | for (int at = cnt_visited - 1; at >= 0; at--) { 111 | v = visited[at]; 112 | f(pos[head[v]], pos[v], false); 113 | } 114 | } 115 | return true; 116 | } 117 | 118 | inline bool anc(int x, int y) { 119 | return (pos[x] <= pos[y] && end[y] <= end[x]); 120 | } 121 | 122 | inline int go_up(int x, int up) { 123 | int target = depth[x] - up; 124 | if (target < 0) { 125 | return -1; 126 | } 127 | while (depth[head[x]] > target) { 128 | x = pv[head[x]]; 129 | } 130 | return order[pos[x] - depth[x] + target]; 131 | } 132 | 133 | inline int lca(int x, int y) { 134 | if (root[x] != root[y]) { 135 | return -1; 136 | } 137 | while (head[x] != head[y]) { 138 | if (depth[head[x]] > depth[head[y]]) { 139 | x = pv[head[x]]; 140 | } else { 141 | y = pv[head[y]]; 142 | } 143 | } 144 | return depth[x] < depth[y] ? x : y; 145 | } 146 | }; 147 | -------------------------------------------------------------------------------- /graph/hld_forest_old.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class hld_forest_old : public lca_forest { 3 | public: 4 | using lca_forest::edges; 5 | using lca_forest::g; 6 | using lca_forest::n; 7 | using lca_forest::pv; 8 | using lca_forest::sz; 9 | using lca_forest::pos; 10 | using lca_forest::order; 11 | using lca_forest::depth; 12 | using lca_forest::dfs; 13 | using lca_forest::dfs_all; 14 | using lca_forest::lca; 15 | using lca_forest::build_lca; 16 | 17 | vector head; 18 | vector visited; 19 | 20 | hld_forest_old(int _n) : lca_forest(_n) { 21 | visited.resize(n); 22 | } 23 | 24 | void build_hld(const vector &vs) { 25 | for (int tries = 0; tries < 2; tries++) { 26 | if (vs.empty()) { 27 | dfs_all(); 28 | } else { 29 | order.clear(); 30 | for (int v : vs) { 31 | dfs(v, false); 32 | } 33 | assert((int) order.size() == n); 34 | } 35 | if (tries == 1) { 36 | break; 37 | } 38 | for (int i = 0; i < n; i++) { 39 | if (g[i].empty()) { 40 | continue; 41 | } 42 | int best = -1, bid = 0; 43 | for (int j = 0; j < (int) g[i].size(); j++) { 44 | int id = g[i][j]; 45 | int v = edges[id].from ^ edges[id].to ^ i; 46 | if (pv[v] != i) { 47 | continue; 48 | } 49 | if (sz[v] > best) { 50 | best = sz[v]; 51 | bid = j; 52 | } 53 | } 54 | swap(g[i][0], g[i][bid]); 55 | } 56 | } 57 | build_lca(); 58 | head.resize(n); 59 | for (int i = 0; i < n; i++) { 60 | head[i] = i; 61 | } 62 | for (int i = 0; i < n - 1; i++) { 63 | int x = order[i]; 64 | int y = order[i + 1]; 65 | if (pv[y] == x) { 66 | head[y] = head[x]; 67 | } 68 | } 69 | } 70 | 71 | void build_hld(int v) { 72 | build_hld(vector(1, v)); 73 | } 74 | 75 | void build_hld_all() { 76 | build_hld(vector()); 77 | } 78 | 79 | bool apply_on_path(int x, int y, bool with_lca, function f) { 80 | // f(x, y, up): up -- whether this part of the path goes up 81 | assert(!head.empty()); 82 | int z = lca(x, y); 83 | if (z == -1) { 84 | return false; 85 | } 86 | { 87 | int v = x; 88 | while (v != z) { 89 | if (depth[head[v]] <= depth[z]) { 90 | f(pos[z] + 1, pos[v], true); 91 | break; 92 | } 93 | f(pos[head[v]], pos[v], true); 94 | v = pv[head[v]]; 95 | } 96 | } 97 | if (with_lca) { 98 | f(pos[z], pos[z], false); 99 | } 100 | { 101 | int v = y; 102 | int cnt_visited = 0; 103 | while (v != z) { 104 | if (depth[head[v]] <= depth[z]) { 105 | f(pos[z] + 1, pos[v], false); 106 | break; 107 | } 108 | visited[cnt_visited++] = v; 109 | v = pv[head[v]]; 110 | } 111 | for (int at = cnt_visited - 1; at >= 0; at--) { 112 | v = visited[at]; 113 | f(pos[head[v]], pos[v], false); 114 | } 115 | } 116 | return true; 117 | } 118 | }; 119 | -------------------------------------------------------------------------------- /graph/lca_forest.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class lca_forest : public dfs_forest { 3 | public: 4 | using dfs_forest::edges; 5 | using dfs_forest::g; 6 | using dfs_forest::n; 7 | using dfs_forest::pv; 8 | using dfs_forest::pos; 9 | using dfs_forest::end; 10 | using dfs_forest::depth; 11 | 12 | int h; 13 | vector> pr; 14 | 15 | lca_forest(int _n) : dfs_forest(_n) { 16 | } 17 | 18 | inline void build_lca() { 19 | assert(!pv.empty()); 20 | int max_depth = 0; 21 | for (int i = 0; i < n; i++) { 22 | max_depth = max(max_depth, depth[i]); 23 | } 24 | h = 1; 25 | while ((1 << h) <= max_depth) { 26 | h++; 27 | } 28 | pr.resize(n); 29 | for (int i = 0; i < n; i++) { 30 | pr[i].resize(h); 31 | pr[i][0] = pv[i]; 32 | } 33 | for (int j = 1; j < h; j++) { 34 | for (int i = 0; i < n; i++) { 35 | pr[i][j] = (pr[i][j - 1] == -1 ? -1 : pr[pr[i][j - 1]][j - 1]); 36 | } 37 | } 38 | } 39 | 40 | inline bool anc(int x, int y) { 41 | return (pos[x] <= pos[y] && end[y] <= end[x]); 42 | } 43 | 44 | inline int go_up(int x, int up) { 45 | assert(!pr.empty()); 46 | up = min(up, (1 << h) - 1); 47 | for (int j = h - 1; j >= 0; j--) { 48 | if (up & (1 << j)) { 49 | x = pr[x][j]; 50 | if (x == -1) { 51 | break; 52 | } 53 | } 54 | } 55 | return x; 56 | } 57 | 58 | inline int lca(int x, int y) { 59 | assert(!pr.empty()); 60 | if (anc(x, y)) { 61 | return x; 62 | } 63 | if (anc(y, x)) { 64 | return y; 65 | } 66 | for (int j = h - 1; j >= 0; j--) { 67 | if (pr[x][j] != -1 && !anc(pr[x][j], y)) { 68 | x = pr[x][j]; 69 | } 70 | } 71 | return pr[x][0]; 72 | } 73 | }; 74 | -------------------------------------------------------------------------------- /graph/mst.cpp: -------------------------------------------------------------------------------- 1 | template 2 | vector find_mst(const undigraph &g, T &ans) { 3 | vector order(g.edges.size()); 4 | iota(order.begin(), order.end(), 0); 5 | sort(order.begin(), order.end(), [&g](int a, int b) { 6 | return g.edges[a].cost < g.edges[b].cost; 7 | }); 8 | dsu d(g.n); 9 | vector ans_list; 10 | ans = 0; 11 | for (int id : order) { 12 | auto &e = g.edges[id]; 13 | if (d.get(e.from) != d.get(e.to)) { 14 | d.unite(e.from, e.to); 15 | ans_list.push_back(id); 16 | ans += e.cost; 17 | } 18 | } 19 | return ans_list; 20 | // returns edge ids of minimum "spanning" forest 21 | } 22 | -------------------------------------------------------------------------------- /graph/scc.cpp: -------------------------------------------------------------------------------- 1 | template 2 | vector find_scc(const digraph &g, int &cnt) { 3 | digraph g_rev = g.reverse(); 4 | vector order; 5 | vector was(g.n, false); 6 | function dfs1 = [&](int v) { 7 | was[v] = true; 8 | for (int id : g.g[v]) { 9 | auto &e = g.edges[id]; 10 | int to = e.to; 11 | if (!was[to]) { 12 | dfs1(to); 13 | } 14 | } 15 | order.push_back(v); 16 | }; 17 | for (int i = 0; i < g.n; i++) { 18 | if (!was[i]) { 19 | dfs1(i); 20 | } 21 | } 22 | vector c(g.n, -1); 23 | function dfs2 = [&](int v) { 24 | for (int id : g_rev.g[v]) { 25 | auto &e = g_rev.edges[id]; 26 | int to = e.to; 27 | if (c[to] == -1) { 28 | c[to] = c[v]; 29 | dfs2(to); 30 | } 31 | } 32 | }; 33 | cnt = 0; 34 | for (int id = g.n - 1; id >= 0; id--) { 35 | int i = order[id]; 36 | if (c[i] != -1) { 37 | continue; 38 | } 39 | c[i] = cnt++; 40 | dfs2(i); 41 | } 42 | return c; 43 | // c[i] <= c[j] for every edge i -> j 44 | } 45 | -------------------------------------------------------------------------------- /graph/topsort.cpp: -------------------------------------------------------------------------------- 1 | template 2 | vector find_topsort(const digraph &g) { 3 | vector deg(g.n, 0); 4 | for (int id = 0; id < (int) g.edges.size(); id++) { 5 | deg[g.edges[id].to]++; 6 | } 7 | vector x; 8 | for (int i = 0; i < g.n; i++) { 9 | if (deg[i] == 0) { 10 | x.push_back(i); 11 | } 12 | } 13 | for (int ptr = 0; ptr < (int) x.size(); ptr++) { 14 | int i = x[ptr]; 15 | for (int id : g.g[i]) { 16 | auto &e = g.edges[id]; 17 | int to = e.to; 18 | if (--deg[to] == 0) { 19 | x.push_back(to); 20 | } 21 | } 22 | } 23 | if ((int) x.size() != g.n) { 24 | return vector(); 25 | } 26 | return x; 27 | } 28 | -------------------------------------------------------------------------------- /graph/tree_dp.cpp: -------------------------------------------------------------------------------- 1 | struct Data { 2 | ${0}... a = ...; 3 | }; 4 | auto Unite = [&](const Data& a, const Data& b) -> Data { 5 | return ...; 6 | }; 7 | auto AddVertex = [&](const Data& a, int v) -> Data { 8 | return ...; 9 | }; 10 | auto MoveUp = [&](const Data& a, int v, int eid) -> Data { 11 | auto& e = g.edges[eid]; 12 | return ...; 13 | }; 14 | g.dfs(0); 15 | vector down(g.n); 16 | vector up(g.n); 17 | vector dp(g.n); 18 | { 19 | for (int it = g.n - 1; it >= 0; it--) { 20 | int i = g.order[it]; 21 | for (int eid : g.g[i]) { 22 | auto& e = g.edges[eid]; 23 | int to = e.from ^ e.to ^ i; 24 | if (to == g.pv[i]) { 25 | continue; 26 | } 27 | down[i] = Unite(down[i], MoveUp(down[to], i, eid)); 28 | } 29 | down[i] = AddVertex(down[i], i); 30 | } 31 | for (int it = 0; it < g.n; it++) { 32 | int i = g.order[it]; 33 | vector children; 34 | vector vals; 35 | for (int eid : g.g[i]) { 36 | auto& e = g.edges[eid]; 37 | int to = e.from ^ e.to ^ i; 38 | if (to == g.pv[i]) { 39 | continue; 40 | } 41 | children.push_back(to); 42 | vals.push_back(MoveUp(down[to], i, eid)); 43 | } 44 | vector suf(vals.size() + 1); 45 | for (int j = int(vals.size()) - 1; j >= 0; j--) { 46 | suf[j] = Unite(vals[j], suf[j + 1]); 47 | } 48 | Data pref; 49 | if (g.pv[i] != -1) { 50 | pref = MoveUp(up[i], i, g.pe[i]); 51 | } 52 | for (int j = 0; j < int(vals.size()); j++) { 53 | up[children[j]] = AddVertex(Unite(pref, suf[j + 1]), i); 54 | pref = Unite(pref, vals[j]); 55 | } 56 | dp[i] = AddVertex(pref, i); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /graph/twosat.cpp: -------------------------------------------------------------------------------- 1 | class twosat { 2 | public: 3 | digraph g; 4 | int n; 5 | 6 | twosat(int _n) : g(digraph(2 * _n)), n(_n) { 7 | } 8 | 9 | // (v[x] == value_x) 10 | inline void add(int x, int value_x) { 11 | assert(0 <= x && x < n); 12 | assert(0 <= value_x && value_x <= 1); 13 | g.add(2 * x + (value_x ^ 1), 2 * x + value_x); 14 | } 15 | 16 | // (v[x] == value_x || v[y] == value_y) 17 | inline void add(int x, int value_x, int y, int value_y) { 18 | assert(0 <= x && x < n && 0 <= y && y < n); 19 | assert(0 <= value_x && value_x <= 1 && 0 <= value_y && value_y <= 1); 20 | g.add(2 * x + (value_x ^ 1), 2 * y + value_y); 21 | g.add(2 * y + (value_y ^ 1), 2 * x + value_x); 22 | } 23 | 24 | inline vector solve() { 25 | int cnt; 26 | vector c = find_scc(g, cnt); 27 | vector res(n); 28 | for (int i = 0; i < n; i++) { 29 | if (c[2 * i] == c[2 * i + 1]) { 30 | return vector(); 31 | } 32 | res[i] = (c[2 * i] < c[2 * i + 1]); 33 | } 34 | return res; 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /graph/undigraph.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class undigraph : public graph { 3 | public: 4 | using graph::edges; 5 | using graph::g; 6 | using graph::n; 7 | 8 | undigraph(int _n) : graph(_n) { 9 | } 10 | 11 | int add(int from, int to, T cost = 1) { 12 | assert(0 <= from && from < n && 0 <= to && to < n); 13 | int id = (int) edges.size(); 14 | g[from].push_back(id); 15 | g[to].push_back(id); 16 | edges.push_back({from, to, cost}); 17 | return id; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /keybindings.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "key": "ctrl+n", 4 | "command": "explorer.newFile" 5 | }, 6 | { 7 | "key": "ctrl+shift+n", 8 | "command": "explorer.newFolder" 9 | }, 10 | { 11 | "key": "ctrl+shift+c", 12 | "command": "copyFilePath", 13 | }, 14 | { 15 | "key": "ctrl+tab", 16 | "command": "workbench.action.nextEditor" 17 | }, 18 | { 19 | "key": "ctrl+shift+tab", 20 | "command": "workbench.action.previousEditor" 21 | }, 22 | { 23 | "key": "ctrl+y", 24 | "command": "editor.action.deleteLines" 25 | }, 26 | { 27 | "key": "ctrl+m", 28 | "command": "-editor.action.toggleTabFocusMode" 29 | }, 30 | { 31 | "key": "home", 32 | "command": "cursorLineStart", 33 | "when": "editorTextFocus" 34 | }, 35 | { 36 | "key": "ctrl+pageUp", 37 | "command": "cursorTop", 38 | "when": "editorTextFocus", 39 | }, 40 | { 41 | "key": "ctrl+pageDown", 42 | "command": "cursorBottom", 43 | "when": "editorTextFocus", 44 | }, 45 | { 46 | "key": "ctrl+`", 47 | "command": "workbench.action.terminal.toggleTerminal", 48 | "when": "terminalFocus" 49 | }, 50 | { 51 | "key": "ctrl+`", 52 | "command": "runCommands", 53 | "when": "editorTextFocus", 54 | "args": { 55 | "commands": [ 56 | "workbench.action.terminal.focus", 57 | { 58 | "command": "workbench.action.terminal.sendSequence", 59 | "args": { 60 | "text": "\u0003cd \"${fileDirname}\"\u000D" 61 | } 62 | } 63 | ] 64 | } 65 | }, 66 | { 67 | "key": "ctrl+enter", 68 | "command": "runCommands", 69 | "args": { 70 | "commands": [ 71 | "workbench.action.terminal.focus", 72 | { 73 | "command": "workbench.action.terminal.sendSequence", 74 | "args": { 75 | "text": "\u0003cd \"${fileDirname}\" && g++ ${fileBasename} -o ${fileBasenameNoExtension}.exe -O2 -Wall -Wl,--stack=536870912 -Wextra -std=c++20 -pedantic -Wshadow -Wformat=2 -Wfloat-equal -Wconversion -Wlogical-op -Wshift-overflow=2 -Wduplicated-cond -Wcast-qual -Wcast-align -D_GLIBCXX_DEBUG -fmax-errors=1 -DLOCAL\u000D" 76 | } 77 | } 78 | ] 79 | } 80 | }, 81 | { 82 | "key": "ctrl+.", 83 | "command": "runCommands", 84 | "args": { 85 | "commands": [ 86 | "workbench.action.terminal.focus", 87 | { 88 | "command": "workbench.action.terminal.sendSequence", 89 | "args": { 90 | "text": "\u0003cd \"${fileDirname}\" && wsl g++ ${fileBasename} -o ${fileBasenameNoExtension}.lxe -g -std=c++17 -D_GLIBCXX_DEBUG && wsl gdb ${fileBasenameNoExtension}.lxe\u000D" 91 | } 92 | } 93 | ] 94 | } 95 | }, 96 | ] 97 | -------------------------------------------------------------------------------- /misc/debug.cpp: -------------------------------------------------------------------------------- 1 | template 2 | string to_string(pair p); 3 | 4 | template 5 | string to_string(tuple p); 6 | 7 | template 8 | string to_string(tuple p); 9 | 10 | string to_string(const string& s) { 11 | return '"' + s + '"'; 12 | } 13 | 14 | string to_string(const char* s) { 15 | return to_string((string) s); 16 | } 17 | 18 | string to_string(bool b) { 19 | return (b ? "true" : "false"); 20 | } 21 | 22 | string to_string(vector v) { 23 | bool first = true; 24 | string res = "{"; 25 | for (int i = 0; i < static_cast(v.size()); i++) { 26 | if (!first) { 27 | res += ", "; 28 | } 29 | first = false; 30 | res += to_string(v[i]); 31 | } 32 | res += "}"; 33 | return res; 34 | } 35 | 36 | template 37 | string to_string(bitset v) { 38 | string res = ""; 39 | for (size_t i = 0; i < N; i++) { 40 | res += static_cast('0' + v[i]); 41 | } 42 | return res; 43 | } 44 | 45 | template 46 | string to_string(A v) { 47 | bool first = true; 48 | string res = "{"; 49 | for (const auto &x : v) { 50 | if (!first) { 51 | res += ", "; 52 | } 53 | first = false; 54 | res += to_string(x); 55 | } 56 | res += "}"; 57 | return res; 58 | } 59 | 60 | template 61 | string to_string(pair p) { 62 | return "(" + to_string(p.first) + ", " + to_string(p.second) + ")"; 63 | } 64 | 65 | template 66 | string to_string(tuple p) { 67 | return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ")"; 68 | } 69 | 70 | template 71 | string to_string(tuple p) { 72 | return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ", " + to_string(get<3>(p)) + ")"; 73 | } 74 | 75 | void debug_out() { cerr << endl; } 76 | 77 | template 78 | void debug_out(Head H, Tail... T) { 79 | cerr << " " << to_string(H); 80 | debug_out(T...); 81 | } 82 | 83 | #ifdef LOCAL 84 | #define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__) 85 | #else 86 | #define debug(...) 42 87 | #endif 88 | -------------------------------------------------------------------------------- /misc/fastinput.cpp: -------------------------------------------------------------------------------- 1 | static struct FastInput { 2 | static constexpr int BUF_SIZE = 1 << 20; 3 | char buf[BUF_SIZE]; 4 | size_t chars_read = 0; 5 | size_t buf_pos = 0; 6 | FILE *in = stdin; 7 | char cur = 0; 8 | 9 | inline char get_char() { 10 | if (buf_pos >= chars_read) { 11 | chars_read = fread(buf, 1, BUF_SIZE, in); 12 | buf_pos = 0; 13 | buf[0] = (chars_read == 0 ? -1 : buf[0]); 14 | } 15 | return cur = buf[buf_pos++]; 16 | } 17 | 18 | inline void tie(int) {} 19 | 20 | inline explicit operator bool() { 21 | return cur != -1; 22 | } 23 | 24 | inline static bool is_blank(char c) { 25 | return c <= ' '; 26 | } 27 | 28 | inline bool skip_blanks() { 29 | while (is_blank(cur) && cur != -1) { 30 | get_char(); 31 | } 32 | return cur != -1; 33 | } 34 | 35 | inline FastInput& operator>>(char& c) { 36 | skip_blanks(); 37 | c = cur; 38 | return *this; 39 | } 40 | 41 | inline FastInput& operator>>(string& s) { 42 | if (skip_blanks()) { 43 | s.clear(); 44 | do { 45 | s += cur; 46 | } while (!is_blank(get_char())); 47 | } 48 | return *this; 49 | } 50 | 51 | template 52 | inline FastInput& read_integer(T& n) { 53 | // unsafe, doesn't check that characters are actually digits 54 | n = 0; 55 | if (skip_blanks()) { 56 | int sign = +1; 57 | if (cur == '-') { 58 | sign = -1; 59 | get_char(); 60 | } 61 | do { 62 | n += n + (n << 3) + cur - '0'; 63 | } while (!is_blank(get_char())); 64 | n *= sign; 65 | } 66 | return *this; 67 | } 68 | 69 | template 70 | inline typename enable_if::value, FastInput&>::type operator>>(T& n) { 71 | return read_integer(n); 72 | } 73 | 74 | #if !defined(_WIN32) || defined(_WIN64) 75 | inline FastInput& operator>>(__int128& n) { 76 | return read_integer(n); 77 | } 78 | #endif 79 | 80 | template 81 | inline typename enable_if::value, FastInput&>::type operator>>(T& n) { 82 | // not sure if really fast, for compatibility only 83 | n = 0; 84 | if (skip_blanks()) { 85 | string s; 86 | (*this) >> s; 87 | sscanf(s.c_str(), "%lf", &n); 88 | } 89 | return *this; 90 | } 91 | } fast_input; 92 | 93 | #define cin fast_input 94 | -------------------------------------------------------------------------------- /misc/fastoutput.cpp: -------------------------------------------------------------------------------- 1 | static struct FastOutput { 2 | static constexpr int BUF_SIZE = 1 << 20; 3 | char buf[BUF_SIZE]; 4 | size_t buf_pos = 0; 5 | static constexpr int TMP_SIZE = 1 << 20; 6 | char tmp[TMP_SIZE]; 7 | FILE *out = stdout; 8 | 9 | inline void put_char(char c) { 10 | buf[buf_pos++] = c; 11 | if (buf_pos == BUF_SIZE) { 12 | fwrite(buf, 1, buf_pos, out); 13 | buf_pos = 0; 14 | } 15 | } 16 | 17 | ~FastOutput() { 18 | fwrite(buf, 1, buf_pos, out); 19 | } 20 | 21 | inline FastOutput& operator<<(char c) { 22 | put_char(c); 23 | return *this; 24 | } 25 | 26 | inline FastOutput& operator<<(const char* s) { 27 | while (*s) { 28 | put_char(*s++); 29 | } 30 | return *this; 31 | } 32 | 33 | inline FastOutput& operator<<(const string& s) { 34 | for (int i = 0; i < (int) s.size(); i++) { 35 | put_char(s[i]); 36 | } 37 | return *this; 38 | } 39 | 40 | template 41 | inline char* integer_to_string(T n) { 42 | // beware of TMP_SIZE 43 | char* p = tmp + TMP_SIZE - 1; 44 | if (n == 0) { 45 | *--p = '0'; 46 | } else { 47 | bool is_negative = false; 48 | if (n < 0) { 49 | is_negative = true; 50 | n = -n; 51 | } 52 | while (n > 0) { 53 | *--p = (char) ('0' + n % 10); 54 | n /= 10; 55 | } 56 | if (is_negative) { 57 | *--p = '-'; 58 | } 59 | } 60 | return p; 61 | } 62 | 63 | template 64 | inline typename enable_if::value, char*>::type stringify(T n) { 65 | return integer_to_string(n); 66 | } 67 | 68 | #if !defined(_WIN32) || defined(_WIN64) 69 | inline char* stringify(__int128 n) { 70 | return integer_to_string(n); 71 | } 72 | #endif 73 | 74 | template 75 | inline typename enable_if::value, char*>::type stringify(T n) { 76 | sprintf(tmp, "%.17f", n); 77 | return tmp; 78 | } 79 | 80 | template 81 | inline FastOutput& operator<<(const T& n) { 82 | auto p = stringify(n); 83 | for (; *p != 0; p++) { 84 | put_char(*p); 85 | } 86 | return *this; 87 | } 88 | } fast_output; 89 | 90 | #define cout fast_output 91 | -------------------------------------------------------------------------------- /misc/lis.cpp: -------------------------------------------------------------------------------- 1 | template 2 | int lis(const vector& a) { 3 | vector u; 4 | for (const T& x : a) { 5 | auto it = lower_bound(u.begin(), u.end(), x); 6 | if (it == u.end()) { 7 | u.push_back(x); 8 | } else { 9 | *it = x; 10 | } 11 | } 12 | return (int) u.size(); 13 | } -------------------------------------------------------------------------------- /misc/pragma.cpp: -------------------------------------------------------------------------------- 1 | #pragma GCC optimize("O3,unroll-loops") 2 | // #pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt") 3 | -------------------------------------------------------------------------------- /misc/radix.cpp: -------------------------------------------------------------------------------- 1 | namespace radix { 2 | 3 | vector p(65537); 4 | 5 | template 6 | void SortShift(vector& a, vector& new_a, int shift) { 7 | assert(a.size() == new_a.size()); 8 | int n = static_cast(a.size()); 9 | fill(p.begin(), p.end(), 0); 10 | for (int i = 0; i < n; i++) p[1 + ((a[i] >> shift) & 0xffff)]++; 11 | for (int i = 1; i <= 65536; i++) p[i] += p[i - 1]; 12 | for (int i = 0; i < n; i++) new_a[p[(a[i] >> shift) & 0xffff]++] = a[i]; 13 | } 14 | 15 | void Sort(vector& a) { 16 | constexpr int32_t flip = static_cast(1) << 31; 17 | for (auto& aa : a) aa ^= flip; 18 | vector b(a.size()); 19 | SortShift(a, b, 0); 20 | SortShift(b, a, 16); 21 | for (auto& aa : a) aa ^= flip; 22 | } 23 | 24 | void Sort(vector& a) { 25 | vector b(a.size()); 26 | SortShift(a, b, 0); 27 | SortShift(b, a, 16); 28 | } 29 | 30 | void Sort(vector& a) { 31 | constexpr int64_t flip = static_cast(1) << 63; 32 | for (auto& aa : a) aa ^= flip; 33 | vector b(a.size()); 34 | SortShift(a, b, 0); 35 | SortShift(b, a, 16); 36 | SortShift(a, b, 32); 37 | SortShift(b, a, 48); 38 | for (auto& aa : a) aa ^= flip; 39 | } 40 | 41 | void Sort(vector& a) { 42 | vector b(a.size()); 43 | SortShift(a, b, 0); 44 | SortShift(b, a, 16); 45 | SortShift(a, b, 32); 46 | SortShift(b, a, 48); 47 | } 48 | 49 | } // namespace radix -------------------------------------------------------------------------------- /misc/rng.cpp: -------------------------------------------------------------------------------- 1 | mt19937_64 rng((unsigned int) chrono::steady_clock::now().time_since_epoch().count()); 2 | -------------------------------------------------------------------------------- /numeric/bm.cpp: -------------------------------------------------------------------------------- 1 | template 2 | vector BM(vector a) { 3 | vector p = {1}; 4 | vector q = {1}; 5 | int l = 0; 6 | for (int r = 1; r <= (int) a.size(); r++) { 7 | T delta = 0; 8 | for (int j = 0; j <= l; j++) { 9 | delta += a[r - 1 - j] * p[j]; 10 | } 11 | q.insert(q.begin(), 0); 12 | if (delta != 0) { 13 | vector t = p; 14 | if (q.size() > t.size()) { 15 | t.resize(q.size()); 16 | } 17 | for (int i = 0; i < (int) q.size(); i++) { 18 | t[i] -= delta * q[i]; 19 | } 20 | if (2 * l <= r - 1) { 21 | q = p; 22 | T od = 1 / delta; 23 | for (T& x : q) { 24 | x *= od; 25 | } 26 | l = r - l; 27 | } 28 | swap(p, t); 29 | } 30 | } 31 | assert((int) p.size() == l + 1); 32 | // assert(l * 2 + 30 < (int) a.size()); 33 | reverse(p.begin(), p.end()); 34 | return p; 35 | } -------------------------------------------------------------------------------- /numeric/extgcd.cpp: -------------------------------------------------------------------------------- 1 | template 2 | T extgcd(T a, T b, T &x, T &y) { 3 | if (a == 0) { 4 | x = 0; 5 | y = 1; 6 | return b; 7 | } 8 | T p = b / a; 9 | T g = extgcd(b - p * a, a, y, x); 10 | x -= p * y; 11 | return g; 12 | } 13 | 14 | template 15 | bool diophantine(T a, T b, T c, T &x, T &y, T &g) { 16 | if (a == 0 && b == 0) { 17 | if (c == 0) { 18 | x = y = g = 0; 19 | return true; 20 | } 21 | return false; 22 | } 23 | if (a == 0) { 24 | if (c % b == 0) { 25 | x = 0; 26 | y = c / b; 27 | g = abs(b); 28 | return true; 29 | } 30 | return false; 31 | } 32 | if (b == 0) { 33 | if (c % a == 0) { 34 | x = c / a; 35 | y = 0; 36 | g = abs(a); 37 | return true; 38 | } 39 | return false; 40 | } 41 | g = extgcd(a, b, x, y); 42 | if (c % g != 0) { 43 | return false; 44 | } 45 | T dx = c / a; 46 | c -= dx * a; 47 | T dy = c / b; 48 | c -= dy * b; 49 | x = dx + (T) ((__int128) x * (c / g) % b); 50 | y = dy + (T) ((__int128) y * (c / g) % a); 51 | g = abs(g); 52 | return true; 53 | // |x|, |y| <= max(|a|, |b|, |c|) [tested] 54 | } 55 | 56 | bool crt(int64_t k1, int64_t m1, int64_t k2, int64_t m2, int64_t &k, int64_t &m) { 57 | k1 %= m1; 58 | if (k1 < 0) k1 += m1; 59 | k2 %= m2; 60 | if (k2 < 0) k2 += m2; 61 | int64_t x, y, g; 62 | if (!diophantine(m1, -m2, k2 - k1, x, y, g)) { 63 | return false; 64 | } 65 | int64_t dx = m2 / g; 66 | int64_t delta = x / dx - (x % dx < 0); 67 | k = m1 * (x - dx * delta) + k1; 68 | m = m1 / g * m2; 69 | assert(0 <= k && k < m); 70 | return true; 71 | } 72 | 73 | // for distinct prime modulos 74 | template 75 | void crt_garner(const vector& p, const vector& a, T& res) { 76 | assert(p.size() == a.size()); 77 | auto inverse = [&](int q, int m) { 78 | q %= m; 79 | if (q < 0) q += m; 80 | int b = m, u = 0, v = 1; 81 | while (q) { 82 | int t = b / q; 83 | b -= t * q; swap(q, b); 84 | u -= t * v; swap(u, v); 85 | } 86 | assert(b == 1); 87 | if (u < 0) u += m; 88 | return u; 89 | }; 90 | vector x(p.size()); 91 | for (int i = 0; i < (int) p.size(); i++) { 92 | assert(0 <= a[i] && a[i] < p[i]); 93 | x[i] = a[i]; 94 | for (int j = 0; j < i; j++) { 95 | x[i] = int(int64_t(x[i] - x[j]) * inverse(p[j], p[i]) % p[i]); 96 | if (x[i] < 0) x[i] += p[i]; 97 | } 98 | } 99 | res = 0; 100 | for (int i = (int) p.size() - 1; i >= 0; i--) { 101 | res = res * p[i] + x[i]; 102 | } 103 | } -------------------------------------------------------------------------------- /numeric/factorizer.cpp: -------------------------------------------------------------------------------- 1 | namespace factorizer { 2 | 3 | template 4 | struct FactorizerVarMod { static T value; }; 5 | template 6 | T FactorizerVarMod::value; 7 | 8 | template 9 | bool IsPrime(T n, const vector& bases) { 10 | if (n < 2) { 11 | return false; 12 | } 13 | vector small_primes = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29}; 14 | for (const T& x : small_primes) { 15 | if (n % x == 0) { 16 | return n == x; 17 | } 18 | } 19 | if (n < 31 * 31) { 20 | return true; 21 | } 22 | int s = 0; 23 | T d = n - 1; 24 | while ((d & 1) == 0) { 25 | d >>= 1; 26 | s++; 27 | } 28 | FactorizerVarMod::value = n; 29 | for (const T& a : bases) { 30 | if (a % n == 0) { 31 | continue; 32 | } 33 | Modular> cur = a; 34 | cur = power(cur, d); 35 | if (cur == 1) { 36 | continue; 37 | } 38 | bool witness = true; 39 | for (int r = 0; r < s; r++) { 40 | if (cur == n - 1) { 41 | witness = false; 42 | break; 43 | } 44 | cur *= cur; 45 | } 46 | if (witness) { 47 | return false; 48 | } 49 | } 50 | return true; 51 | } 52 | 53 | bool IsPrime(int64_t n) { 54 | return IsPrime(n, {2, 325, 9375, 28178, 450775, 9780504, 1795265022}); 55 | } 56 | 57 | bool IsPrime(int32_t n) { 58 | return IsPrime(n, {2, 7, 61}); 59 | } 60 | 61 | // but if you really need uint64_t version... 62 | /* 63 | bool IsPrime(uint64_t n) { 64 | if (n < 2) { 65 | return false; 66 | } 67 | vector small_primes = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29}; 68 | for (uint32_t x : small_primes) { 69 | if (n == x) { 70 | return true; 71 | } 72 | if (n % x == 0) { 73 | return false; 74 | } 75 | } 76 | if (n < 31 * 31) { 77 | return true; 78 | } 79 | uint32_t s = __builtin_ctzll(n - 1); 80 | uint64_t d = (n - 1) >> s; 81 | function witness = [&n, &s, &d](uint64_t a) { 82 | uint64_t cur = 1, p = d; 83 | while (p > 0) { 84 | if (p & 1) { 85 | cur = (__uint128_t) cur * a % n; 86 | } 87 | a = (__uint128_t) a * a % n; 88 | p >>= 1; 89 | } 90 | if (cur == 1) { 91 | return false; 92 | } 93 | for (uint32_t r = 0; r < s; r++) { 94 | if (cur == n - 1) { 95 | return false; 96 | } 97 | cur = (__uint128_t) cur * cur % n; 98 | } 99 | return true; 100 | }; 101 | vector bases_64bit = {2, 325, 9375, 28178, 450775, 9780504, 1795265022}; 102 | for (uint64_t a : bases_64bit) { 103 | if (a % n == 0) { 104 | return true; 105 | } 106 | if (witness(a)) { 107 | return false; 108 | } 109 | } 110 | return true; 111 | } 112 | */ 113 | 114 | vector least = {0, 1}; 115 | vector primes; 116 | int precalculated = 1; 117 | 118 | void RunLinearSieve(int n) { 119 | n = max(n, 1); 120 | least.assign(n + 1, 0); 121 | primes.clear(); 122 | for (int i = 2; i <= n; i++) { 123 | if (least[i] == 0) { 124 | least[i] = i; 125 | primes.push_back(i); 126 | } 127 | for (int x : primes) { 128 | if (x > least[i] || i * x > n) { 129 | break; 130 | } 131 | least[i * x] = x; 132 | } 133 | } 134 | precalculated = n; 135 | } 136 | 137 | void RunSlowSieve(int n) { 138 | n = max(n, 1); 139 | least.assign(n + 1, 0); 140 | for (int i = 2; i * i <= n; i++) { 141 | if (least[i] == 0) { 142 | for (int j = i * i; j <= n; j += i) { 143 | if (least[j] == 0) { 144 | least[j] = i; 145 | } 146 | } 147 | } 148 | } 149 | primes.clear(); 150 | for (int i = 2; i <= n; i++) { 151 | if (least[i] == 0) { 152 | least[i] = i; 153 | primes.push_back(i); 154 | } 155 | } 156 | precalculated = n; 157 | } 158 | 159 | void RunSieve(int n) { 160 | RunLinearSieve(n); 161 | } 162 | 163 | template 164 | vector> MergeFactors(const vector>& a, const vector>& b) { 165 | vector> c; 166 | int i = 0; 167 | int j = 0; 168 | while (i < (int) a.size() || j < (int) b.size()) { 169 | if (i < (int) a.size() && j < (int) b.size() && a[i].first == b[j].first) { 170 | c.emplace_back(a[i].first, a[i].second + b[j].second); 171 | ++i; 172 | ++j; 173 | continue; 174 | } 175 | if (j == (int) b.size() || (i < (int) a.size() && a[i].first < b[j].first)) { 176 | c.push_back(a[i++]); 177 | } else { 178 | c.push_back(b[j++]); 179 | } 180 | } 181 | return c; 182 | } 183 | 184 | template 185 | vector> RhoC(const T& n, const T& c) { 186 | if (n <= 1) { 187 | return {}; 188 | } 189 | if ((n & 1) == 0) { 190 | return MergeFactors({{2, 1}}, RhoC(n / 2, c)); 191 | } 192 | if (IsPrime(n)) { 193 | return {{n, 1}}; 194 | } 195 | FactorizerVarMod::value = n; 196 | Modular> x = 2; 197 | Modular> saved = 2; 198 | T power = 1; 199 | T lam = 1; 200 | while (true) { 201 | x = x * x + c; 202 | T g = __gcd((x - saved)(), n); 203 | if (g != 1) { 204 | return MergeFactors(RhoC(g, c + 1), RhoC(n / g, c + 1)); 205 | } 206 | if (power == lam) { 207 | saved = x; 208 | power <<= 1; 209 | lam = 0; 210 | } 211 | lam++; 212 | } 213 | return {}; 214 | } 215 | 216 | template 217 | vector> Rho(const T& n) { 218 | return RhoC(n, static_cast(1)); 219 | } 220 | 221 | template 222 | vector> Factorize(T x) { 223 | if (x <= 1) { 224 | return {}; 225 | } 226 | if (x <= precalculated) { 227 | vector> ret; 228 | while (x > 1) { 229 | if (!ret.empty() && ret.back().first == least[x]) { 230 | ret.back().second++; 231 | } else { 232 | ret.emplace_back(least[x], 1); 233 | } 234 | x /= least[x]; 235 | } 236 | return ret; 237 | } 238 | if (x <= static_cast(precalculated) * precalculated) { 239 | vector> ret; 240 | if (!IsPrime(x)) { 241 | for (T i : primes) { 242 | T t = x / i; 243 | if (i > t) { 244 | break; 245 | } 246 | if (x == t * i) { 247 | int cnt = 0; 248 | while (x % i == 0) { 249 | x /= i; 250 | cnt++; 251 | } 252 | ret.emplace_back(i, cnt); 253 | if (IsPrime(x)) { 254 | break; 255 | } 256 | } 257 | } 258 | } 259 | if (x > 1) { 260 | ret.emplace_back(x, 1); 261 | } 262 | return ret; 263 | } 264 | return Rho(x); 265 | } 266 | 267 | template 268 | vector BuildDivisorsFromFactors(const vector>& factors) { 269 | vector divisors = {1}; 270 | for (auto& p : factors) { 271 | int sz = (int) divisors.size(); 272 | for (int i = 0; i < sz; i++) { 273 | T cur = divisors[i]; 274 | for (int j = 0; j < p.second; j++) { 275 | cur *= p.first; 276 | divisors.push_back(cur); 277 | } 278 | } 279 | } 280 | sort(divisors.begin(), divisors.end()); 281 | return divisors; 282 | } 283 | 284 | } // namespace factorizer -------------------------------------------------------------------------------- /numeric/fft.cpp: -------------------------------------------------------------------------------- 1 | // make it understandable one day... 2 | namespace fft { 3 | 4 | typedef double dbl; 5 | 6 | struct num { 7 | dbl x, y; 8 | num() { x = y = 0; } 9 | num(dbl x_, dbl y_) : x(x_), y(y_) {} 10 | }; 11 | 12 | inline num operator+(num a, num b) { return num(a.x + b.x, a.y + b.y); } 13 | inline num operator-(num a, num b) { return num(a.x - b.x, a.y - b.y); } 14 | inline num operator*(num a, num b) { return num(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x); } 15 | inline num conj(num a) { return num(a.x, -a.y); } 16 | 17 | int base = 1; 18 | vector roots = {{0, 0}, {1, 0}}; 19 | vector rev = {0, 1}; 20 | 21 | const dbl PI = static_cast(acosl(-1.0)); 22 | 23 | void ensure_base(int nbase) { 24 | if (nbase <= base) { 25 | return; 26 | } 27 | rev.resize(1 << nbase); 28 | for (int i = 0; i < (1 << nbase); i++) { 29 | rev[i] = (rev[i >> 1] >> 1) + ((i & 1) << (nbase - 1)); 30 | } 31 | roots.resize(1 << nbase); 32 | while (base < nbase) { 33 | dbl angle = 2 * PI / (1 << (base + 1)); 34 | // num z(cos(angle), sin(angle)); 35 | for (int i = 1 << (base - 1); i < (1 << base); i++) { 36 | roots[i << 1] = roots[i]; 37 | // roots[(i << 1) + 1] = roots[i] * z; 38 | dbl angle_i = angle * (2 * i + 1 - (1 << base)); 39 | roots[(i << 1) + 1] = num(cos(angle_i), sin(angle_i)); 40 | } 41 | base++; 42 | } 43 | } 44 | 45 | void fft(vector& a, int n = -1) { 46 | if (n == -1) { 47 | n = (int) a.size(); 48 | } 49 | assert((n & (n - 1)) == 0); 50 | int zeros = __builtin_ctz(n); 51 | ensure_base(zeros); 52 | int shift = base - zeros; 53 | for (int i = 0; i < n; i++) { 54 | if (i < (rev[i] >> shift)) { 55 | swap(a[i], a[rev[i] >> shift]); 56 | } 57 | } 58 | for (int k = 1; k < n; k <<= 1) { 59 | for (int i = 0; i < n; i += 2 * k) { 60 | for (int j = 0; j < k; j++) { 61 | num z = a[i + j + k] * roots[j + k]; 62 | a[i + j + k] = a[i + j] - z; 63 | a[i + j] = a[i + j] + z; 64 | } 65 | } 66 | } 67 | } 68 | 69 | vector fa, fb; 70 | 71 | vector square(const vector& a) { 72 | if (a.empty()) { 73 | return {}; 74 | } 75 | int need = (int) a.size() + (int) a.size() - 1; 76 | int nbase = 1; 77 | while ((1 << nbase) < need) nbase++; 78 | ensure_base(nbase); 79 | int sz = 1 << nbase; 80 | if ((sz >> 1) > (int) fa.size()) { 81 | fa.resize(sz >> 1); 82 | } 83 | for (int i = 0; i < (sz >> 1); i++) { 84 | int x = (2 * i < (int) a.size() ? a[2 * i] : 0); 85 | int y = (2 * i + 1 < (int) a.size() ? a[2 * i + 1] : 0); 86 | fa[i] = num(x, y); 87 | } 88 | fft(fa, sz >> 1); 89 | num r(1.0 / (sz >> 1), 0.0); 90 | for (int i = 0; i <= (sz >> 2); i++) { 91 | int j = ((sz >> 1) - i) & ((sz >> 1) - 1); 92 | num fe = (fa[i] + conj(fa[j])) * num(0.5, 0); 93 | num fo = (fa[i] - conj(fa[j])) * num(0, -0.5); 94 | num aux = fe * fe + fo * fo * roots[(sz >> 1) + i] * roots[(sz >> 1) + i]; 95 | num tmp = fe * fo; 96 | fa[i] = r * (conj(aux) + num(0, 2) * conj(tmp)); 97 | fa[j] = r * (aux + num(0, 2) * tmp); 98 | } 99 | fft(fa, sz >> 1); 100 | vector res(need); 101 | for (int i = 0; i < need; i++) { 102 | res[i] = llround(i % 2 == 0 ? fa[i >> 1].x : fa[i >> 1].y); 103 | } 104 | return res; 105 | } 106 | 107 | vector multiply(const vector& a, const vector& b) { 108 | if (a.empty() || b.empty()) { 109 | return {}; 110 | } 111 | if (a == b) { 112 | return square(a); 113 | } 114 | int need = (int) a.size() + (int) b.size() - 1; 115 | int nbase = 1; 116 | while ((1 << nbase) < need) nbase++; 117 | ensure_base(nbase); 118 | int sz = 1 << nbase; 119 | if (sz > (int) fa.size()) { 120 | fa.resize(sz); 121 | } 122 | for (int i = 0; i < sz; i++) { 123 | int x = (i < (int) a.size() ? a[i] : 0); 124 | int y = (i < (int) b.size() ? b[i] : 0); 125 | fa[i] = num(x, y); 126 | } 127 | fft(fa, sz); 128 | num r(0, -0.25 / (sz >> 1)); 129 | for (int i = 0; i <= (sz >> 1); i++) { 130 | int j = (sz - i) & (sz - 1); 131 | num z = (fa[j] * fa[j] - conj(fa[i] * fa[i])) * r; 132 | fa[j] = (fa[i] * fa[i] - conj(fa[j] * fa[j])) * r; 133 | fa[i] = z; 134 | } 135 | for (int i = 0; i < (sz >> 1); i++) { 136 | num A0 = (fa[i] + fa[i + (sz >> 1)]) * num(0.5, 0); 137 | num A1 = (fa[i] - fa[i + (sz >> 1)]) * num(0.5, 0) * roots[(sz >> 1) + i]; 138 | fa[i] = A0 + A1 * num(0, 1); 139 | } 140 | fft(fa, sz >> 1); 141 | vector res(need); 142 | for (int i = 0; i < need; i++) { 143 | res[i] = llround(i % 2 == 0 ? fa[i >> 1].x : fa[i >> 1].y); 144 | } 145 | return res; 146 | } 147 | 148 | vector multiply_mod(const vector& a, const vector& b, int m) { 149 | if (a.empty() || b.empty()) { 150 | return {}; 151 | } 152 | int eq = (a.size() == b.size() && a == b); 153 | int need = (int) a.size() + (int) b.size() - 1; 154 | int nbase = 0; 155 | while ((1 << nbase) < need) nbase++; 156 | ensure_base(nbase); 157 | int sz = 1 << nbase; 158 | if (sz > (int) fa.size()) { 159 | fa.resize(sz); 160 | } 161 | for (int i = 0; i < (int) a.size(); i++) { 162 | int x = (a[i] % m + m) % m; 163 | fa[i] = num(x & ((1 << 15) - 1), x >> 15); 164 | } 165 | fill(fa.begin() + a.size(), fa.begin() + sz, num {0, 0}); 166 | fft(fa, sz); 167 | if (sz > (int) fb.size()) { 168 | fb.resize(sz); 169 | } 170 | if (eq) { 171 | copy(fa.begin(), fa.begin() + sz, fb.begin()); 172 | } else { 173 | for (int i = 0; i < (int) b.size(); i++) { 174 | int x = (b[i] % m + m) % m; 175 | fb[i] = num(x & ((1 << 15) - 1), x >> 15); 176 | } 177 | fill(fb.begin() + b.size(), fb.begin() + sz, num {0, 0}); 178 | fft(fb, sz); 179 | } 180 | dbl ratio = 0.25 / sz; 181 | num r2(0, -1); 182 | num r3(ratio, 0); 183 | num r4(0, -ratio); 184 | num r5(0, 1); 185 | for (int i = 0; i <= (sz >> 1); i++) { 186 | int j = (sz - i) & (sz - 1); 187 | num a1 = (fa[i] + conj(fa[j])); 188 | num a2 = (fa[i] - conj(fa[j])) * r2; 189 | num b1 = (fb[i] + conj(fb[j])) * r3; 190 | num b2 = (fb[i] - conj(fb[j])) * r4; 191 | if (i != j) { 192 | num c1 = (fa[j] + conj(fa[i])); 193 | num c2 = (fa[j] - conj(fa[i])) * r2; 194 | num d1 = (fb[j] + conj(fb[i])) * r3; 195 | num d2 = (fb[j] - conj(fb[i])) * r4; 196 | fa[i] = c1 * d1 + c2 * d2 * r5; 197 | fb[i] = c1 * d2 + c2 * d1; 198 | } 199 | fa[j] = a1 * b1 + a2 * b2 * r5; 200 | fb[j] = a1 * b2 + a2 * b1; 201 | } 202 | fft(fa, sz); 203 | fft(fb, sz); 204 | vector res(need); 205 | for (int i = 0; i < need; i++) { 206 | int64_t aa = llround(fa[i].x); 207 | int64_t bb = llround(fb[i].x); 208 | int64_t cc = llround(fa[i].y); 209 | res[i] = static_cast((aa + ((bb % m) << 15) + ((cc % m) << 30)) % m); 210 | } 211 | return res; 212 | } 213 | 214 | } // namespace fft 215 | 216 | template 217 | typename enable_if::Type, int>::value, vector>>::type operator*( 218 | const vector>& a, 219 | const vector>& b) { 220 | if (a.empty() || b.empty()) { 221 | return {}; 222 | } 223 | if (min(a.size(), b.size()) < 150) { 224 | vector> c(a.size() + b.size() - 1, 0); 225 | for (int i = 0; i < (int) a.size(); i++) { 226 | for (int j = 0; j < (int) b.size(); j++) { 227 | c[i + j] += a[i] * b[j]; 228 | } 229 | } 230 | return c; 231 | } 232 | vector a_mul(a.size()); 233 | for (int i = 0; i < (int) a.size(); i++) { 234 | a_mul[i] = static_cast(a[i]); 235 | } 236 | vector b_mul(b.size()); 237 | for (int i = 0; i < (int) b.size(); i++) { 238 | b_mul[i] = static_cast(b[i]); 239 | } 240 | vector c_mul = fft::multiply_mod(a_mul, b_mul, T::value); 241 | vector> c(c_mul.size()); 242 | for (int i = 0; i < (int) c.size(); i++) { 243 | c[i] = c_mul[i]; 244 | } 245 | return c; 246 | } 247 | 248 | template 249 | typename enable_if::Type, int>::value, vector>>::type& operator*=( 250 | vector>& a, 251 | const vector>& b) { 252 | return a = a * b; 253 | } -------------------------------------------------------------------------------- /numeric/fwht.cpp: -------------------------------------------------------------------------------- 1 | namespace fwht { 2 | 3 | template 4 | void hadamard(vector &a) { 5 | int n = a.size(); 6 | for (int k = 1; k < n; k <<= 1) { 7 | for (int i = 0; i < n; i += 2 * k) { 8 | for (int j = 0; j < k; j++) { 9 | T x = a[i + j]; 10 | T y = a[i + j + k]; 11 | a[i + j] = x + y; 12 | a[i + j + k] = x - y; 13 | } 14 | } 15 | } 16 | } 17 | 18 | template 19 | vector multiply(vector a, vector b) { 20 | int eq = (a == b); 21 | int n = 1; 22 | while (n < (int) max(a.size(), b.size())) { 23 | n <<= 1; 24 | } 25 | a.resize(n); 26 | b.resize(n); 27 | hadamard(a); 28 | if (eq) b = a; else hadamard(b); 29 | for (int i = 0; i < n; i++) { 30 | a[i] *= b[i]; 31 | } 32 | hadamard(a); 33 | T q = 1 / static_cast(n); 34 | for (int i = 0; i < n; i++) { 35 | a[i] *= q; 36 | } 37 | return a; 38 | } 39 | 40 | } // namespace fwht -------------------------------------------------------------------------------- /numeric/gauss.cpp: -------------------------------------------------------------------------------- 1 | const double eps = 1e-9; 2 | 3 | bool IsZero(double v) { 4 | return abs(v) < 1e-9; 5 | } 6 | 7 | enum GAUSS_MODE { 8 | DEGREE, ABS 9 | }; 10 | 11 | template 12 | void GaussianElimination(vector>& a, int limit, GAUSS_MODE mode = DEGREE) { 13 | if (a.empty() || a[0].empty()) { 14 | return; 15 | } 16 | int h = static_cast(a.size()); 17 | int w = static_cast(a[0].size()); 18 | for (int i = 0; i < h; i++) { 19 | assert(w == static_cast(a[i].size())); 20 | } 21 | assert(limit <= w); 22 | vector deg(h); 23 | for (int i = 0; i < h; i++) { 24 | for (int j = 0; j < w; j++) { 25 | deg[i] += !IsZero(a[i][j]); 26 | } 27 | } 28 | int r = 0; 29 | for (int c = 0; c < limit; c++) { 30 | int id = -1; 31 | for (int i = r; i < h; i++) { 32 | if (!IsZero(a[i][c]) && (id == -1 || (mode == DEGREE && deg[i] < deg[id]) || (mode == ABS && abs(a[id][c]) < abs(a[i][c])))) { 33 | id = i; 34 | } 35 | } 36 | if (id == -1) { 37 | continue; 38 | } 39 | if (id > r) { 40 | swap(a[r], a[id]); 41 | swap(deg[r], deg[id]); 42 | for (int j = c; j < w; j++) { 43 | a[id][j] = -a[id][j]; 44 | } 45 | } 46 | vector nonzero; 47 | for (int j = c; j < w; j++) { 48 | if (!IsZero(a[r][j])) { 49 | nonzero.push_back(j); 50 | } 51 | } 52 | T inv_a = 1 / a[r][c]; 53 | for (int i = r + 1; i < h; i++) { 54 | if (IsZero(a[i][c])) { 55 | continue; 56 | } 57 | T coeff = -a[i][c] * inv_a; 58 | for (int j : nonzero) { 59 | if (!IsZero(a[i][j])) deg[i]--; 60 | a[i][j] += coeff * a[r][j]; 61 | if (!IsZero(a[i][j])) deg[i]++; 62 | } 63 | } 64 | ++r; 65 | } 66 | for (r = h - 1; r >= 0; r--) { 67 | for (int c = 0; c < limit; c++) { 68 | if (!IsZero(a[r][c])) { 69 | T inv_a = 1 / a[r][c]; 70 | for (int i = r - 1; i >= 0; i--) { 71 | if (IsZero(a[i][c])) { 72 | continue; 73 | } 74 | T coeff = -a[i][c] * inv_a; 75 | for (int j = c; j < w; j++) { 76 | a[i][j] += coeff * a[r][j]; 77 | } 78 | } 79 | break; 80 | } 81 | } 82 | } 83 | } 84 | 85 | template 86 | T Determinant(vector>/*&*/ a) { 87 | if (a.empty()) { 88 | return T{1}; 89 | } 90 | assert(a.size() == a[0].size()); 91 | GaussianElimination(a, static_cast(a[0].size())); 92 | T d{1}; 93 | for (int i = 0; i < a.h; i++) { 94 | d *= a[i][i]; 95 | } 96 | return d; 97 | } 98 | 99 | template 100 | int Rank(vector>/*&*/ a) { 101 | if (a.empty()) { 102 | return 0; 103 | } 104 | GaussianElimination(a, static_cast(a[0].size())); 105 | int rank = 0; 106 | for (int i = 0; i < static_cast(a.size()); i++) { 107 | for (int j = 0; j < static_cast(a[i].size()); j++) { 108 | if (!IsZero(a[i][j])) { 109 | ++rank; 110 | break; 111 | } 112 | } 113 | } 114 | return rank; 115 | } 116 | 117 | template 118 | vector SolveLinearSystem(vector>/*&*/ a, const vector& b, int w) { 119 | int h = static_cast(a.size()); 120 | assert(h == static_cast(b.size())); 121 | if (h > 0) { 122 | assert(w == static_cast(a[0].size())); 123 | } 124 | for (int i = 0; i < h; i++) { 125 | a[i].push_back(b[i]); 126 | } 127 | GaussianElimination(a, w); 128 | vector x(w, 0); 129 | for (int i = 0; i < h; i++) { 130 | for (int j = 0; j < w; j++) { 131 | if (!IsZero(a[i][j])) { 132 | x[j] = a[i][w] / a[i][j]; 133 | break; 134 | } 135 | } 136 | } 137 | return x; 138 | } 139 | 140 | template 141 | vector> Inverse(vector>/*&*/ a) { 142 | if (a.empty()) { 143 | return a; 144 | } 145 | int h = static_cast(a.size()); 146 | for (int i = 0; i < h; i++) { 147 | assert(h == static_cast(a[i].size())); 148 | } 149 | for (int i = 0; i < h; i++) { 150 | a[i].resize(2 * h); 151 | a[i][i + h] = 1; 152 | } 153 | GaussianElimination(a, h); 154 | for (int i = 0; i < h; i++) { 155 | if (IsZero(a[i][i])) { 156 | return {{}}; 157 | } 158 | } 159 | vector> b(h); 160 | for (int i = 0; i < h; i++) { 161 | b[i] = vector(a[i].begin() + h, a[i].end()); 162 | T coeff = 1 / a[i][i]; 163 | for (int j = 0; j < h; j++) { 164 | b[i][j] *= coeff; 165 | } 166 | } 167 | return b; 168 | } -------------------------------------------------------------------------------- /numeric/matrix.cpp: -------------------------------------------------------------------------------- 1 | template 2 | array, N> operator*(const array, N>& a, const array, M>& b) { 3 | array, N> c; 4 | for (size_t i = 0; i < N; i++) { 5 | for (size_t j = 0; j < K; j++) { 6 | c[i][j] = 0; 7 | for (size_t k = 0; k < M; k++) { 8 | c[i][j] += a[i][k] * b[k][j]; 9 | } 10 | } 11 | } 12 | return c; 13 | } 14 | 15 | template 16 | vector> operator*(const vector>& a, const vector>& b) { 17 | if (a.empty() || b.empty()) { 18 | return {{}}; 19 | } 20 | vector> c(a.size(), vector(b[0].size())); 21 | for (int i = 0; i < static_cast(c.size()); i++) { 22 | for (int j = 0; j < static_cast(c[0].size()); j++) { 23 | c[i][j] = 0; 24 | for (int k = 0; k < static_cast(b.size()); k++) { 25 | c[i][j] += a[i][k] * b[k][j]; 26 | } 27 | } 28 | } 29 | return c; 30 | } 31 | 32 | template 33 | vector>& operator*=(vector>& a, const vector>& b) { 34 | return a = a * b; 35 | } 36 | 37 | template 38 | vector> power(const vector>& a, const U& b) { 39 | assert(b >= 0); 40 | vector binary; 41 | U bb = b; 42 | while (bb > 0) { 43 | binary.push_back(bb & 1); 44 | bb >>= 1; 45 | } 46 | vector> res(a.size(), vector(a.size())); 47 | for (int i = 0; i < static_cast(a.size()); i++) { 48 | res[i][i] = 1; 49 | } 50 | for (int j = (int) binary.size() - 1; j >= 0; j--) { 51 | res *= res; 52 | if (binary[j] == 1) { 53 | res *= a; 54 | } 55 | } 56 | return res; 57 | } -------------------------------------------------------------------------------- /numeric/mint.cpp: -------------------------------------------------------------------------------- 1 | template 2 | T inverse(T a, T m) { 3 | T u = 0, v = 1; 4 | while (a != 0) { 5 | T t = m / a; 6 | m -= t * a; swap(a, m); 7 | u -= t * v; swap(u, v); 8 | } 9 | assert(m == 1); 10 | return u; 11 | } 12 | 13 | template 14 | class Modular { 15 | public: 16 | using Type = typename decay::type; 17 | 18 | constexpr Modular() : value() {} 19 | template 20 | Modular(const U& x) { 21 | value = normalize(x); 22 | } 23 | 24 | template 25 | static Type normalize(const U& x) { 26 | Type v; 27 | if (-mod() <= x && x < mod()) v = static_cast(x); 28 | else v = static_cast(x % mod()); 29 | if (v < 0) v += mod(); 30 | return v; 31 | } 32 | 33 | const Type& operator()() const { return value; } 34 | template 35 | explicit operator U() const { return static_cast(value); } 36 | constexpr static Type mod() { return T::value; } 37 | 38 | Modular& operator+=(const Modular& other) { value += other.value; value -= (value >= mod()) * mod(); return *this; } 39 | Modular& operator-=(const Modular& other) { value -= other.value; value += (value < 0) * mod(); return *this; } 40 | template Modular& operator+=(const U& other) { return *this += Modular(other); } 41 | template Modular& operator-=(const U& other) { return *this -= Modular(other); } 42 | Modular& operator++() { return *this += 1; } 43 | Modular& operator--() { return *this -= 1; } 44 | Modular operator++(int) { Modular result(*this); *this += 1; return result; } 45 | Modular operator--(int) { Modular result(*this); *this -= 1; return result; } 46 | Modular operator-() const { return Modular(-value); } 47 | 48 | template 49 | typename enable_if::Type, int>::value, Modular>::type& operator*=(const Modular& rhs) { 50 | value = normalize(static_cast(value) * static_cast(rhs.value)); 51 | return *this; 52 | } 53 | template 54 | typename enable_if::Type, int64_t>::value, Modular>::type& operator*=(const Modular& rhs) { 55 | int64_t q = int64_t(static_cast(value) * rhs.value / mod()); 56 | value = normalize(value * rhs.value - q * mod()); 57 | return *this; 58 | } 59 | template 60 | typename enable_if::Type>::value, Modular>::type& operator*=(const Modular& rhs) { 61 | value = normalize(value * rhs.value); 62 | return *this; 63 | } 64 | 65 | Modular& operator/=(const Modular& other) { return *this *= Modular(inverse(other.value, mod())); } 66 | 67 | friend const Type& abs(const Modular& x) { return x.value; } 68 | 69 | template 70 | friend bool operator==(const Modular& lhs, const Modular& rhs); 71 | 72 | template 73 | friend bool operator<(const Modular& lhs, const Modular& rhs); 74 | 75 | template 76 | friend V& operator>>(V& stream, Modular& number); 77 | 78 | private: 79 | Type value; 80 | }; 81 | 82 | template bool operator==(const Modular& lhs, const Modular& rhs) { return lhs.value == rhs.value; } 83 | template bool operator==(const Modular& lhs, U rhs) { return lhs == Modular(rhs); } 84 | template bool operator==(U lhs, const Modular& rhs) { return Modular(lhs) == rhs; } 85 | 86 | template bool operator!=(const Modular& lhs, const Modular& rhs) { return !(lhs == rhs); } 87 | template bool operator!=(const Modular& lhs, U rhs) { return !(lhs == rhs); } 88 | template bool operator!=(U lhs, const Modular& rhs) { return !(lhs == rhs); } 89 | 90 | template bool operator<(const Modular& lhs, const Modular& rhs) { return lhs.value < rhs.value; } 91 | 92 | template Modular operator+(const Modular& lhs, const Modular& rhs) { return Modular(lhs) += rhs; } 93 | template Modular operator+(const Modular& lhs, U rhs) { return Modular(lhs) += rhs; } 94 | template Modular operator+(U lhs, const Modular& rhs) { return Modular(lhs) += rhs; } 95 | 96 | template Modular operator-(const Modular& lhs, const Modular& rhs) { return Modular(lhs) -= rhs; } 97 | template Modular operator-(const Modular& lhs, U rhs) { return Modular(lhs) -= rhs; } 98 | template Modular operator-(U lhs, const Modular& rhs) { return Modular(lhs) -= rhs; } 99 | 100 | template Modular operator*(const Modular& lhs, const Modular& rhs) { return Modular(lhs) *= rhs; } 101 | template Modular operator*(const Modular& lhs, U rhs) { return Modular(lhs) *= rhs; } 102 | template Modular operator*(U lhs, const Modular& rhs) { return Modular(lhs) *= rhs; } 103 | 104 | template Modular operator/(const Modular& lhs, const Modular& rhs) { return Modular(lhs) /= rhs; } 105 | template Modular operator/(const Modular& lhs, U rhs) { return Modular(lhs) /= rhs; } 106 | template Modular operator/(U lhs, const Modular& rhs) { return Modular(lhs) /= rhs; } 107 | 108 | template 109 | Modular power(const Modular& a, const U& b) { 110 | assert(b >= 0); 111 | Modular x = a, res = 1; 112 | U p = b; 113 | while (p > 0) { 114 | if (p & 1) res *= x; 115 | x *= x; 116 | p >>= 1; 117 | } 118 | return res; 119 | } 120 | 121 | template 122 | bool IsZero(const Modular& number) { 123 | return number() == 0; 124 | } 125 | 126 | template 127 | string to_string(const Modular& number) { 128 | return to_string(number()); 129 | } 130 | 131 | // U == std::ostream? but done this way because of fastoutput 132 | template 133 | U& operator<<(U& stream, const Modular& number) { 134 | return stream << number(); 135 | } 136 | 137 | // U == std::istream? but done this way because of fastinput 138 | template 139 | U& operator>>(U& stream, Modular& number) { 140 | typename common_type::Type, int64_t>::type x; 141 | stream >> x; 142 | number.value = Modular::normalize(x); 143 | return stream; 144 | } 145 | 146 | // using ModType = int; 147 | 148 | // struct VarMod { static ModType value; }; 149 | // ModType VarMod::value; 150 | // ModType& md = VarMod::value; 151 | // using Mint = Modular; 152 | 153 | constexpr int md = ${0}; 154 | using Mint = Modular::type, md>>; 155 | 156 | // vector fact(1, 1); 157 | // vector inv_fact(1, 1); 158 | 159 | // Mint C(int n, int k) { 160 | // if (k < 0 || k > n) { 161 | // return 0; 162 | // } 163 | // while ((int) fact.size() < n + 1) { 164 | // fact.push_back(fact.back() * (int) fact.size()); 165 | // inv_fact.push_back(1 / fact.back()); 166 | // } 167 | // return fact[n] * inv_fact[k] * inv_fact[n - k]; 168 | // } 169 | 170 | -------------------------------------------------------------------------------- /numeric/ntt.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class NTT { 3 | public: 4 | using Type = typename decay::type; 5 | 6 | static Type md; 7 | static Modular root; 8 | static int base; 9 | static int max_base; 10 | static vector> roots; 11 | static vector rev; 12 | 13 | static void clear() { 14 | root = 0; 15 | base = 0; 16 | max_base = 0; 17 | roots.clear(); 18 | rev.clear(); 19 | } 20 | 21 | static void init() { 22 | md = T::value; 23 | assert(md >= 3 && md % 2 == 1); 24 | auto tmp = md - 1; 25 | max_base = 0; 26 | while (tmp % 2 == 0) { 27 | tmp /= 2; 28 | max_base++; 29 | } 30 | root = 2; 31 | while (power(root, (md - 1) >> 1) == 1) { 32 | root++; 33 | } 34 | assert(power(root, md - 1) == 1); 35 | root = power(root, (md - 1) >> max_base); 36 | base = 1; 37 | rev = {0, 1}; 38 | roots = {0, 1}; 39 | } 40 | 41 | static void ensure_base(int nbase) { 42 | if (md != T::value) { 43 | clear(); 44 | } 45 | if (roots.empty()) { 46 | init(); 47 | } 48 | if (nbase <= base) { 49 | return; 50 | } 51 | assert(nbase <= max_base); 52 | rev.resize(1 << nbase); 53 | for (int i = 0; i < (1 << nbase); i++) { 54 | rev[i] = (rev[i >> 1] >> 1) + ((i & 1) << (nbase - 1)); 55 | } 56 | roots.resize(1 << nbase); 57 | while (base < nbase) { 58 | Modular z = power(root, 1 << (max_base - 1 - base)); 59 | for (int i = 1 << (base - 1); i < (1 << base); i++) { 60 | roots[i << 1] = roots[i]; 61 | roots[(i << 1) + 1] = roots[i] * z; 62 | } 63 | base++; 64 | } 65 | } 66 | 67 | static void fft(vector> &a) { 68 | int n = (int) a.size(); 69 | assert((n & (n - 1)) == 0); 70 | int zeros = __builtin_ctz(n); 71 | ensure_base(zeros); 72 | int shift = base - zeros; 73 | for (int i = 0; i < n; i++) { 74 | if (i < (rev[i] >> shift)) { 75 | swap(a[i], a[rev[i] >> shift]); 76 | } 77 | } 78 | for (int k = 1; k < n; k <<= 1) { 79 | for (int i = 0; i < n; i += 2 * k) { 80 | for (int j = 0; j < k; j++) { 81 | Modular x = a[i + j]; 82 | Modular y = a[i + j + k] * roots[j + k]; 83 | a[i + j] = x + y; 84 | a[i + j + k] = x - y; 85 | } 86 | } 87 | } 88 | } 89 | 90 | static vector> multiply(vector> a, vector> b) { 91 | if (a.empty() || b.empty()) { 92 | return {}; 93 | } 94 | int eq = (a == b); 95 | int need = (int) a.size() + (int) b.size() - 1; 96 | int nbase = 0; 97 | while ((1 << nbase) < need) nbase++; 98 | ensure_base(nbase); 99 | int sz = 1 << nbase; 100 | a.resize(sz); 101 | b.resize(sz); 102 | fft(a); 103 | if (eq) b = a; else fft(b); 104 | Modular inv_sz = 1 / static_cast>(sz); 105 | for (int i = 0; i < sz; i++) { 106 | a[i] *= b[i] * inv_sz; 107 | } 108 | reverse(a.begin() + 1, a.end()); 109 | fft(a); 110 | a.resize(need); 111 | return a; 112 | } 113 | }; 114 | 115 | template typename NTT::Type NTT::md; 116 | template Modular NTT::root; 117 | template int NTT::base; 118 | template int NTT::max_base; 119 | template vector> NTT::roots; 120 | template vector NTT::rev; 121 | 122 | template 123 | vector> inverse(const vector>& a) { 124 | assert(!a.empty()); 125 | int n = (int) a.size(); 126 | vector> b = {1 / a[0]}; 127 | while ((int) b.size() < n) { 128 | vector> x(a.begin(), a.begin() + min(a.size(), b.size() << 1)); 129 | x.resize(b.size() << 1); 130 | b.resize(b.size() << 1); 131 | vector> c = b; 132 | NTT::fft(c); 133 | NTT::fft(x); 134 | Modular inv = 1 / static_cast>((int) x.size()); 135 | for (int i = 0; i < (int) x.size(); i++) { 136 | x[i] *= c[i] * inv; 137 | } 138 | reverse(x.begin() + 1, x.end()); 139 | NTT::fft(x); 140 | rotate(x.begin(), x.begin() + (x.size() >> 1), x.end()); 141 | fill(x.begin() + (x.size() >> 1), x.end(), 0); 142 | NTT::fft(x); 143 | for (int i = 0; i < (int) x.size(); i++) { 144 | x[i] *= c[i] * inv; 145 | } 146 | reverse(x.begin() + 1, x.end()); 147 | NTT::fft(x); 148 | for (int i = 0; i < ((int) x.size() >> 1); i++) { 149 | b[i + ((int) x.size() >> 1)] = -x[i]; 150 | } 151 | } 152 | b.resize(n); 153 | return b; 154 | } 155 | 156 | template 157 | vector> inverse_old(vector> a) { 158 | assert(!a.empty()); 159 | int n = (int) a.size(); 160 | if (n == 1) { 161 | return {1 / a[0]}; 162 | } 163 | int m = (n + 1) >> 1; 164 | vector> b = inverse(vector>(a.begin(), a.begin() + m)); 165 | int need = n << 1; 166 | int nbase = 0; 167 | while ((1 << nbase) < need) { 168 | ++nbase; 169 | } 170 | NTT::ensure_base(nbase); 171 | int size = 1 << nbase; 172 | a.resize(size); 173 | b.resize(size); 174 | NTT::fft(a); 175 | NTT::fft(b); 176 | Modular inv = 1 / static_cast>(size); 177 | for (int i = 0; i < size; ++i) { 178 | a[i] = (2 - a[i] * b[i]) * b[i] * inv; 179 | } 180 | reverse(a.begin() + 1, a.end()); 181 | NTT::fft(a); 182 | a.resize(n); 183 | return a; 184 | } 185 | 186 | template 187 | vector> operator*(const vector>& a, const vector>& b) { 188 | if (a.empty() || b.empty()) { 189 | return {}; 190 | } 191 | if (min(a.size(), b.size()) < 150) { 192 | vector> c(a.size() + b.size() - 1, 0); 193 | for (int i = 0; i < (int) a.size(); i++) { 194 | for (int j = 0; j < (int) b.size(); j++) { 195 | c[i + j] += a[i] * b[j]; 196 | } 197 | } 198 | return c; 199 | } 200 | return NTT::multiply(a, b); 201 | } 202 | 203 | template 204 | vector>& operator*=(vector>& a, const vector>& b) { 205 | return a = a * b; 206 | } -------------------------------------------------------------------------------- /numeric/primitive.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct PrimitiveVarMod { static T value; }; 3 | template 4 | T PrimitiveVarMod::value; 5 | 6 | template 7 | T GetPrimitiveRoot(const T& modulo, const F& factorize) { 8 | if (modulo <= 0) { 9 | return -1; 10 | } 11 | if (modulo == 1 || modulo == 2 || modulo == 4) { 12 | return modulo - 1; 13 | } 14 | vector> modulo_factors = factorize(modulo); 15 | if (modulo_factors[0].first == 2 && (modulo_factors[0].second != 1 || modulo_factors.size() != 2)) { 16 | return -1; 17 | } 18 | if (modulo_factors[0].first != 2 && modulo_factors.size() != 1) { 19 | return -1; 20 | } 21 | set phi_factors; 22 | T phi = modulo; 23 | for (auto& d : modulo_factors) { 24 | phi = phi / d.first * (d.first - 1); 25 | if (d.second > 1) { 26 | phi_factors.insert(d.first); 27 | } 28 | for (auto& e : factorize(d.first - 1)) { 29 | phi_factors.insert(e.first); 30 | } 31 | } 32 | PrimitiveVarMod::value = modulo; 33 | Modular> gen = 2; 34 | while (gen != 0) { 35 | if (power(gen, phi) != 1) { 36 | continue; 37 | } 38 | bool ok = true; 39 | for (auto& p : phi_factors) { 40 | if (power(gen, phi / p) == 1) { 41 | ok = false; 42 | break; 43 | } 44 | } 45 | if (ok) { 46 | return gen(); 47 | } 48 | gen++; 49 | } 50 | assert(false); 51 | return -1; 52 | } 53 | 54 | template 55 | T GetPrimitiveRoot(const T& modulo) { 56 | return GetPrimitiveRoot(modulo, factorizer::Factorize); 57 | } -------------------------------------------------------------------------------- /numeric/simplex.cpp: -------------------------------------------------------------------------------- 1 | typedef long double ld; 2 | 3 | const ld eps = 1e-8; 4 | 5 | vector simplex(vector> a) { 6 | int n = (int) a.size() - 1; 7 | int m = (int) a[0].size() - 1; 8 | vector left(n + 1); 9 | vector up(m + 1); 10 | iota(left.begin(), left.end(), m); 11 | iota(up.begin(), up.end(), 0); 12 | auto pivot = [&](int x, int y) { 13 | swap(left[x], up[y]); 14 | ld k = a[x][y]; 15 | a[x][y] = 1; 16 | vector pos; 17 | for (int j = 0; j <= m; j++) { 18 | a[x][j] /= k; 19 | if (fabs(a[x][j]) > eps) { 20 | pos.push_back(j); 21 | } 22 | } 23 | for (int i = 0; i <= n; i++) { 24 | if (fabs(a[i][y]) < eps || i == x) { 25 | continue; 26 | } 27 | k = a[i][y]; 28 | a[i][y] = 0; 29 | for (int j : pos) { 30 | a[i][j] -= k * a[x][j]; 31 | } 32 | } 33 | }; 34 | while (1) { 35 | int x = -1; 36 | for (int i = 1; i <= n; i++) { 37 | if (a[i][0] < -eps && (x == -1 || a[i][0] < a[x][0])) { 38 | x = i; 39 | } 40 | } 41 | if (x == -1) { 42 | break; 43 | } 44 | int y = -1; 45 | for (int j = 1; j <= m; j++) { 46 | if (a[x][j] < -eps && (y == -1 || a[x][j] < a[x][y])) { 47 | y = j; 48 | } 49 | } 50 | if (y == -1) { 51 | return vector(); // infeasible 52 | } 53 | pivot(x, y); 54 | } 55 | while (1) { 56 | int y = -1; 57 | for (int j = 1; j <= m; j++) { 58 | if (a[0][j] > eps && (y == -1 || a[0][j] > a[0][y])) { 59 | y = j; 60 | } 61 | } 62 | if (y == -1) { 63 | break; 64 | } 65 | int x = -1; 66 | for (int i = 1; i <= n; i++) { 67 | if (a[i][y] > eps && (x == -1 || a[i][0] / a[i][y] < a[x][0] / a[x][y])) { 68 | x = i; 69 | } 70 | } 71 | if (x == -1) { 72 | return vector(); // unbounded 73 | } 74 | pivot(x, y); 75 | } 76 | vector ans(m + 1); 77 | for (int i = 1; i <= n; i++) { 78 | if (left[i] <= m) { 79 | ans[left[i]] = a[i][0]; 80 | } 81 | } 82 | ans[0] = -a[0][0]; 83 | return ans; 84 | } 85 | -------------------------------------------------------------------------------- /numeric/sparsematrix.cpp: -------------------------------------------------------------------------------- 1 | const double eps = 1e-9; 2 | 3 | bool IsZero(double v) { 4 | return abs(v) < 1e-9; 5 | } 6 | 7 | template 8 | class SparseMatrix { 9 | public: 10 | int h; 11 | int w; 12 | vector> rows; 13 | vector> cols; 14 | 15 | SparseMatrix(int h_, int w_) : h(h_), w(w_) { 16 | rows.resize(h); 17 | cols.resize(w); 18 | } 19 | 20 | void set(int i, int j, const T& value) { 21 | if (IsZero(value)) { 22 | rows[i].erase(j); 23 | cols[j].erase(i); 24 | } else { 25 | rows[i][j] = value; 26 | cols[j][i] = value; 27 | } 28 | } 29 | 30 | void modify(int i, int j, const T& value) { 31 | if (IsZero(value)) { 32 | return; 33 | } 34 | auto it = rows[i].find(j); 35 | if (it == rows[i].end()) { 36 | rows[i][j] = value; 37 | cols[j][i] = value; 38 | } else { 39 | it->second += value; 40 | if (IsZero(it->second)) { 41 | rows[i].erase(it); 42 | cols[j].erase(i); 43 | } else { 44 | cols[j][i] = it->second; 45 | } 46 | } 47 | } 48 | 49 | T get(int i, int j) { 50 | auto it = rows[i].find(j); 51 | if (it == rows[i].end()) { 52 | return T{}; 53 | } 54 | return it->second; 55 | } 56 | 57 | void transpose() { 58 | swap(h, w); 59 | swap(rows, cols); 60 | } 61 | }; 62 | 63 | template 64 | void GaussianElimination(SparseMatrix& a, int limit) { 65 | assert(limit <= a.w); 66 | int r = 0; 67 | for (int c = 0; c < limit; c++) { 68 | int mn = a.w + 1; 69 | int id = -1; 70 | for (auto& p : a.cols[c]) { 71 | int i = p.first; 72 | if (i >= r) { 73 | int sz = static_cast(a.rows[i].size()); 74 | if (sz < mn) { 75 | mn = sz; 76 | id = i; 77 | } 78 | } 79 | } 80 | if (id == -1) { 81 | continue; 82 | } 83 | if (id > r) { 84 | set s; 85 | for (auto& p : a.rows[r]) { 86 | s.insert(p.first); 87 | } 88 | for (auto& p : a.rows[id]) { 89 | s.insert(p.first); 90 | } 91 | for (int j : s) { 92 | T tmp = a.get(r, j); 93 | a.set(r, j, a.get(id, j)); 94 | a.set(id, j, -tmp); 95 | } 96 | } 97 | T inv_a = 1 / a.get(r, c); 98 | vector touched_rows; 99 | for (auto& p : a.cols[c]) { 100 | int i = p.first; 101 | if (i > r) { 102 | touched_rows.push_back(i); 103 | T coeff = -p.second * inv_a; 104 | for (auto& q : a.rows[r]) { 105 | if (q.first != c) { 106 | a.modify(i, q.first, coeff * q.second); 107 | } 108 | } 109 | } 110 | } 111 | for (int i : touched_rows) { 112 | a.set(i, c, 0); 113 | } 114 | ++r; 115 | } 116 | } 117 | 118 | template 119 | T Determinant(SparseMatrix/*&*/ a) { 120 | assert(a.h == a.w); 121 | GaussianElimination(a, a.w); 122 | T d{1}; 123 | for (int i = 0; i < a.h; i++) { 124 | d *= a.get(i, i); 125 | } 126 | return d; 127 | } 128 | 129 | template 130 | int Rank(SparseMatrix/*&*/ a) { 131 | GaussianElimination(a, a.w); 132 | int rank = 0; 133 | for (int i = 0; i < a.h; i++) { 134 | if (!a.rows[i].empty()) { 135 | ++rank; 136 | } 137 | } 138 | return rank; 139 | } 140 | 141 | template 142 | vector SolveLinearSystem(SparseMatrix/*&*/ a, const vector& b) { 143 | assert(a.h == static_cast(b.size())); 144 | ++a.w; 145 | a.cols.emplace_back(); 146 | for (int i = 0; i < a.h; i++) { 147 | a.set(i, a.w - 1, b[i]); 148 | } 149 | GaussianElimination(a, a.w - 1); 150 | vector x(a.h, 0); 151 | for (int r = a.h - 1; r >= 0; r--) { 152 | int c = a.rows[r].begin()->first; 153 | if (c == a.w - 1) { 154 | return {}; 155 | } 156 | x[c] = a.get(r, a.w - 1) / a.get(r, c); 157 | vector touched_rows; 158 | for (auto& q : a.cols[c]) { 159 | int i = q.first; 160 | if (i < r) { 161 | touched_rows.push_back(i); 162 | a.modify(i, a.w - 1, -x[c] * q.second); 163 | } 164 | } 165 | for (int i : touched_rows) { 166 | a.set(i, c, 0); 167 | } 168 | } 169 | return x; 170 | } -------------------------------------------------------------------------------- /segtree/dynamic_fenwick.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class DynamicFenwickTree { 3 | public: 4 | HashMap fenw; 5 | int n; 6 | int pw; 7 | 8 | DynamicFenwickTree() : n(0) {} 9 | DynamicFenwickTree(int n_) : n(n_) { 10 | pw = bit_floor(unsigned(n)); 11 | } 12 | 13 | void Modify(int x, T v) { 14 | assert(0 <= x && x < n); 15 | while (x < n) { 16 | fenw[x] += v; 17 | x |= x + 1; 18 | } 19 | } 20 | 21 | T Query(int x) { 22 | assert(0 <= x && x <= n); 23 | T v{}; 24 | while (x > 0) { 25 | auto it = fenw.find(x - 1); 26 | if (it != fenw.end()) { 27 | v += it->second; 28 | } 29 | x &= x - 1; 30 | } 31 | return v; 32 | } 33 | 34 | // Returns the length of the longest prefix with sum <= c 35 | int MaxPrefix(T c) { 36 | T v{}; 37 | int at = 0; 38 | for (int len = pw; len > 0; len >>= 1) { 39 | if (at + len <= n) { 40 | auto nv = v; 41 | auto it = fenw.find(at + len - 1); 42 | if (it != fenw.end()) { 43 | nv += it->second; 44 | } 45 | if (!(c < nv)) { 46 | v = nv; 47 | at += len; 48 | } 49 | } 50 | } 51 | assert(0 <= at && at <= n); 52 | return at; 53 | } 54 | }; 55 | -------------------------------------------------------------------------------- /segtree/dynamic_simple.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class DynamicSimpleSegmentTree { 3 | public: 4 | struct Node { 5 | array c; 6 | Info d; 7 | }; 8 | 9 | Index n; 10 | vector nodes; 11 | 12 | DynamicSimpleSegmentTree() : DynamicSimpleSegmentTree(0, -1) {} 13 | DynamicSimpleSegmentTree(Index n_) : DynamicSimpleSegmentTree(n_, -1) {} 14 | DynamicSimpleSegmentTree(const vector& a) : DynamicSimpleSegmentTree(a, -1) {} 15 | 16 | DynamicSimpleSegmentTree(Index n_, int q) : n(n_) { 17 | if (q >= 0) { 18 | nodes.reserve(2 + q * bit_width(make_unsigned_t(2 * n - 1))); 19 | } 20 | nodes.resize(2); 21 | nodes[1] = {{-1, -1}, Info::GetDefault(0, n)}; 22 | } 23 | 24 | DynamicSimpleSegmentTree(const vector& a, int q) : n(int(a.size())) { 25 | if (q >= 0) { 26 | nodes.reserve(2 * n + q * bit_width(make_unsigned_t(2 * n - 1))); 27 | } 28 | nodes.resize(2 * n); 29 | auto Build = [&](auto&& self, int id, int nl, int nr) -> void { 30 | if (nr - nl == 1) { 31 | nodes[id] = {{-1, -1}, a[nl]}; 32 | return; 33 | } 34 | int mid = (nl + nr) >> 1; 35 | array c = {id + 1, id + 2 * (mid - nl)}; 36 | self(self, c[0], nl, mid); 37 | self(self, c[1], mid, nr); 38 | nodes[id] = {c, nodes[c[0]].d.Unite(nodes[c[1]].d)}; 39 | }; 40 | Build(Build, 1, 0, n); 41 | } 42 | 43 | int SetImpl(int root, Index p, const Info& v, Index nl, Index nr) { 44 | int me; 45 | if (root == -1) { 46 | me = int(nodes.size()); 47 | nodes.push_back({{-1, -1}, Info::GetDefault(nl, nr)}); 48 | } else { 49 | if (Persistent) { 50 | me = int(nodes.size()); 51 | nodes.push_back(nodes[root]); 52 | } else { 53 | me = root; 54 | } 55 | } 56 | if (nr - nl == 1) { 57 | nodes[me].d = v; 58 | } else { 59 | Index mid = (nl + nr) >> 1; 60 | if (p < mid) { 61 | int got = SetImpl(nodes[me].c[0], p, v, nl, mid); 62 | nodes[me].c[0] = got; 63 | } else { 64 | int got = SetImpl(nodes[me].c[1], p, v, mid, nr); 65 | nodes[me].c[1] = got; 66 | } 67 | auto lft = nodes[me].c[0] == -1 ? Info::GetDefault(nl, mid) : nodes[nodes[me].c[0]].d; 68 | auto rgt = nodes[me].c[1] == -1 ? Info::GetDefault(mid, nr) : nodes[nodes[me].c[1]].d; 69 | nodes[me].d = lft.Unite(rgt); 70 | } 71 | return me; 72 | } 73 | 74 | int Set(Index p, const Info& v, int root = Persistent ? -1 : 1) { 75 | assert(0 <= p && p < n && root >= 1); 76 | return SetImpl(root, p, v, 0, n); 77 | } 78 | 79 | Info QueryImpl(int root, Index l, Index r, Index nl, Index nr) { 80 | if (root == -1) { 81 | return Info::GetDefault(max(l, nl), min(r, nr)); 82 | } 83 | if (l <= nl && nr <= r) { 84 | return nodes[root].d; 85 | } 86 | Index mid = (nl + nr) >> 1; 87 | auto lft = l < mid ? QueryImpl(nodes[root].c[0], l, r, nl, mid) : Info(); 88 | auto rgt = r > mid ? QueryImpl(nodes[root].c[1], l, r, mid, nr) : Info(); 89 | return lft.Unite(rgt); 90 | } 91 | 92 | Info Query(Index l, Index r, int root = Persistent ? -1 : 1) { 93 | assert(0 <= l && l <= r && r <= n && root >= 1); 94 | if (l == r) { 95 | return Info(); 96 | } 97 | return QueryImpl(root, l, r, 0, n); 98 | } 99 | 100 | Info Get(Index p, int root = Persistent ? -1 : 1) { 101 | assert(0 <= p && p < n && root >= 1); 102 | Index nl = 0; 103 | Index nr = n; 104 | while (nr - nl > 1 && root != -1) { 105 | Index mid = (nl + nr) >> 1; 106 | if (p < mid) { 107 | root = nodes[root].c[0]; 108 | nr = mid; 109 | } else { 110 | root = nodes[root].c[1]; 111 | nl = mid; 112 | } 113 | } 114 | return root == -1 ? Info::GetDefault(p, p + 1) : nodes[root].d; 115 | } 116 | 117 | template 118 | Index MaxRight(array roots, Index l, F f) { 119 | assert(0 <= l && l <= n); 120 | if (l == n) { 121 | return n; 122 | } 123 | Index res = n; 124 | array sums; 125 | for (int i = 0; i < N; i++) { 126 | sums[i] = Info(); 127 | } 128 | array new_sums; 129 | auto Dfs = [&](auto&& self, array v, Index nl, Index nr) -> void { 130 | if (res != n) { 131 | return; 132 | } 133 | array to; 134 | if (nl < l) { 135 | Index mid = (nl + nr) >> 1; 136 | if (l < mid) { 137 | for (int i = 0; i < N; i++) { 138 | to[i] = v[i] == -1 ? -1 : nodes[v[i]].c[0]; 139 | } 140 | self(self, to, nl, mid); 141 | if (res != n) { 142 | return; 143 | } 144 | } 145 | for (int i = 0; i < N; i++) { 146 | to[i] = v[i] == -1 ? -1 : nodes[v[i]].c[1]; 147 | } 148 | self(self, to, mid, nr); 149 | return; 150 | } 151 | for (int i = 0; i < N; i++) { 152 | new_sums[i] = sums[i].Unite(v[i] == -1 ? Info::GetDefault(nl, nr) : nodes[v[i]].d); 153 | } 154 | if (f(new_sums)) { 155 | sums = new_sums; 156 | return; 157 | } 158 | while (nr - nl > 1) { 159 | Index mid = (nl + nr) >> 1; 160 | for (int i = 0; i < N; i++) { 161 | new_sums[i] = sums[i].Unite(v[i] == -1 || nodes[v[i]].c[0] == -1 ? Info::GetDefault(nl, mid) : nodes[nodes[v[i]].c[0]].d); 162 | } 163 | if (f(new_sums)) { 164 | sums = new_sums; 165 | nl = mid; 166 | for (int i = 0; i < N; i++) { 167 | v[i] = v[i] == -1 ? -1 : nodes[v[i]].c[1]; 168 | } 169 | } else { 170 | nr = mid; 171 | for (int i = 0; i < N; i++) { 172 | v[i] = v[i] == -1 ? -1 : nodes[v[i]].c[0]; 173 | } 174 | } 175 | } 176 | res = nl; 177 | }; 178 | Dfs(Dfs, roots, 0, n); 179 | return res; 180 | } 181 | 182 | template 183 | Index MinLeft(array roots, Index r, F f) { 184 | assert(0 <= r && r <= n); 185 | if (r == 0) { 186 | return 0; 187 | } 188 | Index res = 0; 189 | array sums; 190 | for (int i = 0; i < N; i++) { 191 | sums[i] = Info(); 192 | } 193 | array new_sums; 194 | auto Dfs = [&](auto&& self, array v, Index nl, Index nr) -> void { 195 | if (res != 0) { 196 | return; 197 | } 198 | array to; 199 | if (nr > r) { 200 | Index mid = (nl + nr) >> 1; 201 | if (r > mid) { 202 | for (int i = 0; i < N; i++) { 203 | to[i] = v[i] == -1 ? -1 : nodes[v[i]].c[1]; 204 | } 205 | self(self, to, mid, nr); 206 | if (res != 0) { 207 | return; 208 | } 209 | } 210 | for (int i = 0; i < N; i++) { 211 | to[i] = v[i] == -1 ? -1 : nodes[v[i]].c[0]; 212 | } 213 | self(self, to, nl, mid); 214 | return; 215 | } 216 | for (int i = 0; i < N; i++) { 217 | new_sums[i] = (v[i] == -1 ? Info::GetDefault(nl, nr) : nodes[v[i]].d).Unite(sums[i]); 218 | } 219 | if (f(new_sums)) { 220 | sums = new_sums; 221 | return; 222 | } 223 | while (nr - nl > 1) { 224 | Index mid = (nl + nr) >> 1; 225 | for (int i = 0; i < N; i++) { 226 | new_sums[i] = (v[i] == -1 || nodes[v[i]].c[1] == -1 ? Info::GetDefault(mid, nr) : nodes[nodes[v[i]].c[1]].d).Unite(sums[i]); 227 | } 228 | if (f(new_sums)) { 229 | sums = new_sums; 230 | nr = mid; 231 | for (int i = 0; i < N; i++) { 232 | v[i] = v[i] == -1 ? -1 : nodes[v[i]].c[0]; 233 | } 234 | } else { 235 | nl = mid; 236 | for (int i = 0; i < N; i++) { 237 | v[i] = v[i] == -1 ? -1 : nodes[v[i]].c[1]; 238 | } 239 | } 240 | } 241 | res = nr; 242 | }; 243 | Dfs(Dfs, roots, 0, n); 244 | return res; 245 | } 246 | }; 247 | -------------------------------------------------------------------------------- /segtree/info.cpp: -------------------------------------------------------------------------------- 1 | struct Info { 2 | ${0}... a = ...; 3 | 4 | Info Unite(const Info& b) const { 5 | Info res; 6 | ... 7 | return res; 8 | } 9 | 10 | static Info GetDefault([[maybe_unused]] int l, [[maybe_unused]] int r) { 11 | return Info(); 12 | } 13 | }; 14 | 15 | -------------------------------------------------------------------------------- /segtree/layout.cpp: -------------------------------------------------------------------------------- 1 | namespace seg_tree { 2 | 3 | // Floor of log_2(a); index of highest 1-bit 4 | inline int floor_log_2(int a) { 5 | return a ? bit_width(unsigned(a)) - 1 : -1; 6 | } 7 | 8 | struct point { 9 | int a; 10 | point() : a(0) {} 11 | explicit point(int a_) : a(a_) { assert(a >= -1); } 12 | 13 | explicit operator bool () { return bool(a); } 14 | 15 | // This is useful so you can directly do array indices 16 | /* implicit */ operator int() const { return a; } 17 | 18 | point c(bool z) const { 19 | return point((a << 1) | z); 20 | } 21 | 22 | point operator [] (bool z) const { 23 | return c(z); 24 | } 25 | 26 | point p() const { 27 | return point(a >> 1); 28 | } 29 | 30 | friend std::ostream& operator << (std::ostream& o, const point& p) { return o << int(p); } 31 | 32 | template void for_each(F f) const { 33 | for (int v = a; v > 0; v >>= 1) { 34 | f(point(v)); 35 | } 36 | } 37 | 38 | template void for_parents_down(F f) const { 39 | // strictly greater than 0 40 | for (int L = floor_log_2(a); L > 0; L--) { 41 | f(point(a >> L)); 42 | } 43 | } 44 | 45 | template void for_parents_up(F f) const { 46 | for (int v = a >> 1; v > 0; v >>= 1) { 47 | f(point(v)); 48 | } 49 | } 50 | 51 | point& operator ++ () { ++a; return *this; } 52 | point operator ++ (int) { return point(a++); } 53 | point& operator -- () { --a; return *this; } 54 | point operator -- (int) { return point(a--); } 55 | }; 56 | 57 | struct range { 58 | int a, b; 59 | range() : a(1), b(1) {} 60 | range(int a_, int b_) : a(a_), b(b_) { 61 | assert(1 <= a && a <= b && b <= 2 * a); 62 | } 63 | explicit range(std::array r) : range(r[0], r[1]) {} 64 | 65 | explicit operator std::array() const { 66 | return {a, b}; 67 | } 68 | 69 | const int& operator[] (bool z) const { 70 | return z ? b : a; 71 | } 72 | 73 | friend std::ostream& operator << (std::ostream& o, const range& r) { return o << "[" << r.a << ".." << r.b << ")"; } 74 | 75 | // Iterate over the range from outside-in. 76 | // Calls f(point a) 77 | template void for_each(F f) const { 78 | for (int x = a, y = b; x < y; x >>= 1, y >>= 1) { 79 | if (x & 1) f(point(x++)); 80 | if (y & 1) f(point(--y)); 81 | } 82 | } 83 | 84 | // Iterate over the range from outside-in. 85 | // Calls f(point a, bool is_right) 86 | template void for_each_with_side(F f) const { 87 | for (int x = a, y = b; x < y; x >>= 1, y >>= 1) { 88 | if (x & 1) f(point(x++), false); 89 | if (y & 1) f(point(--y), true); 90 | } 91 | } 92 | 93 | // Iterate over the range from left to right. 94 | // Calls f(point) 95 | template void for_each_l_to_r(F f) const { 96 | int anc_depth = floor_log_2((a - 1) ^ b); 97 | int anc_msk = (1 << anc_depth) - 1; 98 | for (int v = (-a) & anc_msk; v; v &= v - 1) { 99 | int i = countr_zero(unsigned(v)); 100 | f(point(((a - 1) >> i) + 1)); 101 | } 102 | for (int v = b & anc_msk; v; ) { 103 | int i = floor_log_2(v); 104 | f(point((b >> i) - 1)); 105 | v ^= (1 << i); 106 | } 107 | } 108 | 109 | // Iterate over the range from right to left. 110 | // Calls f(point) 111 | template void for_each_r_to_l(F f) const { 112 | int anc_depth = floor_log_2((a - 1) ^ b); 113 | int anc_msk = (1 << anc_depth) - 1; 114 | for (int v = b & anc_msk; v; v &= v - 1) { 115 | int i = countr_zero(unsigned(v)); 116 | f(point((b >> i) - 1)); 117 | } 118 | for (int v = (-a) & anc_msk; v; ) { 119 | int i = floor_log_2(v); 120 | f(point(((a - 1) >> i) + 1)); 121 | v ^= (1 << i); 122 | } 123 | } 124 | 125 | template void for_parents_down(F f) const { 126 | int x = a, y = b; 127 | if ((x ^ y) > x) { x <<= 1, std::swap(x, y); } 128 | int dx = countr_zero(unsigned(x)); 129 | int dy = countr_zero(unsigned(y)); 130 | int anc_depth = floor_log_2((x - 1) ^ y); 131 | for (int i = floor_log_2(x); i > dx; i--) { 132 | f(point(x >> i)); 133 | } 134 | for (int i = anc_depth; i > dy; i--) { 135 | f(point(y >> i)); 136 | } 137 | } 138 | 139 | template void for_parents_up(F f) const { 140 | int x = a, y = b; 141 | if ((x ^ y) > x) { x <<= 1, std::swap(x, y); } 142 | int dx = countr_zero(unsigned(x)); 143 | int dy = countr_zero(unsigned(y)); 144 | int anc_depth = floor_log_2((x - 1) ^ y); 145 | for (int i = dx + 1; i <= anc_depth; i++) { 146 | f(point(x >> i)); 147 | } 148 | for (int v = y >> (dy + 1); v; v >>= 1) { 149 | f(point(v)); 150 | } 151 | } 152 | }; 153 | 154 | struct in_order_layout { 155 | // Alias them in for convenience 156 | using point = seg_tree::point; 157 | using range = seg_tree::range; 158 | 159 | int n, s; 160 | in_order_layout() : n(0), s(0) {} 161 | in_order_layout(int n_) : n(n_), s(n ? bit_ceil(unsigned(n)) : 0) {} 162 | 163 | point get_point(int a) const { 164 | assert(0 <= a && a < n); 165 | a += s; 166 | return point(a >= 2 * n ? a - n : a); 167 | } 168 | 169 | range get_range(int a, int b) const { 170 | assert(0 <= a && a <= b && b <= n); 171 | if (n == 0) return range(); 172 | a += s, b += s; 173 | return range((a >= 2 * n ? 2 * (a - n) : a), (b >= 2 * n ? 2 * (b - n) : b)); 174 | } 175 | 176 | range get_range(std::array p) const { 177 | return get_range(p[0], p[1]); 178 | } 179 | 180 | int get_leaf_index(point pt) const { 181 | int a = int(pt); 182 | assert(n <= a && a < 2 * n); 183 | return (a < s ? a + n : a) - s; 184 | } 185 | 186 | std::array get_node_bounds(point pt) const { 187 | int a = int(pt); 188 | assert(1 <= a && a < 2 * n); 189 | int l = countl_zero(unsigned(a)) - countl_zero(unsigned(2 * n - 1)); 190 | int x = a << l, y = (a + 1) << l; 191 | assert(s <= x && x < y && y <= 2 * s); 192 | return {(x >= 2 * n ? (x >> 1) + n : x) - s, (y >= 2 * n ? (y >> 1) + n : y) - s}; 193 | } 194 | 195 | int get_node_split(point pt) const { 196 | int a = int(pt); 197 | assert(1 <= a && a < n); 198 | int l = countl_zero(unsigned(2 * a + 1)) - countl_zero(unsigned(2 * n - 1)); 199 | int x = (2 * a + 1) << l; 200 | assert(s <= x && x < 2 * s); 201 | return (x >= 2 * n ? (x >> 1) + n : x) - s; 202 | } 203 | 204 | int get_node_size(point pt) const { 205 | auto bounds = get_node_bounds(pt); 206 | return bounds[1] - bounds[0]; 207 | } 208 | }; 209 | 210 | struct circular_layout { 211 | // Alias them in for convenience 212 | using point = seg_tree::point; 213 | using range = seg_tree::range; 214 | 215 | int n; 216 | circular_layout() : n(0) {} 217 | circular_layout(int n_) : n(n_) {} 218 | 219 | point get_point(int a) const { 220 | assert(0 <= a && a < n); 221 | return point(n + a); 222 | } 223 | 224 | range get_range(int a, int b) const { 225 | assert(0 <= a && a <= b && b <= n); 226 | if (n == 0) return range(); 227 | return range(n + a, n + b); 228 | } 229 | 230 | range get_range(std::array p) const { 231 | return get_range(p[0], p[1]); 232 | } 233 | 234 | int get_leaf_index(point pt) const { 235 | int a = int(pt); 236 | assert(n <= a && a < 2 * n); 237 | return a - n; 238 | } 239 | 240 | // Returns {x,y} so that 0 <= x < n and 1 <= y <= n 241 | // If the point is non-wrapping, then 0 <= x < y <= n 242 | std::array get_node_bounds(point pt) const { 243 | int a = int(pt); 244 | assert(1 <= a && a < 2 * n); 245 | int l = countl_zero(unsigned(a)) - countl_zero(unsigned(2 * n - 1)); 246 | int s = bit_ceil(unsigned(n)); 247 | int x = a << l, y = (a + 1) << l; 248 | assert(s <= x && x < y && y <= 2 * s); 249 | return {(x >= 2 * n ? x >> 1 : x) - n, (y > 2 * n ? y >> 1 : y) - n}; 250 | } 251 | 252 | // Returns the split point of the node, such that 1 <= s <= n. 253 | int get_node_split(point pt) const { 254 | int a = int(pt); 255 | assert(1 <= a && a < n); 256 | return get_node_bounds(pt.c(0))[1]; 257 | } 258 | 259 | int get_node_size(point pt) const { 260 | auto bounds = get_node_bounds(pt); 261 | int r = bounds[1] - bounds[0]; 262 | return r > 0 ? r : r + n; 263 | } 264 | }; 265 | 266 | } // namespace seg_tree 267 | -------------------------------------------------------------------------------- /segtree/lazy.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class LazySegmentTree { 3 | public: 4 | int n; 5 | vector infos; 6 | vector tags; 7 | seg_tree::in_order_layout layout; 8 | 9 | void Apply(seg_tree::point a, const Tag& t) { 10 | auto [l, r] = layout.get_node_bounds(a); 11 | if (!t.ApplyTo(infos[a], l, r)) { 12 | assert(a < n); 13 | DowndateNode(a); 14 | Apply(a.c(0), t); 15 | Apply(a.c(1), t); 16 | UpdateNode(a); 17 | return; 18 | } 19 | if (a < n) { 20 | t.ApplyTo(tags[a]); 21 | } 22 | } 23 | 24 | void DowndateNode(seg_tree::point a) { 25 | if (!tags[a].Empty()) { 26 | Apply(a.c(0), tags[a]); 27 | Apply(a.c(1), tags[a]); 28 | tags[a] = Tag(); 29 | } 30 | } 31 | 32 | void UpdateNode(seg_tree::point a) { 33 | infos[a] = infos[a.c(0)].Unite(infos[a.c(1)]); 34 | } 35 | 36 | LazySegmentTree() : LazySegmentTree(0) {} 37 | LazySegmentTree(int n_) : LazySegmentTree(vector(n_)) {} 38 | LazySegmentTree(const vector& a) : n(int(a.size())) { 39 | infos.resize(2 * n); 40 | tags.resize(n); 41 | layout = seg_tree::in_order_layout(n); 42 | for (int i = 0; i < n; i++) { 43 | infos[layout.get_point(i)] = a[i]; 44 | } 45 | for (int i = n - 1; i >= 1; i--) { 46 | UpdateNode(seg_tree::point(i)); 47 | } 48 | } 49 | 50 | void Modify(int l, int r, const Tag& t) { 51 | auto rng = layout.get_range(l, r); 52 | rng.for_parents_down([&](seg_tree::point a) { 53 | DowndateNode(a); 54 | }); 55 | rng.for_each([&](seg_tree::point a) { 56 | Apply(a, t); 57 | }); 58 | rng.for_parents_up([&](seg_tree::point a) { 59 | UpdateNode(a); 60 | }); 61 | } 62 | 63 | void Set(int p, const Info& v) { 64 | auto pt = layout.get_point(p); 65 | pt.for_parents_down([&](seg_tree::point a) { 66 | DowndateNode(a); 67 | }); 68 | infos[pt] = v; 69 | pt.for_parents_up([&](seg_tree::point a) { 70 | UpdateNode(a); 71 | }); 72 | } 73 | 74 | Info Query(int l, int r) { 75 | auto rng = layout.get_range(l, r); 76 | rng.for_parents_down([&](seg_tree::point a) { 77 | DowndateNode(a); 78 | }); 79 | Info res; 80 | rng.for_each_l_to_r([&](seg_tree::point a) { 81 | res = res.Unite(infos[a]); 82 | }); 83 | return res; 84 | } 85 | 86 | Info Get(int p) { 87 | auto pt = layout.get_point(p); 88 | pt.for_parents_down([&](seg_tree::point a) { 89 | DowndateNode(a); 90 | }); 91 | return infos[pt]; 92 | } 93 | 94 | template 95 | int MaxRight(int l, F f) { 96 | auto rng = layout.get_range(l, n); 97 | rng.for_parents_down([&](seg_tree::point a) { 98 | DowndateNode(a); 99 | }); 100 | int res = n; 101 | Info sum; 102 | rng.for_each_l_to_r([&](seg_tree::point a) { 103 | if (res != n) { 104 | return; 105 | } 106 | auto new_sum = sum.Unite(infos[a]); 107 | if (f(new_sum)) { 108 | sum = new_sum; 109 | return; 110 | } 111 | while (a < n) { 112 | DowndateNode(a); 113 | new_sum = sum.Unite(infos[a.c(0)]); 114 | if (f(new_sum)) { 115 | sum = new_sum; 116 | a = a.c(1); 117 | } else { 118 | a = a.c(0); 119 | } 120 | } 121 | res = layout.get_node_bounds(a)[0]; 122 | }); 123 | return res; 124 | } 125 | 126 | template 127 | int MinLeft(int r, F f) { 128 | auto rng = layout.get_range(0, r); 129 | rng.for_parents_down([&](seg_tree::point a) { 130 | DowndateNode(a); 131 | }); 132 | int res = 0; 133 | Info sum; 134 | rng.for_each_r_to_l([&](seg_tree::point a) { 135 | if (res != 0) { 136 | return; 137 | } 138 | auto new_sum = infos[a].Unite(sum); 139 | if (f(new_sum)) { 140 | sum = new_sum; 141 | return; 142 | } 143 | while (a < n) { 144 | DowndateNode(a); 145 | new_sum = infos[a.c(1)].Unite(sum); 146 | if (f(new_sum)) { 147 | sum = new_sum; 148 | a = a.c(0); 149 | } else { 150 | a = a.c(1); 151 | } 152 | } 153 | res = layout.get_node_bounds(a)[1]; 154 | }); 155 | return res; 156 | } 157 | }; 158 | -------------------------------------------------------------------------------- /segtree/simple.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class SimpleSegmentTree { 3 | public: 4 | int n; 5 | vector infos; 6 | seg_tree::in_order_layout layout; 7 | 8 | void UpdateNode(seg_tree::point a) { 9 | infos[a] = infos[a.c(0)].Unite(infos[a.c(1)]); 10 | } 11 | 12 | SimpleSegmentTree(int n_) : SimpleSegmentTree(vector(n_)) {} 13 | 14 | SimpleSegmentTree(const vector& a) : n(int(a.size())) { 15 | assert(n > 0); 16 | infos.resize(2 * n); 17 | layout = seg_tree::in_order_layout(n); 18 | for (int i = 0; i < n; i++) { 19 | infos[layout.get_point(i)] = a[i]; 20 | } 21 | for (int i = n - 1; i >= 1; i--) { 22 | infos[i] = infos[2 * i].Unite(infos[2 * i + 1]); 23 | } 24 | } 25 | 26 | void Set(int p, const Info& v) { 27 | auto pt = layout.get_point(p); 28 | infos[pt] = v; 29 | pt.for_parents_up([&](seg_tree::point a) { 30 | UpdateNode(a); 31 | }); 32 | } 33 | 34 | Info Query(int l, int r) { 35 | auto rng = layout.get_range(l, r); 36 | Info res; 37 | rng.for_each_l_to_r([&](seg_tree::point a) { 38 | res = res.Unite(infos[a]); 39 | }); 40 | return res; 41 | } 42 | 43 | Info Get(int p) { 44 | auto pt = layout.get_point(p); 45 | return infos[pt]; 46 | } 47 | 48 | template 49 | int MaxRight(int l, F f) { 50 | auto rng = layout.get_range(l, n); 51 | int res = n; 52 | Info sum; 53 | rng.for_each_l_to_r([&](seg_tree::point a) { 54 | if (res != n) { 55 | return; 56 | } 57 | auto new_sum = sum.Unite(infos[a]); 58 | if (f(new_sum)) { 59 | sum = new_sum; 60 | return; 61 | } 62 | while (a < n) { 63 | new_sum = sum.Unite(infos[a.c(0)]); 64 | if (f(new_sum)) { 65 | sum = new_sum; 66 | a = a.c(1); 67 | } else { 68 | a = a.c(0); 69 | } 70 | } 71 | res = layout.get_node_bounds(a)[0]; 72 | }); 73 | return res; 74 | } 75 | 76 | template 77 | int MinLeft(int r, F f) { 78 | auto rng = layout.get_range(0, r); 79 | int res = 0; 80 | Info sum; 81 | rng.for_each_r_to_l([&](seg_tree::point a) { 82 | if (res != 0) { 83 | return; 84 | } 85 | auto new_sum = infos[a].Unite(sum); 86 | if (f(new_sum)) { 87 | sum = new_sum; 88 | return; 89 | } 90 | while (a < n) { 91 | new_sum = infos[a.c(1)].Unite(sum); 92 | if (f(new_sum)) { 93 | sum = new_sum; 94 | a = a.c(0); 95 | } else { 96 | a = a.c(1); 97 | } 98 | } 99 | res = layout.get_node_bounds(a)[1]; 100 | }); 101 | return res; 102 | } 103 | }; 104 | -------------------------------------------------------------------------------- /segtree/tag.cpp: -------------------------------------------------------------------------------- 1 | struct Tag { 2 | ${0}... add = ...; 3 | 4 | bool ApplyTo(Info& a, [[maybe_unused]] int l, [[maybe_unused]] int r) const { 5 | ... 6 | return true; 7 | } 8 | 9 | void ApplyTo(Tag& t) const { 10 | ... 11 | t.add += add; 12 | } 13 | 14 | bool Empty() const { 15 | ... 16 | return add == 0; 17 | } 18 | }; 19 | 20 | -------------------------------------------------------------------------------- /settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.autoSave": "afterDelay", 3 | "files.autoSaveDelay": 0, 4 | "terminal.integrated.defaultProfile.windows": "Command Prompt", 5 | "terminal.integrated.commandsToSkipShell": [ 6 | "explorer.newFile" 7 | ], 8 | "editor.autoClosingBrackets": "never", 9 | "editor.autoClosingQuotes": "never", 10 | "editor.autoIndent": "keep", 11 | "editor.minimap.enabled": false, 12 | "editor.parameterHints.enabled": false, 13 | "editor.quickSuggestions": { 14 | "other": false, 15 | "comments": false, 16 | "strings": false 17 | }, 18 | "editor.suggestOnTriggerCharacters": false, 19 | "editor.tabCompletion": "onlySnippets", 20 | "editor.tabSize": 2, 21 | "explorer.incrementalNaming": "smart", 22 | "C_Cpp.default.compilerPath": "g++", 23 | "C_Cpp.default.cppStandard": "c++20", 24 | "C_Cpp.default.defines": [ 25 | "LOCAL", 26 | "_GLIBCXX_DEBUG" 27 | ], 28 | "C_Cpp.autoAddFileAssociations": false, 29 | "telemetry.telemetryLevel": "off", 30 | "workbench.startupEditor": "none", 31 | "extensions.ignoreRecommendations": true 32 | } 33 | -------------------------------------------------------------------------------- /string/duval.cpp: -------------------------------------------------------------------------------- 1 | template 2 | int duval(int n, const T &s) { 3 | assert(n >= 1); 4 | int i = 0, ans = 0; 5 | while (i < n) { 6 | ans = i; 7 | int j = i + 1, k = i; 8 | while (j < n + n && !(s[j % n] < s[k % n])) { 9 | if (s[k % n] < s[j % n]) { 10 | k = i; 11 | } else { 12 | k++; 13 | } 14 | j++; 15 | } 16 | while (i <= k) { 17 | i += j - k; 18 | } 19 | } 20 | return ans; 21 | // returns 0-indexed position of the least cyclic shift 22 | } 23 | 24 | template 25 | int duval(const T &s) { 26 | return duval((int) s.size(), s); 27 | } -------------------------------------------------------------------------------- /string/duval_prefixes.cpp: -------------------------------------------------------------------------------- 1 | template 2 | vector duval_prefixes(int n, const T &s) { 3 | vector z = z_function(n, s); 4 | vector ans(n, 0); 5 | int i = 0, pos = 0; 6 | while (i < n) { 7 | int j = i, k = i; 8 | while (j < n) { 9 | j++; 10 | if (j > pos) { 11 | if (z[k] <= pos - k && s[z[k]] < s[k + z[k]]) { 12 | int shift = (pos - i) / (j - k) * (j - k); 13 | ans[pos] = ans[pos - shift] + shift; 14 | } else { 15 | ans[pos] = i; 16 | } 17 | pos++; 18 | } 19 | if (s[k] < s[j]) k = i; else 20 | if (!(s[j] < s[k])) k++; else 21 | else break; 22 | } 23 | while (i <= k) { 24 | i += j - k; 25 | } 26 | } 27 | return ans; 28 | // returns 0-indexed positions of the least cyclic shifts of all prefixes 29 | } 30 | 31 | template 32 | vector duval_prefixes(const T &s) { 33 | return duval_prefixes((int) s.size(), s); 34 | } -------------------------------------------------------------------------------- /string/hash61.cpp: -------------------------------------------------------------------------------- 1 | struct hash61 { 2 | static const uint64_t md = (1LL << 61) - 1; 3 | static uint64_t step; 4 | static vector pw; 5 | 6 | uint64_t addmod(uint64_t a, uint64_t b) const { 7 | a += b; 8 | if (a >= md) a -= md; 9 | return a; 10 | } 11 | 12 | uint64_t submod(uint64_t a, uint64_t b) const { 13 | a += md - b; 14 | if (a >= md) a -= md; 15 | return a; 16 | } 17 | 18 | uint64_t mulmod(uint64_t a, uint64_t b) const { 19 | uint64_t l1 = (uint32_t) a, h1 = a >> 32, l2 = (uint32_t) b, h2 = b >> 32; 20 | uint64_t l = l1 * l2, m = l1 * h2 + l2 * h1, h = h1 * h2; 21 | uint64_t ret = (l & md) + (l >> 61) + (h << 3) + (m >> 29) + (m << 35 >> 3) + 1; 22 | ret = (ret & md) + (ret >> 61); 23 | ret = (ret & md) + (ret >> 61); 24 | return ret - 1; 25 | } 26 | 27 | void ensure_pw(int sz) { 28 | int cur = (int) pw.size(); 29 | if (cur < sz) { 30 | pw.resize(sz); 31 | for (int i = cur; i < sz; i++) { 32 | pw[i] = mulmod(pw[i - 1], step); 33 | } 34 | } 35 | } 36 | 37 | vector pref; 38 | int n; 39 | 40 | template 41 | hash61(const T& s) { 42 | n = (int) s.size(); 43 | ensure_pw(n + 1); 44 | pref.resize(n + 1); 45 | pref[0] = 1; 46 | for (int i = 0; i < n; i++) { 47 | pref[i + 1] = addmod(mulmod(pref[i], step), s[i]); 48 | } 49 | } 50 | 51 | inline uint64_t operator()(const int from, const int to) const { 52 | assert(0 <= from && from <= to && to <= n - 1); 53 | return submod(pref[to + 1], mulmod(pref[from], pw[to - from + 1])); 54 | } 55 | }; 56 | 57 | uint64_t hash61::step = (md >> 2) + rng() % (md >> 1); 58 | vector hash61::pw = vector(1, 1); -------------------------------------------------------------------------------- /string/kmp.cpp: -------------------------------------------------------------------------------- 1 | template 2 | vector kmp_table(int n, const T &s) { 3 | vector p(n, 0); 4 | int k = 0; 5 | for (int i = 1; i < n; i++) { 6 | while (k > 0 && !(s[i] == s[k])) { 7 | k = p[k - 1]; 8 | } 9 | if (s[i] == s[k]) { 10 | k++; 11 | } 12 | p[i] = k; 13 | } 14 | return p; 15 | } 16 | 17 | template 18 | vector kmp_table(const T &s) { 19 | return kmp_table((int) s.size(), s); 20 | } 21 | 22 | template 23 | vector kmp_search(int n, const T &s, int m, const T &w, const vector &p) { 24 | assert(n >= 1 && (int) p.size() == n); 25 | vector res; 26 | int k = 0; 27 | for (int i = 0; i < m; i++) { 28 | while (k > 0 && (k == n || !(w[i] == s[k]))) { 29 | k = p[k - 1]; 30 | } 31 | if (w[i] == s[k]) { 32 | k++; 33 | } 34 | if (k == n) { 35 | res.push_back(i - n + 1); 36 | } 37 | } 38 | return res; 39 | // returns 0-indexed positions of occurrences of s in w 40 | } 41 | 42 | template 43 | vector kmp_search(const T &s, const T &w, const vector &p) { 44 | return kmp_search((int) s.size(), s, (int) w.size(), w, p); 45 | } -------------------------------------------------------------------------------- /string/manacher.cpp: -------------------------------------------------------------------------------- 1 | template 2 | vector manacher(int n, const T &s) { 3 | if (n == 0) { 4 | return vector(); 5 | } 6 | vector res(2 * n - 1, 0); 7 | int l = -1, r = -1; 8 | for (int z = 0; z < 2 * n - 1; z++) { 9 | int i = (z + 1) >> 1; 10 | int j = z >> 1; 11 | int p = (i >= r ? 0 : min(r - i, res[2 * (l + r) - z])); 12 | while (j + p + 1 < n && i - p - 1 >= 0) { 13 | if (!(s[j + p + 1] == s[i - p - 1])) { 14 | break; 15 | } 16 | p++; 17 | } 18 | if (j + p > r) { 19 | l = i - p; 20 | r = j + p; 21 | } 22 | res[z] = p; 23 | } 24 | return res; 25 | // res[2 * i] = odd radius in position i 26 | // res[2 * i + 1] = even radius between positions i and i + 1 27 | // s = "abaa" -> res = {0, 0, 1, 0, 0, 1, 0} 28 | // in other words, for every z from 0 to 2 * n - 2: 29 | // calculate i = (z + 1) >> 1 and j = z >> 1 30 | // now there is a palindrome from i - res[z] to j + res[z] 31 | // (watch out for i > j and res[z] = 0) 32 | } 33 | 34 | template 35 | vector manacher(const T &s) { 36 | return manacher((int) s.size(), s); 37 | } -------------------------------------------------------------------------------- /string/suffix_array.cpp: -------------------------------------------------------------------------------- 1 | template 2 | vector suffix_array(int n, const T &s, int char_bound) { 3 | vector a(n); 4 | if (n == 0) { 5 | return a; 6 | } 7 | if (char_bound != -1) { 8 | vector aux(char_bound, 0); 9 | for (int i = 0; i < n; i++) { 10 | aux[s[i]]++; 11 | } 12 | int sum = 0; 13 | for (int i = 0; i < char_bound; i++) { 14 | int add = aux[i]; 15 | aux[i] = sum; 16 | sum += add; 17 | } 18 | for (int i = 0; i < n; i++) { 19 | a[aux[s[i]]++] = i; 20 | } 21 | } else { 22 | iota(a.begin(), a.end(), 0); 23 | sort(a.begin(), a.end(), [&s](int i, int j) { return s[i] < s[j]; }); 24 | } 25 | vector sorted_by_second(n); 26 | vector ptr_group(n); 27 | vector new_group(n); 28 | vector group(n); 29 | group[a[0]] = 0; 30 | for (int i = 1; i < n; i++) { 31 | group[a[i]] = group[a[i - 1]] + (!(s[a[i]] == s[a[i - 1]])); 32 | } 33 | int cnt = group[a[n - 1]] + 1; 34 | int step = 1; 35 | while (cnt < n) { 36 | int at = 0; 37 | for (int i = n - step; i < n; i++) { 38 | sorted_by_second[at++] = i; 39 | } 40 | for (int i = 0; i < n; i++) { 41 | if (a[i] - step >= 0) { 42 | sorted_by_second[at++] = a[i] - step; 43 | } 44 | } 45 | for (int i = n - 1; i >= 0; i--) { 46 | ptr_group[group[a[i]]] = i; 47 | } 48 | for (int i = 0; i < n; i++) { 49 | int x = sorted_by_second[i]; 50 | a[ptr_group[group[x]]++] = x; 51 | } 52 | new_group[a[0]] = 0; 53 | for (int i = 1; i < n; i++) { 54 | if (group[a[i]] != group[a[i - 1]]) { 55 | new_group[a[i]] = new_group[a[i - 1]] + 1; 56 | } else { 57 | int pre = (a[i - 1] + step >= n ? -1 : group[a[i - 1] + step]); 58 | int cur = (a[i] + step >= n ? -1 : group[a[i] + step]); 59 | new_group[a[i]] = new_group[a[i - 1]] + (pre != cur); 60 | } 61 | } 62 | swap(group, new_group); 63 | cnt = group[a[n - 1]] + 1; 64 | step <<= 1; 65 | } 66 | return a; 67 | } 68 | 69 | template 70 | vector suffix_array(const T &s, int char_bound) { 71 | return suffix_array((int) s.size(), s, char_bound); 72 | } 73 | 74 | template 75 | vector build_lcp(int n, const T &s, const vector &sa) { 76 | assert((int) sa.size() == n); 77 | vector pos(n); 78 | for (int i = 0; i < n; i++) { 79 | pos[sa[i]] = i; 80 | } 81 | vector lcp(max(n - 1, 0)); 82 | int k = 0; 83 | for (int i = 0; i < n; i++) { 84 | k = max(k - 1, 0); 85 | if (pos[i] == n - 1) { 86 | k = 0; 87 | } else { 88 | int j = sa[pos[i] + 1]; 89 | while (i + k < n && j + k < n && s[i + k] == s[j + k]) { 90 | k++; 91 | } 92 | lcp[pos[i]] = k; 93 | } 94 | } 95 | return lcp; 96 | } 97 | 98 | template 99 | vector build_lcp(const T &s, const vector &sa) { 100 | return build_lcp((int) s.size(), s, sa); 101 | } -------------------------------------------------------------------------------- /string/z.cpp: -------------------------------------------------------------------------------- 1 | template 2 | vector z_function(int n, const T &s) { 3 | vector z(n, n); 4 | int l = 0, r = 0; 5 | for (int i = 1; i < n; i++) { 6 | z[i] = (i > r ? 0 : min(r - i + 1, z[i - l])); 7 | while (i + z[i] < n && s[z[i]] == s[i + z[i]]) { 8 | z[i]++; 9 | } 10 | if (i + z[i] - 1 > r) { 11 | l = i; 12 | r = i + z[i] - 1; 13 | } 14 | } 15 | return z; 16 | } 17 | 18 | template 19 | vector z_function(const T &s) { 20 | return z_function((int) s.size(), s); 21 | } -------------------------------------------------------------------------------- /template/hc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * author: tourist 3 | * created: $CURRENT_DATE.$CURRENT_MONTH.$CURRENT_YEAR $CURRENT_HOUR:$CURRENT_MINUTE:$CURRENT_SECOND 4 | **/ 5 | #include 6 | 7 | using namespace std; 8 | 9 | #ifdef LOCAL 10 | #include "algo/debug.h" 11 | #else 12 | #define debug(...) 42 13 | #endif 14 | 15 | int main() { 16 | ios::sync_with_stdio(false); 17 | cin.tie(nullptr); 18 | int tt; 19 | cin >> tt; 20 | for (int qq = 1; qq <= tt; qq++) { 21 | cout << "Case #" << qq << ": "; 22 | ${0} 23 | } 24 | return 0; 25 | } 26 | 27 | -------------------------------------------------------------------------------- /template/multithreaded.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * author: tourist 3 | * created: $CURRENT_DATE.$CURRENT_MONTH.$CURRENT_YEAR $CURRENT_HOUR:$CURRENT_MINUTE:$CURRENT_SECOND 4 | **/ 5 | #include 6 | 7 | using namespace std; 8 | 9 | class Solution { 10 | public: 11 | int k; 12 | string s, w; 13 | 14 | void readData() { 15 | 16 | } 17 | 18 | void solve(stringstream& out) { 19 | 20 | } 21 | }; 22 | 23 | const int maxThreads = 8; 24 | const int numTests = 1000; 25 | 26 | stringstream out[numTests]; 27 | mutex mu; 28 | int cur, tt; 29 | thread threads[maxThreads]; 30 | 31 | void solutionRunner() { 32 | while (true) { 33 | Solution s; 34 | int id; 35 | mu.lock(); 36 | if (cur >= tt) { 37 | mu.unlock(); 38 | return; 39 | } 40 | id = cur; 41 | cur++; 42 | s.readData(); 43 | mu.unlock(); 44 | s.solve(out[id]); 45 | } 46 | } 47 | 48 | using namespace std::chrono; 49 | 50 | int64_t now() { 51 | milliseconds ms = duration_cast(system_clock::now().time_since_epoch()); 52 | return ms.count(); 53 | } 54 | 55 | int main() { 56 | ios::sync_with_stdio(false); 57 | cin.tie(0); 58 | auto start = now(); 59 | cin >> tt; 60 | cur = 0; 61 | for (int i = 0; i < maxThreads; i++) { 62 | threads[i] = thread(solutionRunner); 63 | } 64 | for (int i = 0; i < maxThreads; i++) { 65 | threads[i].join(); 66 | } 67 | for (int i = 0; i < tt; i++) { 68 | cout << "Case #" << i + 1 << ": " << '\n'; 69 | cout << out[i].str(); 70 | } 71 | cerr << "time = " << now() - start << " ms" << endl; 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /template/multithreaded2.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * author: tourist 3 | * created: $CURRENT_DATE.$CURRENT_MONTH.$CURRENT_YEAR $CURRENT_HOUR:$CURRENT_MINUTE:$CURRENT_SECOND 4 | **/ 5 | #undef _GLIBCXX_DEBUG 6 | 7 | #include 8 | 9 | using namespace std; 10 | 11 | #ifdef LOCAL 12 | #include "algo/debug.h" 13 | #else 14 | #define debug(...) 42 15 | #endif 16 | 17 | mutex mut; 18 | int qq = 0; 19 | int tt; 20 | 21 | class Solution { 22 | public: 23 | int test_id; 24 | 25 | explicit Solution(int test_id_) : test_id(test_id_) {} 26 | 27 | ${0} 28 | 29 | void ReadData() { 30 | 31 | } 32 | 33 | void Solve(stringstream& out) { 34 | 35 | mut.lock(); 36 | debug(++qq, tt, test_id, clock()); 37 | mut.unlock(); 38 | } 39 | }; 40 | 41 | int main() { 42 | ios::sync_with_stdio(false); 43 | cin.tie(0); 44 | cin >> tt; 45 | vector solutions; 46 | solutions.reserve(tt); 47 | for (int test_id = 0; test_id < tt; test_id++) { 48 | solutions.emplace_back(test_id); 49 | solutions.back().ReadData(); 50 | } 51 | debug("input read, kicking off"); 52 | vector outs(tt); 53 | vector threads; 54 | threads.reserve(tt); 55 | for (int test_id = 0; test_id < tt; test_id++) { 56 | threads.emplace_back(&Solution::Solve, &solutions[test_id], ref(outs[test_id])); 57 | } 58 | for (int test_id = 0; test_id < tt; test_id++) { 59 | threads[test_id].join(); 60 | } 61 | for (int i = 0; i < tt; i++) { 62 | cout << "Case #" << i + 1 << ": " << outs[i].str(); 63 | } 64 | return 0; 65 | } 66 | 67 | -------------------------------------------------------------------------------- /template/q1.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * author: tourist 3 | * created: $CURRENT_DATE.$CURRENT_MONTH.$CURRENT_YEAR $CURRENT_HOUR:$CURRENT_MINUTE:$CURRENT_SECOND 4 | **/ 5 | #include 6 | 7 | using namespace std; 8 | 9 | #ifdef LOCAL 10 | #include "algo/debug.h" 11 | #else 12 | #define debug(...) 42 13 | #endif 14 | 15 | int main() { 16 | ios::sync_with_stdio(false); 17 | cin.tie(nullptr); 18 | ${0} 19 | return 0; 20 | } 21 | 22 | -------------------------------------------------------------------------------- /template/qt.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * author: tourist 3 | * created: $CURRENT_DATE.$CURRENT_MONTH.$CURRENT_YEAR $CURRENT_HOUR:$CURRENT_MINUTE:$CURRENT_SECOND 4 | **/ 5 | #include 6 | 7 | using namespace std; 8 | 9 | #ifdef LOCAL 10 | #include "algo/debug.h" 11 | #else 12 | #define debug(...) 42 13 | #endif 14 | 15 | int main() { 16 | ios::sync_with_stdio(false); 17 | cin.tie(nullptr); 18 | int tt; 19 | cin >> tt; 20 | while (tt--) { 21 | ${0} 22 | } 23 | return 0; 24 | } 25 | 26 | --------------------------------------------------------------------------------