├── README.txt ├── alpha ├── persique.cpp └── persistent_array.cpp ├── beta ├── binomial_composite_mod.cpp ├── dsu_bipartite.cpp ├── functional_graph.cpp ├── ilist_treap.cpp ├── linear_equations_solver.cpp ├── mincostflow.cpp ├── modint_unsigned.cpp ├── rrq.cpp └── rsq_segt.cpp ├── geometry └── point.cpp ├── graphs ├── 2sat.cpp ├── README.md ├── dijkstra.cpp ├── dsu.cpp ├── graph.cpp ├── strong_connected_components.cpp └── trees │ ├── README.md │ ├── centriod_decomposition.cpp │ ├── heavylight_decomposition.cpp │ └── tree_dp_root_each.cpp ├── misc ├── README.md ├── bitmask.cpp ├── nearest.cpp └── parallel_binary_search.cpp ├── numeric ├── binomial.cpp ├── crt.cpp ├── factorizer.cpp ├── factors.cpp ├── fibonacci.cpp ├── karatsuba.cpp ├── modint.cpp ├── modint_extentions.cpp ├── ntt.cpp └── sum_of_primes.cpp ├── strings ├── README.md ├── ext │ └── hash_multispan.cpp ├── hasher.cpp └── z_function.cpp ├── structs ├── aggregator.cpp ├── aggregator_queue.cpp ├── aggregator_range_operation.cpp ├── aggregator_static.cpp ├── ext │ ├── rsq_2d_point_add_rectangle_sum.cpp │ └── rsq_2d_rectangle_add_point_get.cpp ├── ilist.cpp ├── persistent_aggregator.cpp ├── rmq.cpp ├── rmq_range_add.cpp ├── rmq_range_assign.cpp ├── rmq_static.cpp ├── rsq.cpp ├── rsq_range_add.cpp └── rsq_range_assign.cpp ├── tests └── rmq_static.cpp └── well-known ├── area_of_union_of_rectangles.cpp ├── mex_rects.cpp ├── numeric_functions.cpp └── sqrt_solver_sorted_ranges.cpp /README.txt: -------------------------------------------------------------------------------- 1 | This is my competitive programming code library. There are many others like it, but this one is mine. My library is my best friend. It is my life. I must master it as I must master my life. Without me, my library is useless. Without my library, I am useless. I must compile my library successful. I must solve straighter than problemsetter, who is trying to challenge me. I must break problem before it breaks me. I will. Before Contest I swear this creed: my library and myself are defenders of my rating, we are the masters of problems, we are the saviors of my life. So be it, until system testing. Accepted. 2 | -------------------------------------------------------------------------------- /alpha/persique.cpp: -------------------------------------------------------------------------------- 1 | template struct persique { 2 | /* 3 | persistent deque 4 | invented by babin74 5 | */ 6 | private: 7 | struct node_base { 8 | virtual size_t size(); 9 | virtual const T& get_value(size_t i); 10 | virtual node_base* push_front(const T &x); 11 | virtual node_base* push_back(const T &x); 12 | virtual node_base* pop_front(); 13 | virtual node_base* pop_back(); 14 | }; 15 | struct node_empty; 16 | struct node_one; 17 | 18 | struct node: node_base { 19 | node_base *p0, *p1; 20 | const size_t sz; 21 | size_t size() { return sz; } 22 | node(node_base *q0, node_base *q1): p0(q0), p1(q1), sz(p0->size() + p1->size()) {} 23 | const T& get_value(size_t i) { 24 | assert(i < sz); 25 | return i%2 ? p1->get_value(i>>1) : p0->get_value(i>>1); 26 | } 27 | node *push_front(const T &x) { 28 | return new node(p1->push_front(x), p0); 29 | } 30 | node *push_back(const T &x) { 31 | return sz % 2 ? new node(p0, p1->push_back(x)) : new node(p0->push_back(x), p1); 32 | } 33 | node_base* pop_front() { 34 | if(sz == 2) return p1; 35 | return new node(p1, p0->pop_front()); 36 | }; 37 | node_base* pop_back() { 38 | if(sz == 2) return p0; 39 | return sz % 2 ? new node(p0->pop_back(), p1) : new node(p0, p1->pop_back()); 40 | } 41 | }; 42 | 43 | struct node_one: node_base { 44 | const T value; 45 | node_one(const T &x): value(x) {} 46 | size_t size() { return 1; } 47 | const T& get_value(size_t) { return value; } 48 | node* push_front(const T &x) { return new node(new node_one(x), this); } 49 | node* push_back(const T &x) { return new node(this, new node_one(x)); } 50 | node_empty* pop_front() { return empty_node; } 51 | node_empty* pop_back() { return empty_node; } 52 | }; 53 | 54 | struct node_empty: node_base { 55 | size_t size() { return 0; } 56 | const T& get_value(size_t) { assert(false); } 57 | node_one* push_front(const T &x) { return new node_one(x); } 58 | node_one* push_back(const T &x) { return new node_one(x); } 59 | node_base* pop_front() { assert(false); } 60 | node_base* pop_back() { assert(false); } 61 | }; 62 | static inline node_empty *empty_node = new node_empty(); 63 | 64 | node_base *p; 65 | persique(node_base *t): p(t) {} 66 | 67 | public: 68 | persique(): p(empty_node) {} 69 | 70 | size_t size() const { return p->size(); } 71 | bool empty() const { return p->size() == 0; } 72 | 73 | persique push_front(const T &x) const { return p->push_front(x); } 74 | persique push_back(const T &x) const { return p->push_back(x); } 75 | persique pop_front() const { return p->pop_front(); } 76 | persique pop_back() const { return p->pop_back(); } 77 | 78 | const T& operator[](size_t i) const { return p->get_value(i); } 79 | const T& front() const { return operator[](0); } 80 | const T& back() const { return operator[](size()-1); } 81 | }; 82 | -------------------------------------------------------------------------------- /alpha/persistent_array.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct persistent_array { 3 | struct node_base { 4 | virtual size_t length(); 5 | virtual const T& get(size_t); 6 | virtual node_base* set_value(size_t, const T&); 7 | }; 8 | struct node_leaf : node_base { 9 | node_leaf(const T& value): val(value) {} 10 | constexpr size_t length(){ return 1; } 11 | const T& get(size_t) { return val; } 12 | node_leaf* set_value(size_t, const T &value){ return new node_leaf(value); } 13 | private: T val; 14 | }; 15 | struct node : node_base { 16 | node(node_base *pl, node_base *pr): l(pl), r(pr), sz(pl->length()+pr->length()) {} 17 | inline size_t length(){ return sz; } 18 | const T& get(size_t i) { 19 | if(size_t m = l->length(); i < m) return l->get(i); 20 | else return r->get(i-m); 21 | } 22 | node* set_value(size_t i, const T& value) { 23 | if(size_t m = l->length(); i < m) return new node(l->set_value(i,value), r); 24 | else return new node(l, r->set_value(i-m,value)); 25 | } 26 | private: 27 | node_base *l, *r; 28 | size_t sz; 29 | }; 30 | persistent_array(const vector &vec): root(build(begin(vec),end(vec))) { } 31 | const T& operator[](size_t i) const { return root->get(i); } 32 | persistent_array set_value(size_t i, const T &value) const { return persistent_array(root->set_value(i,value)); } 33 | size_t size() const { return root ? root->length() : 0; } 34 | private: 35 | node_base *root; 36 | persistent_array(node_base *p): root(p) {} 37 | node_base* build(auto from, auto to) { 38 | if(from >= to) return nullptr; 39 | if(from+1 == to) return new node_leaf(*from); 40 | auto mid = from + (to - from)/2; 41 | return new node(build(from,mid),build(mid,to)); 42 | } 43 | }; -------------------------------------------------------------------------------- /beta/binomial_composite_mod.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct binomial { 3 | struct factorial_device { 4 | uint32_t p, mod; 5 | vector f; 6 | 7 | factorial_device(uint32_t p, uint32_t q): p(p), mod(pow(p, q)), f(mod) { 8 | assert(bmint::get_mod() % mod == 0); 9 | bmint prod = 1; 10 | for(uint32_t k=0; k operator()(uint64_t n) const { 17 | bmint res = 1; 18 | uint64_t q = 0; 19 | bool fq = 0; 20 | while(n > 1) { 21 | fq ^= (n / mod) &1; 22 | res *= f[n % mod]; 23 | n /= p; 24 | q += n; 25 | } 26 | return {p > 2 && fq ? -res : res, q}; 27 | } 28 | }; 29 | 30 | binomial() { 31 | vector mods; 32 | for(uint32_t x=bmint::get_mod(), p=2; x>1; ++p) { 33 | if(p * p > x) p = x; 34 | if(x % p == 0) { 35 | uint32_t q = 0; 36 | do ++q, x /= p; while(x % p == 0); 37 | fs.emplace_back(p, q); 38 | mods.push_back(fs.back().mod); 39 | } 40 | } 41 | crt = CRT{mods}; 42 | } 43 | 44 | bmint operator()(uint64_t n, uint64_t k) const { 45 | if(n < k) return 0; 46 | 47 | vector noms, denoms; 48 | for(auto &f : fs) { 49 | auto [x1, q1] = f(n); 50 | auto [x2, q2] = f(k); 51 | auto [x3, q3] = f(n-k); 52 | 53 | bmint nom = x1 * pow(bmint{f.p}, q1 - q2 - q3); 54 | bmint denom = x2 * x3; 55 | 56 | noms.push_back(*nom % f.mod); 57 | denoms.push_back(*denom % f.mod); 58 | } 59 | 60 | bmint nom = crt.template evaluate(noms); 61 | bmint denom = crt.template evaluate(denoms); 62 | return nom / denom; 63 | } 64 | 65 | private: 66 | CRT crt; 67 | vector fs; 68 | }; 69 | -------------------------------------------------------------------------------- /beta/dsu_bipartite.cpp: -------------------------------------------------------------------------------- 1 | struct dsu_bipartite { 2 | explicit dsu_bipartite(size_t n = 0): p(n), sz(n, 1), o(n) { 3 | iota(begin(p), end(p), 0); 4 | } 5 | size_t get(size_t i) const { 6 | if(i == p[i]) return i; 7 | size_t v = get(p[i]); 8 | o[i] ^= o[p[i]]; 9 | return p[i] = v; 10 | } 11 | bool unite(size_t i, size_t j, bool apart = true) { 12 | size_t vi = get(i), vj = get(j); 13 | if(vi == vj) return false; 14 | apart ^= o[i]^o[j]; 15 | i = vi; 16 | j = vj; 17 | if(sz[i] < sz[j]) swap(i, j); 18 | p[j] = i; 19 | o[j] = apart; 20 | sz[i] += sz[j]; 21 | return true; 22 | } 23 | bool is_safe_to_unite(size_t i, size_t j, bool apart) const { 24 | if(get(i) != get(j)) return true; 25 | return (o[i]^o[j]) == apart; 26 | } 27 | size_t get_part(size_t i) const { 28 | get(i); 29 | return o[i]; 30 | } 31 | private: 32 | mutable vector p; 33 | vector sz; 34 | mutable vector o; 35 | }; 36 | -------------------------------------------------------------------------------- /beta/functional_graph.cpp: -------------------------------------------------------------------------------- 1 | struct func_graph { 2 | func_graph(const std::ranges::range auto &f = std::ranges::empty_view{}) { 3 | const vector p(begin(f), end(f)); 4 | const size_t n = size(p); 5 | if(n == 0) return ; //nothing bad just skip overhead 6 | assert(*std::ranges::max_element(p) < n); 7 | 8 | size_t vn = 0; 9 | vs_pos.resize(n); 10 | 11 | size_t gn = 0, g_none = -1; 12 | vector g_id(n), g_par(n), ts; 13 | 14 | jump.resize(n); 15 | jump_len.resize(n); 16 | vector on_cyc(n, false); 17 | vector used(n, n); 18 | for(size_t i=0; i path; 20 | for(size_t v=i; ; ) { 21 | used[v] = i; 22 | path.push_back(v); 23 | v = p[v]; 24 | if(used[v] <= i) { 25 | if(used[v] == i) { 26 | const auto itv = find(begin(path), end(path), v); 27 | for(auto it = itv; it != end(path); ++it) { 28 | size_t x = *it; 29 | vs_pos[x] = vn++; 30 | jump[x] = v; 31 | jump_len[x] = end(path) - it; 32 | on_cyc[x] = true; 33 | } 34 | path.erase(itv, end(path)); 35 | } 36 | break ; 37 | } 38 | used[v] = i; 39 | } 40 | for(size_t x : std::views::reverse(path)) { 41 | g_id[x] = gn++; 42 | g_par[g_id[x]] = on_cyc[p[x]] ? g_none : g_id[p[x]]; 43 | ts.push_back(x); 44 | } 45 | } 46 | 47 | vector> g(gn + 1); 48 | std::ranges::replace(g_par, g_none, gn); 49 | for(size_t i=0; i vs_pos, jump, jump_len; 77 | 78 | struct path_iterator { 79 | const func_graph &fg; 80 | size_t v; 81 | void operator++() { if(size_t t = fg.jump[v]; t == v) v = -1; else v = t; } 82 | bool operator!=(const path_iterator &it) const { return v != it.v; } 83 | tuple operator*() const { 84 | size_t l = fg.index(v); 85 | bool last = v == fg.jump[v]; 86 | return {l, l + fg.jump_len[v], last}; 87 | } 88 | }; 89 | }; 90 | -------------------------------------------------------------------------------- /beta/ilist_treap.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct ilist_treap { 3 | 4 | struct node { 5 | private: friend ilist_treap; 6 | node *l, *r, *p; 7 | const size_t priority; 8 | size_t sz; 9 | T *value; 10 | node(const T &x): node(new T(x)) {} 11 | node(T *ptr = nullptr): l(nullptr), r(nullptr), p(nullptr), priority(gen()), sz(1), value(ptr) { } 12 | static inline auto gen = mt19937_64(chrono::high_resolution_clock::now().time_since_epoch().count()); 13 | }; 14 | 15 | template 16 | struct node_iterator: public std::iterator { 17 | private: friend ilist_treap; 18 | node *t; 19 | node_iterator(node *ptr): t(ptr) { } 20 | public: 21 | node_iterator(): node_iterator(nullptr) { } 22 | V& operator*() { return *t->value; } 23 | bool operator==(const node_iterator &it) { return t == it.t; } 24 | bool operator!=(const node_iterator &it) { return t != it.t; } 25 | 26 | node_iterator& operator++() { 27 | t = t->r ? leftmost(t->r) : right_parent(t); 28 | return *this; 29 | } 30 | 31 | node_iterator& operator--() { 32 | t = t->l ? rightmost(t->l) : left_parent(t); 33 | return *this; 34 | } 35 | 36 | node_iterator& operator+=(size_t n) { 37 | for(; n--; t = right_parent(t)) 38 | if(size_t sr = sz(t->r); n < sr) { 39 | t = nth(t->r, n); 40 | break ; 41 | } else n-=sr; 42 | return *this; 43 | } 44 | 45 | node_iterator& operator-=(size_t n) { 46 | for(; n--; t = left_parent(t)) 47 | if(size_t sl = sz(t->l); n < sl) { 48 | t = nth(t->l, sl-n-1); 49 | break ; 50 | } else n-=sl; 51 | return *this; 52 | } 53 | 54 | node_iterator operator+(size_t n) const { return node_iterator(t)+=n; } 55 | node_iterator operator-(size_t n) const { return node_iterator(t)-=n; } 56 | 57 | size_t operator-(const node_iterator &it) const { 58 | return get_pos(t) - get_pos(it.t); 59 | } 60 | }; 61 | 62 | using iterator = node_iterator; 63 | using const_iterator = node_iterator; 64 | 65 | struct extracted { 66 | private: friend ilist_treap; 67 | extracted(node *ptr): t(ptr) {} 68 | node *t; 69 | }; 70 | 71 | 72 | ilist_treap() { 73 | root = __end = new node(); 74 | } 75 | 76 | explicit ilist_treap(size_t n, const T &value = {}) { 77 | node* nodes = init_nodes(n); 78 | for(size_t i=0; i> 82 | ilist_treap(_InputIterator first, _InputIterator last) { 83 | size_t n = std::distance(first, last); 84 | node* nodes = init_nodes(n); 85 | for(size_t i=0; ip; 139 | assert(t != __end); 140 | node *&target = p ? ref_in_parent(t) : root; 141 | if(target = merge(t->l, t->r)) target->p = p; 142 | for(node *v = p; v; v = v->p) upd_sz(v); 143 | t->p = t->l = t->r = nullptr; 144 | t->sz = 1; 145 | return iterator(t); 146 | } 147 | 148 | private: 149 | node *root, *__end; 150 | 151 | ilist_treap(node *v): ilist_treap() { 152 | root = merge(v, __end); 153 | } 154 | 155 | node* init_nodes(size_t n) { 156 | node *nodes = new node[n+1]; 157 | T *values = new T[n]; 158 | for(size_t i=0; ipriority < v->priority) { 175 | while(t->p && t->p->priority < v->priority) t = t->p; 176 | if(node *p = t->p; p == nullptr) root = v; 177 | else ref_in_parent(t) = v, v->p = p, t->p = nullptr; 178 | auto [sl, sr] = split(s); 179 | set_left(v, sl); 180 | set_right(v, sr); 181 | } else 182 | if(s->l == nullptr) set_left(s, v); 183 | else { 184 | for(t = s->l; t->r && t->r->priority > v->priority; t = t->r) ; 185 | set_left(v, t->r); 186 | set_right(t, v); 187 | } 188 | for(node *t = v; t; t = t->p) upd_sz(t); 189 | return iterator(v); 190 | } 191 | 192 | static inline size_t sz(node *t) { return t ? t->sz : 0; } 193 | static inline node*& ref_in_parent(node *t) { return t->p->l == t ? t->p->l : t->p->r; } 194 | static inline void set_left(node *v, node *to) { v->l = to; if(to) to->p = v; } 195 | static inline void set_right(node *v, node *to) { v->r = to; if(to) to->p = v; } 196 | static inline void upd_sz(node *t) { if(t) t->sz = sz(t->l) + sz(t->r) + 1; } 197 | 198 | static node* leftmost(node *t) { 199 | while(t->l) t = t->l; 200 | return t; 201 | } 202 | 203 | static node* rightmost(node *t) { 204 | while(t->r) t = t->r; 205 | return t; 206 | } 207 | 208 | static inline node* left_parent(node *t) { 209 | while(t->p->l == t) t = t->p; 210 | return t->p; 211 | } 212 | 213 | static inline node* right_parent(node *t) { 214 | while(t->p->r == t) t = t->p; 215 | return t->p; 216 | } 217 | 218 | static size_t get_pos(node *t) { 219 | size_t pos = sz(t->l); 220 | for(; t->p; t = t->p) if(t->p->r == t) pos += sz(t->p->l)+1; 221 | return pos; 222 | } 223 | 224 | static node* nth(node *v, size_t n) { 225 | assert(n < sz(v)); 226 | for(;;) { 227 | size_t sl = sz(v->l); 228 | if(n == sl) return v; 229 | if(n < sl) v = v->l; 230 | else n -= sl+1, v = v->r; 231 | } 232 | } 233 | 234 | static node* merge(node *l, node *r) { 235 | if(l == nullptr) return r; 236 | if(r == nullptr) return l; 237 | if(l->priority > r->priority) { 238 | l->sz += r->sz; 239 | set_right(l, merge(l->r, r)); 240 | return l; 241 | } else { 242 | r->sz += l->sz; 243 | set_left(r, merge(l, r->l)); 244 | return r; 245 | } 246 | } 247 | 248 | //split by *s such right starts with *s 249 | static pair split(node *s) { 250 | node *l = s->l, *r = s; 251 | if(s->l) s->l->p = nullptr, s->l = nullptr; 252 | upd_sz(r); 253 | for(bool f = true; s->p; ) { 254 | bool cur = s->p->l == s; 255 | s = s->p; 256 | if(f != cur) { 257 | if(cur) set_left(s, r), l->p = nullptr; 258 | else set_right(s, l), r->p = nullptr; 259 | f = cur; 260 | } 261 | if(cur) r = s; else l = s; 262 | upd_sz(s); 263 | } 264 | return {l, r}; 265 | } 266 | 267 | static node* build(node *l, node *r) { 268 | if(l == r) return nullptr; 269 | for(node *t = l++; ; ++l) if(l == r || t->priority < l->priority) { 270 | set_right(t, build(t+1, l)); 271 | upd_sz(t); 272 | if(l == r) return t; 273 | set_left(l, t); 274 | t = l; 275 | } 276 | } 277 | }; 278 | //template using ilist = ilist_treap; 279 | -------------------------------------------------------------------------------- /beta/linear_equations_solver.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct linear_equations_solver { 3 | linear_equations_solver(size_t n): n(n) {} 4 | 5 | void add(const vector &line, const T &value) { 6 | assert(size(line) == n); 7 | a.push_back(line); 8 | b.push_back(value); 9 | } 10 | 11 | optional> solve() { 12 | vector res(n, 0); 13 | for(size_t r=0, c=0; c> a; 55 | vector b; 56 | }; 57 | -------------------------------------------------------------------------------- /beta/mincostflow.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct mincost_flow_graph { 3 | mincost_flow_graph(size_t n): mincost_flow_graph(n, 0, n-1) {} 4 | mincost_flow_graph(size_t n, size_t s, size_t t): g(n), S(s), T(t), p(n) {} 5 | 6 | void add_edge(size_t from, size_t to, F cap, C cost) { 7 | assert(0 <= from && from < size(g)); 8 | g[from].push_back(size(edges)); 9 | edges.push_back({to, 0, cap, cost}); 10 | assert(0 <= to && to < size(g)); 11 | g[to].push_back(size(edges)); 12 | edges.push_back({from, 0, 0, -cost}); 13 | } 14 | 15 | struct result { F flow; C cost; }; 16 | result push(F flow = numeric_limits::max()) { 17 | vector fr(size(p), -1); 18 | vector d(size(p), numeric_limits::max()); 19 | priority_queue, vector>, greater>> q; 20 | q.emplace(d[S] = 0, S); 21 | while(!empty(q)) { 22 | auto [di, i] = q.top(); 23 | q.pop(); 24 | if(di > d[i]) continue ; 25 | for(size_t k : g[i]) if(edges[k].rem() > 0) { 26 | size_t j = edges[k].to; 27 | C dist = d[i] + edges[k].cost + p[i] - p[j]; 28 | if(dist < d[j]) q.emplace(d[j] = dist, j), fr[j] = k; 29 | } 30 | } 31 | 32 | if(fr[T] == -1) return {0, 0}; 33 | 34 | for(size_t k = fr[T]; k != -1; k = fr[edges[k^1].to]) 35 | flow = std::min(flow, edges[k].rem()); 36 | 37 | C cost = 0; 38 | for(size_t k = fr[T]; k != -1; k = fr[edges[k^1].to]) { 39 | cost += edges[k].cost * C(flow); 40 | edges[k].flow += flow; 41 | edges[k^1].flow -= flow; 42 | } 43 | 44 | for(size_t i = 0; i < size(p); ++i) p[i] += d[i]; 45 | return {flow, cost}; 46 | } 47 | 48 | optional mincost(F flow) { 49 | C cost = 0; 50 | while(flow > 0) 51 | if(auto [f, c] = push(flow); f == 0) return nullopt; 52 | else flow -= f, cost += c; 53 | return cost; 54 | } 55 | 56 | result mincost_maxflow() { 57 | F flow = 0; 58 | C cost = 0; 59 | for(;;) { 60 | result r = push(); 61 | if(r.flow == 0) return {flow, cost}; 62 | flow += r.flow; 63 | cost += r.cost; 64 | } 65 | } 66 | 67 | private: 68 | vector> g; 69 | size_t S, T; 70 | vector p; 71 | struct edge { 72 | size_t to; 73 | F flow, cap; 74 | C cost; 75 | F rem() { return cap - flow; } 76 | }; 77 | vector edges; 78 | }; 79 | -------------------------------------------------------------------------------- /beta/modint_unsigned.cpp: -------------------------------------------------------------------------------- 1 | template requires same_as, uint32_t> 2 | struct modint { 3 | modint(): x(0) {} 4 | modint(int64_t val): x(val%mod) { if(x<0) x+=mod; } 5 | modint(unsigned_integral auto val): x(val%mod) {} 6 | static constexpr uint32_t get_mod() { return mod; } 7 | #define __op(O, E, F) modint& operator E(const modint &b) { F return *this; } friend modint operator O(modint a, const modint &b) { return a E b; } 8 | __op(+, +=, if(uint32_t v=mod-b.x; x >= v) x -= v; else x += b.x; ) 9 | __op(-, -=, if(x < b.x) x += mod-b.x; else x -= b.x; ) 10 | __op(*, *=, x = uint64_t(x)*b.x %mod; ) 11 | __op(/, /=, auto i=b.inverse(); assert(i); x = uint64_t(i->x)*x %mod; ) 12 | friend modint operator-(modint a) { if(a.x) a.x = mod - a.x; return a; } 13 | friend modint pow(modint a, uint64_t n) { modint p=1; for(; n; n>>=1, a*=a) if(n&1) p*=a; return p; } 14 | optional inverse() const { 15 | uint32_t a = x, m = mod, p = 1, q = 0; bool q_neg = true; 16 | while(a) swap(p, q += (m / a) * p), swap(a, m %= a), q_neg ^= true; 17 | if(m == 1) return q_neg ? mod - q : q; else return nullopt; 18 | } 19 | bool operator==(const modint&) const = default; 20 | friend ostream& operator<<(ostream &o, const modint &m) { return o< struct rrq { 2 | rrq(const vector &vals, auto build): vals(vals), d(size(vals)), t(d*2) { 3 | for(size_t i=0; i1; ) { 5 | t[i].resize(size(t[i*2])+size(t[i*2+1])); 6 | merge(begin(t[i*2]),end(t[i*2]),begin(t[i*2+1]),end(t[i*2+1]),begin(t[i]),[&](size_t i, size_t j) { 7 | return vals[i] < vals[j]; 8 | }); 9 | } 10 | for(size_t i=1; i>=1, r>>=1) { 15 | if(l&1) call(lower, upper, l, process), ++l; 16 | if(r&1) --r, call(lower, upper, r, process); 17 | } 18 | } 19 | 20 | void operator()(size_t i, auto &&process) const { 21 | for(size_t v=i+d; v; v>>=1) process(v-1, lb(t[v], vals[i])); 22 | } 23 | 24 | private: 25 | vector vals; 26 | size_t d; 27 | vector> t; 28 | inline void call(const T &lower, const T &upper, size_t k, auto&& process) const { 29 | if(size_t l = lb(t[k], lower), r = lb(t[k], upper); l < r) process(k-1, l, r); 30 | } 31 | inline size_t lb(const vector &v, const T &val) const { 32 | return partition_point(begin(v), end(v), [&](size_t i) { return vals[i] < val; }) - begin(v); 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /beta/rsq_segt.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct rsq { 3 | explicit rsq(size_t n = 0): d(n), t(d*2) {} 4 | rsq(const vector &vals): rsq(size(vals)) { 5 | copy(begin(vals), end(vals), begin(t)+d); 6 | for(size_t i=d; i-->1;) t[i] = t[i*2]+t[i*2+1]; 7 | } 8 | void add(size_t i, const T &val) { 9 | for(i+=d; i; i>>=1) t[i] += val; 10 | } 11 | void set_value(size_t i, const T &val) { 12 | if constexpr (has_minus) add(i, val - t[i+d]); 13 | else for(t[i+=d]=val; i>1; i>>=1) t[i>>1] = t[i] + t[i^1]; 14 | } 15 | T operator()(size_t l, size_t r) const { 16 | T s{}; 17 | for(l+=d, r+=d; l>=1, r>>=1) { 18 | if(l&1) s+=t[l], ++l; 19 | if(r&1) --r, s+=t[r]; 20 | } 21 | return s; 22 | } 23 | const T& operator()() const { return t[1]; } 24 | const T& operator[](size_t i) const { return t[i+d]; } 25 | private: 26 | size_t d; 27 | valarray t; 28 | }; 29 | -------------------------------------------------------------------------------- /geometry/point.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct point_t { 3 | T x, y; 4 | point_t(): x(0), y(0) {} 5 | point_t(const T&x, const T&y): x(x), y(y) {} 6 | 7 | point_t& operator+=(const point_t &p) { x+=p.x; y+=p.y; return *this; } 8 | friend point_t operator+(point_t a, const point_t &b) { return a+=b; } 9 | 10 | point_t& operator-=(const point_t &p) { x-=p.x; y-=p.y; return *this; } 11 | friend point_t operator-(point_t a, const point_t &b) { return a-=b; } 12 | 13 | point_t& operator*=(auto &&k) { x*=k; y*=k; return *this; } 14 | friend point_t operator*(point_t a, auto &&k) { return a*=k; } 15 | 16 | point_t operator-() const { return point_t{-x, -y}; } 17 | 18 | auto operator<=>(const point_t &p) const = default; 19 | 20 | friend istream& operator>>(istream&i, point_t &p) { return i >> p.x >> p.y; } 21 | 22 | friend auto sp(const point_t &a, const point_t &b) { 23 | return (M)a.x * b.x + (M)a.y * b.y; 24 | } 25 | 26 | friend auto vp(const point_t &a, const point_t &b) { 27 | return (M)a.x * b.y - (M)a.y * b.x; 28 | } 29 | 30 | friend auto vp(const point_t &a, const point_t &b, const point_t &c) { 31 | return vp(a - c, b - c); 32 | } 33 | }; 34 | 35 | using point = point_t; 36 | ostream& operator<<(ostream&o, const point &p) { return o << "(" << p.x << ", " << p.y << ")"; } 37 | -------------------------------------------------------------------------------- /graphs/2sat.cpp: -------------------------------------------------------------------------------- 1 | struct sat2 { //sat2 a(n); a[i] || !a[j]; 2 | explicit sat2(size_t n = 0): n(n), g(n*2) {} 3 | 4 | struct item { 5 | sat2 &s; size_t i; bool value; 6 | void operator||(const item &o) { s.add_or(i, value, o.i, o.value); } 7 | item operator!() { return {s, i, !value}; } 8 | void operator=(bool val) { s.add_or(i, val, i, val); } 9 | }; 10 | item operator[](size_t i) { return {*this, i, true}; } 11 | 12 | void add_or(size_t i, bool fi, size_t j, bool fj) { 13 | g.add_dir_edge(i+n*fi, j+n*!fj); 14 | g.add_dir_edge(j+n*fj, i+n*!fi); 15 | } 16 | 17 | optional> solve() { 18 | auto cp = strong_connected_components(g).second; 19 | vector res(n); 20 | for(size_t i=0; i y; 24 | } 25 | return res; 26 | } 27 | 28 | private: size_t n; graph g; 29 | }; 30 | -------------------------------------------------------------------------------- /graphs/README.md: -------------------------------------------------------------------------------- 1 | # DSU 2 | ```c++ 3 | dsu g(n); 4 | g.unite(i, j); //true iff i and j was disconnected 5 | if(g[a] == g[b]) //check connection by compare leaders 6 | g.size(v); //size of component 7 | ``` 8 | 9 | # Graph 10 | creating graph of size n 11 | ```c++ 12 | graph g(n); 13 | assert(size(g) == n); 14 | ``` 15 | adding edges 16 | ```c++ 17 | g.add_edge(i, j); 18 | g.add_dir_edge(from, to); 19 | ``` 20 | iterating 21 | ```c++ 22 | for(size_t i : g[v]) 23 | for(int i : g[v]) 24 | ``` 25 | 26 | graphs with edges with information 27 | ```c++ 28 | graph_t g(n); 29 | g.add_edge(i, j, weight, id); 30 | for(auto [i, w, id] : g[v]) //full edge {v, i, w, id} 31 | for(size_t i : g[v]) //only vertex 32 | ``` 33 | 34 | # 2-SAT 35 | 36 | ```c++ 37 | sat2 a(n); 38 | a[i] || !a[j]; //set rule 39 | a[i] = true; //instead of a[i] || a[i] 40 | if(auto res = a.solve()) //solution is *res 41 | else //no solution 42 | ``` 43 | -------------------------------------------------------------------------------- /graphs/dijkstra.cpp: -------------------------------------------------------------------------------- 1 | template 2 | auto dijkstra(const S &start, auto &&gen) { 3 | /*unordered_*/map> dist{{start,{0,start}}}; 4 | for(set> q{{0,start}}; !empty(q); ) { 5 | auto [dv, v] = move(q.extract(begin(q)).value()); 6 | gen(as_const(v), [&](const S &t, W cost) { 7 | const W cur = dv + cost; 8 | if(auto it = dist.find(t); it == end(dist)) { 9 | dist.emplace(t, pair{cur, v}); 10 | q.emplace(cur, t); 11 | } else if(auto &[dt, how] = it->second; cur < dt) { 12 | auto e = q.extract({dt, t}); 13 | e.value().first = dt = cur; 14 | how = v; 15 | q.insert(move(e)); 16 | } 17 | }); 18 | } 19 | return dist; 20 | }; //pass gen as [&](auto &v, auto &&upd) {/*upd(to, edge_cost)*/} 21 | -------------------------------------------------------------------------------- /graphs/dsu.cpp: -------------------------------------------------------------------------------- 1 | struct dsu { 2 | explicit dsu(size_t n = 0): p(n), sz(n,1) { iota(begin(p),end(p),0); } 3 | size_t get(size_t i) const { 4 | size_t v = i; 5 | while(v != p[v]) v = p[v]; 6 | while(i != p[i]) i = exchange(p[i], v); 7 | return v; 8 | } 9 | bool unite(size_t i, size_t j) { 10 | i = get(i); 11 | j = get(j); 12 | if(i == j) return false; 13 | if(sz[i] < sz[j]) swap(i, j); 14 | p[j] = i; 15 | sz[i] += sz[j]; 16 | return true; 17 | } 18 | size_t size(size_t i) const { return sz[get(i)]; } 19 | size_t operator[](size_t i) const { return get(i); } 20 | private: mutable vector p, sz; 21 | }; 22 | -------------------------------------------------------------------------------- /graphs/graph.cpp: -------------------------------------------------------------------------------- 1 | template struct edge_t : public tuple { 2 | edge_t(auto&&... args): tuple(args...) {} 3 | operator size_t() const { return get<0>(*this); } 4 | }; 5 | template struct std::tuple_size> : tuple_size> {}; 6 | template struct std::tuple_element> : tuple_element> {}; 7 | #if __glibcxx_tuple_like 8 | template constexpr bool std::__is_tuple_like_v> = true; 9 | #endif 10 | 11 | template struct graph_t { 12 | using E = conditional_t, size_t>; 13 | explicit graph_t(size_t n): g(n) {} 14 | void add_dir_edge(size_t from, size_t to, const T&... args) { 15 | assert(from& operator[](size_t i) const { return g[i]; } 23 | size_t size() const { return g.size(); } 24 | private: vector> g; 25 | }; 26 | using graph = graph_t<>; 27 | -------------------------------------------------------------------------------- /graphs/strong_connected_components.cpp: -------------------------------------------------------------------------------- 1 | auto strong_connected_components(const auto &g) { 2 | size_t n = size(g), tn = 0, cn = 0, sn = 0; 3 | vector t(n), h(n), c(n), s(n); 4 | function css = [&](size_t v) { 5 | h[v] = t[v] = ++tn; 6 | s[sn++] = v; 7 | for(size_t i : g[v]) { 8 | if(!t[i]) css(i); 9 | if(!c[i] && h[i] < h[v]) h[v] = h[i]; 10 | } 11 | if(h[v] == t[v]) for(++cn; !c[v];) c[s[--sn]] = cn; 12 | }; 13 | for(size_t i=0; i 16 | To construct offline data structure use following snippet 17 | 18 | It returns pair of vectors `level` and `centroid_parent`. Levels numbered from 0 and `level[v] = level[cpar[v]]+1`. 19 | ```c++ 20 | auto centriod_decomposition_offline(const auto &g) { 21 | vector cpar(size(g), -1), w; 22 | centriod_decomposition(g, [&](auto &g, size_t centroid, size_t sizeof_subtree) { 23 | w.push_back(centroid); 24 | for(size_t i : g[centroid]) { 25 | while(cpar[i] != -1) i = cpar[i]; 26 | cpar[i] = centroid; 27 | } 28 | }); 29 | vector level(size(g)); 30 | if(size_t i=size(g)) for(--i; i--; ) level[w[i]] = level[cpar[w[i]]] + 1; 31 | return pair{level, cpar}; 32 | } 33 | ``` 34 | 35 | 36 |
37 | 38 | # Heavy-light Decomposition 39 | ```c++ 40 | heavy_light_decomposition hld(g); //root = 0 by default, otherwise hld(g, root) 41 | ``` 42 | Build takes $O(n)$ time and memory. 43 | 44 | Permutes vertices such vertex `v` now in position `hld.index(v)`. 45 | 46 | ### Path Queries 47 | Decomposes path from `a` to `b` into $O(\log n)$ ranges from permutation. 48 | ```c++ 49 | hld.decompose(a, b, [&](size_t l, size_t r) { 50 | //range [l, r) 51 | }); 52 | ``` 53 | 54 | Ordered path decomposition. All ranges called in correct order as moving from `a` to `b`. 55 | ```c++ 56 | hld.decompose_ordered(a, b, [&](size_t l, size_t r, bool reversed) { 57 | //range [l, r) 58 | if(reversed) // assume range from r-1 to l 59 | else //usual from l to r-1 60 | }); 61 | ``` 62 | 63 | To exclude LCA(a,b) from decomposition pass `exclude_lca = true` as last parameter 64 | ```c++ 65 | hld.decompose(a, b, [&](size_t l, size_t r) { ... }, true); 66 | ``` 67 | 68 | ### LCA 69 | To find lowest common ancestor in $O(\log n)$ use `c = hld.lca(a, b)`. 70 | 71 | But as bonus both `decompose` and `decompose_ordered` returns LCA too. 72 | 73 | ### Decomposition by height 74 | `heavy_light_decomposition(g, root, true)` builds Longest-path decomposition (i.e. heavy edge going to subtree with maximum height). 75 | Convinient for linear time DP on tree. 76 | Methods `decompose`/`lca` works correct but in $O(\sqrt n)$ on [worst case](https://codeforces.com/blog/entry/75410). 77 | 78 |
79 | 80 | # Tree DP Root Each 81 | Calculates DP for each vertex as root of given forest (not only connected tree). 82 | ```c++ 83 | vector res = tree_dp_root_each(g, 84 | [](size_t v) { ... }, //single vertex 85 | [](T dv, T di, auto &edge) { ... } //link function 86 | ); 87 | ``` 88 | `link` means subtree rooted at `i` linked to subtree rooted at `v` (by edge `[v, i]`). 89 | 90 | `edge` exists in `g` and can be used as `auto [v, i, ...] = edge`. 91 | 92 | `dv` is DP of some subtree with root `v` (same for `di` and `i`). 93 | 94 | `link` will be called $O(n\log n)$ times in worst case (more precisely $O(\log(deg_v))$ for each edge [v, i]). 95 | `single` will be called exaclty 2 times for each vertex. 96 | 97 |
98 | Code examples for problems 99 | 100 | Diameter of forest 101 | ```c++ 102 | auto res = tree_dp_root_each(g, 103 | [](size_t v) { return 1; }, 104 | [](int dv, int di, ...) { return max(dv, di+1); } 105 | ); 106 | int diam = *max_element(begin(res), end(res)); 107 | ``` 108 | 109 | [codeforces 1324F](https://codeforces.com/contest/1324/problem/F): Best subtree by balance 110 | ```c++ 111 | auto res = tree_dp_root_each(g, 112 | [&](size_t v){ return a[v] ? 1 : -1; }, 113 | [](int dv, int di, ...) { return dv + max(di, 0); } 114 | ); 115 | ``` 116 | 117 | [atcoder](https://atcoder.jp/contests/dp/tasks/dp_v): Count of black connected subtrees 118 | ```c++ 119 | auto res = tree_dp_root_each(g, 120 | [](size_t v) { return 1; }, 121 | [](mint dv, mint di, ...) { return dv * (di+1); } 122 | ); 123 | ``` 124 | 125 | [codeforces 960E](https://codeforces.com/contest/960/problem/E): +- sum of all paths 126 | ```c++ 127 | struct S { 128 | mint sum, cnt; //sum/count of paths started from root 129 | }; 130 | 131 | auto res = tree_dp_root_each(g, 132 | [&](size_t v) { return S{a[v], 1}; }, 133 | [&](S dv, S di, auto &edge) { 134 | auto [v, i] = edge; 135 | return S{ 136 | dv.sum + a[v] * di.cnt - di.sum, 137 | dv.cnt + di.cnt 138 | }; 139 | } 140 | ); 141 | ``` 142 |
143 | -------------------------------------------------------------------------------- /graphs/trees/centriod_decomposition.cpp: -------------------------------------------------------------------------------- 1 | template 2 | void centriod_decomposition(const graph_t &g, auto &&action) { 3 | const size_t n = size(g); if(n == 0) return ; 4 | vector sub(n, 1), p(n, -1), q(n); 5 | for(size_t qn=1; size_t v : q) 6 | for(size_t i : g[v]) if(i!=p[v]) q[qn++] = i, p[i] = v; 7 | for(size_t i=n-1; i; --i) sub[p[q[i]]] += sub[q[i]]; 8 | graph_t tree(n); 9 | function go = [&](size_t c) { 10 | const size_t sz = sub[c]; 11 | for(size_t pr = -1; exchange(pr,c) != c; ) 12 | for(size_t i : g[c]) if(sub[i] > sz/2) 13 | sub[c] -= sub[i], sub[i] = sz, c = i; 14 | sub[c] = 0; 15 | for(auto &e : g[c]) if(size_t i=e; sub[i]) { 16 | go(i); 17 | apply([&](auto&&...x){ tree.add_edge(c, x...); }, edge_t{e}); 18 | } 19 | action(as_const(tree), c, sz); 20 | }; 21 | go(0); 22 | } 23 | //use action as [&](auto &g, size_t centroid, size_t sizeof_subtree) 24 | -------------------------------------------------------------------------------- /graphs/trees/heavylight_decomposition.cpp: -------------------------------------------------------------------------------- 1 | struct heavy_light_decomposition { 2 | heavy_light_decomposition(const auto &g, size_t root = 0, bool use_longest_path = false): 3 | par(size(g),-1), header(size(g),-1), tin(size(g)) 4 | { 5 | calc(g, root, use_longest_path); 6 | size_t tn = 0; 7 | build(g, root, root, tn); 8 | assert(tn == size(g)); 9 | } 10 | 11 | size_t index(size_t v) const { return tin[v]; } 12 | 13 | size_t lca(size_t x, size_t y) const { return decompose(x, y, [](...){}); } 14 | 15 | size_t decompose(size_t x, size_t y, auto &&process_range, bool exclude_lca = false) const { 16 | for(size_t v;; process_range(tin[v], tin[y] + 1), y = par[v]) { 17 | if(tin[x] > tin[y]) swap(x, y); 18 | if((v = header[y]) == header[x]) break ; 19 | } 20 | if(size_t l = tin[x]+exclude_lca, r = tin[y]+1; l < r) process_range(l, r); 21 | return x; 22 | } 23 | 24 | size_t decompose_ordered(size_t x, size_t y, auto &&process_range, bool exclude_lca = false) const { 25 | vector> sl, sr; 26 | auto f = [&, m = min(tin[x], tin[y])](size_t l, size_t r) { (r-1 > m ? sr : sl).emplace_back(l, r); }; 27 | size_t z = decompose(x, y, f, exclude_lca); 28 | if(tin[x] > tin[y]) sl.swap(sr); 29 | for(auto [l, r] : sl) process_range(l, r, true); 30 | for(auto [l, r] : views::reverse(sr)) process_range(l, r, false); 31 | return z; 32 | } 33 | 34 | private: vector par, header, tin; 35 | 36 | size_t calc(const auto &g, size_t v, bool use_longest_path) { 37 | size_t mx = 0, sz = 1; 38 | for(size_t i : g[v]) if(i!=par[v]) { 39 | par[i] = v; 40 | size_t x = calc(g, i, use_longest_path); 41 | if(x > mx) mx = x, header[v] = i; 42 | sz += x; 43 | } 44 | return use_longest_path ? mx + 1 : sz; 45 | } 46 | 47 | void build(const auto &g, size_t v, size_t f, size_t &tn) { 48 | tin[v] = tn++; 49 | size_t mx = exchange(header[v], f); 50 | if(mx != -1) build(g, mx, f, tn); 51 | for(size_t i : g[v]) if(i!=par[v] && i!=mx) build(g, i, i, tn); 52 | } 53 | }; 54 | -------------------------------------------------------------------------------- /graphs/trees/tree_dp_root_each.cpp: -------------------------------------------------------------------------------- 1 | template 2 | vector tree_dp_root_each( 3 | const graph_t &g, 4 | auto &&single, //[](size_t v) -> S { ... } 5 | auto &&link //[](S dv, S di, auto &edge) -> S { auto [v, i, ...] = edge } 6 | ) { 7 | auto edge_cat = [](size_t v, auto &e) { return tuple_cat(tuple{v}, tuple{e}); }; 8 | 9 | const size_t n = size(g); 10 | vector par(n,-1), q(n); 11 | vector> epar(n); 12 | for(size_t ql=0,qr=0,st=0; st res(n), up(n); 21 | for(size_t v=0; v::iterator; 26 | function exclude = [&](it l, it r, S val) { 27 | if(l+1 == r) { up[*l] = val; return ; } 28 | auto m = l + (r-l)/2; 29 | exclude(l, m, accumulate(m, r, val, cf)); 30 | exclude(m, r, accumulate(l, m, val, cf)); 31 | }; 32 | 33 | for(vector ar; size_t v : q) { 34 | ar.clear(); 35 | for(auto &edge : g[v]) if(size_t i=edge; i!=par[v]) ar.push_back(i); else { 36 | if(par[i]!=-1) up[v] = link(up[v], up[i], epar[i]); 37 | res[v] = link(res[v], up[v], epar[v] = edge_cat(v, edge)); 38 | } 39 | if(!empty(ar)) exclude(begin(ar), end(ar), single(v)); 40 | } 41 | 42 | return res; 43 | } 44 | -------------------------------------------------------------------------------- /misc/README.md: -------------------------------------------------------------------------------- 1 | # Nearest 2 | ```c++ 3 | vector a; 4 | auto next_less = nearest_next(a, less{}); 5 | auto prev_greater_or_equal = nearest_prev(a, greater_equal{}); 6 | ``` 7 | 8 | # Parallel Binary Search 9 | Example of usage in solution of task [New Roads Queries](https://cses.fi/problemset/task/2101/) 10 | ```c++ 11 | size_t queries_count = size(queries), versions_count = size(edges); 12 | auto res_bs = parallel_binary_search(queries_count, versions_count, [&](auto vc) { 13 | dsu g(n); 14 | vc.pred = [&](size_t qi) { 15 | auto [a, b] = queries[qi]; 16 | return g[a] != g[b]; 17 | }; 18 | for(auto [i, j] : edges) { 19 | g.unite(i, j); 20 | vc.commit(); 21 | } 22 | }); 23 | ``` 24 | As result, like in `std::partition_point`, `res_bs[i]` will be first version where `pred` returns false for i-th query, or will be `versions_count+1` if `pred` always returns true. 25 | 26 | Versions numbered from 0 to `versions_count`, where 0-th version is state before first commit. 27 | 28 | `vc.pred` must be set exactly once and before first commit. 29 | 30 | There must be exactly `versions_count` commits. 31 | -------------------------------------------------------------------------------- /misc/bitmask.cpp: -------------------------------------------------------------------------------- 1 | template struct mask_t { 2 | explicit mask_t(T ms = 0): ms(ms) {} 3 | static mask_t ones(size_t n) { return mask_t((T(1) << n) - 1); } 4 | static mask_t ones(size_t l, size_t r) { return ones(r) ^ ones(l); } 5 | static mask_t bit(size_t i) { return mask_t(T(1) << i); } 6 | 7 | bool contains(const mask_t &m) const { return (ms & m.ms) == m.ms; } 8 | 9 | #define mask_op(O, E, F) mask_t& operator E(const mask_t &b) { F return *this; } friend mask_t operator O(mask_t a, const mask_t &b) { return a E b; } 10 | mask_op(&, &=, ms &= b.ms; ) 11 | mask_op(|, |=, ms |= b.ms; ) 12 | mask_op(^, ^=, ms ^= b.ms; ) 13 | 14 | friend bool operator==(const mask_t &a, const mask_t &b) = default; 15 | 16 | operator T() const { return ms; } 17 | const T& operator*() const { return ms; } 18 | 19 | struct bit_reference { 20 | mask_t &ms; 21 | size_t pos; 22 | operator bool() const { return ms.ms >> pos &1; } 23 | void operator=(bool value) { 24 | T bit = T(1) << pos; 25 | if(value) ms.ms |= bit; 26 | else ms.ms &= ~bit; 27 | } 28 | }; 29 | 30 | bit_reference operator[](size_t i) { return {*this, i}; } 31 | bool operator[](size_t i) const { return ms >> i &1; } 32 | mask_t operator()(size_t l, size_t r) const { return *this & ones(l, r); } 33 | 34 | struct submask_iterator { 35 | T ms, cur; 36 | void operator++() { cur = (cur | ~ms) + 1; } 37 | bool operator!=(const submask_iterator &it) const { return cur != it.cur; } 38 | mask_t operator*() const { return mask_t(cur & ms); } 39 | }; 40 | 41 | submask_iterator begin() const { return {ms, ~ms}; } 42 | submask_iterator end() const { return {ms, 0}; } 43 | 44 | private: T ms; 45 | }; 46 | using mask = mask_t; 47 | -------------------------------------------------------------------------------- /misc/nearest.cpp: -------------------------------------------------------------------------------- 1 | template 2 | vector __nearest(const auto &v, auto &&cmp, index_t dir) { 3 | vector f(size(v)); 4 | const index_t n = ssize(v), out = dir < 0 ? -1 : n; 5 | for(index_t i = out-dir, k = 0; k < n; ++k, i-=dir) 6 | for(f[i] = i+dir; f[i]!=out && !cmp(v[f[i]], v[i]); f[i] = f[f[i]]) ; 7 | return f; 8 | } 9 | auto nearest_next(const auto &v, auto &&cmp) { return __nearest(v, cmp, +1); } 10 | auto nearest_prev(const auto &v, auto &&cmp) { return __nearest(v, cmp, -1); } 11 | -------------------------------------------------------------------------------- /misc/parallel_binary_search.cpp: -------------------------------------------------------------------------------- 1 | auto parallel_binary_search(size_t queries_count, size_t versions_count, auto &&action) { 2 | auto ensure = [](bool cond, const char *msg) { if(!cond) __throw_logic_error(msg); }; 3 | using pred_t = function; 4 | 5 | struct assign_helper { 6 | assign_helper(function f): set_pred(f) {} 7 | void operator=(pred_t pred) { set_pred(pred); } 8 | private: function set_pred; 9 | }; 10 | struct vc { assign_helper pred; function commit; }; 11 | 12 | struct range { size_t l, r, qi; }; 13 | vector ranges(queries_count); 14 | for(size_t i=0; i result(queries_count); 17 | while(!empty(ranges)) { 18 | optional pred; 19 | size_t current_version = 0; 20 | auto it = begin(ranges); 21 | auto calc = [&] { 22 | ensure(pred.has_value(), "pred is not set"); 23 | ensure(current_version <= versions_count, "too many versions"); 24 | if(it == end(ranges)) return ; 25 | const size_t m = (it->l + it->r) / 2, pl = it->l; 26 | if(m > current_version) return ; 27 | for(auto mt = it; it != end(ranges) && it->l == pl; ++it) 28 | if((*pred)(it->qi)) it->l = m + 1; 29 | else it->r = m, swap(*it, *mt), ++mt; 30 | }; 31 | action(vc { 32 | assign_helper([&](pred_t f) { 33 | ensure(!pred.has_value(), "pred already set in this scope"); 34 | pred = f; 35 | calc(); 36 | }), 37 | [&] { ++current_version; calc(); } 38 | }); 39 | ensure(current_version == versions_count, "not all versions are commited"); 40 | it = begin(ranges); 41 | for(auto &t : ranges) if(t.l < t.r) *it++ = t; else result[t.qi] = t.r; 42 | ranges.erase(it, end(ranges)); 43 | } 44 | 45 | return result; 46 | } 47 | -------------------------------------------------------------------------------- /numeric/binomial.cpp: -------------------------------------------------------------------------------- 1 | template struct binomial { 2 | binomial(size_t n): f(n+1), finv(n+1) { 3 | f[0] = finv[0] = 1; 4 | for(size_t i=1; i<=n; ++i) f[i] = f[i-1] * i; 5 | finv[n] = T(1) / f[n]; 6 | for(size_t i=n; i>1; --i) finv[i-1] = finv[i] * i; 7 | } 8 | T operator()(size_t n, size_t k) const { 9 | return n < k ? 0 : f.at(n) * finv[n-k] * finv[k]; 10 | } 11 | T factorial(size_t n) const { return f.at(n); } 12 | T inv_factorial(size_t n) const { return finv.at(n); } 13 | private: vector f, finv; 14 | }; 15 | -------------------------------------------------------------------------------- /numeric/crt.cpp: -------------------------------------------------------------------------------- 1 | struct crt_device { 2 | crt_device(){}; 3 | crt_device(const vector &mods): mods(mods), invs(size(mods)) { 4 | for(size_t i=0; i{mods[j]}.inverse().value(); 8 | } 9 | } 10 | 11 | template 12 | T evaluate(vector a) const { 13 | assert(size(a) == size(mods)); 14 | for(size_t i=0; i cur{a[i]}; 17 | for(size_t j=0; j 26 | static T evaluate(const modint &a0, const modint& ...a) { 27 | if constexpr (sizeof...(a) == 0) return T(*a0); else 28 | return evaluate(((a - *a0) * inv)...) * T(mod0) + T(*a0); 29 | } 30 | 31 | template 32 | static vector evaluate(const vector> &a0, const vector>& ...a) { 33 | vector res(size(a0)); assert(((size(a) == size(a0)) && ...)); 34 | for(size_t i=0; i(a0[i], a[i]...); 35 | return res; 36 | } 37 | 38 | private: 39 | vector mods; 40 | vector> invs; 41 | 42 | template static inline const auto inv = 1 / modint{x}; 43 | static inline int tmod; 44 | }; 45 | -------------------------------------------------------------------------------- /numeric/factorizer.cpp: -------------------------------------------------------------------------------- 1 | struct factorizer { 2 | vector minp, primes; 3 | explicit factorizer(int n): minp(n+1) { 4 | for(int i=2; i<=n; ++i) { 5 | if(!minp[i]) minp[i] = primes.emplace_back(i); 6 | for(int p : primes) 7 | if(p <= minp[i] && i*p <= n) minp[i*p] = p; 8 | else break; 9 | } 10 | } 11 | 12 | auto factorization(int x) const { 13 | static pair f[11], *e; 14 | for(e = f; x>1; ++e) { 15 | auto &[p, q] = *e = {minp[x], 0}; 16 | do ++q, x/=p; while(minp[x] == p); 17 | } 18 | return vector(f, e); 19 | } 20 | 21 | auto divisors(int x) const { 22 | static int divs[1500], dn; 23 | for(int p=0,l=dn=divs[0]=1; x>1; x/=p) { 24 | if(p != minp[x]) p = minp[x], l = 0; 25 | for(int r=dn; l using square_t = conditional_t; 3 | 4 | template 5 | bool __miller_rabin(T n) { 6 | assert(n > 1 && n % 2 == 1); 7 | auto test = [n, z=std::countr_zero(n-1)](square_t a) { 8 | square_t r = 1; 9 | for(T d = n>>z; d; d>>=1, a = a*a %n) if(d&1) r = r*a %n; 10 | if(r == 1) return true; 11 | for(uint32_t s=z; s--; r = r*r %n) if(r == n-1) return true; 12 | return false; 13 | }; 14 | return ((A >= n || test(A)) && ...); 15 | } 16 | 17 | template 18 | bool is_prime(T n) { 19 | if(n < 2 || n % 2 == 0) return n == 2; 20 | if constexpr (is_signed_v) return is_prime>(n); 21 | else if constexpr (sizeof(T) > sizeof(uint32_t)) { 22 | if(std::in_range(n)) return is_prime(n); 23 | return __miller_rabin<2, 325, 9375, 28178, 450775, 9780504, 1795265022>(n); 24 | } else return __miller_rabin<2, 7, 61>(n); 25 | } 26 | 27 | template 28 | void __get_factors(T n, auto &p) { 29 | if(n == 1) return ; 30 | assert(n > 1 && n % 2 == 1); 31 | if constexpr (sizeof(T) > sizeof(uint32_t)) { 32 | if(std::in_range(n)) return __get_factors(n, p); 33 | } 34 | if(is_prime(n)) { p.push_back(n); return ; } 35 | static mt19937_64 rnd(chrono::steady_clock::now().time_since_epoch().count()); 36 | for(;;) { 37 | auto &&g = [n, a=rnd()%(n-1)+1](square_t x) { return (x*x + a) %n; }; 38 | for(T x = rnd()%(n-3)+3, y = g(x); x != y; x=g(x), y=g(g(y))) 39 | if(const T d = std::gcd(x 1) 40 | return __get_factors(d, p), __get_factors(n / d, p); 41 | } 42 | } 43 | 44 | template 45 | vector factors(T n) { 46 | assert(n > 0); 47 | vector f; 48 | while(n%2 == 0) n/=2, f.push_back(2); 49 | for(T p = 3; p <= 37 && p*p <= n; p += 2) 50 | while(n%p == 0) n/=p, f.push_back(p); 51 | __get_factors>(n, f); 52 | return f; 53 | } 54 | -------------------------------------------------------------------------------- /numeric/fibonacci.cpp: -------------------------------------------------------------------------------- 1 | template T fibonacci(uint64_t n) { 2 | T x = 0, y = 1; 3 | for(auto i=bit_width(n); i--; ) { 4 | T xx = x*x, xy = x*y, yy = y*y; 5 | if(n>>i&1) x = xx + yy, y = xy + xy + yy; 6 | else x = xy + xy - xx, y = xx + yy; 7 | } 8 | return x; 9 | } 10 | -------------------------------------------------------------------------------- /numeric/karatsuba.cpp: -------------------------------------------------------------------------------- 1 | void convolution_brute(auto a, size_t n, auto b, size_t m, auto ret) { 2 | fill(ret, ret+n+m-1, 0); 3 | for(size_t i=0; i 32 | vector convolution(const vector &a, const vector &b) { 33 | if(size(a) < size(b)) return convolution(b, a); 34 | if(empty(b)) return {}; 35 | size_t n = size(a), m = size(b); 36 | if(m < n/m) { 37 | vector ret(n+m-1); 38 | convolution_brute(begin(a), n, begin(b), m, begin(ret)); 39 | return ret; 40 | } else { 41 | vector ret(n*6), b_ex(n); 42 | copy(begin(b), end(b), begin(b_ex)); 43 | go_karatsuba(begin(a), begin(b_ex), begin(ret), n); 44 | return vector(begin(ret), begin(ret)+n+m-1); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /numeric/modint.cpp: -------------------------------------------------------------------------------- 1 | template requires same_as, int32_t> 2 | struct modint { 3 | modint(): x(0) {} 4 | modint(integral auto val): x(val%mod) { if(x<0) x+=mod; } 5 | static constexpr int32_t get_mod() { return mod; } 6 | #define __op(O, E, F) modint& operator E(const modint &b) { F return *this; } friend modint operator O(modint a, const modint &b) { return a E b; } 7 | __op(+, +=, if(int32_t v=mod-b.x; x >= v) x -= v; else x += b.x; ) 8 | __op(-, -=, if(x >= b.x) x -= b.x; else x += mod-b.x; ) 9 | __op(*, *=, x = int64_t(x)*b.x %mod; ) 10 | __op(/, /=, auto i=b.inverse(); assert(i); x = int64_t(i->x)*x %mod; ) 11 | friend modint operator-(modint a) { if(a.x) a.x = mod - a.x; return a; } 12 | friend modint pow(modint a, uint64_t n) { modint p=1; for(; n; n>>=1, a*=a) if(n&1) p*=a; return p; } 13 | optional inverse() const { 14 | int32_t a = x, m = mod, p = 1, q = 0; 15 | while(a) swap(p, q -= (m / a) * p), swap(a, m %= a); 16 | if(m == 1) return q; else return nullopt; 17 | } 18 | bool operator==(const modint&) const = default; 19 | friend ostream& operator<<(ostream &o, const modint &m) { return o<; 24 | -------------------------------------------------------------------------------- /numeric/modint_extentions.cpp: -------------------------------------------------------------------------------- 1 | template optional sqrt(mint a) { //correct for prime mod 2 | if(*a < 2) return a; 3 | int m = mint::get_mod(); 4 | if(m%2 == 0 || pow(a, m>>1) == -1) return nullopt; 5 | static mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count()); 6 | mint t; do t = rnd(); while(*pow(t*t-4*a, m>>1) < 2); 7 | mint d = 1, c = -t, b = -t; 8 | for(++m; m>>=1; b=a*2-b*b, a*=a) m%2 ? d=c-d*b, c*=a : c=d*a-c*b; 9 | return d; 10 | } 11 | -------------------------------------------------------------------------------- /numeric/ntt.cpp: -------------------------------------------------------------------------------- 1 | namespace NTT { 2 | template struct ntt_device { 3 | using mint = modint; 4 | static constexpr size_t H = std::countr_zero(mod-1); 5 | 6 | static inline const auto roots = [] { 7 | array r{}; 8 | for(int g=2; g &a) { 17 | const size_t n = size(a); assert(std::has_single_bit(n) && n <= (1uz << H)); 18 | for(size_t i=1, j=0, t; i>1; j&t; t>>=1) j^=t; 20 | if((j^=t) < i) swap(a[i], a[j]); 21 | } 22 | for(size_t h=1, k=1; k*2<=n; ++h, k<<=1) 23 | for(size_t p=0; p &a) { 35 | ntt(a); 36 | reverse(begin(a)+1, end(a)); 37 | mint i = 1 / mint(size(a)); 38 | for(mint &val : a) val*=i; 39 | } 40 | }; 41 | 42 | namespace { 43 | constexpr bool is_ntt_prime(int p, size_t size) { 44 | if(p < 2 || p%2 == 0 || (1u << std::countr_zero(p-1)) < size) return false; 45 | for(int i=3; i*i<=p; i+=2) if(p%i == 0) return false; 46 | return true; 47 | } 48 | 49 | template constexpr bool is_ntt_modint = false; 50 | template constexpr bool is_ntt_modint, size> = is_same_v && is_ntt_prime(mod, size); 51 | 52 | template::max(), size_t ...I> 53 | constexpr auto __gen_ntt_mods(index_sequence) { 54 | constexpr auto mods = [] { 55 | array ar{}; 56 | for(size_t i = 0, h = 30; (1u << h) >= size; --h) 57 | for(int c = 1; i < ar.size() && c <= ((max_mod-1)>>h); c+=2) 58 | if(int mod = (c<= min_mod && is_ntt_prime(mod, size)) ar[i++] = mod; 59 | return ar; 60 | }(); 61 | static_assert(mods.back() != 0, "Can't find enough required ntt mods"); 62 | return integer_sequence{}; 63 | } 64 | 65 | template using make_ntt_mods = decltype(__gen_ntt_mods(make_index_sequence{})); 66 | 67 | template vector> convolution(const vector &a, const vector &b) { 68 | if(size(a) < size(b)) return convolution(b, a); 69 | if(empty(b)) return {}; 70 | const size_t n = size(a)+size(b)-1, d = std::bit_ceil(n); 71 | vector> fa(d), fb(d); 72 | copy(begin(a), end(a), begin(fa)); 73 | copy(begin(b), end(b), begin(fb)); 74 | bool equal = fa == fb; 75 | ntt_device::ntt(fa); 76 | if(equal) fb = fa; else ntt_device::ntt(fb); 77 | for(size_t i=0; i::ntt_inv(fa); 79 | fa.resize(n); 80 | return fa; 81 | } 82 | 83 | template auto convolution(const vector &a, const vector &b, integer_sequence) { 84 | return CRT::template evaluate(convolution(a, b)...); 85 | } 86 | } 87 | 88 | template requires is_ntt_modint 89 | auto convolution(const vector &a, const vector &b) { return convolution(a, b); } 90 | 91 | template 92 | auto convolution(const vector &a, const vector &b) { 93 | return convolution(a, b, make_ntt_mods{}); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /numeric/sum_of_primes.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct sum_of_primes { 3 | sum_of_primes(uint64_t n): pr(get_primes(root2(n))), mem_pi(pr.back()+1) { 4 | for(auto p : pr) mem_pi[p] = pow(p); 5 | for(size_t i=1; i(1 << 17, n); 8 | size_t bufm = min(1 << 6, size(pr)); 9 | mem_f.assign(bufm, vector(bufn)); 10 | for(size_t i=0; i(i); 11 | for(size_t j=1; j(pr[j-1]); 13 | for(size_t i=0; i= pr[m] 18 | T f(uint64_t n, size_t m) const { 19 | if(m == 0) return sum_pows(n); 20 | if(m < size(mem_f) && n < size(mem_f[m])) return mem_f[m][n]; 21 | assert(m < size(pr)); 22 | if(uint64_t p = pr[m]; p > n) return 1; //1**K 23 | else if(p * p > n) return pi(n) - pi(p - 1) + 1; 24 | return f(n, m - 1) - f(n / pr[m-1], m - 1) * pow(pr[m-1]); 25 | } 26 | 27 | //sum of p**K for prime numbers 1 <= p <= n 28 | T pi(uint64_t n) const { 29 | if(n < 2) return 0; 30 | if(n <= pr.back()) return mem_pi[n]; 31 | const size_t m = upper_bound(begin(pr), end(pr), root3(n)) - begin(pr); 32 | T res = f(n, m) + pi(pr[m-1]) - 1; 33 | for(size_t k = m; k < size(pr); ++k) 34 | if(uint64_t p = pr[k]; p * p > n) break ; 35 | else res -= (pi(n / p) - pi(p - 1)) * pow(p); 36 | return res; 37 | } 38 | 39 | static inline uint64_t root2(uint64_t x) { return sqrtl(x); } 40 | static inline uint64_t root3(uint64_t x) { return cbrtl(x); } 41 | 42 | template static inline T pow(uint64_t n) { 43 | if constexpr (P == 0) return 1; else 44 | if constexpr (P %2 == 1) return pow(n) * T(n); 45 | else { 46 | T s = pow

(n); 47 | return s * s; 48 | } 49 | } 50 | 51 | template static T sum_pows(uint64_t n) { 52 | static_assert(P <= 3); 53 | if constexpr (P == 0) return n; else 54 | if constexpr (P == 1) { 55 | uint64_t a = n, b = n + 1; 56 | if(a %2 == 0) a /= 2; else b /= 2; 57 | return T(a) * T(b); 58 | } else 59 | if constexpr (P == 2) { 60 | uint64_t a = n, b = n + 1, c = 2 * n + 1; 61 | if(a %2 == 0) a /= 2; else b /= 2; 62 | if(a %3 == 0) a /= 3; else if(b %3 == 0) b /= 3; else c /= 3; 63 | return T(a) * T(b) * T(c); 64 | } else 65 | if constexpr (P == 3) { 66 | T s1 = sum_pows<1>(n); 67 | return s1 * s1; 68 | } 69 | } 70 | 71 | private: 72 | vector pr; 73 | vector mem_pi; 74 | vector> mem_f; 75 | 76 | static auto get_primes(uint32_t n) { 77 | if(n < 11) n = 11; //to fix maxn < 4 (empty pr) or pi(8) (infinite recursion) 78 | vector md(n + 1), pr; 79 | for(uint32_t i = 2; i <= n; ++i) { 80 | if(md[i] == 0) pr.push_back(md[i] = i); 81 | for(uint32_t p : pr) { 82 | if(p > md[i] || p * i > n) break ; 83 | md[p * i] = p; 84 | } 85 | } 86 | return pr; 87 | } 88 | }; 89 | 90 | using count_of_primes = sum_of_primes; 91 | -------------------------------------------------------------------------------- /strings/README.md: -------------------------------------------------------------------------------- 1 | # Hasher 2 | Polynomial hashing with MOD = $2^{61} - 1$ and random BASE 3 | 4 | ```hash_t``` - hash integer value (wrapper of ```uint64_t```) 5 | 6 | ```hashed``` - hashed string 7 | 8 | ```c++ 9 | hashed h = str; 10 | h.length() // length of hashed string 11 | if(h1 == h2) // equality check in O(1) 12 | h = h1 + h2; // concatenations in O(1) 13 | h += 'a'; 14 | ``` 15 | 16 | ```hasher``` - hash array of string/vector 17 | 18 | ```hash_span``` - reference to some range in hasher 19 | 20 | ```c++ 21 | hasher a(str), arev(rbegin(str), rend(str)); 22 | a.substr(start, length); // hashed 23 | a.subhash(start, length); // hash_t 24 | hash_span s = a.subspan(start, length); 25 | s.length(); 26 | assert(a[s.start()] == s[0]); 27 | 28 | if(s1 == s2) // equality check in O(1) 29 | if(s1 < s2) // operator< and longest common prefix 30 | lcp(s1, s2) // both in O(log(Length)) 31 | ``` 32 | 33 | indirection operators: 34 | 35 | ```c++ 36 | *hash_t -> uint64_t 37 | *hashed -> hash_t 38 | *hash_span -> hashed 39 | ``` 40 | -------------------------------------------------------------------------------- /strings/ext/hash_multispan.cpp: -------------------------------------------------------------------------------- 1 | struct hash_multispan { 2 | hash_multispan() {} 3 | hash_multispan(const hash_span &sp): s{sp}, prefs{sp.length()} {} 4 | 5 | hash_multispan& operator+=(const hash_span &sp) { 6 | if(size_t sl = sp.length()) { 7 | s.push_back(sp); 8 | prefs.push_back(length() + sl); 9 | } 10 | return *this; 11 | } 12 | 13 | size_t length() const { return empty(prefs) ? 0 : prefs.back(); } 14 | 15 | char_t operator[](size_t i) const { 16 | assert(i < length()); 17 | auto it = upper_bound(begin(prefs), end(prefs), i); 18 | size_t before = it == begin(prefs) ? 0 : *prev(it); 19 | return s[it - begin(prefs)][i - before]; 20 | } 21 | 22 | hash_multispan subspan(size_t pos, size_t n) const { 23 | assert(pos + n <= length()); 24 | hash_multispan res; 25 | for(auto &&sp : s) { 26 | if(n == 0) break; 27 | if(size_t sl = sp.length(); pos < sl) { 28 | size_t sz = min(sl - pos, n); 29 | res += sp.subspan(pos, sz); 30 | n -= sz; 31 | pos = 0; 32 | } else pos -= sl; 33 | } 34 | return res; 35 | } 36 | 37 | friend bool operator==(const hash_multispan &a, const hash_multispan &b) { 38 | if(a.length() != b.length()) return false; 39 | return *a == *b; 40 | } 41 | 42 | hashed operator*() const { 43 | hashed h; 44 | for(auto &sp : s) h += *sp; 45 | return h; 46 | } 47 | 48 | friend size_t lcp(const hash_multispan &a, const hash_multispan &b) { 49 | size_t i = 0, j = 0, pa = 0, pb = 0, res = 0; 50 | while(i s; 83 | vector prefs; 84 | }; 85 | -------------------------------------------------------------------------------- /strings/hasher.cpp: -------------------------------------------------------------------------------- 1 | namespace kihash { 2 | using char_t = int32_t; 3 | struct hash_t { 4 | static constexpr uint64_t M = (uint64_t(1)<<61) - 1; 5 | hash_t(): x(0) {} 6 | hash_t(uint64_t val): x(val < M ? val : val%M) {} 7 | #define hash_t_op(O, E, F) hash_t& operator E(const hash_t &b) { F return *this; } friend hash_t operator O(hash_t a, const hash_t &b) { return a E b; } 8 | hash_t_op(*, *=, x = mul(x,b.x); ) 9 | hash_t_op(+, +=, x+=b.x; if(x>=M) x-=M; ) 10 | hash_t_op(-, -=, if(x> 32, l2 = (uint32_t)b, h2 = b >> 32; 17 | uint64_t l = l1 * l2, m = l1 * h2 + l2 * h1, h = h1 * h2; 18 | uint64_t ret = (l & M) + (l >> 61) + (h << 3) + (m >> 29) + (m << 35 >> 3) + 1; 19 | ret = (ret & M) + (ret >> 61); 20 | ret = (ret & M) + (ret >> 61); 21 | return ret - 1; 22 | } 23 | }; 24 | 25 | const hash_t X = uint64_t(309935741)<<32 | mt19937(chrono::steady_clock::now().time_since_epoch().count())() | 1; 26 | 27 | hash_t pow_of_X(size_t n) { 28 | hash_t p = 1, a = X; 29 | for(; n; n>>=1, a*=a) if(n&1) p*=a; 30 | return p; 31 | } 32 | 33 | struct hasher; struct hash_span; 34 | struct hashed { 35 | hashed(): h(0), px(1), len(0) {} 36 | hashed(const hash_t &h, size_t len): hashed(h, len, pow_of_X(len)) {} 37 | hashed(const string &s): hashed() { for(auto ch : s) *this += ch; } 38 | hashed(char_t ch): hashed(ch, 1, X) {} 39 | void operator+=(const hashed &a) { h += a.h*px; px *= a.px; len += a.len; } 40 | void operator+=(char_t ch) { h += ch*px; px *= X; ++len; } 41 | friend hashed operator+(hashed a, auto &&b) { a += b; return a; } 42 | bool operator==(const hashed &b) const { return h == b.h && len == b.len; } 43 | hash_t operator*() const { return h; } 44 | size_t length() const { return len; } 45 | private: hash_t h, px; 46 | size_t len; 47 | hashed(hash_t h, size_t len, hash_t px): h(h), px(px), len(len) {} 48 | friend hasher; 49 | }; 50 | 51 | struct hasher { 52 | template hasher(Iter first, Iter last): suf(distance(first,last)+1), data(first,last) { 53 | expand_xpow(size(data)); 54 | for(size_t i=size(data); i--; ) suf[i] = suf[i+1]*X + data[i]; 55 | } 56 | hasher(const string &str): hasher(begin(str), end(str)) {} 57 | hasher(): hasher(""s) {} 58 | hash_t subhash(size_t pos, size_t n) const { 59 | assert(pos + n < size(suf)); 60 | return suf[pos] - suf[pos+n]*xpow[n]; 61 | } 62 | hashed substr(size_t pos, size_t n) const { return {subhash(pos,n), n, xpow[n]}; } 63 | hash_span subspan(size_t, size_t) const; hash_span operator()(size_t, size_t) const; 64 | size_t length() const { return size(data); } 65 | char_t operator[](size_t i) const { return data.at(i); } 66 | private: 67 | vector suf; 68 | vector data; 69 | static inline vector xpow = {1}; 70 | static void expand_xpow(size_t n) { 71 | xpow.reserve(n); 72 | while(size(xpow) <= n) xpow.push_back(xpow.back() * X); 73 | } 74 | }; 75 | 76 | struct hash_span { 77 | hash_span(): p(nullptr) {} 78 | hash_span(const hasher &s, size_t i, size_t n): p(&s), offset(i), len(n) { assert(i + n <= s.length()); } 79 | size_t start() const { return offset; } 80 | size_t length() const { return len; } 81 | char_t operator[](size_t i) const { return (*p)[offset + i]; } 82 | hash_t subhash(size_t pos, size_t n) const { return p->subhash(offset + pos, n); } 83 | hashed substr(size_t pos, size_t n) const { return p->substr(offset + pos, n); } 84 | hash_span subspan(size_t pos, size_t n) const { return {*p, offset + pos, n}; } 85 | hash_span operator()(size_t l, size_t r) const { return subspan(l, r-l); } 86 | hashed operator*() const { return substr(0, len); } 87 | bool operator==(const hash_span &s) const { return s.len == len && s.subhash(0, len) == subhash(0, len); } 88 | friend size_t lcp(const hash_span &a, const hash_span &b) { 89 | size_t l = 1, r = min(a.len, b.len) + 1; 90 | while(l < r) if(size_t m=(l+r)/2; a.subhash(0,m)==b.subhash(0,m)) l = m+1; else r = m; 91 | return l - 1; 92 | } 93 | private: 94 | const hasher *p; 95 | size_t offset, len; 96 | }; 97 | 98 | hash_span hasher::subspan(size_t pos, size_t n) const { return {*this, pos, n}; } 99 | hash_span hasher::operator()(size_t l, size_t r) const { return subspan(l, r-l); } 100 | 101 | auto operator<(auto &&a, auto &&b) -> decltype(lcp(a,b), a[a.length()] < b[b.length()]) { 102 | size_t i = lcp(a, b); 103 | return i < b.length() && (i == a.length() || a[i] < b[i]); 104 | } 105 | } 106 | using namespace kihash; 107 | -------------------------------------------------------------------------------- /strings/z_function.cpp: -------------------------------------------------------------------------------- 1 | vector z_function(auto first, auto last) { 2 | size_t n = last - first; 3 | vector z(n, 0); 4 | for(size_t i=1, j=0; i= i) z[i] = min(z[i-j], j+z[j]-i); 6 | while(i+z[i] < n && *(first+z[i]) == *(first+i+z[i])) ++z[i]; 7 | if(i + z[i] > j + z[j]) j = i; 8 | } 9 | z[0] = n; 10 | return z; 11 | } 12 | -------------------------------------------------------------------------------- /structs/aggregator.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct aggregator { 3 | explicit aggregator(size_t n = 0): d(n), t(d*2) {} 4 | aggregator(size_t n, auto &&gen): aggregator(n) { 5 | for(size_t i=0; i1;) t[i] = T(t[i*2], t[i*2+1]); 7 | } 8 | 9 | void set_value(size_t i, const T &value) { 10 | for(t[i+=d] = value; i>>=1; ) t[i] = T(t[i*2], t[i*2+1]); 11 | } 12 | 13 | T operator()(size_t l, size_t r) const { 14 | T fl{}, fr{}; 15 | for(l+=d,r+=d; l>=1,r>>=1) { 16 | if(l&1) fl = T(fl, t[l]), ++l; 17 | if(r&1) --r, fr = T(t[r], fr); 18 | } 19 | return T(fl, fr); 20 | } 21 | 22 | T operator()() const { return operator()(0, d); } 23 | 24 | private: 25 | size_t d; 26 | vector t; 27 | }; 28 | /* implement: 29 | struct node { 30 | node() 31 | node(const node &vl, const node &vr) 32 | }; 33 | */ 34 | -------------------------------------------------------------------------------- /structs/aggregator_queue.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct aggregator_queue { 3 | aggregator_queue(): rs{} {} 4 | void push(const T &x) { 5 | rs = T(rs, r.emplace_back(x)); 6 | } 7 | void pop() { 8 | if(empty(l)) { 9 | for(T m{}; !empty(r); r.pop_back()) 10 | m = l.emplace_back(r.back(), m); 11 | rs = {}; 12 | } 13 | l.pop_back(); 14 | } 15 | T operator()() { 16 | return empty(l) ? rs : T(l.back(), rs); 17 | } 18 | size_t size() const { return l.size() + r.size(); } 19 | private: 20 | vector l, r; 21 | T rs; 22 | }; 23 | -------------------------------------------------------------------------------- /structs/aggregator_range_operation.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct aggregator { 3 | explicit aggregator(size_t n = 0): d(n), t(d*2) {} 4 | aggregator(size_t n, auto &&gen): aggregator(n) { if(n) build(0, d, 1, gen); } 5 | 6 | void apply(size_t l, size_t r, const O &operation) { 7 | if(l < r) apply(l, r, operation, 0, d, 1); 8 | } 9 | 10 | void set_value(size_t i, const T &value) { 11 | set_value(i, value, 0, d, 1); 12 | } 13 | 14 | T operator()(size_t l, size_t r) const { 15 | return l < r ? calc(l, r, 0, d, 1) : T{}; 16 | } 17 | 18 | const T& operator()() const { return t[1].first; } 19 | 20 | private: 21 | size_t d; 22 | mutable vector>> t; 23 | 24 | void cover(size_t v, const O &operation, size_t length) const { 25 | t[v].first.apply(operation, length); 26 | if(auto &op = t[v].second) op = O(*op, operation); 27 | else op = operation; 28 | } 29 | 30 | inline void push(size_t v, size_t l, size_t r, size_t &m, size_t &vl, size_t &vr) const { 31 | size_t s = r - l, sl = s / 2; m = l + sl; vl = v + 1; vr = v + sl * 2; 32 | if(auto &op = t[v].second) { 33 | cover(vl, op->slice(0, sl), sl); 34 | cover(vr, op->slice(sl, s), s - sl); 35 | op.reset(); 36 | } 37 | } 38 | 39 | void apply(size_t i, size_t j, const O &op, size_t l, size_t r, size_t v) { 40 | if(i == l && j == r) { cover(v, op, r-l); return ; } 41 | size_t m, vl, vr; push(v, l, r, m, vl, vr); 42 | if(j <= m) apply(i, j, op, l, m, vl); else 43 | if(i >= m) apply(i, j, op, m, r, vr); else { 44 | apply(i, m, op.slice(0, m-i), l, m, vl); 45 | apply(m, j, op.slice(m-i, j-i), m, r, vr); 46 | } 47 | t[v].first = T(t[vl].first, t[vr].first); 48 | } 49 | 50 | void set_value(size_t i, const T &value, size_t l, size_t r, size_t v) { 51 | if(l+1 == r) { t[v].first = value; return ; } 52 | size_t m, vl, vr; push(v, l, r, m, vl, vr); 53 | if(i < m) set_value(i, value, l, m, vl); 54 | else set_value(i, value, m, r, vr); 55 | t[v].first = T(t[vl].first, t[vr].first); 56 | } 57 | 58 | T calc(size_t i, size_t j, size_t l, size_t r, size_t v) const { 59 | if(i == l && j == r) return t[v].first; 60 | size_t m, vl, vr; push(v, l, r, m, vl, vr); 61 | if(j <= m) return calc(i, j, l, m, vl); 62 | if(i >= m) return calc(i, j, m, r, vr); 63 | return T(calc(i, m, l, m, vl), calc(m, j, m, r, vr)); 64 | } 65 | 66 | T& build(size_t l, size_t r, size_t v, auto &&gen) { 67 | if(l+1 == r) return t[v].first = gen(l); 68 | size_t m, vl, vr; push(v, l, r, m, vl, vr); 69 | return t[v].first = T(build(l, m, vl, gen), build(m, r, vr, gen)); 70 | } 71 | }; 72 | /* 73 | struct operation { 74 | operation(const operation &op1, const operation &op2) 75 | decltype(auto) slice(size_t start, size_t end) const { return *this; } 76 | }; 77 | struct node { 78 | node() 79 | node(const node &vl, const node &vr) 80 | void apply(const operation &op, size_t length) 81 | }; 82 | */ -------------------------------------------------------------------------------- /structs/aggregator_static.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct aggregator_static { 3 | aggregator_static(size_t n, auto &&gen): t(n ? std::bit_width(n) : 1) { 4 | t[0].resize(size_t(1) << size(t)); 5 | for(size_t i=0; i>1)-1; i>l; --i) a[i-1] = T(a[i-1], a[i]); 10 | for(size_t i=l+(p>>1); i+1= r) return T{}; 16 | if(l == --r) return t[0][l]; 17 | auto &row = t[std::bit_width(l^r)-1]; 18 | return T(row[l], row[r]); 19 | } 20 | private: vector> t; 21 | }; 22 | -------------------------------------------------------------------------------- /structs/ext/rsq_2d_point_add_rectangle_sum.cpp: -------------------------------------------------------------------------------- 1 | template class rsq> 2 | struct rsq_2d_point_add_rectangle_sum { 3 | rsq_2d_point_add_rectangle_sum(vector> points): ys(size(points)) { 4 | for(size_t k=0; k(unique_sz(xs)); 11 | } 12 | 13 | T get_sum(const P &xl, const P &xr, const P &yl, const P &yr) { 14 | if(xl >= xr || yl >= yr) return T{}; 15 | return get_sum(xl, xr, yr) - get_sum(xl, xr, yl); 16 | } 17 | 18 | void add(const P &x, const P &y, const T &val) { 19 | for(size_t v = lb(ys, y); v < size(ys); v|=v+1) 20 | t[v].second.add(lb(t[v].first, x), val); 21 | } 22 | 23 | private: 24 | T get_sum(const P &xl, const P &xr, const P &yr) { 25 | T res{}; 26 | for(size_t v = lb(ys, yr); v--; v&=v+1) 27 | if(size_t l = lb(t[v].first, xl), r = lb(t[v].first, xr); l < r) 28 | res += t[v].second(l, r); 29 | return res; 30 | } 31 | 32 | vector,rsq>> t; 33 | vector

ys; 34 | static size_t unique_sz(auto&&v) { size_t sz = unique(begin(v), end(v)) - begin(v); v.resize(sz); return sz; } 35 | static inline size_t lb(auto&&v, auto&&val) { return lower_bound(begin(v), end(v), val) - begin(v); } 36 | }; 37 | -------------------------------------------------------------------------------- /structs/ext/rsq_2d_rectangle_add_point_get.cpp: -------------------------------------------------------------------------------- 1 | template class rsq> 2 | struct rsq_2d_rectangle_add_point_get { 3 | rsq_2d_rectangle_add_point_get(vector> points): ys(size(points)) { 4 | for(size_t k=0; k(unique_sz(xs)); 11 | } 12 | 13 | T get_value(const P &x, const P &y) const { 14 | T res{}; 15 | for(size_t v=lb(ys, y); v ys; 34 | vector,rsq>> t; 35 | static size_t unique_sz(auto&&v) { size_t sz = unique(begin(v), end(v)) - begin(v); v.resize(sz); return sz; } 36 | static inline size_t lb(auto&&v, auto&&val) { return lower_bound(begin(v), end(v), val) - begin(v); } 37 | }; 38 | -------------------------------------------------------------------------------- /structs/ilist.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct ilist { 3 | 4 | struct node { 5 | private: friend ilist; 6 | node *l, *r, *p; 7 | size_t sz; 8 | T *value; 9 | node(T *ptr = nullptr): l(nullptr), r(nullptr), p(nullptr), sz(1), value(ptr) { } 10 | }; 11 | 12 | template 13 | struct node_iterator: public std::iterator { 14 | private: friend ilist; node *t; 15 | node_iterator(node *ptr): t(ptr) { } 16 | public: node_iterator(): node_iterator(nullptr) { } 17 | V& operator*() { return *t->value; } 18 | bool operator==(const node_iterator &it) const { return t == it.t; } 19 | bool operator!=(const node_iterator &it) const { return t != it.t; } 20 | bool operator<(const node_iterator &it) const { return position(t) < position(it.t); } 21 | 22 | node_iterator& operator++() { 23 | for(;; rotate_big(t)) { 24 | if(t->r) return t = leftmost(t->r), *this; 25 | if(t->p->l == t) return t = t->p, *this; 26 | } 27 | } 28 | 29 | node_iterator& operator--() { 30 | for(;; rotate_big(t)) { 31 | if(t->l) return t = rightmost(t->l), *this; 32 | if(t->p->r == t) return t = t->p, *this; 33 | } 34 | } 35 | 36 | node_iterator operator++(int) { node *r = t; ++*this; return r; } 37 | node_iterator operator--(int) { node *r = t; --*this; return r; } 38 | 39 | node_iterator& operator+=(size_t n) { 40 | if(n > 0) splay(t), t = nth(t->r, n-1); 41 | return *this; 42 | } 43 | 44 | node_iterator& operator-=(size_t n) { 45 | if(n > 0) splay(t), t = nth(t->l, sz(t->l)-n); 46 | return *this; 47 | } 48 | 49 | node_iterator operator+(size_t n) const { return node_iterator(t)+=n; } 50 | node_iterator operator-(size_t n) const { return node_iterator(t)-=n; } 51 | 52 | ptrdiff_t operator-(const node_iterator &it) const { 53 | return position(t) - position(it.t); 54 | } 55 | 56 | ilist& get_ilist_ref() { 57 | return *((ilist*)(rightmost(splay(t))->value)); 58 | } 59 | }; 60 | 61 | using iterator = node_iterator; 62 | using const_iterator = node_iterator; 63 | 64 | struct extracted { 65 | private: friend ilist; 66 | extracted(node *ptr): t(ptr) {} 67 | node *t; 68 | }; 69 | 70 | 71 | ilist(): __end(make_end_node(new_node(),this)), __size(0) {} 72 | ilist(extracted e): ilist(e.t) {} 73 | explicit ilist(size_t n, const T &value = {}): ilist() { resize(n, value); } 74 | 75 | template::iterator_category, bidirectional_iterator_tag>>> 76 | ilist(I first, I last): ilist() { assign(first, last); } 77 | 78 | ilist(ilist &&a) noexcept { *this = std::move(a); } 79 | ilist& operator=(ilist &&a) noexcept { 80 | __end = make_end_node(exchange(a.__end, nullptr), this); 81 | __size = a.__size; 82 | return *this; 83 | } 84 | 85 | ilist(const ilist &a): ilist() { *this = a; } 86 | ilist& operator=(const ilist &a) { 87 | size_t n = a.__size; resize(n); 88 | for(auto v = __end, i = a.__end; n--; ) move_prev(v), move_prev(i), *v->value = *i->value; 89 | return *this; 90 | } 91 | 92 | size_t size() const { return __size; } 93 | bool empty() const { return __size == 0; } 94 | 95 | iterator begin() { return leftmost(splay(__end)); } 96 | iterator end() { return __end; } 97 | const_iterator begin() const { return leftmost(splay(__end)); } 98 | const_iterator end() const { return __end; } 99 | 100 | iterator at(size_t pos) { return nth(splay(__end), pos); } 101 | const_iterator at(size_t pos) const { return nth(splay(__end), pos); } 102 | 103 | T& operator[](size_t pos) { return *at(pos); } 104 | const T& operator[](size_t pos) const { return *at(pos); } 105 | 106 | void clear() { resize(0); } 107 | void resize(size_t n) { if(n > __size) resize_more(n, T{}); else if(n < __size) resize_less(n); } 108 | void resize(size_t n, const T &value) { if(n > __size) resize_more(n, value); else if(n < __size) resize_less(n); } 109 | 110 | auto assign(auto first, auto last) -> decltype(*--last, void()) { 111 | resize(std::distance(first, last)); 112 | for(node *v = __end; first != last; ) move_prev(v), *v->value = *--last; 113 | } 114 | void assign(size_t n, const T &value) { 115 | for(auto [v, i] = pair(__end, __size); i--; ) move_prev(v), *v->value = value; 116 | resize(n, value); 117 | } 118 | 119 | void push_back(const T &x) { insert(__end, x); } 120 | iterator insert(iterator pos, const T &x) { return insert(pos, new_node(x)); } 121 | iterator insert(iterator pos, iterator it) { return insert(pos, it.t); } 122 | iterator insert(iterator pos, extracted e) { return e.t ? insert(pos, splay(e.t)) : pos; } 123 | iterator insert(iterator pos, ilist &&a) { return insert(pos, a.extract(a.begin(),a.end())); } 124 | 125 | iterator erase(iterator it) { 126 | assert(it.t != __end); 127 | auto t = splay(it.t), l = t->l, r = t->r; 128 | t->r = t->l = t->p = r->p = nullptr; 129 | upd_sz(t); 130 | if(l) { 131 | r = leftmost(r); 132 | set_left(r, l); 133 | upd_sz(r); 134 | } 135 | --__size; 136 | return it; 137 | } 138 | 139 | extracted extract(iterator first, iterator last) { 140 | auto [l, suf] = split(first.t); 141 | auto [mid, r] = split(last.t); 142 | set_left(r, l); 143 | upd_sz(r); 144 | __size -= sz(mid); 145 | return extracted(mid); 146 | } 147 | 148 | ilist erase(iterator first, iterator last) { return extract(first, last); } 149 | void remove(iterator it) { remove_node(erase(it).t); } 150 | void remove(iterator first, iterator last) { erase(first, last).clear(); } 151 | 152 | iterator partition_point(auto &&pred) { 153 | auto first_false = __end; 154 | for(node *v = splay(__end)->l, *t; v; v = t) { 155 | if(pred(as_const(*v->value))) t = v->r; 156 | else first_false = v, t = v->l; 157 | if(t == nullptr) splay(v); 158 | } 159 | return first_false; 160 | } 161 | 162 | private: 163 | node *__end; 164 | size_t __size; 165 | 166 | ilist(node *v): ilist() { 167 | __size = sz(v); 168 | set_left(__end, v); 169 | upd_sz(__end); 170 | } 171 | 172 | iterator insert(iterator it, node *v) { 173 | if(v == nullptr) return it; 174 | __size += sz(v); 175 | auto [l, r] = split(it.t); 176 | v = leftmost(v); 177 | set_left(v, l); 178 | set_left(r, v); 179 | upd_sz(v, r); 180 | return iterator(v); 181 | } 182 | 183 | void resize_less(const size_t n) { assert(n <= __size); 184 | auto v = split(nth(splay(__end), n)).first; 185 | for(auto [r, i] = pair(__end, __size-n); i--; ) move_prev(r), remove_node(r); 186 | set_left(splay(__end), v); 187 | upd_sz(__end); 188 | __size = n; 189 | } 190 | 191 | void resize_more(const size_t n, const T &value) { assert(n >= __size); 192 | node *v = leftmost(build(n - __size, value)); 193 | set_left(v, split(__end).first); 194 | set_left(__end, v); 195 | upd_sz(v, __end); 196 | __size = n; 197 | } 198 | 199 | static inline size_t sz(node *v) { return v ? v->sz : 0; } 200 | static inline void set_left(node *v, node *to) { v->l = to; if(to) to->p = v; } 201 | static inline void set_right(node *v, node *to) { v->r = to; if(to) to->p = v; } 202 | static inline void upd_sz(auto... t) { ((t->sz = sz(t->l) + sz(t->r) + 1), ...); } 203 | 204 | static node* leftmost(node *v) { //get leftmost splaying it to the position of v 205 | while(v->l) rotate_right(v), v = v->p; 206 | return v; 207 | } 208 | 209 | static node* rightmost(node *v) { //get rightmost splaying it to the position of v 210 | while(v->r) rotate_left(v), v = v->p; 211 | return v; 212 | } 213 | 214 | static inline ptrdiff_t position(node *v) { return sz(splay(v)->l); } 215 | 216 | static node* nth(node *v, size_t n) { 217 | assert(n < sz(v)); 218 | for(size_t sl; ; v = nl : (n-=sl+1, v->r)) if(n == (sl=sz(v->l))) return splay(v); 219 | } 220 | 221 | static void move_prev(node *&v) { 222 | if(v->l) for(v = v->l; v->r; v = v->r); 223 | else { while(v->p->l == v) v = v->p; v = v->p; } 224 | } 225 | 226 | static inline void upd_after_rotate(node *x, node *y, node *p) { 227 | if(p) p->l == x ? set_left(p, y) : set_right(p, y); else y->p = nullptr; 228 | upd_sz(x, y); 229 | } 230 | 231 | static void rotate_left(node *x) { 232 | node *p = x->p, *r = x->r; 233 | set_right(x, r->l); 234 | set_left(r, x); 235 | upd_after_rotate(x, r, p); 236 | } 237 | 238 | static void rotate_right(node *x) { 239 | node *p = x->p, *l = x->l; 240 | set_left(x, l->r); 241 | set_right(l, x); 242 | upd_after_rotate(x, l, p); 243 | } 244 | 245 | static void rotate_big(node *x) { 246 | auto p = x->p, g = p->p, gg = g->p; 247 | if(gg) gg->l == g ? set_left(gg, x) : set_right(gg, x); else x->p = nullptr; 248 | if(g->l == p) { 249 | if(p->l == x) set_left(g, p->r), set_left(p, x->r), set_right(p, g), set_right(x, p); 250 | else set_left(g, x->r), set_right(p, x->l), set_left(x, p), set_right(x, g); 251 | } else { 252 | if(p->l == x) set_right(g, x->l), set_left(p, x->r), set_right(x, p), set_left(x, g); 253 | else set_right(g, p->l), set_right(p, x->l), set_left(p, g), set_left(x, p); 254 | } 255 | upd_sz(g, p, x); 256 | } 257 | 258 | static node* splay(node *x) { //make x a root 259 | while(node *p = x->p) p->p ? rotate_big(x) : p->l == x ? rotate_right(p) : rotate_left(p); 260 | return x; 261 | } 262 | 263 | static pair split(node *s) { //s will be begin of right part 264 | node *l = splay(s)->l; 265 | if(l) l->p = s->l = nullptr, upd_sz(s); 266 | return {l, s}; 267 | } 268 | 269 | static node* build(size_t n, const T &value) { 270 | if(n-- == 0) return nullptr; 271 | node *v = new_node(value); 272 | set_left(v, build(n/2, value)); 273 | set_right(v, build(n-n/2, value)); 274 | upd_sz(v); 275 | return v; 276 | } 277 | 278 | static node* make_end_node(node *end, ilist *list) { end->value = (T*)list; return end; } 279 | static node* new_node(const T &x) { auto t = new_node(); t->value = new_value(x); return t; } 280 | static node* new_node() { auto v = pointers_manager::new_ptr(); *v = node(); return v; } 281 | static T* new_value(const T &x) { auto v = pointers_manager::new_ptr(); *v = x; return v; } 282 | static void remove_node(node *v) { 283 | if(v->value) pointers_manager::free_ptr(v->value); 284 | pointers_manager::free_ptr(v); 285 | } 286 | 287 | template struct pointers_manager { 288 | static inline vector ptr_pool = {}; 289 | static R* new_ptr() { 290 | if(ptr_pool.empty()) { 291 | ptr_pool.resize(pool_sz_ext); 292 | R *ptrs = new R[pool_sz_ext]; 293 | for(size_t i=pool_sz_ext; i--; ) ptr_pool[i] = ptrs + i; 294 | } 295 | R *ptr = ptr_pool.back(); 296 | ptr_pool.pop_back(); 297 | return ptr; 298 | } 299 | static void free_ptr(R *ptr) { ptr_pool.push_back(ptr); } 300 | }; 301 | 302 | public: ~ilist() { if(__end) { clear(); __end->value = nullptr; remove_node(__end); __end = nullptr; } } 303 | }; 304 | -------------------------------------------------------------------------------- /structs/persistent_aggregator.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct persistent_aggregator { 3 | struct node { 4 | node *l, *r; 5 | T value; 6 | node(const T &value): l(nullptr), r(nullptr), value(value) {} 7 | node(node *l, node *r): l(l), r(r), value(l->value,r->value) {} 8 | }; 9 | 10 | persistent_aggregator(): persistent_aggregator(nullptr, 0) {} 11 | persistent_aggregator(size_t n, auto&& gen): persistent_aggregator(build(0, n, gen), n) {} 12 | 13 | T operator()(size_t l, size_t r) const { return l < r ? calc(root, sz, l, r) : T{}; }; 14 | persistent_aggregator set_value(size_t i, const T &value) const { return {set_value(root, sz, i, value), sz}; } 15 | 16 | private: 17 | node *root; 18 | size_t sz; 19 | persistent_aggregator(node *root, size_t sz): root(root), sz(sz) {} 20 | node* build(auto l, auto r, auto &&gen) { 21 | if(l >= r) return nullptr; 22 | if(l+1 == r) return new node(gen(l)); 23 | auto mid = l + (r - l)/2; 24 | return new node(build(l, mid, gen), build(mid, r, gen)); 25 | } 26 | node* set_value(node *t, size_t sz, size_t i, const T &value) const { 27 | if(sz == 1) return new node(value); 28 | size_t m = sz / 2; 29 | if(i < m) return new node(set_value(t->l, m, i, value), t->r); 30 | return new node(t->l, set_value(t->r, sz-m, i-m, value)); 31 | } 32 | T calc(node *t, size_t sz, size_t i, size_t j) const { 33 | if(i == 0 && j == sz) return t->value; 34 | size_t m = sz / 2; 35 | if(j <= m) return calc(t->l, m, i, j); 36 | if(i >= m) return calc(t->r, sz-m, i-m, j-m); 37 | return T(calc(t->l, m, i, m), calc(t->r, sz-m, 0, j-m)); 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /structs/rmq.cpp: -------------------------------------------------------------------------------- 1 | template{} > 2 | struct rmq { 3 | explicit rmq(size_t n = 0, const T &val = {}): d(n), t(d*2,val) {} 4 | rmq(const vector &vals): d(size(vals)), t(d*2) { 5 | copy(begin(vals), end(vals), begin(t)+d); 6 | for(size_t i=d; i-->1;) t[i] = std::min(t[i*2], t[i*2+1], cmp); 7 | } 8 | void set_value(size_t i, const T &val) { 9 | for(t[i+=d]=val; i>1; i>>=1) t[i>>1] = std::min(t[i], t[i^1], cmp); 10 | } 11 | void update(size_t i, const T &val) { 12 | set_value(i, std::min(t[i+d], val, cmp)); 13 | } 14 | T operator()(size_t l, size_t r) const { assert(l < r); 15 | size_t p = l+=d; 16 | for(++l,r+=d; l>=1,r>>=1) { 17 | if(l&1) { if(cmp(t[l], t[p])) p = l; ++l; } 18 | if(r&1) { --r; if(cmp(t[r], t[p])) p = r; } 19 | } 20 | return t[p]; 21 | } 22 | const T& operator()() const { return t[1]; } 23 | const T& operator[](size_t i) const { return t[i+d]; } 24 | private: 25 | size_t d; 26 | vector t; 27 | }; 28 | -------------------------------------------------------------------------------- /structs/rmq_range_add.cpp: -------------------------------------------------------------------------------- 1 | template{}, class A = T > 2 | struct rmq_range_add { 3 | explicit rmq_range_add(size_t sz = 0): d(std::bit_ceil(sz)), t(d*2) {} 4 | 5 | rmq_range_add(const std::ranges::range auto &vals): rmq_range_add(size(vals)) { 6 | for(auto it=begin(t)+d; auto &&val : vals) it++->first = val; 7 | for(size_t i=d; i-->1; ) t[i].first = std::min(t[i*2].first, t[i*2+1].first, cmp); 8 | } 9 | 10 | void add(size_t l, size_t r, const A &val) { 11 | if(l < r) add(l, r, val, 0, d, 1); 12 | } 13 | 14 | T operator()(size_t l, size_t r) const { 15 | assert(l < r); 16 | return min(l, r, 0, d, 1); 17 | } 18 | 19 | T operator[](size_t i) const { 20 | T result = t[i+=d].first; 21 | while(i>>=1) result += t[i].second; 22 | return result; 23 | } 24 | 25 | private: 26 | size_t d; 27 | vector> t; 28 | 29 | void add(size_t i, size_t j, const A &val, size_t l, size_t r, size_t v) { 30 | if(i == l && j == r) { 31 | t[v].first += val; 32 | t[v].second += val; 33 | return ; 34 | } 35 | size_t m = std::midpoint(l, r); 36 | if(i < m) add(i, std::min(j,m), val, l, m, v*2); 37 | if(m < j) add(std::max(i,m), j, val, m, r, v*2+1); 38 | t[v].first = std::min(t[v*2].first, t[v*2+1].first, cmp) + t[v].second; 39 | } 40 | 41 | T min(size_t i, size_t j, size_t l, size_t r, size_t v) const { 42 | if(i == l && j == r) return t[v].first; 43 | size_t m = std::midpoint(l, r); 44 | return (j<=m ? min(i, j, l, m, v*2) : i>=m ? min(i, j, m, r, v*2+1) 45 | : std::min(min(i, m, l, m, v*2), min(m, j, m, r, v*2+1))) + t[v].second; 46 | } 47 | }; 48 | -------------------------------------------------------------------------------- /structs/rmq_range_assign.cpp: -------------------------------------------------------------------------------- 1 | template{}> 2 | struct rmq_range_assign { 3 | explicit rmq_range_assign(size_t sz = 0): d(std::bit_ceil(sz)), t(d*2) {} 4 | 5 | rmq_range_assign(const std::ranges::range auto &vals): rmq_range_assign(size(vals)) { 6 | for(auto it=begin(t)+d; auto &&val : vals) it++->first = val; 7 | for(size_t i=d; i-->1; ) t[i].first = std::min(t[i*2].first, t[i*2+1].first, cmp); 8 | } 9 | 10 | void assign(size_t l, size_t r, const T &value) { 11 | if(l < r) assign(l, r, value, 0, d, 1); 12 | } 13 | 14 | T operator()(size_t l, size_t r) const { 15 | assert(l < r); 16 | return min(l, r, 0, d, 1); 17 | } 18 | 19 | T operator[](size_t i) const { 20 | T result = t[i+=d].first; 21 | while(i>>=1) if(t[i].second) result = t[i].first; 22 | return result; 23 | } 24 | 25 | private: 26 | size_t d; 27 | vector> t; 28 | 29 | void assign(size_t i, size_t j, const T &val, size_t l, size_t r, size_t v) { 30 | if(i == l && j == r) { 31 | t[v] = {val, true}; 32 | return ; 33 | } 34 | if(t[v].second) { 35 | t[v*2] = t[v*2+1] = t[v]; 36 | t[v].second = false; 37 | } 38 | size_t m = std::midpoint(l, r); 39 | if(i < m) assign(i, std::min(j,m), val, l, m, v*2); 40 | if(m < j) assign(std::max(i,m), j, val, m, r, v*2+1); 41 | t[v].first = std::min(t[v*2].first, t[v*2+1].first, cmp); 42 | } 43 | 44 | T min(size_t i, size_t j, size_t l, size_t r, size_t v) const { 45 | if((i == l && j == r) || t[v].second) return t[v].first; 46 | if(size_t m = std::midpoint(l, r); j <= m) return min(i, j, l, m, v*2); 47 | else if(i >= m) return min(i, j, m, r, v*2+1); 48 | else return std::min(min(i, m, l, m, v*2), min(m, j, m, r, v*2+1), cmp); 49 | } 50 | }; 51 | -------------------------------------------------------------------------------- /structs/rmq_static.cpp: -------------------------------------------------------------------------------- 1 | template{}> 2 | struct rmq { 3 | rmq() {} 4 | rmq(const vector &vals): t(std::bit_width(size(vals))) { 5 | if(!empty(t)) t[0] = vals; 6 | for(size_t k=1, p=1; k> t; 17 | }; 18 | -------------------------------------------------------------------------------- /structs/rsq.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct rsq { 3 | explicit rsq(size_t n = 0): f(n) {} 4 | rsq(const std::ranges::range auto &vals): f(begin(vals), end(vals)) { 5 | for(size_t i=0, j, n=size(f); i f; 19 | }; 20 | -------------------------------------------------------------------------------- /structs/rsq_range_add.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct rsq_range_add { 3 | explicit rsq_range_add(size_t sz = 0): f(sz) {} 4 | 5 | rsq_range_add(const vector &vals): f(size(vals)) { 6 | for(size_t i = 0; i < size(vals); ++i) { 7 | T x{vals[i]}; if(i) x -= T(vals[i-1]); 8 | f[i].first += x; 9 | f[i].second += x * T(i); 10 | if(size_t j = i|(i+1); j < size(f)) { 11 | f[j].first += f[i].first; 12 | f[j].second += f[i].second; 13 | } 14 | } 15 | } 16 | 17 | void add(size_t l, size_t r, const T &val) { 18 | if(l < r) add_suf(l, val), add_suf(r, -val); 19 | } 20 | 21 | T operator()(size_t l, size_t r) const { 22 | return l < r ? sum_until(r) - sum_until(l) : T{}; 23 | } 24 | 25 | T operator[](size_t i) const { return sum_until(i+1) - sum_until(i); } 26 | 27 | private: vector> f; 28 | 29 | void add_suf(size_t i, const T &val) { 30 | for(const T m = val*T(i); i < size(f); i |= i+1) 31 | f[i].first += val, f[i].second += m; 32 | } 33 | 34 | T sum_until(const size_t pos) const { 35 | T a{}, b{}; 36 | for(size_t i = pos; i--; i &= i+1) 37 | a += f[i].first, b += f[i].second; 38 | return a*T(pos) - b; 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /structs/rsq_range_assign.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct rsq_range_assign { 3 | explicit rsq_range_assign(size_t sz = 0): d(std::bit_ceil(sz)), t(d*2) {} 4 | 5 | rsq_range_assign(const std::ranges::range auto &vals): rsq_range_assign(size(vals)) { 6 | for(auto it=begin(t)+d; auto &&val : vals) it++->first = val; 7 | for(size_t i=d; i-->1; ) t[i].first = t[i*2].first + t[i*2+1].first; 8 | } 9 | 10 | void assign(size_t l, size_t r, const A &value) { 11 | if(l < r) assign(l, r, value, 0, d, 1); 12 | } 13 | 14 | T operator()(size_t l, size_t r) const { 15 | return l < r ? sum(l, r, 0, d, 1) : T{}; 16 | } 17 | 18 | private: 19 | size_t d; 20 | vector>> t; 21 | 22 | void assign(size_t i, size_t j, const A &val, size_t l, size_t r, size_t v) { 23 | if(i == l && j == r) { 24 | t[v] = {T(r-l) * val, val}; 25 | return ; 26 | } 27 | size_t m = std::midpoint(l, r); 28 | if(auto &a = t[v].second) { 29 | t[v*2] = t[v*2+1] = {T(m-l) * *a, a}; 30 | a.reset(); 31 | } 32 | if(i < m) assign(i, std::min(j,m), val, l, m, v*2); 33 | if(m < j) assign(std::max(i,m), j, val, m, r, v*2+1); 34 | t[v].first = t[v*2].first + t[v*2+1].first; 35 | } 36 | 37 | T sum(size_t i, size_t j, size_t l, size_t r, size_t v) const { 38 | if(i == l && j == r) return t[v].first; 39 | if(auto a = t[v].second) return T(j-i) * *a; 40 | if(size_t m = std::midpoint(l, r); j <= m) return sum(i, j, l, m, v*2); 41 | else if(i >= m) return sum(i, j, m, r, v*2+1); 42 | else return sum(i, m, l, m, v*2) + sum(m, j, m, r, v*2+1); 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /tests/rmq_static.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #include "../structs/rmq_static.cpp" 5 | 6 | void creation_test() { 7 | //empty 8 | rmq f0; 9 | 10 | //one 11 | rmq f1(vector(1,0)); 12 | 13 | //assign / coping 14 | auto f = f1; 15 | 16 | f1 = rmq(vector(1<<15,-1)); 17 | 18 | f = f1; 19 | } 20 | 21 | template 22 | void all_range_queries(const vector &vals) { 23 | const size_t n = size(vals); 24 | rmq fmin(vals); 25 | rmq fmax(vals); 26 | for(size_t l = 0; l < n; ++l) { 27 | T curmin = vals[l], curmax = vals[l]; 28 | for(size_t r = l+1; r <= n; ++r) { 29 | curmin = min(curmin, vals[r-1]); 30 | assert(fmin(l, r) == curmin); 31 | curmax = max(curmax, vals[r-1]); 32 | assert(fmax(l, r) == curmax); 33 | } 34 | } 35 | } 36 | 37 | void queries_permutations(const size_t n) { 38 | vector vals(n); 39 | iota(begin(vals), end(vals), 0); 40 | do { 41 | all_range_queries(vals); 42 | } while(next_permutation(begin(vals),end(vals))); 43 | } 44 | 45 | int main() { 46 | 47 | creation_test(); 48 | 49 | for(size_t n = 1; n <= 8; ++n) { 50 | queries_permutations(n); 51 | } 52 | 53 | return 0; 54 | } -------------------------------------------------------------------------------- /well-known/area_of_union_of_rectangles.cpp: -------------------------------------------------------------------------------- 1 | //requires @aggregator_range_operation 2 | template 3 | S area_of_union_of_rectangles( 4 | const vector> &rects //[ax, ay, bx, by] 5 | ) { 6 | struct add_op { 7 | D a; 8 | add_op(D add): a{add} {} 9 | add_op(const add_op &x, const add_op &y): a{x.a+y.a} {} 10 | decltype(auto) slice(size_t, size_t) const { return *this; } 11 | }; 12 | 13 | struct min_cnt { 14 | D m; 15 | P cnt; 16 | min_cnt(): min_cnt(0,0) {} 17 | min_cnt(D val, P cnt): m{val}, cnt{cnt} {} 18 | min_cnt(const min_cnt &a, const min_cnt &b): m{min(a.m,b.m)}, cnt{0} { 19 | if(a.m == m) cnt += a.cnt; 20 | if(b.m == m) cnt += b.cnt; 21 | } 22 | void apply(const add_op &o, size_t) { m += o.a; } 23 | }; 24 | 25 | vector

ys; 26 | for(auto [ax, ay, bx, by] : rects) { 27 | assert(ax < bx && ay < by); 28 | ys.push_back(ay); 29 | ys.push_back(by); 30 | } 31 | if(empty(ys)) return 0; 32 | 33 | sort(begin(ys), end(ys)); 34 | ys.erase(unique(begin(ys), end(ys)), end(ys)); 35 | 36 | aggregator t(size(ys)-1, [&](size_t i) { 37 | return min_cnt(0, ys[i+1]-ys[i]); 38 | }); 39 | 40 | vector> events; 41 | events.reserve(size(rects)*2); 42 | for(auto [ax, ay, bx, by] : rects) { 43 | size_t sl = lower_bound(begin(ys), end(ys), ay) - begin(ys); 44 | size_t sr = lower_bound(begin(ys), end(ys), by) - begin(ys); 45 | events.emplace_back(ax, +1, sl, sr); 46 | events.emplace_back(bx, -1, sl, sr); 47 | } 48 | sort(begin(events), end(events), [](auto &e1, auto &e2) { 49 | return get<0>(e1) < get<0>(e2); 50 | }); 51 | 52 | S area = 0; 53 | P H = ys.back() - ys[0], px = 0; 54 | for(auto [x, sig, sl, sr] : events) { 55 | auto &cur = t(); 56 | area += S(x - px) * S(cur.m == 0 ? H - cur.cnt : H); 57 | t.apply(sl, sr, sig); 58 | px = x; 59 | } 60 | 61 | return area; 62 | } 63 | -------------------------------------------------------------------------------- /well-known/mex_rects.cpp: -------------------------------------------------------------------------------- 1 | // mex_rect(l1, l2, x, r1, r2) 2 | // l1 <= l < l2 && r1 <= r < r2 : mex(a[l], ..., a[r]) = x 3 | void mex_rects(const vector &a, auto &&mex_rect) { 4 | const int n = size(a); 5 | //ignore a[i] >= n 6 | 7 | vector st(n), sr(n), sx(n); 8 | // set ls; 9 | 10 | auto del = [&](int l, int t) { 11 | int r = sr[l], x = sx[l]; 12 | assert(r > l); 13 | // ls.erase(l); 14 | mex_rect(st[l], t, x, l, r); 15 | sr[l] = sx[l] = 0; 16 | }; 17 | 18 | auto ins = [&](int l, int r, int x, int t) { 19 | if(l >= r) return ; 20 | // ls.insert(l); 21 | sr[l] = r; 22 | sx[l] = x; 23 | st[l] = t; 24 | }; 25 | 26 | auto replace = [&](int l, int r, int x, int t) { 27 | if(l >= r) return ; 28 | 29 | assert(sr[l] > 0); 30 | for(int i = l; i < r; ) { 31 | int pr = sr[i], px = sx[i]; 32 | del(i, t); 33 | if(pr > r) ins(r, pr, px, t); 34 | i = pr; 35 | } 36 | 37 | ins(l, r, x, t); 38 | }; 39 | 40 | vector u(n+1); 41 | for(int i=0, mex=0, l=0; i nxt(n, n), fpos(n, n); 51 | for(int i=n-1; i>=0; --i) if(int x = a[i]; x < n) { 52 | nxt[i] = fpos[x]; 53 | fpos[x] = i; 54 | } 55 | 56 | rmq mfpos(fpos); 57 | for(int i=0; i 0 ? mfpos(0, x) : i+1, r = fpos[x]; 63 | replace(l, r, x, i+1); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /well-known/numeric_functions.cpp: -------------------------------------------------------------------------------- 1 | //g(n) = a(n) - sum i=2..n g(n/i) * b(i) 2 | //almost O(n ** 2/3) 3 | template 4 | T g(uint64_t maxn, auto &&a, auto &&b, auto &&sumb) { 5 | const uint32_t sq = max(sqrt(maxn), pow(maxn / log(maxn + 1), 2./3) * 2); 6 | vector small(sq + 1, 0), big(maxn / (sq + 1) + 1); 7 | 8 | for(uint32_t n = 1; n <= sq; ++n) { 9 | small[n] += small[n-1] - a(n-1) + a(n); 10 | const T dif = small[n] - small[n-1]; 11 | for(uint32_t i = 2; i * n <= sq; ++i) small[i * n] -= dif * b(i); 12 | } 13 | 14 | for(uint32_t d = maxn / (sq + 1) ; d >= 1; --d) { 15 | const uint64_t n = maxn / d; 16 | const uint32_t sn = sqrt(n), sp = n / (sn + 1); 17 | T res = a(n); 18 | 19 | uint64_t l, r = n; 20 | for(uint32_t k = 1; k <= sn; ++k, r = l) { 21 | l = n / (k + 1); 22 | res -= small[k] * (sumb(r) - sumb(l)); 23 | if(k+1 <= sp) res -= (l <= sq ? small[l] : big[maxn / l]) * b(k+1); 24 | } 25 | 26 | big[d] = res; 27 | } 28 | 29 | return maxn <= sq ? small[maxn] : big[1]; 30 | } 31 | -------------------------------------------------------------------------------- /well-known/sqrt_solver_sorted_ranges.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Given array a_1 .. a_n and m ranges [l, r) 3 | For each range calculate some value based on sorted values of this range 4 | 5 | If value can be changed in O(1) after insertion i between pr and nx 6 | then answers can be found in O(n \sqrt{m} + n \log{n}) 7 | 8 | examples: 9 | https://codeforces.com/contest/765/problem/F 10 | https://www.codechef.com/problems/MINXORSEG 11 | */ 12 | template 13 | vector solve( 14 | const vector &a, 15 | const vector> &segs, 16 | const V &neutral, 17 | auto &&f //(V &val, i, pr, nx) 18 | ) { 19 | 20 | const size_t n = size(a), m = size(segs); if(m == 0) return {}; 21 | const size_t D = max(1, n / sqrt(m*2)); 22 | const size_t K = (n-1) / D + 1; 23 | 24 | vector p(n); 25 | iota(begin(p), end(p), 0); 26 | sort(begin(p), end(p), [&a](size_t i, size_t j) { return a[i] < a[j]; }); 27 | 28 | vector in_st(K, n), in_nx(n, n); 29 | for(size_t k=n; k--; ) { 30 | size_t i = p[k], b = i / D; 31 | in_nx[i] = in_st[b]; 32 | in_st[b] = i; 33 | } 34 | 35 | vector ans(m, neutral); 36 | 37 | vector> qs(K); 38 | 39 | for(size_t k = 0; k < m; ++k) { 40 | auto [ql, qr] = segs[k]; 41 | assert(0 <= ql && ql <= qr && qr <= n); 42 | 43 | const size_t bl = ql / D; 44 | const size_t br = (qr-1) / D; 45 | 46 | if(bl == br) { 47 | for(size_t i = in_st[bl], p = n; i < n; i = in_nx[i]) 48 | if(ql <= i && i < qr) { 49 | f(ans[k], i, p, n); 50 | p = i; 51 | } 52 | } else { 53 | qs[bl].emplace_back(k); 54 | } 55 | } 56 | 57 | 58 | vector pr(n, n), nx(n, n), hist; 59 | auto del = [&](size_t i) { 60 | hist.push_back(i); 61 | if(pr[i] < n) nx[pr[i]] = nx[i]; 62 | if(nx[i] < n) pr[nx[i]] = pr[i]; 63 | }; 64 | 65 | auto undo = [&] { 66 | assert(!empty(hist)); 67 | const size_t i = hist.back(); 68 | hist.pop_back(); 69 | if(size_t l = pr[i]; l < n) nx[l] = i; 70 | if(size_t r = nx[i]; r < n) pr[r] = i; 71 | }; 72 | 73 | auto undo_calc = [&](V &cur) { 74 | const size_t i = hist.back(); 75 | f(cur, i, pr[i], nx[i]); 76 | undo(); 77 | }; 78 | 79 | for(size_t k = 0; k + 1 < n; ++k) nx[p[k]] = p[k+1], pr[p[k+1]] = p[k]; 80 | for(size_t i = 0; i < n; ++i) del(i); 81 | 82 | vector snapshots(n, neutral); 83 | for(size_t bl = K; bl--;) { 84 | const size_t sl = bl * D, sr = min(sl + D, n) - 1; 85 | for(size_t i = sl; i <= sr; ++i) undo(); //#1 86 | 87 | for(size_t i = n; i-- > sl; ) del(i); 88 | 89 | auto &vec = qs[bl]; 90 | sort(begin(vec), end(vec), [&](size_t i, size_t j) { return segs[i].second < segs[j].second; }); 91 | auto it = begin(vec); 92 | 93 | V val = neutral; 94 | for(size_t i = sl; i < n; ++i) { 95 | undo_calc(val); //#2 96 | 97 | while(it != end(vec) && segs[*it].second == i + 1) { 98 | const size_t k = *it++, ql = segs[k].first; 99 | 100 | for(size_t i = sl; i <= sr; ++i) del(i); 101 | 102 | V cur = snapshots[i]; 103 | for(size_t i = ql; i <= sr; ++i) undo_calc(cur); //#3 104 | ans[k] = cur; 105 | 106 | for(size_t i = sl; i < ql; ++i) undo(); //#3 107 | } 108 | 109 | snapshots[i] = val; 110 | } 111 | } 112 | 113 | // #1: n 114 | // #2: (K+1)*K/2 * D = K*K*D/2 = n*K/2 115 | // #3: m * D 116 | 117 | return ans; 118 | } 119 | --------------------------------------------------------------------------------