Full Code of radoslav11/Coding-Library for AI

master 669270c03e85 cached
132 files
324.3 KB
106.6k tokens
1510 symbols
1 requests
Download .txt
Showing preview only (356K chars total). Download the full file or copy to clipboard to get everything.
Repository: radoslav11/Coding-Library
Branch: master
Commit: 669270c03e85
Files: 132
Total size: 324.3 KB

Directory structure:
gitextract_ns7a50wl/

├── README.md
├── data_structures/
│   ├── clever_adding_intervals_set.hpp
│   ├── compressed_fenwick.hpp
│   ├── decremental_constant_set.hpp
│   ├── fenwick.hpp
│   ├── fenwick_2d.hpp
│   ├── fenwick_range_update.hpp
│   ├── fenwick_range_update_range_query.hpp
│   ├── heap.hpp
│   ├── meldable_heap.hpp
│   ├── merge_sort_tree.hpp
│   ├── monoids_lazy.hpp
│   ├── nonintersecting_range_tree.hpp
│   ├── offline_segment_tree_2d.hpp
│   ├── rmq2d.hpp
│   ├── segment_tree.hpp
│   ├── segment_tree_lazy.hpp
│   ├── set_lazy.hpp
│   ├── sparse_table.hpp
│   ├── sparse_table_disjoint.hpp
│   ├── treap.hpp
│   ├── treap_lazy.hpp
│   └── wavelet_tree.hpp
├── dp_optimizations/
│   └── convex_hull_trick.hpp
├── geometry/
│   ├── dynamic_convex_hull.hpp
│   ├── halfplane_intersection.hpp
│   ├── point.hpp
│   ├── polygon.hpp
│   └── voronoi.hpp
├── graph/
│   ├── bcc.hpp
│   ├── bipartite_coloring.hpp
│   ├── bipartite_matching.hpp
│   ├── dijkstra_vlog.hpp
│   ├── directed_cactus.hpp
│   ├── dsu.hpp
│   ├── eppstein_shortest_paths.hpp
│   ├── eulerian_paths.hpp
│   ├── graph.hpp
│   ├── hopcroft_karp.hpp
│   ├── hungarian_algorithm.hpp
│   ├── maxflow.hpp
│   ├── mincost_circulation.hpp
│   ├── mincost_flow.hpp
│   ├── scc.hpp
│   ├── st_numbering.hpp
│   └── two_sat.hpp
├── math/
│   └── gauss_bitset.hpp
├── old_impl/
│   ├── data_structures/
│   │   ├── implicit_treap.hpp
│   │   ├── implicit_treap_basic.hpp
│   │   ├── max_count_segment_tree.cpp
│   │   ├── merging_segment_tree.cpp
│   │   ├── min_segment_tree.cpp
│   │   ├── monotonous_queue.cpp
│   │   ├── persistent_segment_tree.cpp
│   │   ├── persistent_segment_tree_lazy.cpp
│   │   ├── persistent_treap.cpp
│   │   ├── persistent_treap_lazy.cpp
│   │   ├── segment_tree.cpp
│   │   ├── segment_tree_AP.cpp
│   │   ├── segment_tree_add_mult.cpp
│   │   ├── segment_tree_fast.cpp
│   │   ├── segment_tree_lazy_min.cpp
│   │   ├── segment_tree_lazy_sum.cpp
│   │   ├── segment_tree_nonzero.cpp
│   │   ├── segment_tree_with_binary_search.cpp
│   │   └── treap.cpp
│   ├── geometry/
│   │   ├── closest_points.cpp
│   │   ├── convex_hull.cpp
│   │   ├── dynamic_upper_hull.cpp
│   │   ├── kd-tree.cpp
│   │   └── rectangle_union.cpp
│   ├── graph/
│   │   ├── dsu_bipartite.cpp
│   │   ├── eulerian_path.cpp
│   │   ├── max_anticlique.cpp
│   │   ├── maximum_closure.cpp
│   │   ├── mincost_maxflow.cpp
│   │   ├── persistent_dsu.cpp
│   │   ├── scc_tarjan.cpp
│   │   └── st_numbering.cpp
│   ├── math/
│   │   ├── combinatorics.cpp
│   │   ├── fft.cpp
│   │   ├── fft_mod.cpp
│   │   ├── fft_xor.cpp
│   │   ├── fft_xor_mod.cpp
│   │   ├── gauss_elimination_equations.cpp
│   │   ├── gauss_elimination_equations_mod.cpp
│   │   ├── gauss_elimination_equations_mod_number_solutions.cpp
│   │   ├── matrix_exponential.cpp
│   │   └── number_theory.cpp
│   ├── strings/
│   │   ├── aho_corasick.cpp
│   │   ├── aho_corasick_dynamic.cpp
│   │   ├── kmp.cpp
│   │   ├── palindromic_tree.cpp
│   │   ├── rabin_karp.cpp
│   │   ├── suffix_array.cpp
│   │   ├── suffix_array_hash.cpp
│   │   ├── suffix_array_log2.cpp
│   │   ├── suffix_automaton.cpp
│   │   └── trie.cpp
│   └── tree/
│       ├── centroid_decomposition.cpp
│       ├── dsu_on_tree.cpp
│       ├── hld.cpp
│       ├── lca-seg3.cpp
│       ├── link_cut_tree.cpp
│       └── virtual_tree.cpp
├── other/
│   ├── bits/
│   │   ├── bit_trie.hpp
│   │   └── xor_basis.hpp
│   ├── dp_optimizations/
│   │   ├── LiChao_dynamic.cpp
│   │   ├── LiChao_parabolic.cpp
│   │   ├── LiChao_segment_tree_offline.cpp
│   │   ├── convex_hull_trick_max.cpp
│   │   ├── convex_hull_trick_min.cpp
│   │   ├── divide_and_conquer_optimization.cpp
│   │   ├── slope_trick.cpp
│   │   └── slope_trick_priority_queue.cpp
│   ├── queries/
│   │   ├── mo.cpp
│   │   ├── mo_dsu.cpp
│   │   ├── mo_online.cpp
│   │   └── offline_centroid_queries.cpp
│   └── utils/
│       └── count_inversions.cpp
├── strings/
│   ├── aho_corasick.hpp
│   ├── hashing.hpp
│   ├── suffix_array.hpp
│   └── suffix_automaton.hpp
└── tree/
    ├── centroid_decomposition.hpp
    ├── euler_order_segment_tree.cpp
    ├── lca.hpp
    ├── lca_sparse_table.hpp
    ├── line_tree.hpp
    ├── link_cut_tree.hpp
    ├── vertex_add_path_sum.hpp
    └── virtual_tree.hpp

================================================
FILE CONTENTS
================================================

================================================
FILE: README.md
================================================
# Coding-Library

This is a collection of implementations of various data structures and algorithms, intended for competitive programming. Some of these implementations are relatively old, as they are from my IOI times, but might still be a useful point of reference. 

The suggested way to set this up is to create a directory "coding_library" somewhere (or a symlink to this repo), and add it to $CPLUS_INCLUDE_PATH. I plan on making a script that then expands the libraries that you use, but this is still a TODO.


# Random

Useful ideas, that aren't exactly a part of this library.

1) Bitset for almost arbitrary N:
- https://codeforces.com/blog/entry/100910?#comment-896093
- https://codeforces.com/problemsets/acmsguru/problem/99999/415

2) MiniSat based SAT solver that can be used in competitive programming:
- https://github.com/togatoga/togasat?tab=readme-ov-file


================================================
FILE: data_structures/clever_adding_intervals_set.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

template<class T>
struct clever_set {
    map<pair<int, int>, T> value;

    void init(int n) { value[{n, 1}] = (T)0; }

    vector<pair<pair<int, int>, T> > add(int l, int r, T val) {
        auto bg = value.lower_bound({l, 0})->first;
        if(bg.second != l) {
            T val = value[bg];
            value.erase(bg);
            value[{l - 1, bg.second}] = val;
            value[{bg.first, l}] = val;
        }

        auto en = value.lower_bound({r, 0})->first;
        if(en.first != r) {
            T val = value[en];
            value.erase(en);
            value[{en.first, r + 1}] = val;
            value[{r, en.second}] = val;
        }

        vector<pair<pair<int, int>, T> > ret;
        auto itt = value.lower_bound({l, 0});
        while(true) {
            if(itt == value.end() || itt->first.first > r) {
                break;
            }
            ret.push_back({{itt->first.second, itt->first.first}, itt->second});
            ++itt;
        }

        for(auto it: ret) {
            value.erase({it.first.second, it.first.first});
        }

        value[{r, l}] = val;
        return ret;
    }
};


================================================
FILE: data_structures/compressed_fenwick.hpp
================================================
#include <bits/stdc++.h>
#include <coding_library/data_structures/fenwick.hpp>
using namespace std;

template<class T>
struct CompressedFenwick {
    Fenwick<T> t;
    vector<int> li;

    int get_idx(int x) {
        return lower_bound(li.begin(), li.end(), x) - li.begin() + 1;
    }
    void update(int x, T val) { t.update(get_idx(x), val); }

    void add_to_prep(int x) { li.push_back(x); }
    void prepare() {
        sort(li.begin(), li.end());
        li.erase(unique(li.begin(), li.end()), li.end());
        t.init(li.size() + 2);
    }

    T query(int x) { return t.query(get_idx(x) - 1); }
    T size() { return t.query(t.sz); }
};


================================================
FILE: data_structures/decremental_constant_set.hpp
================================================
#include <bits/stdc++.h>
#include <coding_library/graph/dsu.hpp>
using namespace std;

/*
The structures resembles a set on N positions that are said to initially be
active, and supports the following updates:
- Remove some active position from the set.
- query_left(i) to find the first active position before i (inclusive). 
- query_right(i) to find the first active position after i (inclusive).

Main idea is to do DSU on blocks of size w=64 working in O(N alpha(N) / w) =
O(N) overall, and then answer small queries in O(1) using bitwise operations.

Based on Nachia's implementation:
https://codeforces.com/contest/2018/submission/283309295
*/

class DecrementalConstantSet {
  private:
    const uint64_t FULL_MASK = ~0ull;

    int n, b;
    vector<uint64_t> mask;
    vector<int> large_block_left, large_block_right;
    DSU dsu;

    int small_query_prefix(int c, uint64_t filter_mask) {
        uint64_t z = mask[c] & filter_mask;
        return z ? (c << 6) + __builtin_ctzll(z) : -1;
    }

    int small_query_suffix(int c, uint64_t filter_mask) {
        uint64_t z = mask[c] & filter_mask;
        return z ? (c << 6) + 63 - __builtin_clzll(z) : -1;
    }

  public:
    DecrementalConstantSet(int _n)
        : n(_n + 2),
          b((n + 64) >> 6),
          mask(b, FULL_MASK),
          large_block_left(b + 1),
          large_block_right(b + 1),
          dsu(b) {
        iota(large_block_left.begin(), large_block_left.end(), 0);
        iota(large_block_right.begin(), large_block_right.end(), 0);
    }

    void remove(int _i) {
        // Indices are +1
        int i = _i + 1;
        int c = i >> 6, d = i & 63;
        mask[c] &= ~(1ull << d);
        if(mask[c] == 0) {
            for(int dir: {-1, 1}) {
                if(c + dir < 0 || c + dir >= b || mask[c + dir]) {
                    continue;
                }
                int root = dsu.root(c);
                int next_root = dsu.root(c + dir);
                if(root != next_root) {
                    int new_root = dsu.unite(root, next_root);
                    large_block_left[new_root] =
                        min(large_block_left[root],
                            large_block_left[next_root]);
                    large_block_right[new_root] =
                        max(large_block_right[root],
                            large_block_right[next_root]);
                }
            }
        }
    }

    int query_right(int _i) {
        if(_i >= n) {
            return n;
        }
        // Indices are +1 and we undo when we return
        int i = max(_i, 0) + 1;
        int c = i >> 6, d = i & 63;
        if(d > 0) {
            int x = small_query_prefix(c, FULL_MASK << d);
            if(x >= 0) {
                return x - 1;
            }
            c++;
        }

        if(!mask[c]) {
            c = large_block_right[dsu.root(c)] + 1;
        }
        return small_query_prefix(c, FULL_MASK) - 1;
    }

    int query_left(int _i) {
        if(_i < 0) {
            return -1;
        }
        // Indices are +1 and we undo when we return
        int i = min(_i + 1, n);
        int c = i >> 6, d = i & 63;

        if(d < 63) {
            int x = small_query_suffix(c, (1ull << (d + 1)) - 1);
            if(x >= 0) {
                return x - 1;
            }
            c--;
        }

        if(!mask[c]) {
            c = large_block_left[dsu.root(c)] - 1;
        }
        return small_query_suffix(c, FULL_MASK) - 1;
    }
};


================================================
FILE: data_structures/fenwick.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

template<class T>
class Fenwick {
  private:
    int sz, log_size;
    vector<T> tr;

  public:
    void init(int n) {
        sz = n + 1;
        log_size = 31 - __builtin_clz(sz);
        tr.assign(sz + 1, 0);
    }

    void update(int idx, T val) {
        if(idx <= 0) {
            assert(false);
            return;
        }
        for(; idx <= sz; idx += (idx & -idx)) {
            tr[idx] += val;
        }
    }

    T query(int idx) {
        T ans = 0;
        for(; idx >= 1; idx -= (idx & -idx)) {
            ans += tr[idx];
        }

        return ans;
    }

    T query(int l, int r) { return query(r) - query(l - 1); }

    int find_kth(T k) {
        int idx = 0;
        for(int i = log_size; i >= 0; i--) {
            if(idx + (1 << i) < sz && tr[idx + (1 << i)] < k) {
                k -= tr[idx + (1 << i)];
                idx += (1 << i);
            }
        }
        return idx + 1;
    }
};


================================================
FILE: data_structures/fenwick_2d.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

template<class T, T (*merge)(T, T), T (*identity)()>
class Fenwick2d {
  private:
    int sz;
    vector<unordered_map<int, T>> t;

    void update_row(int row, int idx, T val) {
        if(idx == 0) {
            return;
        }
        for(; idx <= sz; idx += (idx & -idx)) {
            if(t[row].find(idx) == t[row].end()) {
                t[row][idx] = merge(identity(), val);
            } else {
                t[row][idx] = merge(t[row][idx], val);
            }
        }
    }

    T query_row(int row, int idx) {
        T ans = identity();
        for(; idx >= 1; idx -= (idx & -idx)) {
            if(t[row].find(idx) == t[row].end()) {
                ans = merge(identity(), ans);
            } else {
                ans = merge(t[row][idx], ans);
            }
        }

        return ans;
    }

  public:
    void init(int _sz) {
        sz = _sz;
        t.assign(sz + 1, unordered_map<int, T>());
    }

    void update(int row, int col, T val) {
        if(col == 0) {
            return;
        }
        for(; row <= sz; row += (row & -row)) {
            update_row(row, col, val);
        }
    }

    T query(int row, int col) {
        T ans = identity();
        for(; row >= 1; row -= (row & -row)) {
            ans = merge(query_row(row, col), ans);
        }

        return ans;
    }
};
// int min_custom(int a, int b) { return min(a, b); }
// int max_custom(int a, int b) { return max(a, b); }
// int sum_custom(int a, int b) { return a + b; }

// int identity_min() { return INT_MAX; }
// int identity_max() { return INT_MIN; }
// int identity_sum() { return 0; }

// Fenwick2d<int, sum_custom, identity_sum> ft;


================================================
FILE: data_structures/fenwick_range_update.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

template<class T>
class FenwickRangeUpdate { 
  private:
    int sz;
    vector<T> tr;

    void update(int idx, T val) {
        if(idx <= 0) {
            assert(false);
            return;
        }
        for(; idx <= sz; idx += (idx & -idx)) {
            tr[idx] += val;
        }
    }

  public:
    void init(int n) {
        sz = n + 1;
        tr.assign(sz + 1, 0);
    }

    T query(int idx) {
        T ans = 0;
        for(; idx >= 1; idx -= (idx & -idx)) {
            ans += tr[idx];
        }

        return ans;
    }

    void update(int l, int r, T val) {
        update(l, val);
        update(r + 1, -val);
    }
};


================================================
FILE: data_structures/fenwick_range_update_range_query.hpp
================================================
#include <bits/stdc++.h>
#include "coding_library/data_structures/fenwick_range_update.hpp"
using namespace std;

template<class T>
class FenwickRangeUpdateRangeQuery {
    int sz;
    FenwickRangeUpdate<T> t0, t1;

    void init(int _sz) {
        sz = _sz;
        t0.init(sz + 1);
        t1.init(sz + 1);
    }

    void update(int l, int r, T val) {
        t0.update(l, r, val);
        t1.update(l, r, -(l - 1) * val);
        t1.update(r + 1, sz, (r - l + 1) * val);
    }

    T query(int idx) { return t0.query(idx) * (T)idx + t1.query(idx); }
    T query(int l, int r) { return query(r) - query(l - 1); }
};


================================================
FILE: data_structures/heap.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

template<class T, bool (*cmp)(T, T)>
class Heap {
  private:
    vector<T> heap_values;
    vector<int> heap, pos_in_heap;

    void push_up(int id) {
        while(id > 0 &&
              cmp(heap_values[heap[id]], heap_values[heap[(id - 1) / 2]])) {
            swap(heap[id], heap[(id - 1) / 2]);
            swap(pos_in_heap[heap[id]], pos_in_heap[heap[(id - 1) / 2]]);
            id = (id - 1) / 2;
        }
    }

    void push_down(int id) {
        while(2 * id + 1 < heap.size()) {
            int child = 2 * id + 1;
            if(child + 1 < heap.size() &&
               cmp(heap_values[heap[child + 1]], heap_values[heap[child]])) {
                child++;
            }
            if(cmp(heap_values[heap[id]], heap_values[heap[child]])) {
                break;
            }
            swap(heap[id], heap[child]);
            swap(pos_in_heap[heap[id]], pos_in_heap[heap[child]]);
            id = child;
        }
    }

  public:
    Heap() { clear(); }

    void clear() {
        heap.clear();
        heap_values.clear();
        pos_in_heap.clear();
    }

    int push(T val) {
        heap.push_back(heap_values.size());
        pos_in_heap.push_back(heap.size() - 1);
        heap_values.push_back(val);
        push_up(heap.size() - 1);
        return heap_values.size() - 1;
    }

    T pop() {
        int ret_node = heap[0];
        swap(pos_in_heap[ret_node], pos_in_heap[heap.back()]);
        swap(heap[0], heap[heap.size() - 1]);
        heap.pop_back();
        pos_in_heap[ret_node] = -1;
        if(heap.size() > 0) {
            push_down(0);
        }
        return heap_values[ret_node];
    }

    size_t size() { return heap.size(); }
    bool empty() { return heap.size() == 0; }

    T top() { return heap_values[heap[0]]; }

    int top_node() { return heap[0]; }

    void update(int node, T val) {
        int p = pos_in_heap[node];
        bool is_push_down = cmp(heap_values[node], val);

        if(is_push_down) {
            heap_values[node] = val;
            push_down(p);
        } else {
            heap_values[node] = val;
            push_up(p);
        }
    }
};



================================================
FILE: data_structures/meldable_heap.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

template<class T = int>
class MeldableHeap {
  private:
    static uint32_t rng() {
        static mt19937 static_rng(random_device{}());
        return static_rng();
    }

    struct Node {
        T key;
        Node *left, *right;

        Node(T _key) : key(_key), left(nullptr), right(nullptr) {}
    };

    Node* merge(Node* a, Node* b) {
        if(!a) {
            return b;
        }
        if(!b) {
            return a;
        }

        if(a->key > b->key) {
            swap(a, b);
        }

        Node* q = new Node(a->key);
        if(rng() & 1) {
            q->left = merge(a->left, b);
            q->right = a->right;
        } else {
            q->left = a->left;
            q->right = merge(a->right, b);
        }

        return q;
    }

    pair<Node*, Node*> pop(Node* a) {
        Node* head = new Node(a->key);
        Node* tail = merge(a->left, a->right);
        return {head, tail};
    }

  public:
    Node* root;

    MeldableHeap() : root(nullptr) {}
    MeldableHeap(Node* _root) : root(_root) {}

    MeldableHeap copy() const {
        MeldableHeap new_heap;
        new_heap.root = root;
        return new_heap;
    }

    MeldableHeap merge(const MeldableHeap<T>& other) {
        MeldableHeap new_heap;
        new_heap.root = merge(root, other.root);
        return new_heap;
    }

    friend MeldableHeap merge(
        const MeldableHeap<T>& a, const MeldableHeap<T>& b
    ) {
        return a.merge(b);
    }

    void push(T key) {
        Node* new_node = new Node(key);
        root = merge(root, new_node);
    }

    T pop() {
        assert(root);
        auto [head, tail] = pop(root);
        root = tail;
        return head->key;
    }

    T top() const { return root->key; }

    tuple<T, MeldableHeap<T>, MeldableHeap<T>> trio() const {
        return {
            root->key, MeldableHeap<T>{root->left}, MeldableHeap<T>{root->right}
        };
    }

    bool empty() const { return root == nullptr; }

    bool operator<(const MeldableHeap<T>& other) const {
        return top() < other.top();
    }
};


================================================
FILE: data_structures/merge_sort_tree.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

// InnerOrderedSet should implement:
//     1) insert(x), which adds one copy of x.
//     2) erase(x), which removes one copy of x.
//     3) count_leq(x), which gives the number of elements <= x.
//
// Example with a treap is given below.

template<class InnerOrderedSet>
class MergeSortTree {
  private:
    int n;
    vector<InnerOrderedSet> nodes;

    void update_rec(int v, int tl, int tr, int pos, int y, int delta) {
        if(delta == 1) {
            nodes[v].insert(y, 1);
        } else if(delta == -1) {
            nodes[v].erase(y);
        }

        if(tl == tr) {
            return;
        }
        int tm = (tl + tr) / 2;
        if(pos <= tm) {
            update_rec(v * 2, tl, tm, pos, y, delta);
        } else {
            update_rec(v * 2 + 1, tm + 1, tr, pos, y, delta);
        }
    }

    int query_rec(int v, int tl, int tr, int ql, int qr, int k) {
        if(ql > tr || qr < tl) {
            return 0;
        }
        if(ql <= tl && tr <= qr) {
            return nodes[v].count_leq(k);
        }
        int tm = (tl + tr) / 2;
        return query_rec(v * 2, tl, tm, ql, qr, k) +
               query_rec(v * 2 + 1, tm + 1, tr, ql, qr, k);
    }

  public:
    void init(int _n) {
        n = _n;
        nodes.resize(4 * (n + 10));
    }

    void update(int x, int y, int delta) { update_rec(1, 1, n, x, y, delta); }

    int query(int qxl, int qxr, int k) {
        return query_rec(1, 1, n, qxl, qxr, k);
    }

    int query(int qxl, int qxr, int qyl, int qyr) {
        return query_rec(1, 1, n, qxl, qxr, qyr) -
               query_rec(1, 1, n, qxl, qxr, qyl - 1);
    }
};

// #include <coding_library/data_structures/treap.hpp>
// int sum_merge(int a, int b) { return a + b; }
// using CountTreap = Treap<int, int, sum_merge>;
// MergeSortTree<CountTreap> st;


================================================
FILE: data_structures/monoids_lazy.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

template<class T>
class MonoidMin {
  public:
    struct MinVal {
        T val;
        bool operator==(const MinVal& other) const { return val == other.val; }
        bool operator!=(const MinVal& other) const { return !(*this == other); }
    };

    struct AddLazy {
        T add_val;
        bool operator==(const AddLazy& other) const {
            return add_val == other.add_val;
        }
        bool operator!=(const AddLazy& other) const {
            return !(*this == other);
        }
    };

    static MinVal merge(MinVal a, MinVal b) { return {min(a.val, b.val)}; }

    static MinVal e() { return {numeric_limits<T>::max()}; }

    static MinVal lazy_apply(AddLazy f, MinVal x) {
        return {x.val + f.add_val};
    }

    static AddLazy lazy_merge(AddLazy a, AddLazy b) {
        return {a.add_val + b.add_val};
    }

    static AddLazy lazy_init(MinVal _) { return {0}; }
};

// SegmentTreeLazy<
//     MonoidMin<int>::MinVal,
//     MonoidMin<int>::merge,
//     MonoidMin<int>::e,
//     MonoidMin<int>::AddLazy,
//     MonoidMin<int>::lazy_apply,
//     MonoidMin<int>::lazy_merge,
//     MonoidMin<int>::lazy_init>

template<class T>
class MonoidSum {
  public:
    using Sum = T;
    using AddLazy = T;

    static Sum merge(Sum a, Sum b) { return a + b; }

    static Sum e() { return 0; }

    static Sum lazy_apply(AddLazy f, Sum x) { return f + x; }

    static AddLazy lazy_merge(AddLazy a, AddLazy b) { return a + b; }

    static AddLazy lazy_init(Sum _) { return 0; }

    static Sum inverse(Sum x) { return -x; }
};

// SegmentTreeLazy<
//     MonoidSum<int>::Sum,
//     MonoidSum<int>::merge,
//     MonoidSum<int>::e,
//     MonoidSum<int>::AddLazy,
//     MonoidSum<int>::lazy_apply,
//     MonoidSum<int>::lazy_merge,
//     MonoidSum<int>::lazy_init>

template<class T>
class MonoidMinWithCount {
  public:
    struct MinWithCount {
        T min_val;
        int count;

        bool operator==(const MinWithCount& other) const {
            return min_val == other.min_val && count == other.count;
        }
        bool operator!=(const MinWithCount& other) const {
            return !(*this == other);
        }
    };

    struct AddLazy {
        T add_val;
        bool operator==(const AddLazy& other) const {
            return add_val == other.add_val;
        }
        bool operator!=(const AddLazy& other) const {
            return !(*this == other);
        }
    };

    static MinWithCount merge(MinWithCount a, MinWithCount b) {
        if(a.min_val < b.min_val) {
            return a;
        }
        if(b.min_val < a.min_val) {
            return b;
        }
        return {a.min_val, a.count + b.count};
    }

    static MinWithCount e() { return {numeric_limits<T>::max(), 0}; }

    static MinWithCount lazy_apply(AddLazy f, MinWithCount x) {
        return {x.min_val + f.add_val, x.count};
    }

    static AddLazy lazy_merge(AddLazy a, AddLazy b) {
        return {a.add_val + b.add_val};
    }
    static AddLazy lazy_init(MinWithCount _) { return {0}; }
};

// SegmentTreeLazy<
//     MonoidMinWithCount<int>::MinWithCount,
//     MonoidMinWithCount<int>::merge,
//     MonoidMinWithCount<int>::e,
//     MonoidMinWithCount<int>::AddLazy,
//     MonoidMinWithCount<int>::lazy_apply,
//     MonoidMinWithCount<int>::lazy_merge,
//     MonoidMinWithCount<int>::lazy_init>

template<class T>
class MonoidSumArithmeticProgression {
    struct Sum {
        T val;
        T l, r;
        bool operator==(const Sum& other) const {
            return val == other.val && l == other.l && r == other.r;
        }
        bool operator!=(const Sum& other) const { return !(*this == other); }
    };
    struct AddLazy {
        T alpha;
        T beta;
        T l_border;
        bool operator==(const AddLazy& other) const {
            return alpha == other.alpha && beta == other.beta &&
                   l_border == other.l_border;
        }
        bool operator!=(const AddLazy& other) const {
            return !(*this == other);
        }
    };

    static Sum merge(Sum a, Sum b) {
        return {
            a.val + b.val,
            a.l,
            b.r,
        };
    }
    static Sum e() { return {0, 0}; }
    static Sum lazy_apply(AddLazy f, Sum x) {
        T delta = x.l - f.l_border;
        T len = x.r - x.l + 1;
        x.val +=
            (delta * f.beta + f.alpha) * len + f.beta * len * (len + 1) / 2;
        return x;
    }
    static AddLazy lazy_merge(AddLazy a, AddLazy b) {
        T delta = b.l_border - a.l_border;
        b.alpha += a.alpha + delta * a.beta;
        b.beta += a.beta;
        return b;
    }
    static AddLazy lazy_init(Sum node) { return {0, 0, node.l}; }
};

// SegmentTreeLazy<
//     MonoidSumArithmeticProgression<int64_t>::Sum,
//     MonoidSumArithmeticProgression<int64_t>::merge,
//     MonoidSumArithmeticProgression<int64_t>::e,
//     MonoidSumArithmeticProgression<int64_t>::AddLazy,
//     MonoidSumArithmeticProgression<int64_t>::lazy_apply,
//     MonoidSumArithmeticProgression<int64_t>::lazy_merge,
//     MonoidSumArithmeticProgression<int64_t>::lazy_init>


================================================
FILE: data_structures/nonintersecting_range_tree.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

/* Based on https://codeforces.com/contest/2063/problem/F2. Main idea is to
   do reverse small-to-large trick and we can store everything with arrays
   instead of using a complicated approach with sets and maps.

   This version only counts the "non-used" elements in the range, so
   we might want to redefine this in a different problem.
*/

class NonintersectingRangeTree {
  public:
    vector<int> pnt, size, par, par_idx;
    vector<bool> used;

    NonintersectingRangeTree(int n) {
        pnt.assign(n + 2, 0);
        iota(pnt.begin(), pnt.end(), 1);

        par_idx.assign(n + 2, 0);
        par = {0};

        size.assign(n + 2, 0);
        used.assign(n + 2, false);

        used[0] = true;
        pnt[0] = n + 2;
        pnt[n + 1] = n + 1;
        size[0] = n;
    }

    void add(int l, int r) {
        pnt[l] = r + 1;
        pnt[r] = r;
        used[l] = true;

        int p = get_parent(l);
        int out_ptr = p + 1, ins_ptr = l + 1;
        int out_size = 0, ins_size = 0;

        while(pnt[out_ptr] != out_ptr && pnt[ins_ptr] != ins_ptr) {
            out_size += !used[out_ptr];
            ins_size += !used[ins_ptr];
            out_ptr = pnt[out_ptr];
            ins_ptr = pnt[ins_ptr];
        }

        int upd_ptr, new_par_idx = par.size();
        if(pnt[out_ptr] == out_ptr) {
            upd_ptr = p + 1;
            par.push_back(p);
            par[par_idx[l]] = l;

            ins_size = size[p] - 2 - out_size;
            size[p] = out_size;
            size[l] = ins_size;
        } else {
            upd_ptr = l + 1;
            par.push_back(l);

            out_size = size[p] - 2 - ins_size;
            size[p] = out_size;
            size[l] = ins_size;
        }

        while(pnt[upd_ptr] != upd_ptr) {
            par_idx[upd_ptr] = new_par_idx;
            upd_ptr = pnt[upd_ptr];
        }
    }

    int get_parent(int x) { return par[par_idx[x]]; }
};


================================================
FILE: data_structures/offline_segment_tree_2d.hpp
================================================
#include <bits/stdc++.h>
#include <coding_library/data_structures/fenwick.hpp>

using namespace std;

template<class T>
class OfflineSegmentTree2d {
  private:
    int n;
    vector<vector<int>> ys;
    vector<Fenwick<T>> ft;

    void collect(int v, int tl, int tr, int pos, int y) {
        ys[v].push_back(y);
        if(tl == tr) {
            return;
        }
        int tm = (tl + tr) / 2;
        if(pos <= tm) {
            collect(v * 2, tl, tm, pos, y);
        } else {
            collect(v * 2 + 1, tm + 1, tr, pos, y);
        }
    }

    void build_compression(int v) {
        sort(ys[v].begin(), ys[v].end());
        ys[v].erase(unique(ys[v].begin(), ys[v].end()), ys[v].end());
        ft[v].init(ys[v].size() + 2);
    }

    void update_rec(int v, int tl, int tr, int pos, int y, T val) {
        if(ys[v].empty()) {
            return;
        }
        auto it = lower_bound(ys[v].begin(), ys[v].end(), y);
        if(it == ys[v].end() || *it != y) {
            return;
        }
        int rank = (it - ys[v].begin()) + 1;
        ft[v].update(rank, val);
        if(tl == tr) {
            return;
        }
        int tm = (tl + tr) / 2;
        if(pos <= tm) {
            update_rec(v * 2, tl, tm, pos, y, val);
        } else {
            update_rec(v * 2 + 1, tm + 1, tr, pos, y, val);
        }
    }

    T query_rec(int v, int tl, int tr, int l, int r, int yl, int yr) {
        if(l > tr || r < tl) {
            return 0;
        }
        if(l <= tl && tr <= r) {
            if(ys[v].empty()) {
                return 0;
            }
            auto itl = lower_bound(ys[v].begin(), ys[v].end(), yl);
            auto itr = upper_bound(itl, ys[v].end(), yr);
            int ly = (itl - ys[v].begin()) + 1;
            int ry = (itr - ys[v].begin());
            return ft[v].query(ly, ry);
        }
        int tm = (tl + tr) / 2;
        return query_rec(v * 2, tl, tm, l, r, yl, yr) +
               query_rec(v * 2 + 1, tm + 1, tr, l, r, yl, yr);
    }

  public:
    void init(int _n) {
        n = _n;
        int tsz = 4 * (n + 10);
        ys.assign(tsz, {});
        ft.resize(tsz);
    }

    void prepare_update(int x, int y) { collect(1, 1, n, x, y); }

    void prepare() {
        for(int v = 1; v < 4 * (n + 10); ++v) {
            if(!ys[v].empty()) {
                build_compression(v);
            }
        }
    }

    void update(int x, int y, T val) { update_rec(1, 1, n, x, y, val); }

    T query(int xl, int xr, int yl, int yr) {
        return query_rec(1, 1, n, xl, xr, yl, yr);
    }
};


================================================
FILE: data_structures/rmq2d.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

struct rmq1d {
    vector<int> rmq;
    int n;
    void init(int N) {
        n = N;
        rmq.resize(4 * n);
    }
    void add(int v, int tl, int tr, int x) {
        ++rmq[v];
        if(tl + 1 == tr) {
            return;
        }
        int m = (tl + tr) >> 1;
        if(x < m) {
            add(v * 2 + 1, tl, m, x);
        } else {
            add(v * 2 + 2, m, tr, x);
        }
    }
    void add(int x) { add(0, 0, n, x); }
    int get(int v, int tl, int tr, int l, int r) {
        if(r <= tl || tr <= l) {
            return 0;
        }
        if(l <= tl && tr <= r) {
            return rmq[v];
        }
        int m = (tl + tr) >> 1;
        return get(v * 2 + 1, tl, m, l, r) + get(v * 2 + 2, m, tr, l, r);
    }
    int get(int l, int r) { return get(0, 0, n, l, r); }
};

struct rmq2d {
    vector<rmq1d> rmq;
    vector<vector<int> > sv;
    int n;
    void init(int N) {
        n = N;
        sv.resize(4 * n);
        rmq.resize(4 * n);
    }
    void prep(int v, int tl, int tr, int x, int y) {
        sv[v].push_back(y);
        if(tl + 1 == tr) {
            return;
        }
        int m = (tl + tr) >> 1;
        if(x < m) {
            prep(v * 2 + 1, tl, m, x, y);
        } else {
            prep(v * 2 + 2, m, tr, x, y);
        }
    }
    void prep(int x, int y) { prep(0, 0, n, x, y); }
    void add(int v, int tl, int tr, int x, int y) {
        int k = lower_bound(sv[v].begin(), sv[v].end(), y) - sv[v].begin();
        rmq[v].add(k);
        if(tl + 1 == tr) {
            return;
        }
        int m = (tl + tr) >> 1;
        if(x < m) {
            add(v * 2 + 1, tl, m, x, y);
        } else {
            add(v * 2 + 2, m, tr, x, y);
        }
    }
    void add(int x, int y) { add(0, 0, n, x, y); }
    void build(int v, int tl, int tr) {
        sort(sv[v].begin(), sv[v].end());
        rmq[v].init(sv[v].size());
        if(tl + 1 == tr) {
            return;
        }
        int m = (tl + tr) >> 1;
        build(v * 2 + 1, tl, m);
        build(v * 2 + 2, m, tr);
    }
    void init2() { build(0, 0, n); }
    int get(int v, int tl, int tr, int l1, int r1, int l2, int r2) {
        if(r1 <= tl || tr <= l1) {
            return 0;
        }
        if(l1 <= tl && tr <= r1) {
            l2 = lower_bound(sv[v].begin(), sv[v].end(), l2) - sv[v].begin();
            r2 = lower_bound(sv[v].begin(), sv[v].end(), r2) - sv[v].begin();
            return rmq[v].get(l2, r2);
        }
        int m = (tl + tr) >> 1;
        return get(v * 2 + 1, tl, m, l1, r1, l2, r2) +
               get(v * 2 + 2, m, tr, l1, r1, l2, r2);
    }
    int get(int l1, int r1, int l2, int r2) {
        return get(0, 0, n, l1, r1, l2, r2);
    }
};


================================================
FILE: data_structures/segment_tree.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

// Motivated by atcoder library, but adapted to my style. All ranges are
// inclusive in this implementation.
// https://atcoder.github.io/ac-library/production/document_en/segtree.html

template<class T, T (*merge)(T, T), T (*e)()>
class SegmentTree {
  private:
    int n, size;
    vector<T> tr;

    void pull(int x) { tr[x] = merge(tr[2 * x], tr[2 * x + 1]); }

  public:
    SegmentTree() { init(vector<T>()); }
    SegmentTree(int _n) { init(vector<T>(_n, e())); }
    SegmentTree(const vector<T>& _a) { init(_a); }

    void init(const vector<T>& _a) {
        n = _a.size();
        size = 1;
        while(size < n) {
            size <<= 1;
        }

        tr.assign(2 * size, e());
        for(int i = 0; i < n; i++) {
            tr[size + i] = _a[i];
        }
        for(int i = size - 1; i > 0; i--) {
            pull(i);
        }
    }

    void update(int pos, T val) {
        pos += size;
        tr[pos] = val;
        for(pos >>= 1; pos > 0; pos >>= 1) {
            pull(pos);
        }
    }

    T get_pos(int pos) { return tr[pos + size]; }

    T query(int l, int r) {
        T ansl = e(), ansr = e();
        for(l += size, r += size + 1; l < r; l >>= 1, r >>= 1) {
            if(l & 1) {
                ansl = merge(ansl, tr[l++]);
            }
            if(r & 1) {
                ansr = merge(tr[--r], ansr);
            }
        }
        return merge(ansl, ansr);
    }

    T query_all() { return tr[1]; }

    template<bool (*f)(T)>
    int max_right(int l) const {
        return max_right(l, [](T x) { return f(x); });
    }
    template<class F>
    int max_right(int l, F f) const {
        if(l == n) {
            return n;
        }

        l += size;
        T sm = e();
        do {
            while(l % 2 == 0) {
                l >>= 1;
            }
            if(!f(merge(sm, tr[l]))) {
                while(l < size) {
                    l = (2 * l);
                    if(f(merge(sm, tr[l]))) {
                        sm = merge(sm, tr[l]);
                        l++;
                    }
                }
                return l - size;
            }
            sm = merge(sm, tr[l]);
            l++;
        } while((l & -l) != l);
        return n;
    }

    template<bool (*f)(T)>
    int min_left(int r) const {
        return min_left(r, [](T x) { return f(x); });
    }
    template<class F>
    int min_left(int r, F f) const {
        if(r == -1) {
            return 0;
        }

        r += size + 1;
        T sm = e();
        do {
            r--;
            while(r > 1 && (r % 2)) {
                r >>= 1;
            }
            if(!f(merge(tr[r], sm))) {
                while(r < size) {
                    r = (2 * r + 1);
                    if(f(merge(tr[r], sm))) {
                        sm = merge(tr[r], sm);
                        r--;
                    }
                }
                return r + 1 - size;
            }
            sm = merge(tr[r], sm);
        } while((r & -r) != r);
        return 0;
    }
};

// int min_custom(int a, int b) { return min(a, b); }
// int min_e() { return INT_MAX; }
// int max_custom(int a, int b) { return max(a, b); }
// int max_e() { return INT_MIN; }


================================================
FILE: data_structures/segment_tree_lazy.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

// Motivated by atcoder library, but adapted to my style. All ranges are
// inclusive in this implementation.
// https://atcoder.github.io/ac-library/production/document_en/segtree.html
//
// Another difference is that I support a callback from the tree node to
// the lazy node, which is useful when we want to maintain a push that is
// not uniform across the left and right child (arithmetic progression add).

template<
    class T, T (*merge)(T, T), T (*e)(), class G, T (*lazy_apply)(G, T),
    G (*lazy_merge)(G, G), G (*lazy_init)(T)>
class SegmentTreeLazy {
  private:
    int n, size, log_size;
    vector<T> tr;
    vector<G> lazy;

    void pull(int x) { tr[x] = merge(tr[2 * x], tr[2 * x + 1]); }

    void push_one(int x, G f) {
        tr[x] = lazy_apply(f, tr[x]);
        if(x < size) {
            lazy[x] = lazy_merge(f, lazy[x]);
        }
    }

    void push(int x) {
        push_one(2 * x, lazy[x]);
        push_one(2 * x + 1, lazy[x]);
        lazy[x] = lazy_init(tr[x]);
    }

    void push_all_down(int x) {
        for(int i = log_size; i >= 1; i--) {
            push(x >> i);
        }
    }

    void push_all_open_range(int l, int r) {
        for(int i = log_size; i >= 1; i--) {
            if(((l >> i) << i) != l) {
                push(l >> i);
            }
            if(((r >> i) << i) != r) {
                push((r - 1) >> i);
            }
        }
    }

  public:
    SegmentTreeLazy() { init(vector<T>()); }
    SegmentTreeLazy(int _n) { init(vector<T>(_n, e())); }
    SegmentTreeLazy(const vector<T> &_a) { init(_a); }

    void init(const vector<T> &_a) {
        n = _a.size();
        size = 1;
        log_size = 0;
        while(size < n) {
            size <<= 1;
            log_size++;
        }

        tr.assign(2 * size, e());
        lazy.resize(size);
        for(int i = 0; i < n; i++) {
            tr[size + i] = _a[i];
        }
        for(int i = size - 1; i > 0; i--) {
            pull(i);
            lazy[i] = lazy_init(tr[i]);
        }
    }

    void update(int pos, T val) {
        pos += size;
        push_all_down(pos);
        tr[pos] = val;
        for(pos >>= 1; pos > 0; pos >>= 1) {
            pull(pos);
        }
    }

    void apply_lazy(int l, int r, G f) {
        if(l > r) {
            return;
        }

        l += size, r += size + 1;
        push_all_open_range(l, r);
        for(int l0 = l, r0 = r; l0 < r0; l0 >>= 1, r0 >>= 1) {
            if(l0 & 1) {
                push_one(l0++, f);
            }
            if(r0 & 1) {
                push_one(--r0, f);
            }
        }

        for(int i = 1; i <= log_size; i++) {
            if(((l >> i) << i) != l) {
                pull(l >> i);
            }
            if(((r >> i) << i) != r) {
                pull((r - 1) >> i);
            }
        }
    }

    T get_pos(int pos) {
        pos += size;
        push_all_down(pos);
        return tr[pos];
    }

    T query(int l, int r) {
        T ansl = e(), ansr = e();
        l += size, r += size + 1;
        push_all_open_range(l, r);

        for(; l < r; l >>= 1, r >>= 1) {
            if(l & 1) {
                ansl = merge(ansl, tr[l++]);
            }
            if(r & 1) {
                ansr = merge(tr[--r], ansr);
            }
        }
        return merge(ansl, ansr);
    }

    T query_all() { return tr[1]; }

    template<bool (*f)(T)>
    int max_right(int l) const {
        return max_right(l, [](T x) { return f(x); });
    }
    template<class F>
    int max_right(int l, F f) const {
        if(l == n) {
            return n;
        }

        l += size;
        push_all_down(l);
        T sm = e();
        do {
            while(l % 2 == 0) {
                l >>= 1;
            }
            if(!f(merge(sm, tr[l]))) {
                while(l < size) {
                    push(l);
                    l = (2 * l);
                    if(f(merge(sm, tr[l]))) {
                        sm = merge(sm, tr[l]);
                        l++;
                    }
                }
                return l - size;
            }
            sm = merge(sm, tr[l]);
            l++;
        } while((l & -l) != l);
        return n;
    }

    template<bool (*f)(T)>
    int min_left(int r) const {
        return min_left(r, [](T x) { return f(x); });
    }
    template<class F>
    int min_left(int r, F f) const {
        if(r == -1) {
            return 0;
        }

        r += size + 1;
        push_all_down(r - 1);
        T sm = e();
        do {
            r--;
            while(r > 1 && (r % 2)) {
                r >>= 1;
            }
            if(!f(merge(tr[r], sm))) {
                while(r < size) {
                    push(r);
                    r = (2 * r + 1);
                    if(f(merge(tr[r], sm))) {
                        sm = merge(tr[r], sm);
                        r--;
                    }
                }
                return r + 1 - size;
            }
            sm = merge(tr[r], sm);
        } while((r & -r) != r);
        return 0;
    }
};


================================================
FILE: data_structures/set_lazy.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

template<typename T, template<typename...> class Container = multiset>
class SetLazy : private Container<T> {
  private:
    T lazy_value = T();

    class Iterator {
      private:
        typename Container<T>::iterator it;
        const T& lazy_value;

      public:
        Iterator(typename Container<T>::iterator it, const T& lazy_value)
            : it(it), lazy_value(lazy_value) {}

        T operator*() const { return *it + lazy_value; }
        Iterator& operator++() {
            ++it;
            return *this;
        }
        Iterator operator++(int) {
            Iterator tmp = *this;
            ++it;
            return tmp;
        }
        bool operator==(const Iterator& other) const { return it == other.it; }
        bool operator!=(const Iterator& other) const { return it != other.it; }

        typename Container<T>::iterator base() const { return it; }
    };

  public:
    void insert(const T& value) { Container<T>::insert(value - lazy_value); }

    void erase(const T& value) { Container<T>::erase(value - lazy_value); }
    void erase(Iterator it) { Container<T>::erase(it.base()); }

    void add_all(const T& x) { lazy_value += x; }

    T get_lazy_value() const { return lazy_value; }

    bool count(const T& value) const {
        return Container<T>::find(value - lazy_value) != Container<T>::end();
    }

    Iterator find(const T& value) {
        auto it = Container<T>::find(value - lazy_value);
        return it != Container<T>::end() ? Iterator(it, lazy_value) : end();
    }

    Iterator lower_bound(const T& value) {
        return Iterator(
            Container<T>::lower_bound(value - lazy_value), lazy_value
        );
    }

    Iterator upper_bound(const T& value) {
        return Iterator(
            Container<T>::upper_bound(value - lazy_value), lazy_value
        );
    }

    Iterator begin() { return Iterator(Container<T>::begin(), lazy_value); }
    Iterator end() { return Iterator(Container<T>::end(), lazy_value); }

    const Iterator begin() const {
        return Iterator(Container<T>::begin(), lazy_value);
    }
    const Iterator end() const {
        return Iterator(Container<T>::end(), lazy_value);
    }

    using Container<T>::size;
    using Container<T>::empty;

    void merge(const SetLazy<T, Container>& other) {
        for(const auto& value: other) {
            insert(value);
        }
    }

    void print() const {
        std::cout << "{";
        for(const auto& value: *this) {
            std::cout << value << ", ";
        }
        std::cout << "}" << std::endl;
    }
};

/*
SetLazy<int> multiset_lazy // Uses multiset by default
SetLazy<int, std::set> set_lazy; // Uses set explicitly
*/


================================================
FILE: data_structures/sparse_table.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

template<class T, T (*merge)(T, T)>
class SparseTable {
  private:
    int n;
    vector<vector<T>> dp;
    vector<int> prec_lg2;

  public:
    SparseTable() {
        n = 0;
        dp.clear();
        prec_lg2.clear();
    }

    void init(const vector<T>& a) {
        n = a.size();
        prec_lg2.resize(n + 1);
        for(int i = 2; i <= n; i++) {
            prec_lg2[i] = prec_lg2[i >> 1] + 1;
        }

        dp.assign(prec_lg2[n] + 1, vector<T>(n));
        dp[0] = a;

        for(int j = 1; (1 << j) <= n; j++) {
            for(int i = 0; i + (1 << j) <= n; i++) {
                dp[j][i] = merge(dp[j - 1][i], dp[j - 1][i + (1 << (j - 1))]);
            }
        }
    }

    T query(int l, int r) {
        int k = prec_lg2[r - l + 1];
        return merge(dp[k][l], dp[k][r - (1 << k) + 1]);
    }
};

// int min_custom(int a, int b) { return min(a, b); }
// SparseTable<int, min_custom> tbl;


================================================
FILE: data_structures/sparse_table_disjoint.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

template<class T, T (*merge)(T, T)>
class SparseTableDisjoint {
  private:
    int n;
    vector<int> prec_lg2, mask;
    vector<vector<T>> dp;
    vector<T> a;

    void init_dnc(int l, int r, int lvl) {
        if(l == r) {
            dp[lvl][l] = a[l];
            return;
        }

        int m = (l + r) >> 1;
        init_dnc(l, m, lvl + 1);
        init_dnc(m + 1, r, lvl + 1);

        dp[lvl][m] = a[m];
        for(int i = m - 1; i >= l; i--) {
            dp[lvl][i] = merge(a[i], dp[lvl][i + 1]);
        }

        dp[lvl][m + 1] = a[m + 1];
        mask[m + 1] |= 1 << lvl;
        for(int i = m + 2; i <= r; i++) {
            dp[lvl][i] = merge(dp[lvl][i - 1], a[i]);
            mask[i] |= 1 << lvl;
        }
    }

  public:
    SparseTableDisjoint() {
        n = 0;
        a.clear();
        dp.clear();
        prec_lg2.clear();
        mask.clear();
    }

    void init(const vector<T>& _a) {
        a = _a;
        n = a.size();
        prec_lg2.assign(4 * n + 1, 0);
        for(int i = 2; i <= 4 * n; i++) {
            prec_lg2[i] = prec_lg2[i >> 1] + 1;
        }

        dp.assign(prec_lg2[n] + 2, vector<T>(n));
        mask.assign(n, 0);
        init_dnc(0, n - 1, 0);
    }

    T query(int l, int r) {
        if(l == r) {
            return a[l];
        }

        int mask_diff = mask[l] ^ mask[r];
        int k = prec_lg2[mask_diff & -mask_diff];
        return merge(dp[k][l], dp[k][r]);
    }
};

// int min_custom(int a, int b) { return min(a, b); }
// sparse_table_disjoint<int, min_custom> st;


================================================
FILE: data_structures/treap.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

template<class KeyT, class T, T (*merge_func)(T, T), uint64_t (*rng)()>
struct TreapNode {
    KeyT key;
    T data, subtree;
    uint64_t prior;
    size_t size;
    TreapNode *left, *right;

    TreapNode(KeyT key, T data)
        : key(key), data(data), left(nullptr), right(nullptr), size(1) {
        prior = rng();
    }

    void pull() {
        subtree = data;
        size = 1;
        if(left) {
            subtree = merge_func(left->subtree, subtree);
            size += left->size;
        }
        if(right) {
            subtree = merge_func(subtree, right->subtree);
            size += right->size;
        }
    }

    friend pair<TreapNode*, TreapNode*> split(TreapNode* t, KeyT key) {
        if(!t) {
            return {nullptr, nullptr};
        }
        if(key < t->key) {
            auto [left, t_left] = split(t->left, key);
            t->left = t_left;
            t->pull();
            return {left, t};
        } else {
            auto [t_right, right] = split(t->right, key);
            t->right = t_right;
            t->pull();
            return {t, right};
        }
    }

    friend pair<TreapNode*, TreapNode*> split_by_size(
        TreapNode* t, size_t size
    ) {
        if(!t) {
            return {nullptr, nullptr};
        }

        size_t left_size = t->left ? t->left->size : 0;
        if(left_size >= size) {
            auto [left, t_left] = split_by_size(t->left, size);
            t->left = t_left;
            t->pull();
            return {left, t};
        } else {
            auto [t_right, right] =
                split_by_size(t->right, size - 1 - left_size);
            t->right = t_right;
            t->pull();
            return {t, right};
        }
    }

    friend TreapNode* merge(TreapNode* l, TreapNode* r) {
        if(!l || !r) {
            return l ? l : r;
        } else if(l->prior > r->prior) {
            l->right = merge(l->right, r);
            l->pull();
            return l;
        } else {
            r->left = merge(l, r->left);
            r->pull();
            return r;
        }
    }

    friend TreapNode* unordered_merge(TreapNode* l, TreapNode* r) {
        if(!l) {
            return r;
        }
        if(!r) {
            return l;
        }
        if(l->prior < r->prior) {
            swap(l, r);
        }
        auto [t1, t2] = split(r, l->key);
        l->left = unordered_merge(l->left, t1);
        l->right = unordered_merge(l->right, t2);
        l->pull();
        return l;
    }

    friend void insert_in(TreapNode*& t, TreapNode* it) {
        if(!t) {
            t = it;
        } else if(it->prior > t->prior) {
            auto [t1, t2] = split(t, it->key);
            it->left = t1;
            it->right = t2;
            t = it;
        } else {
            insert_in(it->key < t->key ? t->left : t->right, it);
        }
        t->pull();
    }

    friend TreapNode* erase_from(
        TreapNode*& t, KeyT key, bool delete_node = false
    ) {
        T return_data;
        if(t->key == key) {
            auto tmp = t;
            t = merge(t->left, t->right);

            return_data = tmp->data;
            if(delete_node) {
                delete tmp;
                return_data = nullptr;
            }
        } else {
            return_data =
                erase_from(key < t->key ? t->left : t->right, key, delete_node);
        }
        if(t) {
            t->pull();
        }
        return return_data;
    }
};

template<class KeyT, class T, T (*merge_func)(T, T)>
class Treap {
  public:
    static uint64_t rng() {
        static mt19937_64 static_rng(random_device{}());
        return static_rng();
    }

    using Node = TreapNode<KeyT, T, merge_func, Treap::rng>;

    void _pull_all(Node* t) {
        if(t) {
            _pull_all(t->left);
            _pull_all(t->right);
            t->pull();
        }
    }

    Node* root;

    Treap() { root = nullptr; }
    Treap(const vector<pair<KeyT, T>>& a) { build_cartesian_tree(a); }

    void build_cartesian_tree(const vector<pair<KeyT, T>>& a) {
        vector<Node*> st;

        function<Node*(Node*)> recycle_stack = [&](Node* last) {
            Node* new_last = st.back();
            st.pop_back();
            new_last->right = last;
            return new_last;
        };

        for(const auto& [key, val]: a) {
            Node* new_node = new Node(key, val);
            Node* last = nullptr;
            while(!st.empty() && st.back()->prior < new_node->prior) {
                last = recycle_stack(last);
            }

            new_node->left = last;
            st.push_back(new_node);
        }

        root = nullptr;
        while(!st.empty()) {
            root = recycle_stack(root);
        }

        _pull_all(root);
    }

    void insert(KeyT key, T data) {
        Node* new_node = new Node(key, data);
        insert_in(root, new_node);
    }

    Node* erase(KeyT key) { return erase_from(root, key); }

    friend Treap<KeyT, T, merge_func> merge_treaps(
        Treap<KeyT, T, merge_func> l, Treap<KeyT, T, merge_func> r
    ) {
        Treap<KeyT, T, merge_func> res;
        res.root = unordered_merge(l.root, r.root);
        return res;
    }

    int count_leq(KeyT max_key) {
        int cnt = 0;
        Node* cur = root;
        while(cur) {
            if(cur->key <= max_key) {
                cnt += (cur->left ? cur->left->size : 0) + 1;
                cur = cur->right;
            } else {
                cur = cur->left;
            }
        }
        return cnt;
    }
};

// pair<int64_t, int64_t> plus_func(
//     pair<int64_t, int64_t> a, pair<int64_t, int64_t> b
// ) {
//     return {a.first + b.first, a.second + b.second};
// }

// using TreapWithCount = Treap<int64_t, pair<int64_t, int64_t>, plus_func>;
// using Node = TreapWithCount::Node;

// pair<Node*, Node*> split_by_count(Node* t, int64_t k) {
//     if(!t) {
//         return {nullptr, nullptr};
//     }
//     if(t->left && t->left->subtree.first >= k) {
//         auto [left, t_left] = split_by_count(t->left, k);
//         t->left = t_left;
//         t->pull();
//         return {left, t};
//     } else {
//         k -= (t->left ? t->left->subtree.first : 0);
//         if(k < t->data.first) {
//             Node* new_left = new Node(t->key, {k, k * t->key});
//             t->data.first -= k;
//             t->data.second = t->data.first * t->key;

//             insert_in(t->left, new_left);
//             new_left = t->left;
//             t->left = nullptr;
//             t->pull();
//             return {new_left, t};
//         }

//         auto [t_right, new_right] = split_by_count(t->right, k -
//         t->data.first); t->right = t_right; t->pull(); return {t, new_right};
//     }
// }


================================================
FILE: data_structures/treap_lazy.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

template<
    class KeyT, class T, T (*merge_func)(T, T), class LazyT, uint64_t (*rng)()>
struct TreapNode {
    KeyT key;
    T data, subtree;
    uint64_t prior;
    size_t size;
    TreapNode *left, *right;
    LazyT lazy;

    TreapNode(KeyT key, T data)
        : key(key), data(data), left(nullptr), right(nullptr), size(1) {
        prior = rng();
        lazy = LazyT();
    }

    void pull() {
        subtree = data;
        size = 1;
        if(left) {
            left->push();
            subtree = merge_func(left->subtree, subtree);
            size += left->size;
        }
        if(right) {
            right->push();
            subtree = merge_func(subtree, right->subtree);
            size += right->size;
        }
    }

    void push() { lazy.apply_lazy(this); }

    friend void push_lazy(TreapNode* t) {
        if(t) {
            t->push();
        }
    }

    friend pair<TreapNode*, TreapNode*> split(TreapNode* t, KeyT key) {
        if(!t) {
            return {nullptr, nullptr};
        }

        t->push();
        if(key < t->key) {
            auto [left, t_left] = split(t->left, key);
            t->left = t_left;
            t->pull();
            return {left, t};
        } else {
            auto [t_right, right] = split(t->right, key);
            t->right = t_right;
            t->pull();
            return {t, right};
        }
    }

    friend pair<TreapNode*, TreapNode*> split_by_size(
        TreapNode* t, size_t size
    ) {
        if(!t) {
            return {nullptr, nullptr};
        }

        t->push();
        size_t left_size = t->left ? t->left->size : 0;
        if(left_size >= size) {
            auto [left, t_left] = split_by_size(t->left, size);
            t->left = t_left;
            t->pull();
            return {left, t};
        } else {
            auto [t_right, right] =
                split_by_size(t->right, size - 1 - left_size);
            t->right = t_right;
            t->pull();
            return {t, right};
        }
    }

    friend TreapNode* merge(TreapNode* l, TreapNode* r) {
        push_lazy(l);
        push_lazy(r);
        if(!l || !r) {
            return l ? l : r;
        } else if(l->prior > r->prior) {
            l->right = merge(l->right, r);
            l->pull();
            return l;
        } else {
            r->left = merge(l, r->left);
            r->pull();
            return r;
        }
    }

    friend TreapNode* unordered_merge(TreapNode* l, TreapNode* r) {
        push_lazy(l);
        push_lazy(r);
        if(!l) {
            return r;
        }
        if(!r) {
            return l;
        }
        if(l->prior < r->prior) {
            swap(l, r);
        }
        auto [t1, t2] = split(r, l->key);
        l->left = unordered_merge(l->left, t1);
        l->right = unordered_merge(l->right, t2);
        l->pull();
        return l;
    }

    friend void insert_in(TreapNode*& t, TreapNode* it) {
        if(!t) {
            t = it;
        } else {
            t->push();
            if(it->prior > t->prior) {
                auto [t1, t2] = split(t, it->key);
                it->left = t1;
                it->right = t2;
                t = it;
            } else {
                insert_in(it->key < t->key ? t->left : t->right, it);
            }
        }
        t->pull();
    }

    friend TreapNode* erase_from(
        TreapNode*& t, KeyT key, bool delete_node = false
    ) {
        t->push();
        T return_data;
        if(t->key == key) {
            auto tmp = t;
            t = merge(t->left, t->right);

            return_data = tmp->data;
            if(delete_node) {
                delete tmp;
            }
        } else {
            return_data =
                erase_from(key < t->key ? t->left : t->right, key, delete_node);
        }
        if(t) {
            t->pull();
        }
        return return_data;
    }
};

template<class KeyT, class T, T (*merge_func)(T, T), class LazyT>
class Treap {
  public:
    static uint64_t rng() {
        static mt19937_64 static_rng(random_device{}());
        // FOR DEBUG:
        // static mt19937_64 static_rng(42);
        return static_rng();
    }

    using Node = TreapNode<KeyT, T, merge_func, LazyT, Treap::rng>;

    void _pull_all(Node* t) {
        if(t) {
            t->push();
            _pull_all(t->left);
            _pull_all(t->right);
            t->pull();
        }
    }

    Node* root;

    Treap() { root = nullptr; }
    Treap(const vector<pair<KeyT, T>>& a) { build_cartesian_tree(a); }

    void build_cartesian_tree(const vector<pair<KeyT, T>>& a) {
        vector<Node*> st;

        function<Node*(Node*)> recycle_stack = [&](Node* last) {
            Node* new_last = st.back();
            st.pop_back();
            new_last->right = last;
            return new_last;
        };

        for(const auto& [key, val]: a) {
            Node* new_node = new Node(key, val);
            Node* last = nullptr;
            while(!st.empty() && st.back()->prior < new_node->prior) {
                last = recycle_stack(last);
            }

            new_node->left = last;
            st.push_back(new_node);
        }

        root = nullptr;
        while(!st.empty()) {
            root = recycle_stack(root);
        }

        _pull_all(root);
    }

    void insert(KeyT key, T data) {
        Node* new_node = new Node(key, data);
        insert_in(root, new_node);
    }

    void erase(KeyT key) { return erase_from(root, key); }

    friend Treap<KeyT, T, merge_func, LazyT> merge_treaps(
        Treap<KeyT, T, merge_func, LazyT> l, Treap<KeyT, T, merge_func, LazyT> r
    ) {
        Treap<KeyT, T, merge_func, LazyT> res;
        res.root = unordered_merge(l.root, r.root);
        return res;
    }
};

// template<class T>
// struct ReverseLazy {
//     bool should_reverse;

//     ReverseLazy() { should_reverse = false; }

//     template<class G, uint64_t (*rng)(), T (*merge_func)(T, T)>
//     void apply_lazy(TreapNode<G, T, merge_func, ReverseLazy, rng>* node) {
//         if(!node || !should_reverse) {
//             return;
//         }

//         swap(node->left, node->right);
//         if(node->left) {
//             node->left->lazy.should_reverse ^= true;
//         }
//         if(node->right) {
//             node->right->lazy.should_reverse ^= true;
//         }

//         should_reverse = false;
//     }
// };

// struct EmptyMonoid {
//     static EmptyMonoid merge(EmptyMonoid a, EmptyMonoid b) {
//         return EmptyMonoid();
//     }
// };

// template<class T>
// struct AddLazy {
//     T add_key = 0;
//     T add_data = 0;

//     template<class G, uint64_t (*rng)(), T (*merge_func)(T, T)>
//     void apply_lazy(TreapNode<pair<T, G>, T, merge_func, AddLazy, rng>* node)
//     {
//         if(!node || (add_key == 0 && add_data == 0)) {
//             return;
//         }

//         node->key.first += add_key;
//         node->data += add_data;
//         node->subtree += add_data * (T)node->size;

//         if(node->left) {
//             node->left->lazy.add_data += add_data;
//             node->left->lazy.add_key += add_key;
//         }

//         if(node->right) {
//             node->right->lazy.add_data += add_data;
//             node->right->lazy.add_key += add_key;
//         }

//         add_key = 0;
//         add_data = 0;
//     }
// };

// int64_t add(int64_t a, int64_t b) { return a + b; }
// using TreapWithLazy = Treap<pair<int64_t, int>, int64_t, add,
// AddLazy<int64_t>>; using Node = TreapWithLazy::Node;

// Tested on https://codeforces.com/contest/702/problem/F.
// https://codeforces.com/contest/702/submission/283296920
// https://codeforces.com/problemsets/acmsguru/submission/99999/294488144


================================================
FILE: data_structures/wavelet_tree.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

// wvlt = new WaveletTree();
// wvlt->init(arr, 0, n);                     
// 
// All queries are 1-indexed.

class WaveletTree {
  private:
    int lo{1}, hi{0};
    WaveletTree *left{nullptr}, *right{nullptr};
    vector<int> b;
    int psz{0};

  public:
    WaveletTree() = default;

    void init(const vector<int>& arr, int x, int y) {
        lo = x;
        hi = y;
        if(lo == hi || arr.empty()) {
            return;
        }
        int mid = (lo + hi) >> 1;
        auto f = [mid](int x) { return x <= mid; };
        b.resize(arr.size() + 1);
        b[0] = 0;
        for(size_t i = 0; i < arr.size(); ++i) {
            b[i + 1] = b[i] + f(arr[i]);
        }
        psz = arr.size();

        // Create a mutable copy of the array
        vector<int> arr_copy(arr);
        auto pivot = stable_partition(arr_copy.begin(), arr_copy.end(), f);

        left = new WaveletTree();
        right = new WaveletTree();
        left->init(vector<int>(arr_copy.begin(), pivot), lo, mid);
        right->init(vector<int>(pivot, arr_copy.end()), mid + 1, hi);
    }

    int kth(int l, int r, int k) const {
        if(l > r) {
            return 0;
        }
        if(lo == hi) {
            return lo;
        }
        int inLeft = b[r] - b[l - 1], lb = b[l - 1], rb = b[r];
        if(k <= inLeft) {
            return left->kth(lb + 1, rb, k);
        }
        return right->kth(l - lb, r - rb, k - inLeft);
    }

    int LTE(int l, int r, int k) const {
        if(l > r || k < lo) {
            return 0;
        }
        if(hi <= k) {
            return r - l + 1;
        }
        int lb = b[l - 1], rb = b[r];
        return left->LTE(lb + 1, rb, k) + right->LTE(l - lb, r - rb, k);
    }

    int count(int l, int r, int k) const {
        if(l > r || k < lo || k > hi) {
            return 0;
        }
        if(lo == hi) {
            return r - l + 1;
        }
        int lb = b[l - 1], rb = b[r];
        int mid = (lo + hi) >> 1;
        if(k <= mid) {
            return left->count(lb + 1, rb, k);
        }
        return right->count(l - lb, r - rb, k);
    }
};


================================================
FILE: dp_optimizations/convex_hull_trick.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

template<class T, bool maximum = true>
class ConvexHullTrick {
  public:
    static constexpr T inf = is_integral_v<T> ? numeric_limits<T>::max()
                                              : numeric_limits<T>::infinity();

    T div(T a, T b) {
        if constexpr(is_integral_v<T>) {
            return a / b - ((a ^ b) < 0 && a % b);
        } else {
            return a / b;
        }
    }

    struct Line {
        mutable T k, m, p;
        bool operator<(const Line& o) const { return k < o.k; }
        bool operator<(T x) const { return p < x; }
    };

    multiset<Line, less<>> hull;

    using Iter = typename multiset<Line, less<>>::iterator;

    bool intersect(Iter x, Iter y) {
        if(y == hull.end()) {
            return x->p = inf, 0;
        }
        if(x->k == y->k) {
            x->p = x->m > y->m ? inf : -inf;
        } else {
            x->p = div(y->m - x->m, x->k - y->k);
        }
        return x->p >= y->p;
    }

    void add(T k, T m) {
        if constexpr(!maximum) {
            k = -k;
            m = -m;
        }
        auto z = hull.insert({k, m, 0}), y = z++, x = y;
        while(intersect(y, z)) {
            z = hull.erase(z);
        }
        if(x != hull.begin() && intersect(--x, y)) {
            intersect(x, y = hull.erase(y));
        }
        while((y = x) != hull.begin() && (--x)->p >= y->p) {
            intersect(x, hull.erase(y));
        }
    }

    T query(T x) {
        assert(!hull.empty());
        auto l = *hull.lower_bound(x);
        T res = l.k * x + l.m;
        if constexpr(!maximum) {
            res = -res;
        }
        return res;
    }
};


================================================
FILE: geometry/dynamic_convex_hull.hpp
================================================
#include <bits/stdc++.h>
#include <coding_library/geometry/point.hpp>
using namespace std;

// Tested on problem 277 from SGU:
// https://codeforces.com/problemsets/acmsguru/problem/99999/277

class DynamicConvexHull {
  public:
    set<Point> lower;
    set<Point> upper;

  private:
    coord_t lower_sum = 0;
    coord_t upper_sum = 0;

    using Iter = set<Point>::iterator;

    void add_to_hull(set<Point>& hull, coord_t& sum, const Point& p, int sign) {
        if(hull.empty()) {
            hull.insert(p);
            return;
        }

        auto right = hull.lower_bound(p);

        if(right != hull.end() && right->x == p.x) {
            if(sign * (p.y - right->y) >= 0) {
                return;
            }
            Iter left = (right != hull.begin()) ? prev(right) : hull.end();
            Iter right_next = next(right);
            if(left != hull.end()) {
                sum -= (*left) ^ (*right);
            }
            if(right_next != hull.end()) {
                sum -= (*right) ^ (*right_next);
            }
            if(left != hull.end() && right_next != hull.end()) {
                sum += (*left) ^ (*right_next);
            }
            hull.erase(right);
            right = right_next;
        }

        Iter left = (right != hull.begin()) ? prev(right) : hull.end();

        if(left != hull.end() && right != hull.end()) {
            if(sign * ccw(*left, *right, p) >= 0) {
                return;
            }
            sum -= (*left) ^ (*right);
        }

        while(left != hull.end() && left != hull.begin()) {
            Iter left_left = prev(left);
            if(sign * ccw(*left_left, *left, p) > 0) {
                break;
            }
            sum -= (*left_left) ^ (*left);
            hull.erase(left);
            left = left_left;
        }

        while(right != hull.end()) {
            Iter right_next = next(right);
            if(right_next == hull.end()) {
                break;
            }
            if(sign * ccw(p, *right, *right_next) > 0) {
                break;
            }
            sum -= (*right) ^ (*right_next);
            hull.erase(right);
            right = right_next;
        }

        if(left != hull.end()) {
            sum += (*left) ^ p;
        }
        if(right != hull.end()) {
            sum += p ^ (*right);
        }

        hull.insert(p);
    }

  public:
    DynamicConvexHull() = default;

    void add(const Point& p) {
        add_to_hull(lower, lower_sum, p, 1);
        add_to_hull(upper, upper_sum, p, -1);
    }

    coord_t doubled_area() const {
        if(lower.empty() || upper.empty()) {
            return 0;
        }

        coord_t result = lower_sum - upper_sum;

        const Point& right_lower = *lower.rbegin();
        const Point& right_upper = *upper.rbegin();
        if(!(right_lower == right_upper)) {
            result += right_lower ^ right_upper;
        }

        const Point& left_lower = *lower.begin();
        const Point& left_upper = *upper.begin();
        if(!(left_lower == left_upper)) {
            result += left_upper ^ left_lower;
        }

        return result;
    }
};


================================================
FILE: geometry/halfplane_intersection.hpp
================================================
#include <bits/stdc++.h>
#include <coding_library/geometry/point.hpp>

using namespace std;

using Line = pair<Point, Point>;

class HalfPlaneIntersection {
  private:
    vector<Line> lines;
    deque<int> dq;
    bool empty_intersection = false;

    Point dir(int i) const { return lines[i].second - lines[i].first; }

    bool outside(int i, const Point& pt) const {
        return ccw(lines[i].first, lines[i].second, pt) < 0;
    }

    Point inter(int i, int j) const {
        return line_line_intersection(
            lines[i].first, lines[i].second, lines[j].first, lines[j].second
        );
    }

    bool is_parallel(int i, int j) const {
        return abs(dir(i) ^ dir(j)) < Point::eps;
    }

    bool same_direction(int i, int j) const { return (dir(i) * dir(j)) > 0; }

  public:
    static vector<Line> sort_by_angle(const vector<Line>& lines) {
        vector<Line> sorted = lines;
        sort(sorted.begin(), sorted.end(), [](const Line& a, const Line& b) {
            return (a.second - a.first).angle() < (b.second - b.first).angle();
        });
        return sorted;
    }

    HalfPlaneIntersection(const vector<Line>& lines, bool is_sorted = false)
        : lines(is_sorted ? lines : sort_by_angle(lines)) {
        int n = this->lines.size();

        for(int i = 0; i < n; i++) {
            while(dq.size() > 1 &&
                  outside(i, inter(dq.back(), dq[dq.size() - 2]))) {
                dq.pop_back();
            }
            while(dq.size() > 1 && outside(i, inter(dq.front(), dq[1]))) {
                dq.pop_front();
            }

            if(!dq.empty() && is_parallel(i, dq.back())) {
                if(!same_direction(i, dq.back())) {
                    empty_intersection = true;
                    return;
                }
                if(outside(i, this->lines[dq.back()].first)) {
                    dq.pop_back();
                } else {
                    continue;
                }
            }

            dq.push_back(i);
        }

        while(dq.size() > 2 &&
              outside(dq.front(), inter(dq.back(), dq[dq.size() - 2]))) {
            dq.pop_back();
        }
        while(dq.size() > 2 && outside(dq.back(), inter(dq.front(), dq[1]))) {
            dq.pop_front();
        }

        if(dq.size() < 3) {
            empty_intersection = true;
        }
    }

    bool is_non_empty() const { return !empty_intersection; }

    vector<Point> get_polygon() const {
        if(empty_intersection) {
            return {};
        }
        vector<Point> result(dq.size());
        for(size_t i = 0; i + 1 < dq.size(); i++) {
            result[i] = inter(dq[i], dq[i + 1]);
        }
        result.back() = inter(dq.back(), dq.front());
        return result;
    }
};


================================================
FILE: geometry/point.hpp
================================================
#ifndef POINT_HPP
#define POINT_HPP

#include <bits/stdc++.h>
using namespace std;

using coord_t = double;

struct Point {
    static constexpr coord_t eps = 1e-9;
    static inline const coord_t PI = acos((coord_t)-1.0);

    coord_t x, y;
    Point(coord_t x = 0, coord_t y = 0) : x(x), y(y) {}

    Point operator+(const Point& p) const { return Point(x + p.x, y + p.y); }
    Point operator-(const Point& p) const { return Point(x - p.x, y - p.y); }
    Point operator*(coord_t c) const { return Point(x * c, y * c); }
    Point operator/(coord_t c) const { return Point(x / c, y / c); }

    coord_t operator*(const Point& p) const { return x * p.x + y * p.y; }
    coord_t operator^(const Point& p) const { return x * p.y - y * p.x; }

    bool operator==(const Point& p) const { return x == p.x && y == p.y; }
    bool operator!=(const Point& p) const { return x != p.x || y != p.y; }
    bool operator<(const Point& p) const {
        return x != p.x ? x < p.x : y < p.y;
    }
    bool operator>(const Point& p) const {
        return x != p.x ? x > p.x : y > p.y;
    }
    bool operator<=(const Point& p) const {
        return x != p.x ? x < p.x : y <= p.y;
    }
    bool operator>=(const Point& p) const {
        return x != p.x ? x > p.x : y >= p.y;
    }

    coord_t norm2() const { return x * x + y * y; }
    coord_t norm() const { return sqrt(norm2()); }
    coord_t angle() const { return atan2(y, x); }

    Point rotate(coord_t a) const {
        return Point(x * cos(a) - y * sin(a), x * sin(a) + y * cos(a));
    }

    Point perp() const { return Point(-y, x); }
    Point unit() const { return *this / norm(); }
    Point normal() const { return perp().unit(); }
    Point project(const Point& p) const {
        return *this * (*this * p) / norm2();
    }
    Point reflect(const Point& p) const {
        return *this * 2 * (*this * p) / norm2() - p;
    }

    friend ostream& operator<<(ostream& os, const Point& p) {
        return os << p.x << ' ' << p.y;
    }
    friend istream& operator>>(istream& is, Point& p) {
        return is >> p.x >> p.y;
    }

    friend int ccw(const Point& a, const Point& b, const Point& c) {
        coord_t v = (b - a) ^ (c - a);
        if(-eps <= v && v <= eps) {
            return 0;
        } else if(v > 0) {
            return 1;
        } else {
            return -1;
        }
    }

    friend bool point_on_segment(
        const Point& a, const Point& b, const Point& p
    ) {
        return ccw(a, b, p) == 0 && p.x >= min(a.x, b.x) - eps &&
               p.x <= max(a.x, b.x) + eps && p.y >= min(a.y, b.y) - eps &&
               p.y <= max(a.y, b.y) + eps;
    }

    friend bool point_in_triangle(
        const Point& a, const Point& b, const Point& c, const Point& p
    ) {
        int d1 = ccw(a, b, p);
        int d2 = ccw(b, c, p);
        int d3 = ccw(c, a, p);
        return (d1 >= 0 && d2 >= 0 && d3 >= 0) ||
               (d1 <= 0 && d2 <= 0 && d3 <= 0);
    }

    friend Point line_line_intersection(
        const Point& a1, const Point& b1, const Point& a2, const Point& b2
    ) {
        return a1 +
               (b1 - a1) * ((a2 - a1) ^ (b2 - a2)) / ((b1 - a1) ^ (b2 - a2));
    }

    friend bool collinear(const Point& a, const Point& b) {
        return abs(a ^ b) < eps;
    }

    friend Point circumcenter(const Point& a, const Point& b, const Point& c) {
        Point mid_ab = (a + b) / 2.0;
        Point mid_ac = (a + c) / 2.0;
        Point perp_ab = (b - a).perp();
        Point perp_ac = (c - a).perp();
        return line_line_intersection(
            mid_ab, mid_ab + perp_ab, mid_ac, mid_ac + perp_ac
        );
    }

    friend coord_t arc_area(
        const Point& center, coord_t r, const Point& p1, const Point& p2
    ) {
        coord_t theta1 = (p1 - center).angle();
        coord_t theta2 = (p2 - center).angle();
        if(theta2 < theta1 - eps) {
            theta2 += 2 * PI;
        }

        coord_t d_theta = theta2 - theta1;
        coord_t cx = center.x, cy = center.y;
        coord_t area = r * cx * (sin(theta2) - sin(theta1)) -
                       r * cy * (cos(theta2) - cos(theta1)) + r * r * d_theta;
        return area / 2.0;
    }

    friend vector<Point> intersect_circles(
        const Point& c1, coord_t r1, const Point& c2, coord_t r2
    ) {
        Point d = c2 - c1;
        coord_t dist = d.norm();

        if(dist > r1 + r2 + eps || dist < abs(r1 - r2) - eps || dist < eps) {
            return {};
        }

        coord_t a = (r1 * r1 - r2 * r2 + dist * dist) / (2 * dist);
        coord_t h_sq = r1 * r1 - a * a;
        if(h_sq < -eps) {
            return {};
        }
        if(h_sq < 0) {
            h_sq = 0;
        }
        coord_t h = sqrt(h_sq);

        Point mid = c1 + d.unit() * a;
        Point perp_dir = d.perp().unit();

        if(h < eps) {
            return {mid};
        }
        return {mid + perp_dir * h, mid - perp_dir * h};
    }

    friend optional<Point> intersect_ray_segment(
        const Point& ray_start, const Point& ray_through, const Point& seg_a,
        const Point& seg_b
    ) {
        Point ray_dir = ray_through - ray_start;
        if(ray_dir.norm2() < Point::eps) {
            return {};
        }
        Point seg_dir = seg_b - seg_a;
        coord_t denom = ray_dir ^ seg_dir;
        if(fabs(denom) < eps) {
            return {};
        }
        coord_t t = ((seg_a - ray_start) ^ seg_dir) / denom;
        if(t < eps) {
            return {};
        }
        coord_t s = ((seg_a - ray_start) ^ ray_dir) / denom;
        if(s < eps || s > 1 - eps) {
            return {};
        }
        return ray_start + ray_dir * t;
    }
};

#endif  // POINT_HPP


================================================
FILE: geometry/polygon.hpp
================================================
#ifndef POLYGON_HPP
#define POLYGON_HPP

#include <bits/stdc++.h>
#include <coding_library/geometry/point.hpp>
using namespace std;

class Polygon {
  public:
    vector<Point> points;

    Polygon() {}
    Polygon(const vector<Point>& points) : points(points) {}

    int size() const { return points.size(); }
    const Point& operator[](int i) const { return points[i]; }
    Point& operator[](int i) { return points[i]; }

    coord_t area() const {
        coord_t a = 0;
        for(int i = 0; i < size(); i++) {
            a += points[i] ^ points[(i + 1) % size()];
        }
        return a / 2.0;
    }
};

class PointInConvexPolygon {
  private:
    Point min_point;
    vector<Point> points_by_angle;

    void prepare() {
        points_by_angle = polygon.points;
        vector<Point>::iterator min_point_it =
            min_element(points_by_angle.begin(), points_by_angle.end());
        min_point = *min_point_it;

        points_by_angle.erase(min_point_it);
        sort(
            points_by_angle.begin(), points_by_angle.end(),
            [&](const Point& a, const Point& b) {
                int d = ccw(min_point, a, b);
                if(d != 0) {
                    return d > 0;
                }
                return (a - min_point).norm2() < (b - min_point).norm2();
            }
        );
    }

  public:
    Polygon polygon;
    PointInConvexPolygon(const Polygon& polygon) : polygon(polygon) {
        prepare();
    }

    bool contains(const Point& p) const {
        int l = 0, r = (int)points_by_angle.size() - 1;
        while(r - l > 1) {
            int m = (l + r) / 2;
            if(ccw(min_point, points_by_angle[m], p) >= 0) {
                l = m;
            } else {
                r = m;
            }
        }

        return point_in_triangle(
            min_point, points_by_angle[l], points_by_angle[r], p
        );
    }
};

class ConvexHull : public Polygon {
  public:
    int lower_end;
    vector<Point> lower, upper;

    ConvexHull(const vector<Point>& points) {
        this->points = points;
        sort(this->points.begin(), this->points.end());
        this->points.erase(
            unique(this->points.begin(), this->points.end()), this->points.end()
        );

        if(this->points.size() <= 2) {
            lower_end = (int)this->points.size() - 1;
            lower = this->points;
            upper = {this->points.back()};
            if(this->points.size() > 1) {
                upper.push_back(this->points.front());
            }
            return;
        }

        vector<int> hull = {0};
        vector<bool> used(this->points.size());

        function<void(int, int)> expand_hull = [&](int i, int min_hull_size) {
            while((int)hull.size() >= min_hull_size &&
                  ccw(this->points[hull[hull.size() - 2]],
                      this->points[hull.back()], this->points[i]) >= 0) {
                used[hull.back()] = false;
                hull.pop_back();
            }
            hull.push_back(i);
            used[i] = true;
        };

        for(int i = 1; i < (int)this->points.size(); i++) {
            expand_hull(i, 2);
        }

        int uhs = hull.size();
        for(int i = (int)this->points.size() - 2; i >= 0; i--) {
            if(!used[i]) {
                expand_hull(i, uhs + 1);
            }
        }

        hull.pop_back();

        vector<Point> pts;
        for(int i: hull) {
            pts.push_back(this->points[i]);
        }
        reverse(pts.begin(), pts.end());
        this->points = std::move(pts);

        lower_end = size() - uhs;
        lower.assign(
            this->points.begin(), this->points.begin() + lower_end + 1
        );
        upper.assign(this->points.begin() + lower_end, this->points.end());
        upper.push_back(this->points[0]);
    }

    pair<int, int> tangents_from(const Point& p) const {
        int n = size();
        if(n <= 1) {
            return {0, 0};
        }

        int a = 0, b = 0;
        auto update = [&](int id) {
            id %= n;
            if(ccw(p, points[a], points[id]) > 0) {
                a = id;
            }
            if(ccw(p, points[b], points[id]) < 0) {
                b = id;
            }
        };

        auto bin_search = [&](int low, int high) {
            if(low >= high) {
                return;
            }
            update(low);
            int sl = ccw(p, points[low % n], points[(low + 1) % n]);
            while(low + 1 < high) {
                int mid = (low + high) / 2;
                if(ccw(p, points[mid % n], points[(mid + 1) % n]) == sl) {
                    low = mid;
                } else {
                    high = mid;
                }
            }
            update(high);
        };

        int lid =
            (int)(lower_bound(lower.begin(), lower.end(), p) - lower.begin());
        bin_search(0, lid);
        bin_search(lid, (int)lower.size() - 1);

        int uid =
            (int)(lower_bound(upper.begin(), upper.end(), p, greater<Point>()) -
                  upper.begin());
        int base = lower_end;
        bin_search(base, base + uid);
        bin_search(base + uid, base + (int)upper.size() - 1);
        return {a, b};
    }
};

#endif  // POLYGON_HPP


================================================
FILE: geometry/voronoi.hpp
================================================
#ifndef VORONOI_HPP
#define VORONOI_HPP

#include <bits/stdc++.h>
#include <coding_library/geometry/point.hpp>
using namespace std;

// Variation of code by Monogon: https://codeforces.com/blog/entry/85638.
// We rotate the points with a small angle as the implementation doesn't
// directly handle the case of two equal X coordinates.

class VoronoiDiagram {
  private:
    static constexpr coord_t INF = 1e100;
    static inline coord_t sweep_x;

    struct Arc {
        mutable Point p, q;
        mutable int id = 0, i;

        Arc(const Point& p, const Point& q, int i) : p(p), q(q), i(i) {}

        coord_t get_y(coord_t x) const {
            if(q.y == INF) {
                return INF;
            }
            x += Point::eps;
            Point mid = (p + q) / 2.0;
            Point dir = (p - mid).perp();
            coord_t D = (x - p.x) * (x - q.x);
            if(D < 0) {
                return -INF;
            }

            if(abs(dir.y) < Point::eps) {
                return (x < mid.x) ? -INF : INF;
            }

            return mid.y +
                   ((mid.x - x) * dir.x + sqrtl(D) * dir.norm()) / dir.y;
        }

        bool operator<(const coord_t& y) const { return get_y(sweep_x) < y; }

        bool operator<(const Arc& o) const {
            return get_y(sweep_x) < o.get_y(sweep_x);
        }
    };

    using Beach = multiset<Arc, less<>>;

    struct Event {
        coord_t x;
        int id;
        Beach::iterator it;

        Event(coord_t x, int id, Beach::iterator it) : x(x), id(id), it(it) {}

        bool operator<(const Event& e) const { return x > e.x; }
    };

    Beach beach_line;
    vector<pair<Point, int>> vertices;
    priority_queue<Event> event_queue;
    vector<pair<int, int>> edges;
    vector<bool> valid;
    int n, next_vertex_id;

    void update_vertex_event(Beach::iterator it) {
        if(it->i == -1) {
            return;
        }

        valid[-it->id] = false;
        auto prev_it = prev(it);

        if(collinear(it->q - it->p, prev_it->p - it->p)) {
            return;
        }

        it->id = --next_vertex_id;
        valid.push_back(true);

        Point center = circumcenter(it->p, it->q, prev_it->p);
        coord_t event_x = center.x + (center - it->p).norm();

        bool valid_event =
            event_x > sweep_x - Point::eps &&
            prev_it->get_y(event_x) + Point::eps > it->get_y(event_x);
        if(valid_event) {
            event_queue.push(Event(event_x, it->id, it));
        }
    }

    void add_edge(int i, int j) {
        if(i == -1 || j == -1) {
            return;
        }
        edges.push_back({vertices[i].second, vertices[j].second});
    }

    void add_point(int i) {
        Point p = vertices[i].first;

        auto split_it = beach_line.lower_bound(p.y);
        auto new_it = beach_line.insert(split_it, Arc(p, split_it->p, i));
        auto prev_it =
            beach_line.insert(new_it, Arc(split_it->p, p, split_it->i));

        add_edge(i, split_it->i);

        update_vertex_event(prev_it);
        update_vertex_event(new_it);
        update_vertex_event(split_it);
    }

    void remove_arc(Beach::iterator it) {
        auto prev_it = prev(it);
        auto next_it = next(it);

        beach_line.erase(it);
        prev_it->q = next_it->p;

        add_edge(prev_it->i, next_it->i);

        update_vertex_event(prev_it);
        update_vertex_event(next_it);
    }

  public:
    VoronoiDiagram(const vector<Point>& points, bool fix_coordinates = true) {
        n = points.size();
        vertices.resize(n);

        for(int i = 0; i < n; i++) {
            vertices[i] = {points[i], i};
        }

        if(fix_coordinates && n > 0) {
            // Rotate around center by 1.0 radians.
            for(int i = 0; i < n; i++) {
                vertices[i].first = vertices[i].first.rotate(1.0);
            }
        }

        sort(vertices.begin(), vertices.end());
    }

    vector<pair<int, int>> compute(coord_t X = 1e9) {
        edges.clear();
        beach_line.clear();
        event_queue = priority_queue<Event>();

        X *= 3;
        beach_line.insert(Arc(Point(-X, -X), Point(-X, X), -1));
        beach_line.insert(Arc(Point(-X, X), Point(INF, INF), -1));

        for(int i = 0; i < n; i++) {
            event_queue.push(Event(vertices[i].first.x, i, beach_line.end()));
        }

        next_vertex_id = 0;
        valid.assign(1, false);

        while(!event_queue.empty()) {
            Event e = event_queue.top();
            event_queue.pop();
            sweep_x = e.x;

            if(e.id >= 0) {
                add_point(e.id);
            } else if(valid[-e.id]) {
                remove_arc(e.it);
            }
        }

        return edges;
    }

    const vector<pair<int, int>>& get_edges() const { return edges; }
};

#endif  // VORONOI_HPP


================================================
FILE: graph/bcc.hpp
================================================
#include <bits/stdc++.h>

using namespace std;

class biconnected_components {
  private:
    vector<int> low, disc;

    void tarjan(int u, int pr, int &dfs_time, vector<pair<int, int>> &st) {
        low[u] = disc[u] = ++dfs_time;

        int child_cnt = 0;
        for(int v: adj[u]) {
            if(v != pr) {
                if(disc[v] == -1) {
                    st.push_back({u, v});
                    tarjan(v, u, dfs_time, st);
                    child_cnt++;
                    low[u] = min(low[u], low[v]);

                    if((pr == -1 && child_cnt > 1) ||
                       (pr != -1 && disc[u] <= low[v])) {
                        vector<pair<int, int>> curr = {make_pair(u, v)};
                        while(st.back() != make_pair(u, v)) {
                            curr.push_back(st.back());
                            st.pop_back();
                        }

                        st.pop_back();
                        if(curr.size() == 1) {
                            bridges.push_back(curr.back());
                        } else {
                            bcc.push_back(curr);
                        }
                    }
                } else if(disc[v] < disc[u]) {
                    low[u] = min(low[u], disc[v]);
                    st.push_back({u, v});
                }
            }
        }
    }

  public:
    int n;
    vector<vector<int>> adj;
    vector<vector<pair<int, int>>> bcc;
    vector<pair<int, int>> bridges;

    void add_edge(int u, int v) {
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    void init(int _n) {
        n = _n;
        adj.assign(n + 1, {});
    }

    void compute_bcc() {
        bcc.clear();
        bridges.clear();
        low.assign(n + 1, -1);
        disc.assign(n + 1, -1);

        int dfs_time = 0;
        for(int i = 0; i < n; i++) {
            if(disc[i] == -1) {
                vector<pair<int, int>> st;
                tarjan(i, -1, dfs_time, st);
                if(!st.empty()) {
                    if(st.size() == 1) {
                        bridges.push_back(st.back());
                    } else {
                        bcc.push_back(st);
                    }
                    st.clear();
                }
            }
        }
    }
};

// int n, m;
// biconnected_components bcc;
// void read() {
//     cin >> n >> m;
//     bcc.init(n);
//     for(int i = 0; i < m; i++) {
//         int u, v;
//         cin >> u >> v;
//         bcc.add_edge(u, v);
//     }
// }


================================================
FILE: graph/bipartite_coloring.hpp
================================================
#include <bits/stdc++.h>
#include <coding_library/graph/hopcroft_karp.hpp>
using namespace std;

struct Edge {
    int u, v, idx;
    Edge(int _u = 0, int _v = 0, int _idx = 0) : u(_u), v(_v), idx(_idx) {}
};

class BipartiteColoring {
  private:
    vector<vector<pair<Edge, int>>> edges_for_ver;
    vector<bool> used;
    vector<vector<pair<int, int>>> adj;
    vector<int> memory_m;

    template<class T>
    static void make_larger_if_needed(vector<T>& v, int size) {
        if(v.size() < size) {
            v.resize(size);
        }
    }

    pair<vector<Edge>, vector<Edge>> partition_edges_euler(
        const vector<Edge>& edges, const vector<int>& vers, int n
    ) {
        make_larger_if_needed(adj, 2 * n);
        make_larger_if_needed(memory_m, edges.size());

        for(int v: vers) {
            adj[v].clear();
            adj[v + n].clear();
        }

        for(int ei = 0; ei < (int)edges.size(); ei++) {
            auto e = edges[ei];
            adj[e.u].push_back({e.v + n, ei});
            adj[e.v + n].push_back({e.u, ei});
            memory_m[ei] = 0;
        }

        function<void(int, vector<Edge>&, vector<Edge>&)> dfs =
            [&](int v, vector<Edge>& subgraph_0, vector<Edge>& subgraph_1) {
                while(!adj[v].empty()) {
                    auto [u, ei] = adj[v].back();
                    adj[v].pop_back();
                    if(memory_m[ei] == 1) {
                        continue;
                    }
                    memory_m[ei] = 1;
                    dfs(u, subgraph_0, subgraph_1);
                    if(v < n) {
                        subgraph_0.push_back(edges[ei]);
                    } else {
                        subgraph_1.push_back(edges[ei]);
                    }
                    break;
                }
            };

        vector<Edge> subgraph_0, subgraph_1;
        for(int v: vers) {
            while(!adj[v].empty()) {
                dfs(v, subgraph_0, subgraph_1);
            }
        }

        return {subgraph_0, subgraph_1};
    }

    vector<Edge> hopcroft_one_colour(
        const vector<Edge>& edges, int n, vector<vector<Edge>>& answer
    ) {
        make_larger_if_needed(edges_for_ver, n);
        make_larger_if_needed(used, (int)edges.size());

        for(int i = 0; i < n; i++) {
            edges_for_ver[i].clear();
        }
        for(int i = 0; i < (int)edges.size(); i++) {
            used[i] = false;
        }

        HopcroftKarp bm(n, n);
        for(int i = 0; i < (int)edges.size(); i++) {
            auto e = edges[i];
            bm.add_edge(e.u, e.v);
            edges_for_ver[e.u].push_back({e, i});
        }

        int max_match = bm.max_matching();
        assert(max_match == n);

        vector<Edge> assigned;
        vector<pair<int, int>> matches = bm.get_matching();
        for(auto [u, v]: matches) {
            for(auto [e, ei]: edges_for_ver[u]) {
                if(e.v == v && !used[ei]) {
                    used[ei] = true;
                    assigned.push_back(e);
                    break;
                }
            }
        }

        vector<Edge> new_edges;
        for(int i = 0; i < (int)edges.size(); i++) {
            if(!used[i]) {
                new_edges.push_back(edges[i]);
            }
        }

        answer.push_back(assigned);
        return new_edges;
    }

    // We don't actually use this function as it's actually slower than the
    // above one.
    vector<Edge> good_worst_case_one_colour(
        const vector<Edge>& _edges, int n, int original_m,
        vector<vector<Edge>>& answer
    ) {
        static vector<int> memory_m;
        make_larger_if_needed(memory_m, original_m);

        int m = _edges.size();
        int d = m / n;

        int l = 0;
        while((1 << l) <= m) {
            l++;
        }

        int alpha = (1 << l) / d;
        int beta = (1 << l) - d * alpha;

        vector<Edge> edges = _edges;
        vector<int> multiplicity(edges.size(), alpha);
        for(int i = 0; i < m; i++) {
            auto& e = edges[i];
            memory_m[e.idx] = i;
        }

        for(int i = 0; i < n; i++) {
            edges.push_back(Edge(i, i, -1));
            multiplicity.push_back(beta);
        }

        vector<int> vers(n);
        iota(vers.begin(), vers.end(), 0);
        while(l--) {
            vector<Edge> new_edges;
            for(int i = 0; i < (int)edges.size(); i++) {
                if(multiplicity[i] % 2) {
                    new_edges.push_back(edges[i]);
                }
                multiplicity[i] /= 2;
            }

            auto [subgraph_0, subgraph_1] =
                partition_edges_euler(new_edges, vers, n);

            int cnt0 = 0, cnt1 = 0;
            for(auto& e: subgraph_0) {
                if(e.idx == -1) {
                    cnt0++;
                }
            }

            for(auto& e: subgraph_1) {
                if(e.idx == -1) {
                    cnt1++;
                }
            }

            if(cnt0 > cnt1) {
                swap(subgraph_0, subgraph_1);
            }

            for(int i = 0; i < (int)subgraph_0.size(); i++) {
                auto& e = subgraph_0[i];
                if(e.idx == -1) {
                    multiplicity[m + e.u] += 1;
                } else {
                    int multiplicity_idx = memory_m[e.idx];
                    multiplicity[multiplicity_idx] += 1;
                }
            }
        }

        vector<Edge> answer_edges, subgraph_rest;
        for(int i = 0; i < m; i++) {
            auto& e = edges[i];
            if(multiplicity[i]) {
                answer_edges.push_back(e);
            } else {
                subgraph_rest.push_back(e);
            }
        }

        answer.push_back(answer_edges);
        return subgraph_rest;
    }

  public:
    int euler_colour(
        const vector<Edge>& edges, int n, int m, vector<vector<Edge>>& answer
    ) {
        static vector<int> memory;
        make_larger_if_needed(memory, n);

        vector<int> vers, _vers;
        for(auto e: edges) {
            _vers.push_back(e.u);
            _vers.push_back(e.v);
        }

        int max_degree = 0;
        for(int v: _vers) {
            memory[v] = -1;
        }
        for(int v: _vers) {
            if(memory[v] == -1) {
                vers.push_back(v);
                memory[v] = 0;
            }
        }
        for(auto e: edges) {
            memory[e.u]++;
            max_degree = max(max_degree, memory[e.u]);
        }

        if(max_degree == 0) {
            return 0;
        }
        if(max_degree == 1) {
            answer.push_back({});
            for(auto e: edges) {
                answer.back().push_back(e);
            }
            return 1;
        }

        if(max_degree % 2 == 1) {
            auto subgraph = hopcroft_one_colour(edges, n, answer);
            // Uncomment if we want something that is good in worst case.
            // auto subgraph = good_worst_case_one_colour(edges, n, m, answer);
            return 1 + euler_colour(subgraph, n, m, answer);
        }

        auto [subgraph_0, subgraph_1] =
            partition_edges_euler(edges, vers, n);
        int colour_num_subgraph_0 = euler_colour(subgraph_0, n, m, answer);

        int d = max_degree, q = 0;
        while((1 << q) < (max_degree / 2)) {
            q++;
        }
        int to_remove_count = (1 << q) - (max_degree / 2);
        if(to_remove_count > 0 && colour_num_subgraph_0 >= to_remove_count) {
            for(int i = answer.size() - 1; i >= answer.size() - to_remove_count;
                i--) {
                for(auto& e: answer[i]) {
                    subgraph_1.push_back(e);
                }
            }
            answer.erase(answer.end() - to_remove_count, answer.end());
        }

        int colour_num_subgraph_1 = euler_colour(subgraph_1, n, m, answer);
        return colour_num_subgraph_0 + colour_num_subgraph_1;
    }
};


================================================
FILE: graph/bipartite_matching.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

class BipartiteMatching {
  private:
    int n, m, visited_timer;
    vector<int> visited;

    bool try_kuhn(int u) {
        if(visited[u] == visited_timer) {
            return false;
        }

        visited[u] = visited_timer;
        for(int v: adj[u]) {
            if(match[v] == -1 || try_kuhn(match[v])) {
                match[v] = u;
                inv_match[u] = v;
                return true;
            }
        }
        return false;
    }

    int pre_match() {
        int matching_size = 0;
        for(int u = 0; u < n; u++) {
            if(inv_match[u] == -1) {
                for(int v: adj[u]) {
                    if(match[v] == -1) {
                        matching_size++;
                        match[v] = u;
                        inv_match[u] = v;
                        break;
                    }
                }
            }
        }

        return matching_size;
    }

  public:
    vector<int> match, inv_match;
    vector<vector<int>> adj;

    BipartiteMatching(int _n, int _m = -1) : n(_n), m(_m == -1 ? _n : _m) {
        adj.assign(n, vector<int>());
        clear(false);
    }

    void clear(bool clear_adj = true) {
        match.assign(m, -1);
        inv_match.assign(n, -1);

        visited_timer = 0;
        visited.assign(n, 0);
        if(clear_adj) {
            adj.assign(n, vector<int>());
        }
    }

    void add_edge(int u, int v) { adj[u].push_back(v); }

    bool match_vertex(int u) {
        if(inv_match[u] != -1) {
            return false;
        }

        visited_timer++;
        return try_kuhn(u);
    }

    int max_matching(bool shuffle_edges = false, bool pre_matching = false) {
        if(shuffle_edges) {
            for(int i = 0; i < n; i++) {
                shuffle(
                    adj[i].begin(), adj[i].end(),
                    mt19937(
                        chrono::steady_clock::now().time_since_epoch().count()
                    )
                );
            }
        }

        int ans = 0;
        if(pre_matching) {
            ans += pre_match();
        }

        for(int i = 0; i < n; i++) {
            ans += match_vertex(i);
        }

        return ans;
    }

    vector<pair<int, int>> get_matching() {
        vector<pair<int, int>> res;
        for(int i = 0; i < m; i++) {
            if(match[i] != -1) {
                res.emplace_back(match[i], i);
            }
        }
        return res;
    }
};


================================================
FILE: graph/dijkstra_vlog.hpp
================================================
#include <bits/stdc++.h>
#include <coding_library/data_structures/heap.hpp>

using namespace std;

template<typename T>
vector<T> dijkstra(int src, const vector<vector<pair<int, T>>>& adj) {
    static auto cmp_min = [](int a, int b) -> bool { return a > b; };

    int n = adj.size();
    vector<T> dist(n, numeric_limits<T>::max());
    vector<int> pq_node(n, -1);
    vector<int> pq_node_to_ver(n, -1);
    Heap<T, +cmp_min> pq;

    function<void(int, T)> update = [&](int u, T d) {
        dist[u] = min(dist[u], d);
        if(pq_node[u] == -1) {
            pq_node[u] = pq.push(dist[u]);
            pq_node_to_ver[pq_node[u]] = u;
        } else {
            pq.update(pq_node[u], dist[u]);
        }
    };

    update(src, 0);
    while(!pq.empty()) {
        int u = pq_node_to_ver[pq.top_node()];
        pq.pop();

        for(auto [v, w]: adj[u]) {
            update(v, dist[u] + w);
        }
    }

    return dist;
}


================================================
FILE: graph/directed_cactus.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

class DirectedCactus {
  private:
    int n;
    vector<vector<int>> adj;
    vector<int> nxt, jump, dep, in_time, out_time;

    void dfs(int u, int &dfs_time, vector<bool> &used, vector<int> &buff) {
        used[u] = true;
        in_time[u] = dfs_time++;
        buff.push_back(u);
        for(int v: adj[u]) {
            if(!used[v]) {
                dep[v] = dep[u] + 1;
                dfs(v, dfs_time, used, buff);
            }
        }
        out_time[u] = dfs_time - 1;
    }

  public:
    DirectedCactus() {
        n = 0;
        nxt.clear();
    }
    DirectedCactus(vector<int> _nxt) { init(_nxt); }

    void init(vector<int> _nxt) {
        nxt = _nxt;
        n = nxt.size();
        in_time.resize(n);
        out_time.resize(n);
        jump.resize(n);

        adj.assign(n, {});
        for(int i = 0; i < n; i++) {
            adj[nxt[i]].push_back(i);
        }

        int dfs_time = 0;
        vector<bool> used(n, false);
        dep.assign(n, 0);
        for(int i = 0; i < n; i++) {
            if(!used[i]) {
                vector<int> buff;

                int root = i;
                while(!used[root]) {
                    used[root] = true;
                    buff.push_back(root);
                    root = nxt[root];
                }

                for(int u: buff) {
                    used[u] = false;
                }
                buff.clear();

                dfs(root, dfs_time, used, buff);
                for(int u: buff) {
                    jump[u] = nxt[root];
                }
            }
        }
    }

    int distance(int from, int to) {
        if(in_time[to] <= in_time[from] && out_time[from] <= out_time[to]) {
            return dep[from] - dep[to];
        }

        int to_add = dep[from] + 1;
        from = jump[from];
        if(in_time[to] <= in_time[from] && out_time[from] <= out_time[to]) {
            return dep[from] - dep[to] + to_add;
        }
        return -1;
    }
};


================================================
FILE: graph/dsu.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

class DSU {
  public:
    int n;
    vector<int> par;
    vector<int> sz;

    DSU(int _n = 0) { init(_n); }

    void init(int _n) {
        n = _n;
        par.assign(n + 1, 0);
        sz.assign(n + 1, 0);
        for(int i = 0; i <= n; i++) {
            par[i] = i;
            sz[i] = 1;
        }
    }

    int root(int u) { return par[u] = ((u == par[u]) ? u : root(par[u])); }
    bool connected(int x, int y) { return root(x) == root(y); }

    int unite(int x, int y) {
        x = root(x), y = root(y);
        if(x == y) {
            return x;
        }
        if(sz[x] > sz[y]) {
            swap(x, y);
        }
        par[x] = y;
        sz[y] += sz[x];
        return y;
    }

    vector<vector<int>> components() {
        vector<vector<int>> comp(n + 1);
        for(int i = 0; i <= n; i++) {
            comp[root(i)].push_back(i);
        }
        return comp;
    }
};


================================================
FILE: graph/eppstein_shortest_paths.hpp
================================================
#include <bits/stdc++.h>
#include <coding_library/data_structures/meldable_heap.hpp>
using namespace std;

template<class T = int>
class EppsteinShortestPaths {
  private:
    const T inf = numeric_limits<T>::max() / 2;

    struct Edge {
        int u, v;
        T w;
        Edge(int _u = 0, int _v = 0, T _w = 0) : u(_u), v(_v), w(_w) {}
    };

    pair<vector<T>, vector<int>> build_dijkstra_tree(int t) {
        vector<T> dist(n, inf);

        priority_queue<pair<T, int>, vector<pair<T, int>>, greater<>> pq;
        dist[t] = 0;
        pq.emplace(0, t);

        while(!pq.empty()) {
            auto [d, u] = pq.top();
            pq.pop();
            if(d != dist[u]) {
                continue;
            }

            for(auto [v, idx]: rev_adj[u]) {
                T nd = d + edges[idx].w;
                if(nd < dist[v]) {
                    dist[v] = nd;
                    pq.emplace(nd, v);
                }
            }
        }

        vector<int> tree(n, -1);
        for(int u = 0; u < n; u++) {
            for(auto [v, idx]: adj[u]) {
                if(dist[u] == dist[v] + edges[idx].w) {
                    tree[u] = idx;
                    break;
                }
            }
        }

        return {dist, tree};
    }

    vector<int> topsort(const vector<int>& tree) {
        vector<int> deg(n, 0);
        for(int u = 0; u < n; u++) {
            if(tree[u] != -1) {
                deg[edges[tree[u]].v]++;
            }
        }

        queue<int> q;
        for(int u = 0; u < n; u++) {
            if(deg[u] == 0) {
                q.push(u);
            }
        }

        vector<int> order;
        while(!q.empty()) {
            int u = q.front();
            q.pop();
            order.push_back(u);

            if(tree[u] != -1) {
                int v = edges[tree[u]].v;
                deg[v]--;
                if(deg[v] == 0) {
                    q.push(v);
                }
            }
        }

        return order;
    }

  public:
    int n;
    vector<vector<pair<int, int>>> adj;
    vector<vector<pair<int, int>>> rev_adj;
    vector<Edge> edges;

    void init(int _n) {
        n = _n;
        edges.clear();
        adj.assign(n, {});
        rev_adj.assign(n, {});
    }

    EppsteinShortestPaths(int n = 0) { init(n); }

    int add_edge(int u, int v, T w, bool directed = true) {
        int idx = edges.size();
        edges.emplace_back(u, v, w);
        adj[u].emplace_back(v, idx);
        rev_adj[v].emplace_back(u, idx);

        if(!directed) {
            edges.emplace_back(v, u, w);
            adj[v].emplace_back(u, idx + 1);
            rev_adj[u].emplace_back(v, idx + 1);
        }

        return idx;
    }

    vector<T> get_k_shortest_paths(int s, int t, int k) {
        auto dist_and_tree = build_dijkstra_tree(t);
        auto dist = dist_and_tree.first;
        auto tree = dist_and_tree.second;

        if(dist[s] == inf || k <= 0) {
            return vector<T>();
        }

        vector<MeldableHeap<pair<T, int>>> heaps(n);
        for(int u = 0; u < n; u++) {
            for(auto& [v, idx]: adj[u]) {
                if(tree[u] == idx) {
                    continue;
                }

                T cost = edges[idx].w + dist[v] - dist[u];
                heaps[u].push({cost, v});
            }
        }

        auto order = topsort(tree);
        reverse(order.begin(), order.end());
        for(int u: order) {
            if(tree[u] != -1) {
                int par = edges[tree[u]].v ^ edges[tree[u]].u ^ u;
                heaps[u] = heaps[u].merge(heaps[par]);
            }
        }

        vector<T> ans = {dist[s]};
        if(heaps[s].empty()) {
            return ans;
        }

        priority_queue<
            pair<T, MeldableHeap<pair<T, int>>>,
            vector<pair<T, MeldableHeap<pair<T, int>>>>, greater<>>
            pq;
        pq.emplace(dist[s] + heaps[s].top().first, heaps[s].copy());

        while(!pq.empty() && (int)ans.size() < k) {
            auto [d, meld_heap] = pq.top();
            pq.pop();
            ans.push_back(d);

            auto [head, left_heap, right_heap] = meld_heap.trio();
            if(!left_heap.empty()) {
                pq.emplace(d - head.first + left_heap.top().first, left_heap);
            }
            if(!right_heap.empty()) {
                pq.emplace(d - head.first + right_heap.top().first, right_heap);
            }

            int v = head.second;
            if(!heaps[v].empty()) {
                pq.emplace(d + heaps[v].top().first, heaps[v].copy());
            }
        }

        return ans;
    }
};


================================================
FILE: graph/eulerian_paths.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

// This implementation find cnt_odd_vertices / 2 eulerian paths that cover
// all edges of the graph. The way to use it is to create an object and
// incrementally add edges to it. Then, call find_paths() to get the paths.
// If the number of paths is 1, we have either a cycle or a path.
//
// Tested on:
// https://codeforces.com/problemsets/acmsguru/problem/99999/101
// https://codesprintla24.kattis.com/contests/codesprintla24open/problems/catbusplan

class EulerianPaths {
  private:
    void dfs(int u, vector<int>& path, vector<bool>& used, vector<int>& po) {
        for(; po[u] < (int)adj[u].size();) {
            int idx = po[u]++;
            if(!used[adj[u][idx].second >> 1]) {
                used[adj[u][idx].second >> 1] = true;
                dfs(adj[u][idx].first, path, used, po);
                path.push_back(adj[u][idx].second);
            }
        }
    }

  public:
    int n, m;
    vector<int> deg;
    vector<vector<pair<int, int>>> adj;
    vector<pair<int, int>> edges;

    EulerianPaths(int _n = 0) { init(_n); }

    void init(int _n) {
        n = _n;
        m = 0;
        adj.assign(n + 1, {});
        deg.assign(n + 1, 0);
        edges.clear();
    }

    int add_edge(int u, int v) {
        adj[u].push_back({v, m * 2});
        adj[v].push_back({u, m * 2 + 1});
        edges.push_back({u, v});
        deg[u]++;
        deg[v]++;
        m++;

        return edges.size() - 1;
    }

    vector<vector<int>> find_paths() {
        vector<bool> used(m, false);
        vector<int> po(n + 1, 0);

        vector<int> odd_vertices;
        for(int i = 0; i <= n; i++) {
            if(deg[i] % 2 == 1) {
                odd_vertices.push_back(i);
            }
        }

        int total_edges = m;
        for(int i = 0; i < (int)odd_vertices.size() / 2; i++) {
            int u = odd_vertices[2 * i], v = odd_vertices[2 * i + 1];
            adj[u].push_back({v, 2 * total_edges});
            adj[v].push_back({u, 2 * total_edges + 1});
            total_edges++;
            used.push_back(false);
            edges.push_back({u, v});
        }

        vector<vector<int>> paths;
        for(int u = 0; u <= n; u++) {
            if(!adj[u].empty()) {
                vector<int> path;
                dfs(u, path, used, po);
                if(!path.empty()) {
                    // Rotate the path so that we always start with a fake edge
                    // if there is at least one.
                    auto it = find_if(path.begin(), path.end(), [&](int x) {
                        return x >= 2 * m;
                    });
                    if(it != path.end()) {
                        rotate(path.begin(), it, path.end());
                    }

                    vector<int> current_path;
                    for(int x: path) {
                        if(x < 2 * m) {
                            current_path.push_back(x);
                        } else if(!current_path.empty()) {
                            paths.push_back(current_path);
                            current_path.clear();
                        }
                    }
                    if(!current_path.empty()) {
                        paths.push_back(current_path);
                    }
                }
            }
        }

        return paths;
    }

    pair<int, int> get_edge(int edge_i) {
        if(edge_i & 1) {
            return edges[edge_i >> 1];
        } else {
            return {edges[edge_i >> 1].second, edges[edge_i >> 1].first};
        }
    }

    vector<pair<int, int>> get_path_edges(const vector<int>& path) {
        vector<pair<int, int>> result;
        for(int edge_i: path) {
            result.push_back(get_edge(edge_i));
        }
        return result;
    }

    bool is_cycle(const vector<int>& path) {
        int start = get_edge(path[0]).first;
        int end = get_edge(path.back()).second;
        return start == end;
    }
};


================================================
FILE: graph/graph.hpp
================================================
#include <bits/stdc++.h>
#include <coding_library/graph/dsu.hpp>
using namespace std;

class UndirectedGraph {
  public:
    int n, m;
    vector<vector<int>> adj;
    vector<pair<int, int>> edges;

    bool maintain_dsu;
    DSU dsu;

    UndirectedGraph(int _n = 0, bool _maintain_dsu = false) {
        init(_n, _maintain_dsu);
    }

    void init(int _n, bool _maintain_dsu = false) {
        m = 0;
        n = _n;
        maintain_dsu = _maintain_dsu;
        adj.assign(n + 1, {});
        edges.clear();

        if(maintain_dsu) {
            dsu.init(n);
        }
    }

    void read_edges(int _m, int idx_offset = -1) {
        for(int i = 0; i < _m; i++) {
            int u, v;
            cin >> u >> v;
            u += idx_offset;
            v += idx_offset;
            add_edge(u, v);
        }
    }

    void add_edges(const vector<pair<int, int>>& new_edges) {
        for(auto [u, v]: new_edges) {
            add_edge(u, v);
        }
    }

    void add_edge(int u, int v) {
        adj[u].push_back(v);
        adj[v].push_back(u);
        edges.emplace_back(u, v);
        m++;

        if(maintain_dsu) {
            dsu.unite(u, v);
        }
    }

    DSU& get_dsu() {
        if(!maintain_dsu) {
            dsu.init(n);
            for(auto [u, v]: edges) {
                dsu.unite(u, v);
            }
        }

        return dsu;
    }
};


================================================
FILE: graph/hopcroft_karp.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

// Hopcroft-Karp algorithm for bipartite matching that runs in O(E sqrt(V)).
// Motivated by this submission: https://judge.yosupo.jp/submission/52112, but
// adapted to match coding_library/graph/bipartite_matching.cpp.

class HopcroftKarp {
  private:
    int n, m;
    vector<int> dist;

    bool bfs() {
        queue<int> q;
        dist.assign(n, -1);
        for(int u = 0; u < n; u++) {
            if(inv_match[u] == -1) {
                dist[u] = 0;
                q.push(u);
            }
        }

        bool found = false;
        while(!q.empty()) {
            int u = q.front();
            q.pop();
            for(int v: adj[u]) {
                int m = match[v];
                if(m == -1) {
                    found = true;
                } else if(dist[m] == -1) {
                    dist[m] = dist[u] + 1;
                    q.push(m);
                }
            }
        }

        return found;
    }

    bool dfs(int u) {
        for(int v: adj[u]) {
            int m = match[v];
            if(m == -1 || (dist[m] == dist[u] + 1 && dfs(m))) {
                inv_match[u] = v;
                match[v] = u;
                return true;
            }
        }
        dist[u] = -1;
        return false;
    }

  public:
    vector<int> match, inv_match;
    vector<vector<int>> adj;

    HopcroftKarp(int _n, int _m = -1) : n(_n), m(_m == -1 ? _n : _m) {
        adj.assign(n, vector<int>());
        clear(false);
    }

    void clear(bool clear_adj = true) {
        match.assign(m, -1);
        inv_match.assign(n, -1);
        if(clear_adj) {
            adj.assign(n, vector<int>());
        }
    }

    void add_edge(int u, int v) { adj[u].push_back(v); }

    int max_matching(bool shuffle_edges = false) {
        if(shuffle_edges) {
            for(int i = 0; i < n; i++) {
                shuffle(
                    adj[i].begin(), adj[i].end(),
                    mt19937(
                        chrono::steady_clock::now().time_since_epoch().count()
                    )
                );
            }
        }

        int ans = 0;
        while(bfs()) {
            for(int u = 0; u < n; u++) {
                if(inv_match[u] == -1 && dfs(u)) {
                    ans++;
                }
            }
        }
        return ans;
    }

    vector<pair<int, int>> get_matching() {
        vector<pair<int, int>> matches;
        for(int u = 0; u < n; u++) {
            if(inv_match[u] != -1) {
                matches.emplace_back(u, inv_match[u]);
            }
        }
        return matches;
    }

    pair<vector<int>, vector<int>> minimum_vertex_cover() {
        vector<int> left_cover, right_cover;
        bfs();

        for(int u = 0; u < n; u++) {
            if(dist[u] == -1) {
                left_cover.push_back(u);
            }
        }

        for(int v = 0; v < m; v++) {
            if(match[v] != -1 && dist[match[v]] != -1) {
                right_cover.push_back(v);
            }
        }

        return {left_cover, right_cover};
    }
};

using BipartiteMatching = HopcroftKarp;


================================================
FILE: graph/hungarian_algorithm.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

// Based on http://e-maxx.ru/algo/assignment_hungary#6 but wrapped in a class
// and zero-based indexing. Optimizes the assignment so that the cost is
// minimized. Also make sure that n <= m.

template<class T>
class HungarianAlgorithm {
  private:
    const T INF = numeric_limits<T>::max() / 2;
    vector<int> way;

  public:
    int n, m;
    vector<vector<T>> cost;
    vector<int> assignment;
    vector<T> pot_left, pot_right;

    HungarianAlgorithm(const vector<vector<T>>& a) {
        n = a.size();
        m = a[0].size();
        assert(n <= m);

        cost.assign(n + 1, vector<T>(m + 1));
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                cost[i][j] = a[i][j];
            }
        }

        pot_left.assign(n + 1, 0);
        pot_right.assign(m + 1, 0);
        assignment.assign(m + 1, n);
        way.assign(m + 1, m);

        for(int i = 0; i < n; i++) {
            assignment[m] = i;
            int j0 = m;
            vector<T> minv(m + 1, INF);
            vector<bool> used(m + 1, false);
            do {
                used[j0] = true;
                int i0 = assignment[j0], j1 = m;
                T delta = INF;
                for(int j = 0; j < m; j++) {
                    if(!used[j]) {
                        T cur = cost[i0][j] - pot_left[i0] - pot_right[j];
                        if(cur < minv[j]) {
                            minv[j] = cur;
                            way[j] = j0;
                        }
                        if(minv[j] < delta) {
                            delta = minv[j];
                            j1 = j;
                        }
                    }
                }
                for(int j = 0; j <= m; j++) {
                    if(used[j]) {
                        pot_left[assignment[j]] += delta;
                        pot_right[j] -= delta;
                    } else {
                        minv[j] -= delta;
                    }
                }
                j0 = j1;
            } while(assignment[j0] != n);

            do {
                int j1 = way[j0];
                assignment[j0] = assignment[j1];
                j0 = j1;
            } while(j0 != m);
        }
    }

    T get_cost() {
        T ans = 0;
        for(int j = 0; j < m; j++) {
            ans += cost[assignment[j]][j];
        }
        return ans;
    }
};


================================================
FILE: graph/maxflow.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

template<class T>
class MaxFlow {
  private:
    struct Edge {
        T flow, cap;
        int idx, rev, to;
        Edge(int _to, int _rev, T _flow, T _cap, int _idx)
            : to(_to), rev(_rev), flow(_flow), cap(_cap), idx(_idx) {}
    };

    vector<int> dist, po;
    int n;

    bool bfs(int s, int t) {
        fill(dist.begin(), dist.end(), -1);
        fill(po.begin(), po.end(), 0);

        queue<int> q;
        q.push(s);
        dist[s] = 0;

        while(!q.empty()) {
            int u = q.front();
            q.pop();

            for(Edge e: adj[u]) {
                if(dist[e.to] == -1 && e.flow < e.cap) {
                    dist[e.to] = dist[u] + 1;
                    q.push(e.to);
                }
            }
        }
        return dist[t] != -1;
    }

    T dfs(int u, int t, T fl = inf) {
        if(u == t) {
            return fl;
        }

        for(; po[u] < (int)adj[u].size(); po[u]++) {
            auto& e = adj[u][po[u]];
            if(dist[e.to] == dist[u] + 1 && e.flow < e.cap) {
                T f = dfs(e.to, t, min(fl, e.cap - e.flow));
                e.flow += f;
                adj[e.to][e.rev].flow -= f;
                if(f > 0) {
                    return f;
                }
            }
        }

        return 0;
    }

  public:
    constexpr static T inf = numeric_limits<T>::max();

    MaxFlow(int n = 0) { init(n); }

    vector<vector<Edge>> adj;

    void init(int _n) {
        n = _n;
        adj.assign(n + 1, {});
        dist.resize(n + 1);
        po.resize(n + 1);
    }

    void add_edge(int u, int v, T w, int idx = -1) {
        adj[u].push_back(Edge(v, adj[v].size(), 0, w, idx));
        adj[v].push_back(Edge(u, adj[u].size() - 1, 0, 0, -1));
    }

    T flow(int s, int t) {
        assert(s != t);

        T ret = 0, to_add;
        while(bfs(s, t)) {
            while((to_add = dfs(s, t))) {
                ret += to_add;
            }
        }

        return ret;
    }
};


================================================
FILE: graph/mincost_circulation.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

// In some rare cases, we might want to find the min cost circulation instead of
// min cost flow, and this is non-trivial in the presence of negative cycles (as
// we would like to select them up to their capacity). The two common approaches are 
// using cost scaling push relabel, or the network simplex. Some resources to check are:
//
//     - https://codeforces.com/blog/entry/104075?#comment-925064
//     - https://codeforces.com/blog/entry/57018
//     - https://codeforces.com/blog/entry/94190 (+ regular simplex)
//
// Here we use bicsi's implementation, based on brunovsky's blog (last one mentioned), which
// is fairly clean and works well (and it's easy to recover the answer).

template<typename T>
class MinCostCirculation {
  private:
    struct Edge {
        int from, to;
        T capacity, cost, flow;
        Edge(int _from, int _to, T _capacity, T _cost, T _flow = 0)
            : from(_from),
              to(_to),
              capacity(_capacity),
              cost(_cost),
              flow(_flow) {}
    };

    int n;
    vector<Edge> edges;
    vector<int> pei, depth;
    vector<T> dual;
    vector<set<int>> tree;

    void dfs(int node) {
        for(auto ei: tree[node]) {
            if(ei == pei[node]) {
                continue;
            }
            int vec = edges[ei].to;
            dual[vec] = dual[node] + edges[ei].cost;
            pei[vec] = (ei ^ 1);
            depth[vec] = 1 + depth[node];
            dfs(vec);
        }
    }

    template<typename CB>
    void walk(int ei, CB&& cb) {
        cb(ei);
        int a = edges[ei].from, b = edges[ei].to;
        while(a != b) {
            if(depth[a] > depth[b]) {
                cb(pei[a] ^ 1), a = edges[pei[a]].to;
            } else {
                cb(pei[b]), b = edges[pei[b]].to;
            }
        }
    }

  public:
    MinCostCirculation(int _n = 0) { init(_n); }

    void init(int _n) {
        n = _n;
        edges.clear();
        pei.assign(n + 1, -1);
        depth.assign(n + 1, 0);
        dual.assign(n + 1, 0);
        tree.assign(n + 1, set<int>());
    }

    int size() const { return n; }

    int add_edge(int from, int to, T capacity, T cost) {
        int id = edges.size();
        edges.push_back(Edge(from, to, capacity, cost, 0));
        edges.push_back(Edge(to, from, 0, -cost, 0));
        return id;
    }

    T min_circulation() {
        for(int i = 0; i < n; i++) {
            int ei = add_edge(n, i, 0, 0);
            tree[n].insert(ei);
            tree[i].insert(ei ^ 1);
        }

        T answer = 0;
        T flow;
        int cost, ein, eout, ptr = 0;
        const int B = 3 * n;
        for(int z = 0; z < (int)edges.size() / B + 1; z++) {
            if(!z) {
                dfs(n);
            }

            pair<T, int> pin = {0, -1};
            for(int t = 0; t < B; t++, (++ptr) %= (int)edges.size()) {
                auto& e = edges[ptr];
                if(e.flow < e.capacity) {
                    pin =
                        min(pin,
                            make_pair(dual[e.from] + e.cost - dual[e.to], ptr));
                }
            }

            tie(cost, ein) = pin;
            if(cost == 0) {
                continue;
            }

            pair<T, int> pout = {edges[ein].capacity - edges[ein].flow, ein};
            walk(ein, [&](int ei) {
                pout =
                    min(pout,
                        make_pair(edges[ei].capacity - edges[ei].flow, ei));
            });

            tie(flow, eout) = pout;
            walk(ein, [&](int ei) {
                edges[ei].flow += flow, edges[ei ^ 1].flow -= flow;
            });

            tree[edges[ein].from].insert(ein);
            tree[edges[ein].to].insert(ein ^ 1);
            tree[edges[eout].from].erase(eout);
            tree[edges[eout].to].erase(eout ^ 1);

            answer += flow * cost;
            z = -1;
        }
        return answer;
    }

    const Edge& get_edge(int id) const { return edges[id]; }
};


================================================
FILE: graph/mincost_flow.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

// Based on Ormlis' implementation

template<typename T>
class MinCostFlow {
  private:
    const static T inf = numeric_limits<T>::max();

    struct Edge {
        int to, rev;
        T capacity, cost, flow;
        Edge(int _to, int _rev, T _capacity, T _cost, T _flow)
            : to(_to),
              rev(_rev),
              capacity(_capacity),
              cost(_cost),
              flow(_flow) {}
    };

    int n;
    vector<vector<Edge>> g;
    vector<T> potential;
    vector<pair<int, int>> parent;
    vector<pair<T, T>> dist;

    void build_potential(int source) {
        fill(potential.begin(), potential.end(), inf);
        potential[source] = 0;

        while(true) {
            bool any = false;
            for(int v = 0; v < n; v++) {
                for(const auto& e: g[v]) {
                    if(e.capacity != 0 && potential[v] != inf &&
                       potential[v] + e.cost < potential[e.to]) {
                        potential[e.to] = potential[v] + e.cost;
                        any = true;
                    }
                }
            }
            if(!any) {
                break;
            }
        }
    }

    bool dijkstra(int source, int sink, T flow_limit, T flow) {
        fill(dist.begin(), dist.end(), make_pair(inf, flow_limit - flow));
        dist[source].first = 0;

        priority_queue<pair<T, int>, vector<pair<T, int>>, greater<>> q;
        q.push({0, source});

        while(!q.empty()) {
            auto [cur_dist, v] = q.top();
            q.pop();
            if(cur_dist > dist[v].first) {
                continue;
            }

            for(const auto& e: g[v]) {
                if(potential[e.to] != inf &&
                   cur_dist + e.cost - potential[e.to] + potential[v] <
                       dist[e.to].first &&
                   e.flow < e.capacity) {
                    parent[e.to] = {v, e.rev};
                    dist[e.to] = {
                        cur_dist + e.cost - potential[e.to] + potential[v],
                        min(dist[v].second, e.capacity - e.flow)
                    };
                    q.push({dist[e.to].first, e.to});
                }
            }
        }
        return dist[sink].first != inf;
    }

  public:
    MinCostFlow(int _n = 0) { init(_n); }

    void init(int _n) {
        n = _n;
        g.assign(n, {});
        potential.resize(n);
        parent.resize(n);
        dist.resize(n);
    }

    int size() const { return n; }

    int add_edge(int from, int to, T capacity, T cost) {
        int id = g[from].size();
        g[from].push_back(
            Edge(to, g[to].size() + (from == to), capacity, cost, 0)
        );
        g[to].push_back(Edge(from, id, 0, -cost, 0));
        return id;
    }

    pair<T, T> flow(int source, int sink, T flow_limit = inf) {
        for(int v = 0; v < n; v++) {
            for(auto& e: g[v]) {
                e.flow = 0;
            }
        }

        T cost = 0, flow = 0;
        build_potential(source);

        while(flow < flow_limit && dijkstra(source, sink, flow_limit, flow)) {
            T delta = dist[sink].second;
            flow += delta;

            for(int v = sink; v != source; v = parent[v].first) {
                auto& e = g[parent[v].first][g[v][parent[v].second].rev];
                cost += e.cost * delta;
                e.flow += delta;
                g[v][parent[v].second].flow -= delta;
            }

            for(int i = 0; i < n; i++) {
                if(dist[i].first != inf) {
                    potential[i] += dist[i].first;
                }
            }
        }
        return {cost, flow};
    }
};


================================================
FILE: graph/scc.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

class StronglyConnectedComponents {
  private:
    vector<bool> visited;

    void dfs1(int u) {
        visited[u] = true;
        for(int v: adj[u]) {
            if(!visited[v]) {
                dfs1(v);
            }
        }

        top_sort.push_back(u);
    }

    void dfs2(int u) {
        for(int v: radj[u]) {
            if(comp[v] == -1) {
                comp[v] = comp[u];
                dfs2(v);
            }
        }
    }

  public:
    int n;
    vector<vector<int>> adj, radj;
    vector<int> comp, comp_ids, top_sort;

    StronglyConnectedComponents() {}
    StronglyConnectedComponents(int _n) { init(_n); }

    void add_edge(int u, int v) {
        adj[u].push_back(v);
        radj[v].push_back(u);
    }

    void init(int _n) {
        n = _n;
        comp_ids.clear();
        top_sort.clear();
        adj.assign(n, {});
        radj.assign(n, {});
    }

    void find_components() {
        comp.assign(n, -1);
        visited.assign(n, false);

        for(int i = 0; i < n; i++) {
            if(!visited[i]) {
                dfs1(i);
            }
        }

        reverse(top_sort.begin(), top_sort.end());
        for(int u: top_sort) {
            if(comp[u] == -1) {
                comp[u] = (int)comp_ids.size();
                comp_ids.push_back(comp[u]);
                dfs2(u);
            }
        }
    }
};


================================================
FILE: graph/st_numbering.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

class STNumbering {
  private:
    vector<int> low, disc, par, sign;
    vector<int> preorder;
    int dfs_time;

    bool tarjan_check(int u, int pr) {
        low[u] = disc[u] = ++dfs_time;
        int child_cnt = 0;
        for(int v: adj[u]) {
            if(v != pr) {
                if(disc[v] == -1) {
                    child_cnt++;
                    if(!tarjan_check(v, u)) {
                        return false;
                    }
                    low[u] = min(low[u], low[v]);
                    if(pr != -1 && low[v] >= disc[u]) {
                        return false;
                    }
                } else {
                    low[u] = min(low[u], disc[v]);
                }
            }
        }
        if(pr == -1 && child_cnt > 1) {
            return false;
        }
        return true;
    }

    void tarjan(int u, int pr) {
        low[u] = disc[u] = ++dfs_time;
        for(int v: adj[u]) {
            if(v != pr) {
                if(disc[v] == -1) {
                    preorder.push_back(v);
                    tarjan(v, u);
                    low[u] = min(low[u], low[v]);
                    par[v] = u;
                } else {
                    low[u] = min(low[u], disc[v]);
                }
            }
        }
    }

  public:
    int n;
    vector<vector<int>> adj;
    vector<int> ordering;

    STNumbering() {}
    STNumbering(int _n) { init(_n); }

    void init(int _n) {
        n = _n;
        adj.assign(n, {});
        ordering.clear();
    }

    void add_edge(int u, int v) {
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    bool find_ordering(int s, int t) {
        low.assign(n, -1);
        disc.assign(n, -1);
        par.assign(n, -1);
        sign.assign(n, 0);
        preorder.clear();
        ordering.clear();
        dfs_time = 0;

        adj[s].push_back(t);
        adj[t].push_back(s);

        if(!tarjan_check(t, -1)) {
            adj[s].pop_back();
            adj[t].pop_back();
            return false;
        }

        for(int i = 0; i < n; i++) {
            if(disc[i] == -1) {
                adj[s].pop_back();
                adj[t].pop_back();
                return false;
            }
        }

        fill(low.begin(), low.end(), -1);
        fill(disc.begin(), disc.end(), -1);
        fill(sign.begin(), sign.end(), 0);
        preorder.clear();
        dfs_time = 0;

        disc[s] = low[s] = ++dfs_time;
        sign[disc[s]] = -1;
        tarjan(t, -1);

        list<int> st_li;
        vector<list<int>::iterator> it_ver(n + 1);

        st_li.push_back(s);
        st_li.push_back(t);
        it_ver[disc[s]] = st_li.begin();
        it_ver[disc[t]] = next(st_li.begin());

        for(int v: preorder) {
            if(sign[low[v]] == -1) {
                it_ver[disc[v]] = st_li.insert(it_ver[disc[par[v]]], v);
            } else {
                it_ver[disc[v]] = st_li.insert(next(it_ver[disc[par[v]]]), v);
            }
            sign[disc[par[v]]] = -sign[low[v]];
        }

        ordering.assign(st_li.begin(), st_li.end());
        adj[s].pop_back();
        adj[t].pop_back();
        return true;
    }
};


================================================
FILE: graph/two_sat.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

class TwoSat {
  private:
    vector<bool> visited;

    void dfs1(int u) {
        visited[u] = true;
        for(int v: adj[u]) {
            if(!visited[v]) {
                dfs1(v);
            }
        }

        top_sort.push_back(u);
    }

    void dfs2(int u) {
        for(int v: radj[u]) {
            if(comp[v] == -1) {
                comp[v] = comp[u];
                dfs2(v);
            }
        }
    }

  public:
    int n;
    vector<vector<int>> adj, radj;
    vector<int> comp, comp_ids, top_sort;

    TwoSat() {}
    TwoSat(int _n) { init(_n); }

    void init(int _n) {
        n = _n;
        comp_ids.clear();
        top_sort.clear();
        adj.assign(2 * n, {});
        radj.assign(2 * n, {});
    }

    void add_implication(int u, int v, bool neg_u = false, bool neg_v = false) {
        adj[u << 1 | neg_u].push_back(v << 1 | neg_v);
        radj[v << 1 | neg_v].push_back(u << 1 | neg_u);
    }

    pair<bool, vector<bool>> solve() {
        comp.assign(2 * n, -1);
        visited.assign(2 * n, false);

        for(int i = 0; i < 2 * n; i++) {
            if(!visited[i]) {
                dfs1(i);
            }
        }

        reverse(top_sort.begin(), top_sort.end());
        for(int u: top_sort) {
            if(comp[u] == -1) {
                comp[u] = (int)comp_ids.size();
                comp_ids.push_back(comp[u]);
                dfs2(u);
            }
        }

        vector<bool> assignment(n);
        for(int i = 0; i < n; i++) {
            if(comp[i << 1] == comp[i << 1 | 1]) {
                return {false, {}};
            }

            assignment[i] = comp[i << 1] > comp[i << 1 | 1];
        }

        return {true, assignment};
    }
};


================================================
FILE: math/gauss_bitset.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

template<size_t N>
class GaussBitset {
  public:
    int n_var;
    vector<bitset<N + 1>> rows;
    vector<int> where;
    bool solvable = false;

    GaussBitset(int n_var_) : n_var(n_var_) {}

    void add_equation(const vector<int>& coeffs, int rhs) {
        bitset<N + 1> row;
        for(int i = 0; i < n_var; i++) {
            if(coeffs[i] % 2) {
                row[i] = 1;
            }
        }
        row[n_var] = rhs % 2;
        rows.push_back(row);
    }

    void eliminate() {
        int n_eq = (int)rows.size();
        where.assign(n_var, -1);
        int row = 0;
        for(int col = 0; col < n_var && row < n_eq; col++) {
            int sel = -1;
            for(int i = row; i < n_eq; i++) {
                if(rows[i][col]) {
                    sel = i;
                    break;
                }
            }
            if(sel == -1) {
                continue;
            }
            swap(rows[sel], rows[row]);
            where[col] = row;
            for(int i = 0; i < n_eq; i++) {
                if(i != row && rows[i][col]) {
                    rows[i] ^= rows[row];
                }
            }
            row++;
        }
        solvable = true;
        for(int i = row; i < n_eq; i++) {
            if(rows[i][n_var]) {
                solvable = false;
                break;
            }
        }
    }

    bool has_solution() const { return solvable; }

    vector<int> free_variables() const {
        vector<int> fv;
        for(int v = 0; v < n_var; v++) {
            if(where[v] == -1) {
                fv.push_back(v);
            }
        }
        return fv;
    }

    vector<int> any_solution() const {
        vector<int> x(n_var, 0);
        for(int v = 0; v < n_var; v++) {
            if(where[v] != -1) {
                x[v] = rows[where[v]][n_var];
            }
        }
        return x;
    }
};


================================================
FILE: old_impl/data_structures/implicit_treap.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

random_device rd;
mt19937 mt(rd());

struct implicit_treap {
    struct node {
        int val, sz, priority, lazy, rev, sum;
        node *l, *r, *par;

        node() {
            lazy = 0;
            rev = 0;
            val = 0;
            sz = 0;
            priority = 0;
            l = NULL;
            r = NULL;
            par = NULL;
        }
        node(int _val) {
            val = _val;
            sum = _val;
            rev = 0;
            lazy = 0;
            sz = 1;
            priority = mt();

            l = NULL;
            r = NULL;
            par = NULL;
        }
    };

    typedef node *pnode;

    pnode root;
    map<int, pnode> position;

    void clear() {
        root = NULL;
        position.clear();
    }

    implicit_treap() { clear(); }

    int size(pnode p) { return p ? p->sz : 0; }
    void update_size(pnode &p) {
        if(p) {
            p->sz = size(p->l) + size(p->r) + 1;
        }
    }

    void update_parent(pnode &p) {
        if(!p) {
            return;
        }
        if(p->l) {
            p->l->par = p;
        }
        if(p->r) {
            p->r->par = p;
        }
    }

    void push(pnode &p) {
        if(!p) {
            return;
        }
        p->sum += size(p) * p->lazy;
        p->val += p->lazy;

        if(p->rev) {
            swap(p->l, p->r);
        }

        if(p->l) {
            p->l->lazy += p->lazy;
            p->l->rev ^= p->rev;
        }
        if(p->r) {
            p->r->lazy += p->lazy;
            p->r->rev ^= p->rev;
        }

        p->lazy = 0;
        p->rev = 0;
    }

    void reset(pnode &t) {
        if(t) {
            t->sum = t->val;
        }
    }

    void combine(pnode &t, pnode l, pnode r) {
        if(!l) {
            t = r;
            return;
        }
        if(!r) {
            t = l;
            return;
        }
        t->sum = l->sum + r->sum;
    }

    void operation(pnode &t) {
        if(!t) {
            return;
        }

        reset(t);
        push(t->l);
        push(t->r);

        combine(t, t->l, t);
        combine(t, t, t->r);
    }

    void split(pnode t, pnode &l, pnode &r, int k, int add = 0) {
        if(t == NULL) {
            l = NULL;
            r = NULL;
            return;
        }
        push(t);

        int idx = add + size(t->l);
        if(idx <= k) {
            split(t->r, t->r, r, k, idx + 1), l = t;
        } else {
            split(t->l, l, t->l, k, add), r = t;
        }

        update_parent(t);
        update_size(t);
        operation(t);
    }

    void merge(pnode &t, pnode l, pnode r) {
        push(l);
        push(r);

        if(!l) {
            t = r;
            return;
        }
        if(!r) {
            t = l;
            return;
        }

        if(l->priority > r->priority) {
            merge(l->r, l->r, r), t = l;
        } else {
            merge(r->l, l, r->l), t = r;
        }

        update_parent(t);
        update_size(t);
        operation(t);
    }

    void insert(int pos, int val) {
        if(root == NULL) {
            pnode to_add = new node(val);
            root = to_add;
            position[val] = root;
            return;
        }

        pnode l, r, mid;
        mid = new node(val);
        position[val] = mid;

        split(root, l, r, pos - 1);
        merge(l, l, mid);
        merge(root, l, r);
    }

    void erase(int qL, int qR) {
        pnode l, r, mid;

        split(root, l, r, qL - 1);
        split(r, mid, r, qR - qL);
        merge(root, l, r);
    }

    int query(int qL, int qR) {
        pnode l, r, mid;

        split(root, l, r, qL - 1);
        split(r, mid, r, qR - qL);

        int answer = mid->sum;

        merge(r, mid, r);
        merge(root, l, r);

        return answer;
    }

    void update(int qL, int qR, int val) {
        pnode l, r, mid;

        split(root, l, r, qL - 1);
        split(r, mid, r, qR - qL);

        mid->lazy += val;

        merge(r, mid, r);
        merge(root, l, r);
    }

    void reverse(int qL, int qR) {
        pnode l, r, mid;

        split(root, l, r, qL - 1);
        split(r, mid, r, qR - qL);

        mid->rev ^= 1;
        merge(r, mid, r);
        merge(root, l, r);
    }

    void cyclic_shift(int qL, int qR, int k) {
        if(qL == qR) {
            return;
        }
        k %= (qR - qL + 1);

        pnode l, r, mid, fh, sh;
        split(root, l, r, qL - 1);
        split(r, mid, r, qR - qL);

        split(mid, fh, sh, (qR - qL + 1) - k - 1);
        merge(mid, sh, fh);

        merge(r, mid, r);
        merge(root, l, r);
    }

    int get_pos(pnode curr, pnode son = nullptr) {
        if(!son) {
            if(curr == root) {
                return size(curr->l);
            } else {
                return size(curr->l) + get_pos(curr->par, curr);
            }
        }

        if(curr == root) {
            if(son == curr->l) {
                return 0;
            } else {
                return size(curr->l) + 1;
            }
        }

        if(curr->l == son) {
            return get_pos(curr->par, curr);
        } else {
            return get_pos(curr->par, curr) + size(curr->l) + 1;
        }
    }

    int get_pos(int value) { return get_pos(position[value]); }
};

implicit_treap build(const vector<int> &a) {
    implicit_treap t;
    t.clear();
    for(int i = 0; i < (int)a.size(); i++) {
        t.insert(i, a[i]);
    }

    return t;
}


================================================
FILE: old_impl/data_structures/implicit_treap_basic.hpp
================================================
#include <bits/stdc++.h>
using namespace std;

random_device rd;
mt19937 mt(rd());

struct implicit_treap {
    struct node {
        int sz, mx, val, prior;
        node *l, *r;
        node() {
            sz = 0;
            mx = 0;
            val = 0;
            prior = 0;
            l = nullptr;
            r = nullptr;
        }
        node(int _val) {
            val = _val;
            mx = val;
            sz = 1;
            prior = mt();
            l = nullptr;
            r = nullptr;
        }
    };

    typedef node *pnode;

    int size(pnode v) { return v ? v->sz : 0; }
    void update_size(pnode &v) {
        if(v) {
            v->sz = size(v->l) + size(v->r) + 1;
        }
    }
    void reset(pnode &v) {
        if(v) {
            v->mx = v->val;
        }
    }

    void combine(pnode &v, pnode l, pnode r) {
        if(!l) {
            v = r;
            return;
        }
        if(!r) {
            v = l;
            return;
        }

        v->mx = max(l->mx, r->mx);
    }

    void operation(pnode &v) {
        if(!v) {
            return;
        }

        reset(v);
        combine(v, v->l, v);
        combine(v, v, v->r);
    }

    void merge(pnode &t, pnode l, pnode r) {
        if(!l) {
            t = r;
            return;
        }
        if(!r) {
            t = l;
            return;
        }

        if(l->prior > r->prior) {
            merge(l->r, l->r, r), t = l;
        } else {
            merge(r->l, l, r->l), t = r;
        }

        update_size(t);
        operation(t);
    }

    void split(pnode t, pnode &l, pnode &r, int k, int add = 0) {
        if(!t) {
            l = nullptr;
            r = nullptr;
            return;
        }

        int idx = add + size(t->l);
        if(idx <= k) {
            split(t->r, t->r, r, k, idx + 1), l = t;
        } else {
            split(t->l, l, t->l, k, add), r = t;
        }

        update_size(t);
        operation(t);
    }

    pnode root;
    implicit_treap() { root = nullptr; }

    void insert(int pos, int val) {
        if(!root) {
            pnode nw = new node(val);
            root = nw;
            return;
        }

        pnode l, r, nw = new node(val);

        split(root, l, r, pos - 1);
        merge(l, l, nw);
        merge(root, l, r);
    }

    int query_max(int qL, int qR) {
        pnode l, r, mid;

        split(root, l, r, qL - 1);
        split(r, mid, r, qR - qL);

        int ret = mid ? mid->mx : -1;

        merge(r, mid, r);
        merge(root, l, r);

        return ret;
    }
};


================================================
FILE: old_impl/data_structures/max_count_segment_tree.cpp
================================================
#include <bits/stdc++.h>
using namespace std;
const int MAXN = (1 << 20);

struct count_max_segment_tree {
    struct node {
        int mx, cnt, lazy;
        node() { mx = -(int)1e9, cnt = 0, lazy = 0; }
        node(int v) {
            mx = v;
            cnt = 1;
            lazy = 0;
        }
    };

    node merge(node a, node b) {
        node ret = node();
        ret.mx = max(a.mx, b.mx);

        ret.cnt = 0;
        if(ret.mx == a.mx) {
            ret.cnt += a.cnt;
        }
        if(ret.mx == b.mx) {
            ret.cnt += b.cnt;
        }

        return ret;
    }

    node tr[MAXN << 2];

    void push(int l, int r, int idx) {
        if(tr[idx].lazy) {
            tr[idx].mx += tr[idx].lazy;
            if(l != r) {
                tr[2 * idx + 1].lazy += tr[idx].lazy;
                tr[2 * idx + 2].lazy += tr[idx].lazy;
            }
            tr[idx].lazy = 0;
        }
    }

    void init(int l, int r, int idx) {
        if(l == r) {
            tr[idx] = node(-l);
            return;
        }

        int mid = (l + r) >> 1;
        init(l, mid, 2 * idx + 1);
        init(mid + 1, r, 2 * idx + 2);

        tr[idx] = merge(tr[2 * idx + 1], tr[2 * idx + 2]);
    }

    void add(int ql, int qr, int v, int l, int r, int idx) {
        push(l, r, idx);

        if(qr < l || ql > r) {
            return;
        }

        if(ql <= l && r <= qr) {
            tr[idx].lazy += v;
            push(l, r, idx);
            return;
        }

        int mid = (l + r) >> 1;
        add(ql, qr, v, l, mid, 2 * idx + 1);
        add(ql, qr, v, mid + 1, r, 2 * idx + 2);

        tr[idx] = merge(tr[2 * idx + 1], tr[2 * idx + 2]);
    }

    node query(int ql, int qr, int l, int r, int idx) {
        push(l, r, idx);

        if(qr < l || ql > r) {
            return node();
        }

        if(ql <= l && r <= qr) {
            return tr[idx];
        }

        int mid = (l + r) >> 1;
        return merge(
            query(ql, qr, l, mid, 2 * idx + 1),
            query(ql, qr, mid + 1, r, 2 * idx + 2)
        );
    }

    void walk(int l, int r, int idx) {
        push(l, r, idx);

        if(l == r) {
            cout << l << ": "
                 << "{" << tr[idx].mx << " " << tr[idx].cnt
                 << " lazy=" << tr[idx].lazy << "}"
                 << " ";
            return;
        }

        int mid = (l + r) >> 1;
        walk(l, mid, 2 * idx + 1);
        walk(mid + 1, r, 2 * idx + 2);

        tr[idx] = merge(tr[2 * idx + 1], tr[2 * idx + 2]);
    }
};


================================================
FILE: old_impl/data_structures/merging_segment_tree.cpp
================================================
#include <bits/stdc++.h>
using namespace std;

struct node {
    int sz;
    node *l, *r;

    node() {
        sz = 0;
        l = r = nullptr;
    }
    node(int _s) {
        sz = _s;
        l = r = nullptr;
    }
};

typedef node *pnode;

inline int size(pnode p) { return p ? p->sz : 0; }

inline void update_size(pnode &p) {
    if(!p) {
        return;
    }
    p->sz = 1 + size(p->l) + size(p->r);
}

pnode init(int val, int l, int r) {
    pnode ret = new node(1);
    if(l == r) {
        return ret;
    }

    int mid = (l + r) >> 1;
    if(val <= mid) {
        ret->l = init(val, l, mid);
    } else {
        ret->r = init(val, mid + 1, r);
    }

    return ret;
}

pnode merge(pnode l, pnode r) {
    if(!l) {
        return r;
    }
    if(!r) {
        return l;
    }

    l->l = merge(l->l, r->l);
    l->r = merge(l->r, r->r);
    l->sz += r->sz;

    return l;
}

pair<pnode, pnode> split(pnode &t, int k) {
    if(!t) {
        return {nullptr, nullptr};
    }

    pair<pnode, pnode> ret, tmp;
    ret.second = new node();

    int L = size(t->l);
    if(L < k) {
        tmp = split(t->r, k - L);
        ret.second = tmp.second;
        ret.first = t;
        ret.first->r = tmp.first;
    } else {
        tmp = split(t->l, k);
        ret.first = tmp.first;
        ret.second = t;
        ret.second->l = tmp.second;
    }

    update_size(ret.first);
    update_size(ret.second);
    return ret;
}

int kth(pnode t, int k, int l, int r) {
    if(!t) {
        return -1;
    }
    if(l == r) {
        return l;
    }

    int mid = (l + r) >> 1, L = size(t->l);
    if(L < k) {
        return kth(t->r, k - L, l, mid);
    } else {
        return kth(t->l, k, mid + 1, r);
    }
}


================================================
FILE: old_impl/data_structures/min_segment_tree.cpp
================================================
#include <bits/stdc++.h>
#define endl '\n'

#define SZ(x) ((int)x.size())
#define ALL(V) V.begin(), V.end()
#define L_B lower_bound
#define U_B upper_bound
#define pb push_back

using namespace std;
template<class T, class T1> int chkmin(T &x, const T1 &y) { return x > y ? x = y, 1 : 0; }
template<class T, class T1> int chkmax(T &x, const T1 &y) { return x < y ? x = y, 1 : 0; }
const int MAXN = (1 << 20);

struct segment_tree_min {
	struct node {
		int mn, pos;
		node() {
			mn = (int)1e9;
			pos = -1;
		} 

		node(int v, int i) {
			mn = v;
			pos = i;
		}
	};

	node merge(node a, node b) {
		node ret = a;
		if(chkmin(ret.mn, b.mn)) ret.pos = b.pos;
		return ret;
	}

	node tr[MAXN << 2];

	void init(int l, int r, int idx) {
		if(l == r) {
			tr[idx] = node();
			return;
		}

		int mid = (l + r) >> 1;
		init(l, mid, 2 * idx + 1);
		init(mid + 1, r, 2 * idx + 2);
		tr[idx] = merge(tr[2 * idx + 1], tr[2 * idx + 2]);
	}

	void update(int pos, int v, int l, int r, int idx) {
		if(l == r) {
			tr[idx] = node(v, pos);
			return;
		}

		int mid = (l + r) >> 1;
		if(pos <= mid) update(pos, v, l, mid, 2 * idx + 1);
		else update(pos, v, mid + 1, r, 2 * idx + 2);
		tr[idx] = merge(tr[2 * idx + 1], tr[2 * idx + 2]);
	}

	node query(int ql, int qr, int l, int r, int idx) {
		if(ql > r || qr < l) {
			return node();
		} 

		if(ql <= l && r <= qr) {
			return tr[idx];
		}

		int mid = (l + r) >> 1;
		return merge(query(ql, qr, l, mid, 2 * idx + 1),
				query(ql, qr, mid + 1, r, 2 * idx + 2));
	}
};

void read() {

}

void solve() {

}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);

	read();
	solve();
	return 0;
}



================================================
FILE: old_impl/data_structures/monotonous_queue.cpp
================================================
#include <bits/stdc++.h>
#define endl '\n'

using namespace std;
template<class T, class T2> inline void chkmax(T &x, const T2 &y) { if(x < y) x = y; }
template<class T, class T2> inline void chkmin(T &x, const T2 &y) { if(x > y) x = y; }
const int MAXN = (1 << 20);

template<class T>
struct monotonous_queue_max
{
	int len, current_position;
	deque<pair<T, int> > Q;

	monotonous_queue_max() { Q.clear(); current_position = 0; len = 0; }

	void init(int _l)
	{
		len = _l;
		current_position = 0;
		Q.clear();
	}

	void push_back(T x)
	{
		while(!Q.empty() && current_position - Q.front().second >= len) Q.pop_front();
		while(!Q.empty() && x >= Q.back().first) Q.pop_back();
		Q.push_back({x, current_position++});
	}

	T query()
	{
		if(Q.empty()) return -(T)1e9;
		return Q.front().first;
	}
};

template<class T>
struct monotonous_queue_min
{
	int len, current_position;
	deque<pair<T, int> > Q;

	monotonous_queue_min() { Q.clear(); current_position = 0; len = 0; }

	void init(int _l)
	{
		len = _l;
		current_position = 0;
		Q.clear();
	}

	void push_back(T x)
	{
		while(!Q.empty() && current_position - Q.front().second >= len) Q.pop_front();
		while(!Q.empty() && x <= Q.back().first) Q.pop_back();
		Q.push_back({x, current_position++});
	}

	T query()
	{
		if(Q.empty()) return (T)1e9;
		return Q.front().first;
	}
};

void read()
{

}

void solve()
{

}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	read();
	solve();
	return 0;
}



================================================
FILE: old_impl/data_structures/persistent_segment_tree.cpp
================================================
#include <bits/stdc++.h>
#define endl '\n'

using namespace std;
const int MAXN = (1 << 20);

struct node {
    int sum;
    node *l, *r;
    node() {
        l = nullptr;
        r = nullptr;
        sum = 0;
    }
    node(int x) {
        sum = x;
        l = nullptr;
        r = nullptr;
    }
};

node* merge(node* l, node* r) {
    node* ret = new node(0);
    ret->sum = l->sum + r->sum;
    ret->l = l;
    ret->r = r;
    return ret;
}

node* init(int l, int r) {
    if(l == r) {
        return (new node(0));
    }

    int mid = (l + r) >> 1;
    return merge(init(l, mid), init(mid + 1, r));
}

node* update(int pos, int val, int l, int r, node* nd) {
    if(pos < l || pos > r) {
        return nd;
    }
    if(l == r) {
        return (new node(val));
    }

    int mid = (l + r) >> 1;
    return merge(
        update(pos, val, l, mid, nd->l), update(pos, val, mid + 1, r, nd->r)
    );
}

int query(int qL, int qR, int l, int r, node* nd) {
    if(qL <= l && r <= qR) {
        return nd->sum;
    }
    if(qL > r || qR < l) {
        return 0;
    }

    int mid = (l + r) >> 1;
    return query(qL, qR, l, mid, nd->l) + query(qL, qR, mid + 1, r, nd->r);
}

int get_kth(int k, int l, int r, node* nd) {
    if(l == r) {
        return l;
    }

    int mid = (l + r) >> 1;
    if(nd->l->sum < k) {
        return get_kth(k - nd->l->sum, mid + 1, r, nd->r);
    } else {
        return get_kth(k, l, mid, nd->l);
    }
}

void read() {}

node* t[MAXN];

void solve() {}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    read();
    solve();
    return 0;
}


================================================
FILE: old_impl/data_structures/persistent_segment_tree_lazy.cpp
================================================
#include <bits/stdc++.h>
#define endl '\n'

using namespace std;
template<class T, class T2>
inline void chkmax(T &x, const T2 &y) {
    if(x < y) {
        x = y;
    }
}
template<class T, class T2>
inline void chkmin(T &x, const T2 &y) {
    if(x > y) {
        x = y;
    }
}
const int MAXN = (1 << 20);

int n, q;
int a[MAXN];

struct node {
    int64_t lazy, sum;
    node *l, *r;

    node() {
        lazy = sum = 0;
        l = r = nullptr;
    }
    node(int64_t val) {
        lazy = 0;
        sum = val;
        l = r = nullptr;
    }
};

typedef node *pnode;

pnode merge(pnode a, pnode b) {
    pnode ret = new node();

    ret->sum = a->sum + b->sum;
    ret->l = a;
    ret->r = b;

    return ret;
}

pnode cop(pnode b) {
    if(!b) {
        return nullptr;
    }

    pnode ret = new node();
    ret->sum = b->sum;
    ret->lazy = b->lazy;

    ret->l = b->l;
    ret->r = b->r;
    return ret;
}

void push(int l, int r, pnode &ver) {
    if(!ver->lazy) {
        return;
    }

    ver->sum += (r - l + 1) * 1ll * ver->lazy;

    ver->l = cop(ver->l);
    ver->r = cop(ver->r);

    if(l != r) {
        ver->l->lazy += ver->lazy;
        ver->r->lazy += ver->lazy;
    }

    ver->lazy = 0;
}

pnode init(int l, int r) {
    if(l == r) {
        return new node(a[l]);
    }
    int mid = (l + r) >> 1;
    return merge(init(l, mid), init(mid + 1, r));
}

pnode update(int qL, int qR, int val, int l, int r, pnode prv) {
    push(l, r, prv);

    if(qL <= l && r <= qR) {
        pnode ret = cop(prv);
        ret->lazy += val;
        push(l, r, ret);
        return ret;
    }

    if(qL > r || qR < l) {
        return prv;
    }

    int mid = (l + r) >> 1;
    return merge(
        update(qL, qR, val, l, mid, prv->l),
        update(qL, qR, val, mid + 1, r, prv->r)
    );
}

int64_t query(int qL, int qR, int l, int r, pnode nd) {
    push(l, r, nd);
    if(qL > r || qR < l) {
        return 0;
    }
    if(qL <= l && r <= qR) {
        return nd->sum;
    }

    int mid = (l + r) >> 1;
    return query(qL, qR, l, mid, nd->l) + query(qL, qR, mid + 1, r, nd->r);
}

void read() {
    cin >> n >> q;
    for(int i = 0; i < n; i++) {
        cin >> a[i];
    }
}

pnode root[MAXN];

void solve() { root[1] = init(0, n - 1); }

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    read();
    solve();
    return 0;
}


================================================
FILE: old_impl/data_structures/persistent_treap.cpp
================================================
#include <bits/stdc++.h>
#define endl '\n'

using namespace std;
const int MAXN = (1 << 20);

random_device rd;
mt19937 mt(rd());

struct persistent_treap
{
	struct node
	{
		int sz, mx, val;		
		node *l, *r;
		node() { sz = 0; mx = 0; val = 0; l = nullptr; r = nullptr; }
		node(int _val) { val = _val; mx = val; sz = 1; l = nullptr; r = nullptr; }
	};

	typedef node* pnode;

	pnode copy_node(pnode prv)
	{
		if(!prv) return nullptr;

		pnode ret = new node();
		ret->l = prv->l;
		ret->r = prv->r;
		ret->val = prv->val;
		ret->sz = prv->sz;
		ret->mx = prv->mx;
		return ret;
	}

	int size(pnode v) { return v ? v->sz : 0; }
	void update_size(pnode &v) { if(v) v->sz = size(v->l) + size(v->r) + 1; }
	void reset(pnode &v) { if(v) v->mx = v->val; }
	bool hey(int a, int b) { return (int)mt() % (a + b) < a; }

	void combine(pnode &v, pnode l, pnode r) 
	{
		if(!l) { v = r; return; }
		if(!r) { v = l; return; }

		v->mx = max(l->mx, r->mx);
	}

	void operation(pnode &v) 
	{  
		if(!v) return;

		reset(v);
		combine(v, v->l, v);
		combine(v, v, v->r);
	}

	void merge(pnode &t, pnode l, pnode r)
	{	
		if(!l) { t = copy_node(r); return; }
		if(!r) { t = copy_node(l); return; }

		if(hey(size(l), size(r)))
		{
			t = copy_node(l);
			merge(t->r, l->r, r);
		}
		else	
		{
			t = copy_node(r);
			merge(t->l, l, r->l);
		}

		update_size(t);
		operation(t);
	}

	void split(pnode t, pnode &l, pnode &r, int k, int add = 0)
	{
		if(!t) { l = nullptr; r = nullptr; return; }

		int idx = add + size(t->l);
		if(idx <= k)
		{
			l = copy_node(t);
			split(t->r, l->r, r, k, idx + 1);
			update_size(l);
			operation(l);
		}
		else
		{
			r = copy_node(t);
			split(t->l, l, r->l, k, add);
			update_size(r);
			operation(r);
		}

		update_size(t);
		operation(t);
	}

	pnode root;
	persistent_treap() { root = nullptr; }

	void insert(int pos, int val)
	{
		if(!root)
		{
			pnode nw = new node(val);
			root = nw;
			return;
		}

		pnode l, r, nw = new node(val);

		split(root, l, r, pos - 1);
		merge(l, l, nw);
		merge(root, l, r);
	}

	int query_max(int qL, int qR)
	{
		pnode l, r, mid;

		split(root, l, r, qL - 1);
		split(r, mid, r, qR - qL);

		int ret = mid ? mid->mx : -1;

		merge(r, mid, r);
		merge(root, l, r);

		return ret;
	}
};


void read()
{

}

void solve()
{

}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	read();
	solve();
	return 0;
}



================================================
FILE: old_impl/data_structures/persistent_treap_lazy.cpp
================================================
#include <bits/stdc++.h>
#define endl '\n'

using namespace std;
const int MAXN = (1 << 20);

random_device rd;
mt19937 mt(rd());

struct persistent_treap
{
	struct node
	{
		int sz, mx, val, lazy;		
		node *l, *r;
		node() { sz = 0; mx = 0; lazy = 0; val = 0; l = nullptr; r = nullptr; }
		node(int _val) { lazy = 0; val = _val; mx = val; sz = 1; l = nullptr; r = nullptr; }
	};

	typedef node* pnode;

	pnode copy_node(pnode prv)
	{
		if(!prv) return nullptr;

		pnode ret = new node();
		ret->l = prv->l;
		ret->r = prv->r;
		ret->val = prv->val;
		ret->sz = prv->sz;
		ret->mx = prv->mx;
		ret->lazy = prv->lazy;
		return ret;
	}

	int size(pnode v) { return v ? v->sz : 0; }
	void update_size(pnode &v) { if(v) v->sz = size(v->l) + size(v->r) + 1; }
	void reset(pnode &v) { if(v) v->mx = v->val; }
	bool hey(int a, int b) { return (int)mt() % (a + b) < a; }

	void push(pnode &t)
	{
		if(t && t->lazy)
		{
			t->mx += t->lazy;
			t->val += t->lazy;
			if(t->l) t->l = copy_node(t->l), t->l->lazy += t->lazy;
			if(t->r) t->r = copy_node(t->r), t->r->lazy += t->lazy;
			t->lazy = 0;
		}
	}

	void combine(pnode &v, pnode l, pnode r) 
	{
		if(!l) { v = r; return; }
		if(!r) { v = l; return; }

		v->mx = max(l->mx, r->mx);
	}

	void operation(pnode &v) 
	{  
		if(!v) return;

		push(v->l);
		push(v->r);

		reset(v);
		combine(v, v->l, v);
		combine(v, v, v->r);
	}

	void merge(pnode &t, pnode l, pnode r)
	{	
		push(l), push(r);

		if(!l) { t = copy_node(r); return; }
		if(!r) { t = copy_node(l); return; }

		if(hey(size(l), size(r)))
		{
			t = copy_node(l);
			merge(t->r, l->r, r);
		}
		else	
		{
			t = copy_node(r);
			merge(t->l, l, r->l);
		}

		update_size(t);
		operation(t);
	}

	void split(pnode t, pnode &l, pnode &r, int k, int add = 0)
	{
		push(t);

		if(!t) { l = nullptr; r = nullptr; return; }

		int idx = add + size(t->l);
		if(idx <= k)
		{
			l = copy_node(t);
			split(t->r, l->r, r, k, idx + 1);
			update_size(l);
			operation(l);
		}
		else
		{
			r = copy_node(t);
			split(t->l, l, r->l, k, add);
			update_size(r);
			operation(r);
		}

		update_size(t);
		operation(t);
	}

	pnode root;
	persistent_treap() { root = nullptr; }

	void insert(int pos, int val)
	{
		if(!root)
		{
			pnode nw = new node(val);
			root = nw;
			return;
		}

		pnode l, r, nw = new node(val);

		split(root, l, r, pos - 1);
		merge(l, l, nw);
		merge(root, l, r);
	}

	int query_max(int qL, int qR)
	{
		pnode l, r, mid;

		split(root, l, r, qL - 1);
		split(r, mid, r, qR - qL);

		int ret = mid ? mid->mx : -1;

		merge(r, mid, r);
		merge(root, l, r);

		return ret;
	}
};


void read()
{

}

void solve()
{

}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	read();
	solve();
	return 0;
}



================================================
FILE: old_impl/data_structures/segment_tree.cpp
================================================
#include <bits/stdc++.h>
#define endl '\n'

using namespace std;
const int MAXN = (1 << 18);

int n, m;
int a[MAXN];

struct node {
	int sum;
	node() { sum = 0; }
	node(int val) {
		sum = val;
	}
};

node merge(node l, node r) {
	node temp;
	temp.sum = l.sum + r.sum;
	return temp;
}

struct segment_tree {
	node tr[MAXN << 2];

	void init(int l, int r, int idx) {
		if(l == r) {
			tr[idx] = node(a[l]);
			return;
		}

		int mid = (l + r) >> 1;
		init(l, mid, 2 * idx + 1);
		init(mid + 1, r, 2 * idx + 2);

		tr[idx] = merge(tr[2 * idx + 1], tr[2 * idx + 2]);
	}

	void update(int pos, int val, int l, int r, int idx) {
		if(l > pos || r < pos)
			return;

		if(l == r && l == pos) {
			tr[idx].sum += val;
			return;
		}

		int mid = (l + r) >> 1;
		update(pos, val, l, mid, 2 * idx + 1);
		update(pos, val, mid + 1, r, 2 * idx + 2);

		tr[idx] = merge(tr[2 * idx + 1], tr[2 * idx + 2]);
	}

	node query(int qL, int qR, int l, int r, int idx) {
		if(l > qR || r < qL) {
			return node();
		}

		if(qL <= l && r <= qR) {
			return tr[idx];
		}

		int mid = (l + r) >> 1;
		return merge(query(qL, qR, l, mid, 2 * idx + 1), query(qL, qR, mid + 1, r, 2 * idx + 2));
	}
};

void read()
{
	cin >> n >> m;
	for(int i = 0; i < n; i++)
		cin >> a[i];
}

segment_tree t;

void solve()
{
	t.init(0, n - 1, 0);

	for(int i = 0; i < m; i++)
	{
		int l, r;
		cin >> l >> r;
		cout << t.query(l, r, 0, n - 1, 0).sum << endl;
	}
}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	read();
	solve();
	return 0;
}



================================================
FILE: old_impl/data_structures/segment_tree_AP.cpp
================================================
#include <bits/stdc++.h>
#define endl '\n'

using namespace std;
const int MAXN = (1 << 18);

int n, m;
int a[MAXN];

struct node_ap
{
	int sum, lazy, lazy_ap;
	
	node_ap() {sum = 0; lazy = 0; lazy_ap = 0;}
	node_ap(int val)
	{
		sum = val;
		lazy = 0;
		lazy_ap = 0;
	}
};

node_ap temp, broken;

node_ap merge(node_ap l, node_ap r)
{
	temp.sum = l.sum + r.sum;
	temp.lazy = 0;
	temp.lazy_ap = 0;
	return temp;
}

struct segment_tree_ap
{
	node_ap tr[4 * MAXN];

	void update(int l, int r, int idx)
	{
		if(tr[idx].lazy)
		{
			tr[idx].sum += (r - l + 1) * tr[idx].lazy;

			if(l != r)
			{
				tr[2 * idx + 1].lazy += tr[idx].lazy;
				tr[2 * idx + 2].lazy += tr[idx].lazy;
			}

			tr[idx].lazy = 0;
		}	

		if(tr[idx].lazy_ap)
		{
			int mid = (l + r) >> 1;
			tr[idx].sum += ((r - l + 1) * (r - l + 2) / 2) * tr[idx].lazy_ap;

			if(l != r)
			{
				tr[2 * idx + 1].lazy_ap += tr[idx].lazy_ap;
				tr[2 * idx + 2].lazy_ap += tr[idx].lazy_ap;
				tr[2 * idx + 2].lazy += tr[idx].lazy_ap * (mid - l + 1);
			}

			tr[idx].lazy_ap = 0;
		}
	}

	void init(int l, int r, int idx)
	{
		if(l == r)
		{
			tr[idx] = node_ap(a[l]);
			return;
		}

		int mid = (l + r) >> 1;
		init(l, mid, 2 * idx + 1);
		init(mid + 1, r, 2 * idx + 2);

		tr[idx] = merge(tr[2 * idx + 1], tr[2 * idx + 2]);
	}	
	
	void update(int qL, int qR, int val, int prog, int l, int r, int idx)
	{
		update(l, r, idx);

		if(qL > r || l > qR)
			return;

		if(qL <= l && r <= qR)
		{
			tr[idx].lazy += val + (l - qL) * prog;
			tr[idx].lazy_ap += prog;
			update(l, r, idx);
			return;
		}

		int mid = (l + r) >> 1;
		update(qL, qR, val, prog, l, mid, 2 * idx + 1);
		update(qL, qR, val, prog, mid + 1, r, 2 * idx + 2);

		tr[idx] = merge(tr[2 * idx + 1], tr[2 * idx + 2]);
	}

	node_ap query(int qL, int qR, int l, int r, int idx)
	{
		update(l, r, idx);

		if(l > qR || r < qL)
			return broken;

		if(qL <= l && r <= qR)
			return tr[idx];

		int mid = (l + r) >> 1;
		return merge(query(qL, qR, l, mid, 2 * idx + 1), query(qL, qR, mid + 1, r, 2 * idx + 2));
	}                 
};

void read()
{

}

segment_tree_ap t;

void solve()
{
	t.init(0, n - 1, 0);

}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	read();
	solve();
	return 0;
}



================================================
FILE: old_impl/data_structures/segment_tree_add_mult.cpp
================================================
#include <bits/stdc++.h>
#define endl '\n'

//#pragma GCC optimize ("O3")
//#pragma GCC target ("sse4")

using namespace std;
template<class T, class T2> inline int chkmax(T &x, const T2 &y) { return x < y ? x = y, 1 : 0; }
template<class T, class T2> inline int chkmin(T &x, const T2 &y) { return x > y ? x = y, 1 : 0; }
const int MAXN = (1 << 20);
const int mod = (int)1e9 + 7;

struct node
{
	int sum, lazy, mult;

	node() {sum = 0; mult = 1; lazy = 0;}
	node(int val)
	{
		sum = val;
		lazy = 0;
		mult = 1;
	}
};

node temp, broken;

node merge(node l, node r)
{
	temp.sum = (l.sum + r.sum) % mod;
	temp.lazy = 0;
	temp.mult = 1;
	return temp;
}

struct segment_tree
{
	node tr[4 * MAXN];

	void push(int l, int r, int idx)
	{
		if(tr[idx].mult != 1)
		{
			tr[idx].sum = (tr[idx].sum * 1ll * tr[idx].mult) % mod;
			tr[idx].sum %= mod;

			if(l != r)
			{
				tr[2 * idx + 1].mult = (tr[2 * idx + 1].mult * 1ll * tr[idx].mult) % mod;
				tr[2 * idx + 2].mult = (tr[2 * idx + 2].mult * 1ll * tr[idx].mult) % mod;
				tr[2 * idx + 1].lazy = (tr[2 * idx + 1].lazy * 1ll * tr[idx].mult) % mod;
				tr[2 * idx + 2].lazy = (tr[2 * idx + 2].lazy * 1ll * tr[idx].mult) % mod;
			}

			tr[idx].mult = 1;
		}

		if(tr[idx].lazy)
		{
			tr[idx].sum += ((r - l + 1) * 1ll * tr[idx].lazy) % mod;
			tr[idx].sum %= mod;

			if(l != r)
			{
				tr[2 * idx + 1].lazy = (tr[2 * idx + 1].lazy + tr[idx].lazy) % mod;
				tr[2 * idx + 2].lazy = (tr[2 * idx + 2].lazy + tr[idx].lazy) % mod;
			}

			tr[idx].lazy = 0;
		}
	}

	void init(int l, int r, int idx)
	{
		if(l == r)
		{
			tr[idx] = node();
			return;
		}

		int mid = (l + r) >> 1;
		init(l, mid, 2 * idx + 1);
		init(mid + 1, r, 2 * idx + 2);

		tr[idx] = merge(tr[2 * idx + 1], tr[2 * idx + 2]);
	}

	void mult(int qL, int qR, int x, int l, int r, int idx)
	{
		push(l, r, idx);
		if(qL > r || l > qR)
			return;

		if(qL <= l && r <= qR)
		{
			tr[idx].mult = (tr[idx].mult * 1ll * x) % mod;
			push(l, r, idx);
			return;
		}		

		int mid = (l + r) >> 1;
		mult(qL, qR, x, l, mid, 2 * idx + 1);
		mult(qL, qR, x, mid + 1, r, 2 * idx + 2);

		tr[idx] = merge(tr[2 * idx + 1], tr[2 * idx + 2]);
	}
	
	void add(int qL, int qR, int x, int l, int r, int idx)
	{
		push(l, r, idx);
		if(qL > r || l > qR)
			return;

		if(qL <= l && r <= qR)
		{
			tr[idx].lazy = (tr[idx].lazy + x) % mod;
			push(l, r, idx);
			return;
		}		

		int mid = (l + r) >> 1;
		add(qL, qR, x, l, mid, 2 * idx + 1);
		add(qL, qR, x, mid + 1, r, 2 * idx + 2);

		tr[idx] = merge(tr[2 * idx + 1], tr[2 * idx + 2]);
	}

	node query(int qL, int qR, int l, int r, int idx)
	{
		push(l, r, idx);

		if(l > qR || r < qL)
			return broken;

		if(qL <= l && r <= qR)
			return tr[idx];

		int mid = (l + r) >> 1;
		return merge(query(qL, qR, l, mid, 2 * idx + 1), query(qL, qR, mid + 1, r, 2 * idx + 2));
	}
};

void read()
{

}

void solve()
{

}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	read();
	solve();
	return 0;
}



================================================
FILE: old_impl/data_structures/segment_tree_fast.cpp
================================================
#include <bits/stdc++.h>
#define endl '\n'

using namespace std;
const int MAXN = (1 << 20);

struct node {
    int mx;
    node() { mx = -1e9; }
    node(int val) { mx = val; }
};

node temp;

node merge(node l, node r) {
    temp.mx = max(l.mx, r.mx);
    return temp;
}

struct segment_tree {
    int n;
    node t[2 * MAXN];

    void init(int sz) {
        n = sz;
        for(int i = 0; i < n; i++) {
            t[i + n] = node();
        }
        for(int i = n - 1; i > 0; --i) {
            t[i] = merge(t[i << 1], t[i << 1 | 1]);
        }
    }

    void modify(int p, const node &value) {
        for(t[p += n] = value; p >>= 1;) {
            t[p] = merge(t[p << 1], t[p << 1 | 1]);
        }
    }

    node query(int l, int r) {
        node resl, resr;
        for(l += n, r += n; l < r; l >>= 1, r >>= 1) {
            if(l & 1) {
                resl = merge(resl, t[l++]);
            }
            if(r & 1) {
                resr = merge(t[--r], resr);
            }
        }

        return merge(resl, resr);
    }
};

void read() {}

segment_tree t;

void solve() {}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    read();
    solve();
    return 0;
}


================================================
FILE: old_impl/data_structures/segment_tree_lazy_min.cpp
================================================
#include <bits/stdc++.h>
#include <limits>
using namespace std;

template<class T>
class segment_tree_min {
  private:
    static const T max_possible_value = std::numeric_limits<T>::max();

    struct node {
        T mn;
        int pos;

        node() {
            mn = max_possible_value;
            pos = -1;
        }

        node(T val, int p) {
            mn = val;
            pos = p;
        }
    };

    node merge(node l, node r) {
        node temp;
        temp.mn = min(l.mn, r.mn);
        if(l.mn == temp.mn) {
            temp.pos = l.pos;
        } else {
            temp.pos = r.pos;
        }

        return temp;
    }

    void push(int l, int r, int idx) {
        if(lazy[idx]) {
            tr[idx].mn += lazy[idx];

            if(l != r) {
                lazy[2 * idx + 1] += lazy[idx];
                lazy[2 * idx + 2] += lazy[idx];
            }

            lazy[idx] = 0;
        }
    }

    int n;
    vector<T> lazy;
    vector<node> tr;

    void init(int l, int r, int idx, const vector<T> &a) {
        if(l == r) {
            tr[idx] = node(a[l], l);
            return;
        }

        int mid = (l + r) >> 1;
        init(l, mid, 2 * idx + 1, a);
        init(mid + 1, r, 2 * idx + 2, a);

        tr[idx] = merge(tr[2 * idx + 1], tr[2 * idx + 2]);
    }

    void update(int qL, int qR, T val, int l, int r, int idx) {
        push(l, r, idx);

        if(qL > r || l > qR) {
            return;
        }

        if(qL <= l && r <= qR) {
            lazy[idx] += val;
            push(l, r, idx);
            return;
        }

        int mid = (l + r) >> 1;
        update(qL, qR, val, l, mid, 2 * idx + 1);
        update(qL, qR, val, mid + 1, r, 2 * idx + 2);

        tr[idx] = merge(tr[2 * idx + 1], tr[2 * idx + 2]);
    }

    node query(int qL, int qR, int l, int r, int idx) {
        push(l, r, idx);

        if(l > qR || r < qL) {
            return node();
        }

        if(qL <= l && r <= qR) {
            return tr[idx];
        }

        int mid = (l + r) >> 1;
        return merge(
            query(qL, qR, l, mid, 2 * idx + 1),
            query(qL, qR, mid + 1, r, 2 * idx + 2)
        );
    }

  public:
    void init(const vector<T> &a) {
        n = a.size();
        tr.resize(4 * n);
        lazy.assign(4 * n, 0);
        init(0, n - 1, 0, a);
    }

    void update(int qL, int qR, int val) {
        if(qR < qL) {
            return;
        }
        update(qL, qR, val, 0, n - 1, 0);
    }

    node query(int qL, int qR) {
        if(qR < qL) {
            return node();
        }

        return query(qL, qR, 0, n - 1, 0);
    }
};

int n, m;
vector<int> a;

void read() {
    cin >> n >> m;
    a.resize(n);
    for(int i = 0; i < n; i++) {
        cin >> a[i];
    }
}

segment_tree_min<int> t;

void solve() {}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    read();
    solve();
    return 0;
}


================================================
FILE: old_impl/data_structures/segment_tree_lazy_sum.cpp
================================================
#include <bits/stdc++.h>
using namespace std;

template<class T>
class segment_tree_sum {
  private:
    struct node {
        T sum;

        node() { sum = 0; }
        node(T val) { sum = val; }
    };

    node merge(node l, node r) {
        node temp;
        temp.sum = l.sum + r.sum;
        return temp;
    }

    void push(int l, int r, int idx) {
        if(lazy[idx]) {
            tr[idx].sum += lazy[idx] * (r - l + 1);

            if(l != r) {
                lazy[2 * idx + 1] += lazy[idx];
                lazy[2 * idx + 2] += lazy[idx];
            }

            lazy[idx] = 0;
        }
    }

    int n;
    vector<T> lazy;
    vector<node> tr;

    void init(int l, int r, int idx, const vector<T> &a) {
        if(l == r) {
            tr[idx] = node(a[l]);
            return;
        }

        int mid = (l + r) >> 1;
        init(l, mid, 2 * idx + 1, a);
        init(mid + 1, r, 2 * idx + 2, a);

        tr[idx] = merge(tr[2 * idx + 1], tr[2 * idx + 2]);
    }

    void update(int qL, int qR, T val, int l, int r, int idx) {
        push(l, r, idx);

        if(qL > r || l > qR) {
            return;
        }

        if(qL <= l && r <= qR) {
            lazy[idx] += val;
            push(l, r, idx);
            return;
        }

        int mid = (l + r) >> 1;
        update(qL, qR, val, l, mid, 2 * idx + 1);
        update(qL, qR, val, mid + 1, r, 2 * idx + 2);

        tr[idx] = merge(tr[2 * idx + 1], tr[2 * idx + 2]);
    }

    node query(int qL, int qR, int l, int r, int idx) {
        push(l, r, idx);

        if(l > qR || r < qL) {
            return node();
        }

        if(qL <= l && r <= qR) {
            return tr[idx];
        }

        int mid = (l + r) >> 1;
        return merge(
            query(qL, qR, l, mid, 2 * idx + 1),
            query(qL, qR, mid + 1, r, 2 * idx + 2)
        );
    }

  public:
    void init(vector<T> a) {
        n = a.size();
        tr.resize(4 * n);
        lazy.assign(4 * n, 0);
        init(0, n - 1, 0, a);
    }

    void update(int qL, int qR, int val) {
        if(qR < qL) {
            return;
        }
        update(qL, qR, val, 0, n - 1, 0);
    }

    node query(int qL, int qR) {
        if(qR < qL) {
            return node();
        }

        return query(qL, qR, 0, n - 1, 0);
    }
};

int n, m;
vector<int> a;

void read() {
    cin >> n >> m;
    a.resize(n);
    for(int i = 0; i < n; i++) {
        cin >> a[i];
    }
}

segment_tree_sum<int> t;

void solve() {}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    read();
    solve();
    return 0;
}


================================================
FILE: old_impl/data_structures/segment_tree_nonzero.cpp
================================================
#include <bits/stdc++.h>
#define endl '\n'

using namespace std;
const int MAXN = (1 << 20);

struct segment_tree
{
	int ord[4 * MAXN], sum[4 * MAXN];

	void init(int l, int r, int idx) 
	{  
		if(l == r)
		{
			ord[idx] = 0;
			sum[idx] = 0; 
			return;
		}

		int mid = (l + r) >> 1;
		init(l, mid, 2 * idx + 1);
		init(mid + 1, r, 2 * idx + 2);
	
		if(ord[idx]) sum[idx] = (r - l + 1);
		else sum[idx] = sum[2 * idx + 1] + sum[2 * idx + 2];
	}

	void update(int qL, int qR, int val, int l, int r, int idx)
	{
		if(r < qL || l > qR)
			return;

		if(qL <= l && r <= qR)
		{
			ord[idx] += val;
			if(ord[idx] > 0) sum[idx] = (r - l + 1);
			else sum[idx] = sum[2 * idx + 1] + sum[2 * idx + 2];
			return;
		}
	
		int mid = (l + r) >> 1;
		update(qL, qR, val, l, mid, 2 * idx + 1);
		update(qL, qR, val, mid + 1, r, 2 * idx + 2);

		if(ord[idx] > 0) sum[idx] = (r - l + 1);
		else sum[idx] = sum[2 * idx + 1] + sum[2 * idx + 2];
	}
};

void read()
{

}	

segment_tree t;

void solve()
{

}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	read();
	solve();
	return 0;
}



================================================
FILE: old_impl/data_structures/segment_tree_with_binary_search.cpp
================================================
#include <bits/stdc++.h>
#define endl '\n'

using namespace std;
template<class T, class T2> inline void chkmax(T &x, const T2 &y) { if(x < y) x = y; }
template<class T, class T2> inline void chkmin(T &x, const T2 &y) { if(x > y) x = y; }
const int MAXN = (1 << 20);
const int inf = (int)1e9 + 42;

struct node
{
	int mn;
	node() { mn = inf; }
	node(int val) { mn = val; }
};

node temp, broken;

node merge(node l, node r)
{
	temp.mn = min(l.mn, r.mn);
	return temp;
}

int bound_L[MAXN], bound_R[MAXN];
struct segment_tree
{
	node tr[4 * MAXN];

	void init(int l, int r, int idx)
	{
		bound_L[idx] = l;
		bound_R[idx] = r;
		if(l == r)
		{
			tr[idx] = node(inf);
			return;
		}

		int mid = (l + r) >> 1;
		init(l, mid, 2 * idx + 1);
		init(mid + 1, r, 2 * idx + 2);

		tr[idx] = merge(tr[2 * idx + 1], tr[2 * idx + 2]);
	}

	void update(int pos, int val, int l, int r, int idx)
	{
		if(l > pos || r < pos)
			return;

		if(l == r && l == pos)
		{
			tr[idx].mn = val;
			return;
		}

		int mid = (l + r) >> 1;
		update(pos, val, l, mid, 2 * idx + 1);
		update(pos, val, mid + 1, r, 2 * idx + 2);

		tr[idx] = merge(tr[2 * idx + 1], tr[2 * idx + 2]);
	}

	void get_nodes(int qL, int qR, int l, int r, int idx, vector<int> &li)
	{
		if(l > qR || r < qL) return;
		if(qL <= l && r <= qR)
		{
			li.push_back(idx);
			return;
		}

		int mid = (l + r) >> 1;
		get_nodes(qL, qR, l, mid, 2 * idx + 1, li);
		get_nodes(qL, qR, mid + 1, r, 2 * idx + 2, li);
	}

	int get_right(int l, int r, int idx, int X)
	{
		if(l == r) return l;
		int mid = (l + r) >> 1;
		if(tr[2 * idx + 1].mn <= X) return get_right(l, mid, 2 * idx + 1, X);
		else return get_right(mid + 1, r, 2 * idx + 2, X);
	}

	int get_left(int l, int r, int idx, int X)
	{
		if(l == r) return l;
		int mid = (l + r) >> 1;
		if(tr[2 * idx + 2].mn <= X) return get_left(mid + 1, r, 2 * idx + 2, X);
		else return get_left(l, mid, 2 * idx + 1, X);
	}
};

int n;
segment_tree t;

int get_left(int pos, int val)
{
	vector<int> li;
	t.get_nodes(1, pos, 1, n, 0, li);
	reverse(li.begin(), li.end());

	for(int it: li)
		if(t.tr[it].mn <= val) 
			return t.get_left(bound_L[it], bound_R[it], it, val);

	return 0;
}

int get_right(int pos, int val)
{
	vector<int> li;
	t.get_nodes(pos, n, 1, n, 0, li);

	for(int it: li)
		if(t.tr[it].mn <= val) 
			return t.get_right(bound_L[it], bound_R[it], it, val);


	return n + 1;
}

void read()
{

}

void solve()
{

}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	read();
	solve();
	return 0;
}



================================================
FILE: old_impl/data_structures/treap.cpp
================================================
#include <bits/stdc++.h>
using namespace std;

random_device rd;
mt19937 mt(rd());

struct node {
    int sz, prior, value;
    node *l, *r;
    node() {
        value = 0;
        sz = 0;
        prior = 0;
        l = nullptr;
        r = nullptr;
    }
    node(int v) {
        value = v;
        sz = 1;
        prior = mt();
        l = nullptr;
        r = nullptr;
    }
};

typedef node *pnode;

inline int size(pnode v) { return v ? v->sz : 0; }

void pull(pnode &v) {
    if(!v) {
        return;
    }
    v->sz = size(v->l) + size(v->r) + 1;
}

void merge(pnode &t, pnode l, pnode r) {
    if(!l) {
        t = r;
        return;
    }
    if(!r) {
        t = l;
        return;
    }

    if(l->prior > r->prior) {
        merge(l->r, l->r, r), t = l;
    } else {
        merge(r->l, l, r->l), t = r;
    }

    pull(t);
}

void split(pnode t, pnode &l, pnode &r, int k) {
    if(!t) {
        l = nullptr;
        r = nullptr;
        return;
    }

    if(t->value <= k) {
        split(t->r, t->r, r, k), l = t;
    } else {
        split(t->l, l, t->l, k), r = t;
    }

    pull(t);
}

void merge_op(pnode &t, pnode l, pnode r) {
    if(!l) {
        t = r;
        return;
    }
    if(!r) {
        t = l;
        return;
    }

    if(l->prior < r->prior) {
        swap(l, r);
    }

    pnode L, R;
    split(r, L, R, l->value - mt() % 2);
    merge_op(l->r, l->r, R);
    merge_op(l->l, L, l->l);

    t = l;
    pull(t);
}

void split_sz(pnode t, pnode &l, pnode &r, int k, int add = 0) {
    if(!t) {
        l = nullptr;
        r = nullptr;
        return;
    }

    int idx = add + size(t->l);
    if(idx <= k) {
        split_sz(t->r, t->r, r, k, idx + 1), l = t;
    } else {
        split_sz(t->l, l, t->l, k, add), r = t;
    }

    pull(t);
}

void read() {}

void solve() {}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    read();
    solve();
    return 0;
}


================================================
FILE: old_impl/geometry/closest_points.cpp
================================================
#include <bits/stdc++.h>
#define endl '\n'

#define int long long

using namespace std;
const int MAXN = (1 << 20);
const double eps = 0.000001;
const int inf = (int)1e17 + 42;

struct point
{
	int x, y;

	point() {x = 0; y = 0;}
	point(int _x, int _y)
	{
		x = _x;
		y = _y;
	}
};

bool cmpbyx(point a, point b)
{
	if(a.x == b.x) return a.y < b.y;
	return a.x < b.x;
}

bool cmpbyy(point a, point b)
{
	if(a.y == b.y) return a.x < b.x;
	return a.y < b.y;
}

int n;
int a[MAXN];

void read()
{
	cin >> n;
	for(int i = 1; i <= n; i++)
		cin >> a[i];
}

vector<point> p;
int dist(point p_i, point p_j) { return (p_i.x - p_j.x) * (p_i.x - p_j.x) + (p_i.y - p_j.y) * (p_i.y - p_j.y); }

int rec(int l, int r)
{
	if(l == r) return inf;

	int ret, mid = (l + r) >> 1;
	double d;
	ret = min(rec(l, mid), rec(mid + 1, r));
	d = sqrt(ret);

	vector<point> c;
	for(int i = l; i <= r; i++)
		if(abs(p[i].x - p[mid].x) <= d)
			c.push_back(p[i]);

	sort(c.begin(), c.end(), cmpbyy);

	for(int i = 0; i < c.size(); i++)
		for(int j = i + 1; j < c.size() && (c[j].y - c[i].y) <= d; j++)
		{
			ret = min(ret, dist(c[i], c[j]));
			d = sqrt(ret);
		}
		
	return ret;
}

void solve()
{
	a[0] = 0;
	for(int i = 1; i <= n; i++)
		a[i] += a[i - 1];

	for(int i = 1; i <= n; i++)
		p.push_back(point(i, a[i]));

	sort(p.begin(), p.end(), cmpbyx);

	int ans = rec(0, n - 1);
	cout << ans << endl;
}

#undef int
int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	read();
	solve();
	return 0;
}



================================================
FILE: old_impl/geometry/convex_hull.cpp
================================================
#include <bits/stdc++.h>
#define endl '\n'

#define double long double

using namespace std;
const int MAXN = (1 << 20);
const double dinf = (double)1e17;
const double eps = 0.00000000000001;

struct point {
	double x, y;
	point() {x = 0; y = 0;}
	point(double _x, double _y) {
		x = _x;
		y = _y;
	}
};

bool cmp(point a, point b) {
	if(a.x == b.x) return a.y < b.y;
	return a.x < b.x;
}

double slope(point a, point b) {
	double deltax = b.x - a.x;
	double deltay = b.y - a.y;
	if(max(-deltax, deltax) < eps) return (((deltax < 0) ? (-1) : 1) * deltay < 0) ? (-dinf) : (dinf);

	return deltay / deltax; 
}

struct convex_hull {
	vector<point> st;
	convex_hull() {st.clear();}
	void compute_hull(vector<point> vec) {
		sort(vec.begin(), vec.end(), cmp);
	
		for(int i = 0; i < (int)vec.size(); i++) {
			while(st.size() >= 2 && slope(st[st.size() - 2], vec[i]) >= slope(st[st.size() - 2], st[st.size() - 1])) 
				st.pop_back();
			st.push_back(vec[i]);
		}
		
		st.pop_back();
		int k = st.size();
	
		for(int i = vec.size() - 1; i >= 0; i--) {
			while(st.size() - k >= 2 && slope(vec[i], st[st.size() - 2]) >= slope(st[st.size() - 1], st[st.size() - 2]))
				st.pop_back();
			st.push_back(vec[i]);
		}

		st.pop_back();
	}
};

int n;
vector<point> a;

void read()
{
	cin >> n;

	for(int i = 0; i < n; i++)
	{
		double x, y;
		cin >> x >> y;
		a.push_back(point(x, y));
	}
}

convex_hull hull;

void solve()
{
	hull.compute_hull(a);
}	

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	read();
	solve();
	return 0;
}



================================================
FILE: old_impl/geometry/dynamic_upper_hull.cpp
================================================
#include <bits/stdc++.h>
#define endl '\n'

#define SZ(x) ((int)x.size())
#define ALL(V) V.begin(), V.end()
#define L_B lower_bound
#define U_B upper_bound
#define pb push_back

using namespace std;
template<class T, class T1> int chkmin(T &x, const T1 &y) { return x > y ? x = y, 1 : 0; }
template<class T, class T1> int chkmax(T &x, const T1 &y) { return x < y ? x = y, 1 : 0; }
const int MAXN = (int)5e4 + 42;

struct PT
{
	int x, y;
	PT() { x = y = 0; }
	PT(int _x, int _y) { x = _x; y = _y; }

	int64_t operator&(const PT &other) { return x * 1ll * other.y - y * 1ll * other.x; }
	PT operator+(const PT &other) const { return PT(x + other.x, y + other.y); }
	PT operator-(const PT &other) const { return PT(x - other.x, y - other.y); }
};

random_device rd;
mt19937 mt(rd());

int64_t eval(PT L, PT R) { return (L.y + R.y) * 1ll * (R.x - L.x); }

struct node
{
	PT pnt;
	int prior, sz;
	int64_t answer;

	node *l, *r, *leftmost, *rightmost, *prv;
	node() { sz = 0; answer = prior = 0; leftmost = rightmost = prv = l = r = nullptr; pnt = PT(); }
	node(PT a) {leftmost = rightmost = this; sz = 1; answer = 0; pnt = a; prior = mt(); prv = l = r = nullptr; }
};

using pnode = node*;

inline int size(pnode &t) { return t ? t->sz : 0; }

void pull(pnode &t)
{
	if(!t) return;

	t->answer = 0;
	t->sz = size(t->l) + size(t->r) + 1;
	t->leftmost = t->rightmost = t;
	t->prv = nullptr;

	if(t->l)
	{
		t->answer += t->l->answer;
		t->answer += eval(t->l->rightmost->pnt, t->pnt);
		t->prv = t->l->rightmost;
		t->leftmost = t->l->leftmost;
	}

	if(t->r)
	{
		t->answer += t->r->answer;
		t->answer += eval(t->pnt, t->r->leftmost->pnt);
		t->r->leftmost->prv = t;
		t->rightmost = t->r->rightmost;
	}
}

void merge(pnode &t, pnode l, pnode r)
{
	if(!l) { t = r; return; }
	if(!r) { t = l; return; }

	if(l->prior > r->prior)
		merge(l->r, l->r, r), t = l;
	else
		merge(r->l, l, r->l), t = r;

	pull(t);
}

void split_x(pnode t, pnode &l, pnode &r, int k)
{
	if(!t) { l = r = nullptr; return; }

	if(t->pnt.x <= k)
		split_x(t->r, t->r, r, k), l = t;
	else
		split_x(t->l, l, t->l, k), r = t;

	pull(t);
}

void split_sz(pnode t, pnode &l, pnode &r, int k, int add = 0)
{
	if(!t) { l = r = nullptr; return; }

	int idx = size(t->l) + add;
	if(idx <= k)
		split_sz(t->r, t->r, r, k, idx + 1), l = t;
	else
		split_sz(t->l, l, t->l, k, add), r = t;

	pull(t);
}

int q, T;
int tin[MAXN], tout[MAXN], n = 0;
PT p[MAXN];

void read()
{
	cin >> q >> T;
	for(int i = 0; i < q; i++)
	{
		char type;
		cin >> type;

		if(type == '+')
		{
			tin[n++] = i;
			tout[n - 1] = q - 1;

			int _p, _t;
			cin >> _p >> _t;
			p[n - 1] = PT(_t, _p);
		}
		else
		{
			int idx = 0;
			cin >> idx;
			tout[idx] = i - 1;
		}
	}
}

pnode root;
vector<int> li[4 * MAXN];
int64_t answer[MAXN];

void add(int ql, int qr, int i, int l, int r, int idx)
{
	if(r < ql || qr < l)
		return;

	if(ql <= l && r <= qr)
	{
		li[idx].pb(i);
		return;
	}

	int mid = (l + r) >> 1;
	add(ql, qr, i, l, mid, 2 * idx + 1);
	add(ql, qr, i, mid + 1, r, 2 * idx + 2);
}

int64_t cww(const PT &a, const PT &b, const PT &c) { return (b - a) & (c - a); }

int find_pref(pnode t, PT R)
{
	if(!t) return 0;
	if(!t->prv || cww(t->prv->pnt, t->pnt, R) < 0)
		return max(t->pnt.x, find_pref(t->r, R));
	else
		return find_pref(t->l, R);
}

int find_suff(pnode t, PT L)
{
	if(!t) return 0;
	if(t->prv == nullptr)
		return find_suff(t->r, L);
	else 
	{
		if(cww(L, t->prv->pnt, t->pnt) >= 0)
			return max(t->prv->pnt.x, find_suff(t->r, L));
		else
			return find_suff(t->l, L);
	}
}


pair<bool, pnode> add(pnode &t, PT pnt)
{
	pnode l, r, nw = new node(pnt);
	split_x(t, l, r, pnt.x);

	if(cww(l->rightmost->pnt, pnt, r->leftmost->pnt) >= 0)
	{
		merge(t, l, r);
		return {false, nullptr};
	}

	int good_pref = find_pref(l, pnt), bad_pref = find_suff(r, pnt);
	pnode rem_l, rem_r;

	split_x(l, l, rem_l, good_pref);
	split_x(r, rem_r, r, bad_pref);

	//cout << "Adding " << pnt.x << " " << pnt.y << " -> " << good_pref << " " << bad_pref << endl << flush;
	//cout << "Sizes: " << size(l) << " " << size(r) << endl << flush;

	assert(l != nullptr);
	assert(r != nullptr);

	pnode ret;
	merge(t, l, nw);
	merge(t, t, r);
	merge(ret, rem_l, rem_r);

	return {true, ret};
}

void solve(int l, int r, int idx)
{
	stack<pair<int, pnode> > ST;
	for(int i: li[idx])
	{
		pair<bool, pnode> q = add(root, p[i]);
		if(q.first == true) ST.push({p[i].x, q.second});
	}

	if(l == r)
		answer[l] = root->answer;
	else
	{
		int mid = (l + r) >> 1;
		solve(l, mid, 2 * idx + 1);
		solve(mid + 1, r, 2 * idx + 2);
	}

	while(!ST.empty())
	{
		auto mid = ST.top();
		ST.pop();

		pnode L, R, dummy;
		split_x(root, L, R, mid.first);
		split_x(L, L, dummy, mid.first - 1);

		merge(root, L, mid.second);
		merge(root, root, R);
	}
}

void solve()
{
	for(int i = 0; i < n; i++) add(tin[i], tout[i], i, 0, q - 1, 0);

	root = nullptr;
	merge(root, root, new node(PT(0, 0)));
	merge(root, root, new node(PT(T, 0)));
	solve(0, q - 1, 0);

	for(int i = 0; i < q; i++)
		cout << answer[i] << endl;
}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	read();
	solve();
	return 0;
}


================================================
FILE: old_impl/geometry/kd-tree.cpp
================================================
#include <bits/stdc++.h>
#define endl '\n'

using namespace std;
const int MAXN = (int)1e5 + 42 + 17;
const int MAXD = 5;

inline int64_t sq(int x) { return x * 1ll * x; }

struct point
{
	int c[MAXD];
	point() { }
};

struct cmp
{
	int current_d;
	cmp() { current_d = 0; }
	cmp(int d) { current_d = d; }
	bool operator() (const point& a, const point& b)  { return a.c[current_d] < b.c[current_d]; }
}; 

int64_t sq_dist(point a, point b, int d)
{
	int64_t answer = 0;
	for(int i = 0; i < d; i++)
		answer += sq(a.c[i] - b.c[i]);

	return answer;
}

struct kd_tree
{
	struct node
	{
		point p;
		int L, R, axis;
		node() { L = -1; R = -1; }
		node(point _p) { L = -1; R = -1; p = _p; }
	};

	int psz = 0, D, root;
	node tr[MAXN << 2];

	kd_tree() { D = 0; psz = 0; }	
	kd_tree(int d) { D = d; psz = 0; }

	int new_node() { return psz++; }

	int build(point *from, point *to, int axis)
	{
		if(to - from == 0) 
			return -1;
	
		point *mid = from + (to - from) / 2;
		
		nth_element(from, mid, to, cmp(axis));
	
		int c_node = new_node();
		tr[c_node] = node(*mid);
		
		tr[c_node].axis = axis;

		tr[c_node].L = build(from, mid, (axis + 1) % D);
		tr[c_node].R = build(mid + 1, to, (axis + 1) % D);

		return c_node;
	}

	void init(point *from, point *to, int d) 
	{ 
		D = d;
		random_shuffle(from, to);
		root = build(from, to, 0);  
	}

	void query(int idx, point q, int64_t &answer)
	{
		if(idx == -1) return;
		answer = min(answer, sq_dist(q, tr[idx].p, D));
		
		if(tr[idx].p.c[tr[idx].axis] <= q.c[tr[idx].axis])
		{
			query(tr[idx].R, q, answer); 
			if(tr[idx].L != -1 && q.c[tr[idx].axis] - sqrt(answer) <= tr[idx].p.c[tr[idx].axis]) query(tr[idx].L, q, answer); 
		}		
		else
		{
			query(tr[idx].L, q, answer); 
			if(tr[idx].R != -1 && q.c[tr[idx].axis] + sqrt(answer) >= tr[idx].p.c[tr[idx].axis]) query(tr[idx].R, q, answer); 
		}
	}

	double nearest_neigbhor(point q)
	{
		int64_t answer = (1ll << 62ll);
		query(root, q, answer);
		return sqrt(answer); 
	}
};

int n, d;
point li[MAXN];

void read()
{
	cin >> n >> d;
	for(int i = 0; i < n; i++)
		for(int x = 0; x < d; x++)
			cin >> li[i].c[x];
}

kd_tree t;

void solve()
{
	t.init(li, li + n, d);

	int q;
	cin >> q;
	for(int i = 0; i < q; i++)
	{
		point q;
		for(int x = 0; x < d; x++)
			cin >> q.c[x];

		cout << setprecision(10) << fixed << t.nearest_neigbhor(q) << endl;
	}
}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	read();
	solve();
	return 0;
}



================================================
FILE: old_impl/geometry/rectangle_union.cpp
================================================
#include <bits/stdc++.h>
#define endl '\n'

#define int long long

using namespace std;
const int MAXN = (1 << 21);
const int bound = (int)1e6 + 42;
const int inf = (int)1e9 + 42;

struct edge
{
	int x, y1, y2, val;
	edge() {x = -1; y1 = -1; y2 = -1; val = -1;}
	edge(int _x, int _y1, int _y2, int _val)
	{
		x = _x;
		y1 = _y1;
		y2 = _y2;
		val = _val;
	}
};

bool operator<(const edge &e1, const edge &e2)
{
	return e1.x < e2.x;
}

int n;
vector<edge> e;

void read()
{
	cin >> n;
	for(int i = 0; i < n; i++)
	{
		int mnx, mny, mxx, mxy;
		cin >> mnx >> mny >> mxx >> mxy;

		if(mxx < mnx) swap(mxx, mnx);
		if(mxy < mny) swap(mxy, mny);
		mnx--;
		mny--;

		e.push_back(edge(mnx, mny, mxy, 1));
		e.push_back(edge(mxx, mny, mxy, -1));
	}	
}

int valy[MAXN];
vector<int> comy;
map<int, int> id_y;
int sz_y;

void compress()
{
	for(int i = 0; i < e.size(); i++)
	{
		comy.push_back(e[i].y1);
		comy.push_back(e[i].y2);
	}

	sort(comy.begin(), comy.end());
	id_y[comy[0]] = 1;

	for(int i = 1; i < comy.size(); i++)
		if(comy[i] != comy[i - 1])
			id_y[comy[i]] = id_y[comy[i - 1]] + 1ll;

	for(int i = 0; i < comy.size(); i++)
		valy[id_y[comy[i]]] = comy[i];

	for(int i = 0; i < e.size(); i++)
	{
		e[i].y1 = id_y[e[i].y1];
		e[i].y2 = id_y[e[i].y2];
	}

	sz_y = id_y.size();
}

struct segment_tree
{
	struct node
	{
		int lazy, ans;
		node() {lazy = 0, ans = 0;}
		node(int v) { ans = v; lazy = 0;}
	};

	node tr[4 * MAXN];

	void update(int qL, int qR, int val, int l, int r, int idx)
	{
		if(qL <= l && r <= qR)
		{
			tr[idx].lazy += val;
			if(tr[idx].lazy == 0) tr[idx].ans = tr[2 * idx + 1].ans + tr[2 * idx + 2].ans; 
			else tr[idx].ans = valy[r] - valy[l];
			return;
		}

		if(qL > r || qR < l)
			return;
	
		if(l + 1 >= r)
			return;

		int mid = (l + r) >> 1;
		update(qL, qR, val, l, mid, 2 * idx + 1);
		update(qL, qR, val, mid, r, 2 * idx + 2);

		if(tr[idx].lazy == 0) tr[idx].ans = tr[2 * idx + 1].ans + tr[2 * idx + 2].ans;
		else tr[idx].ans = valy[r] - valy[l];
	}
};

segment_tree t;

inline int mabs(int x) { return x < 0 ? -x : x; }

int rectangle_union()
{
	compress();
	sort(e.begin(), e.end());

	int ans = 0, last = -inf;
	for(int i = 0; i < e.size(); i++)
	{
		ans += mabs(e[i].x - last) * (long long)t.tr[0].ans;
		t.update(e[i].y1, e[i].y2, e[i].val, 1, sz_y, 0);
		last = e[i].x;
	}

	return ans;
}

void solve()
{
	cout << rectangle_union() << endl;	
}

#undef int
int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	read();
	solve();
	return 0;
}



================================================
FILE: old_impl/graph/dsu_bipartite.cpp
================================================
#include
Download .txt
gitextract_ns7a50wl/

├── README.md
├── data_structures/
│   ├── clever_adding_intervals_set.hpp
│   ├── compressed_fenwick.hpp
│   ├── decremental_constant_set.hpp
│   ├── fenwick.hpp
│   ├── fenwick_2d.hpp
│   ├── fenwick_range_update.hpp
│   ├── fenwick_range_update_range_query.hpp
│   ├── heap.hpp
│   ├── meldable_heap.hpp
│   ├── merge_sort_tree.hpp
│   ├── monoids_lazy.hpp
│   ├── nonintersecting_range_tree.hpp
│   ├── offline_segment_tree_2d.hpp
│   ├── rmq2d.hpp
│   ├── segment_tree.hpp
│   ├── segment_tree_lazy.hpp
│   ├── set_lazy.hpp
│   ├── sparse_table.hpp
│   ├── sparse_table_disjoint.hpp
│   ├── treap.hpp
│   ├── treap_lazy.hpp
│   └── wavelet_tree.hpp
├── dp_optimizations/
│   └── convex_hull_trick.hpp
├── geometry/
│   ├── dynamic_convex_hull.hpp
│   ├── halfplane_intersection.hpp
│   ├── point.hpp
│   ├── polygon.hpp
│   └── voronoi.hpp
├── graph/
│   ├── bcc.hpp
│   ├── bipartite_coloring.hpp
│   ├── bipartite_matching.hpp
│   ├── dijkstra_vlog.hpp
│   ├── directed_cactus.hpp
│   ├── dsu.hpp
│   ├── eppstein_shortest_paths.hpp
│   ├── eulerian_paths.hpp
│   ├── graph.hpp
│   ├── hopcroft_karp.hpp
│   ├── hungarian_algorithm.hpp
│   ├── maxflow.hpp
│   ├── mincost_circulation.hpp
│   ├── mincost_flow.hpp
│   ├── scc.hpp
│   ├── st_numbering.hpp
│   └── two_sat.hpp
├── math/
│   └── gauss_bitset.hpp
├── old_impl/
│   ├── data_structures/
│   │   ├── implicit_treap.hpp
│   │   ├── implicit_treap_basic.hpp
│   │   ├── max_count_segment_tree.cpp
│   │   ├── merging_segment_tree.cpp
│   │   ├── min_segment_tree.cpp
│   │   ├── monotonous_queue.cpp
│   │   ├── persistent_segment_tree.cpp
│   │   ├── persistent_segment_tree_lazy.cpp
│   │   ├── persistent_treap.cpp
│   │   ├── persistent_treap_lazy.cpp
│   │   ├── segment_tree.cpp
│   │   ├── segment_tree_AP.cpp
│   │   ├── segment_tree_add_mult.cpp
│   │   ├── segment_tree_fast.cpp
│   │   ├── segment_tree_lazy_min.cpp
│   │   ├── segment_tree_lazy_sum.cpp
│   │   ├── segment_tree_nonzero.cpp
│   │   ├── segment_tree_with_binary_search.cpp
│   │   └── treap.cpp
│   ├── geometry/
│   │   ├── closest_points.cpp
│   │   ├── convex_hull.cpp
│   │   ├── dynamic_upper_hull.cpp
│   │   ├── kd-tree.cpp
│   │   └── rectangle_union.cpp
│   ├── graph/
│   │   ├── dsu_bipartite.cpp
│   │   ├── eulerian_path.cpp
│   │   ├── max_anticlique.cpp
│   │   ├── maximum_closure.cpp
│   │   ├── mincost_maxflow.cpp
│   │   ├── persistent_dsu.cpp
│   │   ├── scc_tarjan.cpp
│   │   └── st_numbering.cpp
│   ├── math/
│   │   ├── combinatorics.cpp
│   │   ├── fft.cpp
│   │   ├── fft_mod.cpp
│   │   ├── fft_xor.cpp
│   │   ├── fft_xor_mod.cpp
│   │   ├── gauss_elimination_equations.cpp
│   │   ├── gauss_elimination_equations_mod.cpp
│   │   ├── gauss_elimination_equations_mod_number_solutions.cpp
│   │   ├── matrix_exponential.cpp
│   │   └── number_theory.cpp
│   ├── strings/
│   │   ├── aho_corasick.cpp
│   │   ├── aho_corasick_dynamic.cpp
│   │   ├── kmp.cpp
│   │   ├── palindromic_tree.cpp
│   │   ├── rabin_karp.cpp
│   │   ├── suffix_array.cpp
│   │   ├── suffix_array_hash.cpp
│   │   ├── suffix_array_log2.cpp
│   │   ├── suffix_automaton.cpp
│   │   └── trie.cpp
│   └── tree/
│       ├── centroid_decomposition.cpp
│       ├── dsu_on_tree.cpp
│       ├── hld.cpp
│       ├── lca-seg3.cpp
│       ├── link_cut_tree.cpp
│       └── virtual_tree.cpp
├── other/
│   ├── bits/
│   │   ├── bit_trie.hpp
│   │   └── xor_basis.hpp
│   ├── dp_optimizations/
│   │   ├── LiChao_dynamic.cpp
│   │   ├── LiChao_parabolic.cpp
│   │   ├── LiChao_segment_tree_offline.cpp
│   │   ├── convex_hull_trick_max.cpp
│   │   ├── convex_hull_trick_min.cpp
│   │   ├── divide_and_conquer_optimization.cpp
│   │   ├── slope_trick.cpp
│   │   └── slope_trick_priority_queue.cpp
│   ├── queries/
│   │   ├── mo.cpp
│   │   ├── mo_dsu.cpp
│   │   ├── mo_online.cpp
│   │   └── offline_centroid_queries.cpp
│   └── utils/
│       └── count_inversions.cpp
├── strings/
│   ├── aho_corasick.hpp
│   ├── hashing.hpp
│   ├── suffix_array.hpp
│   └── suffix_automaton.hpp
└── tree/
    ├── centroid_decomposition.hpp
    ├── euler_order_segment_tree.cpp
    ├── lca.hpp
    ├── lca_sparse_table.hpp
    ├── line_tree.hpp
    ├── link_cut_tree.hpp
    ├── vertex_add_path_sum.hpp
    └── virtual_tree.hpp
Download .txt
SYMBOL INDEX (1510 symbols across 131 files)

FILE: data_structures/clever_adding_intervals_set.hpp
  type clever_set (line 5) | struct clever_set {
    method init (line 8) | void init(int n) { value[{n, 1}] = (T)0; }
    method add (line 10) | vector<pair<pair<int, int>, T> > add(int l, int r, T val) {

FILE: data_structures/compressed_fenwick.hpp
  type CompressedFenwick (line 6) | struct CompressedFenwick {
    method get_idx (line 10) | int get_idx(int x) {
    method update (line 13) | void update(int x, T val) { t.update(get_idx(x), val); }
    method add_to_prep (line 15) | void add_to_prep(int x) { li.push_back(x); }
    method prepare (line 16) | void prepare() {
    method T (line 22) | T query(int x) { return t.query(get_idx(x) - 1); }
    method T (line 23) | T size() { return t.query(t.sz); }

FILE: data_structures/decremental_constant_set.hpp
  class DecrementalConstantSet (line 19) | class DecrementalConstantSet {
    method small_query_prefix (line 28) | int small_query_prefix(int c, uint64_t filter_mask) {
    method small_query_suffix (line 33) | int small_query_suffix(int c, uint64_t filter_mask) {
    method DecrementalConstantSet (line 39) | DecrementalConstantSet(int _n)
    method remove (line 50) | void remove(int _i) {
    method query_right (line 75) | int query_right(int _i) {
    method query_left (line 96) | int query_left(int _i) {

FILE: data_structures/fenwick.hpp
  class Fenwick (line 5) | class Fenwick {
    method init (line 11) | void init(int n) {
    method update (line 17) | void update(int idx, T val) {
    method T (line 27) | T query(int idx) {
    method T (line 36) | T query(int l, int r) { return query(r) - query(l - 1); }
    method find_kth (line 38) | int find_kth(T k) {

FILE: data_structures/fenwick_2d.hpp
  class Fenwick2d (line 5) | class Fenwick2d {
    method update_row (line 10) | void update_row(int row, int idx, T val) {
    method T (line 23) | T query_row(int row, int idx) {
    method init (line 37) | void init(int _sz) {
    method update (line 42) | void update(int row, int col, T val) {
    method T (line 51) | T query(int row, int col) {

FILE: data_structures/fenwick_range_update.hpp
  class FenwickRangeUpdate (line 5) | class FenwickRangeUpdate {
    method update (line 10) | void update(int idx, T val) {
    method init (line 21) | void init(int n) {
    method T (line 26) | T query(int idx) {
    method update (line 35) | void update(int l, int r, T val) {

FILE: data_structures/fenwick_range_update_range_query.hpp
  class FenwickRangeUpdateRangeQuery (line 6) | class FenwickRangeUpdateRangeQuery {
    method init (line 10) | void init(int _sz) {
    method update (line 16) | void update(int l, int r, T val) {
    method T (line 22) | T query(int idx) { return t0.query(idx) * (T)idx + t1.query(idx); }
    method T (line 23) | T query(int l, int r) { return query(r) - query(l - 1); }

FILE: data_structures/heap.hpp
  class Heap (line 5) | class Heap {
    method push_up (line 10) | void push_up(int id) {
    method push_down (line 19) | void push_down(int id) {
    method Heap (line 36) | Heap() { clear(); }
    method clear (line 38) | void clear() {
    method push (line 44) | int push(T val) {
    method T (line 52) | T pop() {
    method size (line 64) | size_t size() { return heap.size(); }
    method empty (line 65) | bool empty() { return heap.size() == 0; }
    method T (line 67) | T top() { return heap_values[heap[0]]; }
    method top_node (line 69) | int top_node() { return heap[0]; }
    method update (line 71) | void update(int node, T val) {

FILE: data_structures/meldable_heap.hpp
  class MeldableHeap (line 5) | class MeldableHeap {
    method rng (line 7) | static uint32_t rng() {
    type Node (line 12) | struct Node {
      method Node (line 16) | Node(T _key) : key(_key), left(nullptr), right(nullptr) {}
    method Node (line 19) | Node* merge(Node* a, Node* b) {
      method Node (line 16) | Node(T _key) : key(_key), left(nullptr), right(nullptr) {}
    method pop (line 43) | pair<Node*, Node*> pop(Node* a) {
    method MeldableHeap (line 52) | MeldableHeap() : root(nullptr) {}
    method MeldableHeap (line 53) | MeldableHeap(Node* _root) : root(_root) {}
    method MeldableHeap (line 55) | MeldableHeap copy() const {
    method MeldableHeap (line 61) | MeldableHeap merge(const MeldableHeap<T>& other) {
    method MeldableHeap (line 67) | MeldableHeap merge(
    method push (line 73) | void push(T key) {
    method T (line 78) | T pop() {
    method T (line 85) | T top() const { return root->key; }
    method trio (line 87) | tuple<T, MeldableHeap<T>, MeldableHeap<T>> trio() const {
    method empty (line 93) | bool empty() const { return root == nullptr; }

FILE: data_structures/merge_sort_tree.hpp
  class MergeSortTree (line 12) | class MergeSortTree {
    method update_rec (line 17) | void update_rec(int v, int tl, int tr, int pos, int y, int delta) {
    method query_rec (line 35) | int query_rec(int v, int tl, int tr, int ql, int qr, int k) {
    method init (line 48) | void init(int _n) {
    method update (line 53) | void update(int x, int y, int delta) { update_rec(1, 1, n, x, y, delta...
    method query (line 55) | int query(int qxl, int qxr, int k) {
    method query (line 59) | int query(int qxl, int qxr, int qyl, int qyr) {

FILE: data_structures/monoids_lazy.hpp
  class MonoidMin (line 5) | class MonoidMin {
    type MinVal (line 7) | struct MinVal {
    type AddLazy (line 13) | struct AddLazy {
    method MinVal (line 23) | static MinVal merge(MinVal a, MinVal b) { return {min(a.val, b.val)}; }
    method MinVal (line 25) | static MinVal e() { return {numeric_limits<T>::max()}; }
    method MinVal (line 27) | static MinVal lazy_apply(AddLazy f, MinVal x) {
    method AddLazy (line 31) | static AddLazy lazy_merge(AddLazy a, AddLazy b) {
    method AddLazy (line 35) | static AddLazy lazy_init(MinVal _) { return {0}; }
  class MonoidSum (line 48) | class MonoidSum {
    method Sum (line 53) | static Sum merge(Sum a, Sum b) { return a + b; }
    method Sum (line 55) | static Sum e() { return 0; }
    method Sum (line 57) | static Sum lazy_apply(AddLazy f, Sum x) { return f + x; }
    method AddLazy (line 59) | static AddLazy lazy_merge(AddLazy a, AddLazy b) { return a + b; }
    method AddLazy (line 61) | static AddLazy lazy_init(Sum _) { return 0; }
    method Sum (line 63) | static Sum inverse(Sum x) { return -x; }
  class MonoidMinWithCount (line 76) | class MonoidMinWithCount {
    type MinWithCount (line 78) | struct MinWithCount {
    type AddLazy (line 90) | struct AddLazy {
    method MinWithCount (line 100) | static MinWithCount merge(MinWithCount a, MinWithCount b) {
    method MinWithCount (line 110) | static MinWithCount e() { return {numeric_limits<T>::max(), 0}; }
    method MinWithCount (line 112) | static MinWithCount lazy_apply(AddLazy f, MinWithCount x) {
    method AddLazy (line 116) | static AddLazy lazy_merge(AddLazy a, AddLazy b) {
    method AddLazy (line 119) | static AddLazy lazy_init(MinWithCount _) { return {0}; }
  class MonoidSumArithmeticProgression (line 132) | class MonoidSumArithmeticProgression {
    type Sum (line 133) | struct Sum {
    type AddLazy (line 141) | struct AddLazy {
    method Sum (line 154) | static Sum merge(Sum a, Sum b) {
    method Sum (line 161) | static Sum e() { return {0, 0}; }
    method Sum (line 162) | static Sum lazy_apply(AddLazy f, Sum x) {
    method AddLazy (line 169) | static AddLazy lazy_merge(AddLazy a, AddLazy b) {
    method AddLazy (line 175) | static AddLazy lazy_init(Sum node) { return {0, 0, node.l}; }

FILE: data_structures/nonintersecting_range_tree.hpp
  class NonintersectingRangeTree (line 12) | class NonintersectingRangeTree {
    method NonintersectingRangeTree (line 17) | NonintersectingRangeTree(int n) {
    method add (line 33) | void add(int l, int r) {
    method get_parent (line 73) | int get_parent(int x) { return par[par_idx[x]]; }

FILE: data_structures/offline_segment_tree_2d.hpp
  class OfflineSegmentTree2d (line 7) | class OfflineSegmentTree2d {
    method collect (line 13) | void collect(int v, int tl, int tr, int pos, int y) {
    method build_compression (line 26) | void build_compression(int v) {
    method update_rec (line 32) | void update_rec(int v, int tl, int tr, int pos, int y, T val) {
    method T (line 53) | T query_rec(int v, int tl, int tr, int l, int r, int yl, int yr) {
    method init (line 73) | void init(int _n) {
    method prepare_update (line 80) | void prepare_update(int x, int y) { collect(1, 1, n, x, y); }
    method prepare (line 82) | void prepare() {
    method update (line 90) | void update(int x, int y, T val) { update_rec(1, 1, n, x, y, val); }
    method T (line 92) | T query(int xl, int xr, int yl, int yr) {

FILE: data_structures/rmq2d.hpp
  type rmq1d (line 4) | struct rmq1d {
    method init (line 7) | void init(int N) {
    method add (line 11) | void add(int v, int tl, int tr, int x) {
    method add (line 23) | void add(int x) { add(0, 0, n, x); }
    method get (line 24) | int get(int v, int tl, int tr, int l, int r) {
    method get (line 34) | int get(int l, int r) { return get(0, 0, n, l, r); }
  type rmq2d (line 37) | struct rmq2d {
    method init (line 41) | void init(int N) {
    method prep (line 46) | void prep(int v, int tl, int tr, int x, int y) {
    method prep (line 58) | void prep(int x, int y) { prep(0, 0, n, x, y); }
    method add (line 59) | void add(int v, int tl, int tr, int x, int y) {
    method add (line 72) | void add(int x, int y) { add(0, 0, n, x, y); }
    method build (line 73) | void build(int v, int tl, int tr) {
    method init2 (line 83) | void init2() { build(0, 0, n); }
    method get (line 84) | int get(int v, int tl, int tr, int l1, int r1, int l2, int r2) {
    method get (line 97) | int get(int l1, int r1, int l2, int r2) {

FILE: data_structures/segment_tree.hpp
  class SegmentTree (line 9) | class SegmentTree {
    method pull (line 14) | void pull(int x) { tr[x] = merge(tr[2 * x], tr[2 * x + 1]); }
    method SegmentTree (line 17) | SegmentTree() { init(vector<T>()); }
    method SegmentTree (line 18) | SegmentTree(int _n) { init(vector<T>(_n, e())); }
    method SegmentTree (line 19) | SegmentTree(const vector<T>& _a) { init(_a); }
    method init (line 21) | void init(const vector<T>& _a) {
    method update (line 37) | void update(int pos, T val) {
    method T (line 45) | T get_pos(int pos) { return tr[pos + size]; }
    method T (line 47) | T query(int l, int r) {
    method T (line 60) | T query_all() { return tr[1]; }
    method max_right (line 63) | int max_right(int l) const {
    method max_right (line 67) | int max_right(int l, F f) const {
    method min_left (line 95) | int min_left(int r) const {
    method min_left (line 99) | int min_left(int r, F f) const {

FILE: data_structures/segment_tree_lazy.hpp
  class SegmentTreeLazy (line 15) | class SegmentTreeLazy {
    method pull (line 21) | void pull(int x) { tr[x] = merge(tr[2 * x], tr[2 * x + 1]); }
    method push_one (line 23) | void push_one(int x, G f) {
    method push (line 30) | void push(int x) {
    method push_all_down (line 36) | void push_all_down(int x) {
    method push_all_open_range (line 42) | void push_all_open_range(int l, int r) {
    method SegmentTreeLazy (line 54) | SegmentTreeLazy() { init(vector<T>()); }
    method SegmentTreeLazy (line 55) | SegmentTreeLazy(int _n) { init(vector<T>(_n, e())); }
    method SegmentTreeLazy (line 56) | SegmentTreeLazy(const vector<T> &_a) { init(_a); }
    method init (line 58) | void init(const vector<T> &_a) {
    method update (line 78) | void update(int pos, T val) {
    method apply_lazy (line 87) | void apply_lazy(int l, int r, G f) {
    method T (line 113) | T get_pos(int pos) {
    method T (line 119) | T query(int l, int r) {
    method T (line 135) | T query_all() { return tr[1]; }
    method max_right (line 138) | int max_right(int l) const {
    method max_right (line 142) | int max_right(int l, F f) const {
    method min_left (line 172) | int min_left(int r) const {
    method min_left (line 176) | int min_left(int r, F f) const {

FILE: data_structures/set_lazy.hpp
  class SetLazy (line 5) | class SetLazy : private Container<T> {
    class Iterator (line 9) | class Iterator {
      method Iterator (line 15) | Iterator(typename Container<T>::iterator it, const T& lazy_value)
      method T (line 18) | T operator*() const { return *it + lazy_value; }
      method Iterator (line 19) | Iterator& operator++() {
      method Iterator (line 23) | Iterator operator++(int) {
      method base (line 31) | typename Container<T>::iterator base() const { return it; }
    method insert (line 35) | void insert(const T& value) { Container<T>::insert(value - lazy_value); }
    method erase (line 37) | void erase(const T& value) { Container<T>::erase(value - lazy_value); }
    method erase (line 38) | void erase(Iterator it) { Container<T>::erase(it.base()); }
    method add_all (line 40) | void add_all(const T& x) { lazy_value += x; }
    method T (line 42) | T get_lazy_value() const { return lazy_value; }
    method count (line 44) | bool count(const T& value) const {
    method Iterator (line 48) | Iterator find(const T& value) {
      method Iterator (line 15) | Iterator(typename Container<T>::iterator it, const T& lazy_value)
      method T (line 18) | T operator*() const { return *it + lazy_value; }
      method Iterator (line 19) | Iterator& operator++() {
      method Iterator (line 23) | Iterator operator++(int) {
      method base (line 31) | typename Container<T>::iterator base() const { return it; }
    method Iterator (line 53) | Iterator lower_bound(const T& value) {
      method Iterator (line 15) | Iterator(typename Container<T>::iterator it, const T& lazy_value)
      method T (line 18) | T operator*() const { return *it + lazy_value; }
      method Iterator (line 19) | Iterator& operator++() {
      method Iterator (line 23) | Iterator operator++(int) {
      method base (line 31) | typename Container<T>::iterator base() const { return it; }
    method Iterator (line 59) | Iterator upper_bound(const T& value) {
      method Iterator (line 15) | Iterator(typename Container<T>::iterator it, const T& lazy_value)
      method T (line 18) | T operator*() const { return *it + lazy_value; }
      method Iterator (line 19) | Iterator& operator++() {
      method Iterator (line 23) | Iterator operator++(int) {
      method base (line 31) | typename Container<T>::iterator base() const { return it; }
    method Iterator (line 65) | Iterator begin() { return Iterator(Container<T>::begin(), lazy_value); }
      method Iterator (line 15) | Iterator(typename Container<T>::iterator it, const T& lazy_value)
      method T (line 18) | T operator*() const { return *it + lazy_value; }
      method Iterator (line 19) | Iterator& operator++() {
      method Iterator (line 23) | Iterator operator++(int) {
      method base (line 31) | typename Container<T>::iterator base() const { return it; }
    method Iterator (line 66) | Iterator end() { return Iterator(Container<T>::end(), lazy_value); }
      method Iterator (line 15) | Iterator(typename Container<T>::iterator it, const T& lazy_value)
      method T (line 18) | T operator*() const { return *it + lazy_value; }
      method Iterator (line 19) | Iterator& operator++() {
      method Iterator (line 23) | Iterator operator++(int) {
      method base (line 31) | typename Container<T>::iterator base() const { return it; }
    method Iterator (line 68) | const Iterator begin() const {
      method Iterator (line 15) | Iterator(typename Container<T>::iterator it, const T& lazy_value)
      method T (line 18) | T operator*() const { return *it + lazy_value; }
      method Iterator (line 19) | Iterator& operator++() {
      method Iterator (line 23) | Iterator operator++(int) {
      method base (line 31) | typename Container<T>::iterator base() const { return it; }
    method Iterator (line 71) | const Iterator end() const {
      method Iterator (line 15) | Iterator(typename Container<T>::iterator it, const T& lazy_value)
      method T (line 18) | T operator*() const { return *it + lazy_value; }
      method Iterator (line 19) | Iterator& operator++() {
      method Iterator (line 23) | Iterator operator++(int) {
      method base (line 31) | typename Container<T>::iterator base() const { return it; }
    method merge (line 78) | void merge(const SetLazy<T, Container>& other) {
    method print (line 84) | void print() const {

FILE: data_structures/sparse_table.hpp
  class SparseTable (line 5) | class SparseTable {
    method SparseTable (line 12) | SparseTable() {
    method init (line 18) | void init(const vector<T>& a) {
    method T (line 35) | T query(int l, int r) {

FILE: data_structures/sparse_table_disjoint.hpp
  class SparseTableDisjoint (line 5) | class SparseTableDisjoint {
    method init_dnc (line 12) | void init_dnc(int l, int r, int lvl) {
    method SparseTableDisjoint (line 36) | SparseTableDisjoint() {
    method init (line 44) | void init(const vector<T>& _a) {
    method T (line 57) | T query(int l, int r) {

FILE: data_structures/treap.hpp
  type TreapNode (line 5) | struct TreapNode {
    method TreapNode (line 12) | TreapNode(KeyT key, T data)
    method pull (line 17) | void pull() {
    method split (line 30) | pair<TreapNode*, TreapNode*> split(TreapNode* t, KeyT key) {
    method split_by_size (line 47) | pair<TreapNode*, TreapNode*> split_by_size(
    method TreapNode (line 69) | TreapNode* merge(TreapNode* l, TreapNode* r) {
    method TreapNode (line 83) | TreapNode* unordered_merge(TreapNode* l, TreapNode* r) {
    method insert_in (line 100) | void insert_in(TreapNode*& t, TreapNode* it) {
    method TreapNode (line 114) | TreapNode* erase_from(
  class Treap (line 139) | class Treap {
    method rng (line 141) | static uint64_t rng() {
    method _pull_all (line 148) | void _pull_all(Node* t) {
    method Treap (line 158) | Treap() { root = nullptr; }
    method Treap (line 159) | Treap(const vector<pair<KeyT, T>>& a) { build_cartesian_tree(a); }
    method build_cartesian_tree (line 161) | void build_cartesian_tree(const vector<pair<KeyT, T>>& a) {
    method insert (line 190) | void insert(KeyT key, T data) {
    method Node (line 195) | Node* erase(KeyT key) { return erase_from(root, key); }
    method merge_treaps (line 197) | Treap<KeyT, T, merge_func> merge_treaps(
    method count_leq (line 205) | int count_leq(KeyT max_key) {

FILE: data_structures/treap_lazy.hpp
  type TreapNode (line 6) | struct TreapNode {
    method TreapNode (line 14) | TreapNode(KeyT key, T data)
    method pull (line 20) | void pull() {
    method push (line 35) | void push() { lazy.apply_lazy(this); }
    method push_lazy (line 37) | void push_lazy(TreapNode* t) {
    method split (line 43) | pair<TreapNode*, TreapNode*> split(TreapNode* t, KeyT key) {
    method split_by_size (line 62) | pair<TreapNode*, TreapNode*> split_by_size(
    method TreapNode (line 85) | TreapNode* merge(TreapNode* l, TreapNode* r) {
    method TreapNode (line 101) | TreapNode* unordered_merge(TreapNode* l, TreapNode* r) {
    method insert_in (line 120) | void insert_in(TreapNode*& t, TreapNode* it) {
    method TreapNode (line 137) | TreapNode* erase_from(
  class Treap (line 162) | class Treap {
    method rng (line 164) | static uint64_t rng() {
    method _pull_all (line 173) | void _pull_all(Node* t) {
    method Treap (line 184) | Treap() { root = nullptr; }
    method Treap (line 185) | Treap(const vector<pair<KeyT, T>>& a) { build_cartesian_tree(a); }
    method build_cartesian_tree (line 187) | void build_cartesian_tree(const vector<pair<KeyT, T>>& a) {
    method insert (line 216) | void insert(KeyT key, T data) {
    method erase (line 221) | void erase(KeyT key) { return erase_from(root, key); }
    method merge_treaps (line 223) | Treap<KeyT, T, merge_func, LazyT> merge_treaps(

FILE: data_structures/wavelet_tree.hpp
  class WaveletTree (line 9) | class WaveletTree {
    method WaveletTree (line 17) | WaveletTree() = default;
    method init (line 19) | void init(const vector<int>& arr, int x, int y) {
    method kth (line 44) | int kth(int l, int r, int k) const {
    method LTE (line 58) | int LTE(int l, int r, int k) const {
    method count (line 69) | int count(int l, int r, int k) const {

FILE: dp_optimizations/convex_hull_trick.hpp
  class ConvexHullTrick (line 5) | class ConvexHullTrick {
    method T (line 10) | T div(T a, T b) {
    type Line (line 18) | struct Line {
    method intersect (line 28) | bool intersect(Iter x, Iter y) {
    method add (line 40) | void add(T k, T m) {
    method T (line 57) | T query(T x) {

FILE: geometry/dynamic_convex_hull.hpp
  class DynamicConvexHull (line 8) | class DynamicConvexHull {
    method add_to_hull (line 19) | void add_to_hull(set<Point>& hull, coord_t& sum, const Point& p, int s...
    method DynamicConvexHull (line 89) | DynamicConvexHull() = default;
    method add (line 91) | void add(const Point& p) {
    method coord_t (line 96) | coord_t doubled_area() const {

FILE: geometry/halfplane_intersection.hpp
  class HalfPlaneIntersection (line 8) | class HalfPlaneIntersection {
    method Point (line 14) | Point dir(int i) const { return lines[i].second - lines[i].first; }
    method outside (line 16) | bool outside(int i, const Point& pt) const {
    method Point (line 20) | Point inter(int i, int j) const {
    method is_parallel (line 26) | bool is_parallel(int i, int j) const {
    method same_direction (line 30) | bool same_direction(int i, int j) const { return (dir(i) * dir(j)) > 0; }
    method sort_by_angle (line 33) | static vector<Line> sort_by_angle(const vector<Line>& lines) {
    method HalfPlaneIntersection (line 41) | HalfPlaneIntersection(const vector<Line>& lines, bool is_sorted = false)
    method is_non_empty (line 82) | bool is_non_empty() const { return !empty_intersection; }
    method get_polygon (line 84) | vector<Point> get_polygon() const {

FILE: geometry/point.hpp
  type Point (line 9) | struct Point {
    method Point (line 14) | Point(coord_t x = 0, coord_t y = 0) : x(x), y(y) {}
    method Point (line 16) | Point operator+(const Point& p) const { return Point(x + p.x, y + p.y); }
    method Point (line 17) | Point operator-(const Point& p) const { return Point(x - p.x, y - p.y); }
    method Point (line 18) | Point operator*(coord_t c) const { return Point(x * c, y * c); }
    method Point (line 19) | Point operator/(coord_t c) const { return Point(x / c, y / c); }
    method coord_t (line 21) | coord_t operator*(const Point& p) const { return x * p.x + y * p.y; }
    method coord_t (line 22) | coord_t operator^(const Point& p) const { return x * p.y - y * p.x; }
    method coord_t (line 39) | coord_t norm2() const { return x * x + y * y; }
    method coord_t (line 40) | coord_t norm() const { return sqrt(norm2()); }
    method coord_t (line 41) | coord_t angle() const { return atan2(y, x); }
    method Point (line 43) | Point rotate(coord_t a) const {
    method Point (line 47) | Point perp() const { return Point(-y, x); }
    method Point (line 48) | Point unit() const { return *this / norm(); }
    method Point (line 49) | Point normal() const { return perp().unit(); }
    method Point (line 50) | Point project(const Point& p) const {
    method Point (line 53) | Point reflect(const Point& p) const {
    method ostream (line 57) | ostream& operator<<(ostream& os, const Point& p) {
    method istream (line 60) | istream& operator>>(istream& is, Point& p) {
    method ccw (line 64) | int ccw(const Point& a, const Point& b, const Point& c) {
    method point_on_segment (line 75) | bool point_on_segment(
    method point_in_triangle (line 83) | bool point_in_triangle(
    method Point (line 93) | Point line_line_intersection(
    method collinear (line 100) | bool collinear(const Point& a, const Point& b) {
    method Point (line 104) | Point circumcenter(const Point& a, const Point& b, const Point& c) {
    method coord_t (line 114) | coord_t arc_area(
    method intersect_circles (line 130) | vector<Point> intersect_circles(
    method intersect_ray_segment (line 159) | optional<Point> intersect_ray_segment(

FILE: geometry/polygon.hpp
  class Polygon (line 8) | class Polygon {
    method Polygon (line 12) | Polygon() {}
    method Polygon (line 13) | Polygon(const vector<Point>& points) : points(points) {}
    method size (line 15) | int size() const { return points.size(); }
    method Point (line 16) | const Point& operator[](int i) const { return points[i]; }
    method Point (line 17) | Point& operator[](int i) { return points[i]; }
    method coord_t (line 19) | coord_t area() const {
  class PointInConvexPolygon (line 28) | class PointInConvexPolygon {
    method prepare (line 33) | void prepare() {
    method PointInConvexPolygon (line 54) | PointInConvexPolygon(const Polygon& polygon) : polygon(polygon) {
    method contains (line 58) | bool contains(const Point& p) const {
  class ConvexHull (line 75) | class ConvexHull : public Polygon {
    method ConvexHull (line 80) | ConvexHull(const vector<Point>& points) {
    method tangents_from (line 139) | pair<int, int> tangents_from(const Point& p) const {

FILE: geometry/voronoi.hpp
  class VoronoiDiagram (line 12) | class VoronoiDiagram {
    type Arc (line 17) | struct Arc {
      method Arc (line 21) | Arc(const Point& p, const Point& q, int i) : p(p), q(q), i(i) {}
      method coord_t (line 23) | coord_t get_y(coord_t x) const {
    type Event (line 52) | struct Event {
      method Event (line 57) | Event(coord_t x, int id, Beach::iterator it) : x(x), id(id), it(it) {}
    method update_vertex_event (line 69) | void update_vertex_event(Beach::iterator it) {
    method add_edge (line 95) | void add_edge(int i, int j) {
    method add_point (line 102) | void add_point(int i) {
    method remove_arc (line 117) | void remove_arc(Beach::iterator it) {
    method VoronoiDiagram (line 131) | VoronoiDiagram(const vector<Point>& points, bool fix_coordinates = tru...
    method compute (line 149) | vector<pair<int, int>> compute(coord_t X = 1e9) {

FILE: graph/bcc.hpp
  class biconnected_components (line 5) | class biconnected_components {
    method tarjan (line 9) | void tarjan(int u, int pr, int &dfs_time, vector<pair<int, int>> &st) {
    method add_edge (line 50) | void add_edge(int u, int v) {
    method init (line 55) | void init(int _n) {
    method compute_bcc (line 60) | void compute_bcc() {

FILE: graph/bipartite_coloring.hpp
  type Edge (line 5) | struct Edge {
    method Edge (line 7) | Edge(int _u = 0, int _v = 0, int _idx = 0) : u(_u), v(_v), idx(_idx) {}
  class BipartiteColoring (line 10) | class BipartiteColoring {
    method make_larger_if_needed (line 18) | static void make_larger_if_needed(vector<T>& v, int size) {
    method partition_edges_euler (line 24) | pair<vector<Edge>, vector<Edge>> partition_edges_euler(
    method hopcroft_one_colour (line 71) | vector<Edge> hopcroft_one_colour(
    method good_worst_case_one_colour (line 119) | vector<Edge> good_worst_case_one_colour(
    method euler_colour (line 206) | int euler_colour(

FILE: graph/bipartite_matching.hpp
  class BipartiteMatching (line 4) | class BipartiteMatching {
    method try_kuhn (line 9) | bool try_kuhn(int u) {
    method pre_match (line 25) | int pre_match() {
    method BipartiteMatching (line 47) | BipartiteMatching(int _n, int _m = -1) : n(_n), m(_m == -1 ? _n : _m) {
    method clear (line 52) | void clear(bool clear_adj = true) {
    method add_edge (line 63) | void add_edge(int u, int v) { adj[u].push_back(v); }
    method match_vertex (line 65) | bool match_vertex(int u) {
    method max_matching (line 74) | int max_matching(bool shuffle_edges = false, bool pre_matching = false) {
    method get_matching (line 98) | vector<pair<int, int>> get_matching() {

FILE: graph/dijkstra_vlog.hpp
  function dijkstra (line 7) | vector<T> dijkstra(int src, const vector<vector<pair<int, T>>>& adj) {

FILE: graph/directed_cactus.hpp
  class DirectedCactus (line 4) | class DirectedCactus {
    method dfs (line 10) | void dfs(int u, int &dfs_time, vector<bool> &used, vector<int> &buff) {
    method DirectedCactus (line 24) | DirectedCactus() {
    method DirectedCactus (line 28) | DirectedCactus(vector<int> _nxt) { init(_nxt); }
    method init (line 30) | void init(vector<int> _nxt) {
    method distance (line 69) | int distance(int from, int to) {

FILE: graph/dsu.hpp
  class DSU (line 4) | class DSU {
    method DSU (line 10) | DSU(int _n = 0) { init(_n); }
    method init (line 12) | void init(int _n) {
    method root (line 22) | int root(int u) { return par[u] = ((u == par[u]) ? u : root(par[u])); }
    method connected (line 23) | bool connected(int x, int y) { return root(x) == root(y); }
    method unite (line 25) | int unite(int x, int y) {
    method components (line 38) | vector<vector<int>> components() {

FILE: graph/eppstein_shortest_paths.hpp
  class EppsteinShortestPaths (line 6) | class EppsteinShortestPaths {
    type Edge (line 10) | struct Edge {
      method Edge (line 13) | Edge(int _u = 0, int _v = 0, T _w = 0) : u(_u), v(_v), w(_w) {}
    method build_dijkstra_tree (line 16) | pair<vector<T>, vector<int>> build_dijkstra_tree(int t) {
    method topsort (line 52) | vector<int> topsort(const vector<int>& tree) {
    method init (line 91) | void init(int _n) {
    method EppsteinShortestPaths (line 98) | EppsteinShortestPaths(int n = 0) { init(n); }
    method add_edge (line 100) | int add_edge(int u, int v, T w, bool directed = true) {
    method get_k_shortest_paths (line 115) | vector<T> get_k_shortest_paths(int s, int t, int k) {

FILE: graph/eulerian_paths.hpp
  class EulerianPaths (line 13) | class EulerianPaths {
    method dfs (line 15) | void dfs(int u, vector<int>& path, vector<bool>& used, vector<int>& po) {
    method EulerianPaths (line 32) | EulerianPaths(int _n = 0) { init(_n); }
    method init (line 34) | void init(int _n) {
    method add_edge (line 42) | int add_edge(int u, int v) {
    method find_paths (line 53) | vector<vector<int>> find_paths() {
    method get_edge (line 108) | pair<int, int> get_edge(int edge_i) {
    method get_path_edges (line 116) | vector<pair<int, int>> get_path_edges(const vector<int>& path) {
    method is_cycle (line 124) | bool is_cycle(const vector<int>& path) {

FILE: graph/graph.hpp
  class UndirectedGraph (line 5) | class UndirectedGraph {
    method UndirectedGraph (line 14) | UndirectedGraph(int _n = 0, bool _maintain_dsu = false) {
    method init (line 18) | void init(int _n, bool _maintain_dsu = false) {
    method read_edges (line 30) | void read_edges(int _m, int idx_offset = -1) {
    method add_edges (line 40) | void add_edges(const vector<pair<int, int>>& new_edges) {
    method add_edge (line 46) | void add_edge(int u, int v) {
    method DSU (line 57) | DSU& get_dsu() {

FILE: graph/hopcroft_karp.hpp
  class HopcroftKarp (line 8) | class HopcroftKarp {
    method bfs (line 13) | bool bfs() {
    method dfs (line 41) | bool dfs(int u) {
    method HopcroftKarp (line 58) | HopcroftKarp(int _n, int _m = -1) : n(_n), m(_m == -1 ? _n : _m) {
    method clear (line 63) | void clear(bool clear_adj = true) {
    method add_edge (line 71) | void add_edge(int u, int v) { adj[u].push_back(v); }
    method max_matching (line 73) | int max_matching(bool shuffle_edges = false) {
    method get_matching (line 96) | vector<pair<int, int>> get_matching() {
    method minimum_vertex_cover (line 106) | pair<vector<int>, vector<int>> minimum_vertex_cover() {

FILE: graph/hungarian_algorithm.hpp
  class HungarianAlgorithm (line 9) | class HungarianAlgorithm {
    method HungarianAlgorithm (line 20) | HungarianAlgorithm(const vector<vector<T>>& a) {
    method T (line 78) | T get_cost() {

FILE: graph/maxflow.hpp
  class MaxFlow (line 5) | class MaxFlow {
    type Edge (line 7) | struct Edge {
      method Edge (line 10) | Edge(int _to, int _rev, T _flow, T _cap, int _idx)
    method bfs (line 17) | bool bfs(int s, int t) {
    method T (line 39) | T dfs(int u, int t, T fl = inf) {
    method MaxFlow (line 62) | MaxFlow(int n = 0) { init(n); }
    method init (line 66) | void init(int _n) {
    method add_edge (line 73) | void add_edge(int u, int v, T w, int idx = -1) {
    method T (line 78) | T flow(int s, int t) {

FILE: graph/mincost_circulation.hpp
  class MinCostCirculation (line 17) | class MinCostCirculation {
    type Edge (line 19) | struct Edge {
      method Edge (line 22) | Edge(int _from, int _to, T _capacity, T _cost, T _flow = 0)
    method dfs (line 36) | void dfs(int node) {
    method walk (line 50) | void walk(int ei, CB&& cb) {
    method MinCostCirculation (line 63) | MinCostCirculation(int _n = 0) { init(_n); }
    method init (line 65) | void init(int _n) {
    method size (line 74) | int size() const { return n; }
    method add_edge (line 76) | int add_edge(int from, int to, T capacity, T cost) {
    method T (line 83) | T min_circulation() {
    method Edge (line 137) | const Edge& get_edge(int id) const { return edges[id]; }
      method Edge (line 22) | Edge(int _from, int _to, T _capacity, T _cost, T _flow = 0)

FILE: graph/mincost_flow.hpp
  class MinCostFlow (line 7) | class MinCostFlow {
    type Edge (line 11) | struct Edge {
      method Edge (line 14) | Edge(int _to, int _rev, T _capacity, T _cost, T _flow)
    method build_potential (line 28) | void build_potential(int source) {
    method dijkstra (line 49) | bool dijkstra(int source, int sink, T flow_limit, T flow) {
    method MinCostFlow (line 81) | MinCostFlow(int _n = 0) { init(_n); }
    method init (line 83) | void init(int _n) {
    method size (line 91) | int size() const { return n; }
    method add_edge (line 93) | int add_edge(int from, int to, T capacity, T cost) {
    method flow (line 102) | pair<T, T> flow(int source, int sink, T flow_limit = inf) {

FILE: graph/scc.hpp
  class StronglyConnectedComponents (line 4) | class StronglyConnectedComponents {
    method dfs1 (line 8) | void dfs1(int u) {
    method dfs2 (line 19) | void dfs2(int u) {
    method StronglyConnectedComponents (line 33) | StronglyConnectedComponents() {}
    method StronglyConnectedComponents (line 34) | StronglyConnectedComponents(int _n) { init(_n); }
    method add_edge (line 36) | void add_edge(int u, int v) {
    method init (line 41) | void init(int _n) {
    method find_components (line 49) | void find_components() {

FILE: graph/st_numbering.hpp
  class STNumbering (line 4) | class STNumbering {
    method tarjan_check (line 10) | bool tarjan_check(int u, int pr) {
    method tarjan (line 35) | void tarjan(int u, int pr) {
    method STNumbering (line 56) | STNumbering() {}
    method STNumbering (line 57) | STNumbering(int _n) { init(_n); }
    method init (line 59) | void init(int _n) {
    method add_edge (line 65) | void add_edge(int u, int v) {
    method find_ordering (line 70) | bool find_ordering(int s, int t) {

FILE: graph/two_sat.hpp
  class TwoSat (line 4) | class TwoSat {
    method dfs1 (line 8) | void dfs1(int u) {
    method dfs2 (line 19) | void dfs2(int u) {
    method TwoSat (line 33) | TwoSat() {}
    method TwoSat (line 34) | TwoSat(int _n) { init(_n); }
    method init (line 36) | void init(int _n) {
    method add_implication (line 44) | void add_implication(int u, int v, bool neg_u = false, bool neg_v = fa...
    method solve (line 49) | pair<bool, vector<bool>> solve() {

FILE: math/gauss_bitset.hpp
  class GaussBitset (line 5) | class GaussBitset {
    method GaussBitset (line 12) | GaussBitset(int n_var_) : n_var(n_var_) {}
    method add_equation (line 14) | void add_equation(const vector<int>& coeffs, int rhs) {
    method eliminate (line 25) | void eliminate() {
    method has_solution (line 58) | bool has_solution() const { return solvable; }
    method free_variables (line 60) | vector<int> free_variables() const {
    method any_solution (line 70) | vector<int> any_solution() const {

FILE: old_impl/data_structures/implicit_treap.hpp
  type implicit_treap (line 7) | struct implicit_treap {
    type node (line 8) | struct node {
      method node (line 12) | node() {
      method node (line 22) | node(int _val) {
    method clear (line 41) | void clear() {
    method implicit_treap (line 46) | implicit_treap() { clear(); }
    method size (line 48) | int size(pnode p) { return p ? p->sz : 0; }
    method update_size (line 49) | void update_size(pnode &p) {
    method update_parent (line 55) | void update_parent(pnode &p) {
    method push (line 67) | void push(pnode &p) {
    method reset (line 91) | void reset(pnode &t) {
    method combine (line 97) | void combine(pnode &t, pnode l, pnode r) {
    method operation (line 109) | void operation(pnode &t) {
    method split (line 122) | void split(pnode t, pnode &l, pnode &r, int k, int add = 0) {
    method merge (line 142) | void merge(pnode &t, pnode l, pnode r) {
    method insert (line 166) | void insert(int pos, int val) {
    method erase (line 183) | void erase(int qL, int qR) {
    method query (line 191) | int query(int qL, int qR) {
    method update (line 205) | void update(int qL, int qR, int val) {
    method reverse (line 217) | void reverse(int qL, int qR) {
    method cyclic_shift (line 228) | void cyclic_shift(int qL, int qR, int k) {
    method get_pos (line 245) | int get_pos(pnode curr, pnode son = nullptr) {
    method get_pos (line 269) | int get_pos(int value) { return get_pos(position[value]); }
  function implicit_treap (line 272) | implicit_treap build(const vector<int> &a) {
    type node (line 8) | struct node {
      method node (line 12) | node() {
      method node (line 22) | node(int _val) {
    method clear (line 41) | void clear() {
    method implicit_treap (line 46) | implicit_treap() { clear(); }
    method size (line 48) | int size(pnode p) { return p ? p->sz : 0; }
    method update_size (line 49) | void update_size(pnode &p) {
    method update_parent (line 55) | void update_parent(pnode &p) {
    method push (line 67) | void push(pnode &p) {
    method reset (line 91) | void reset(pnode &t) {
    method combine (line 97) | void combine(pnode &t, pnode l, pnode r) {
    method operation (line 109) | void operation(pnode &t) {
    method split (line 122) | void split(pnode t, pnode &l, pnode &r, int k, int add = 0) {
    method merge (line 142) | void merge(pnode &t, pnode l, pnode r) {
    method insert (line 166) | void insert(int pos, int val) {
    method erase (line 183) | void erase(int qL, int qR) {
    method query (line 191) | int query(int qL, int qR) {
    method update (line 205) | void update(int qL, int qR, int val) {
    method reverse (line 217) | void reverse(int qL, int qR) {
    method cyclic_shift (line 228) | void cyclic_shift(int qL, int qR, int k) {
    method get_pos (line 245) | int get_pos(pnode curr, pnode son = nullptr) {
    method get_pos (line 269) | int get_pos(int value) { return get_pos(position[value]); }

FILE: old_impl/data_structures/implicit_treap_basic.hpp
  type implicit_treap (line 7) | struct implicit_treap {
    type node (line 8) | struct node {
      method node (line 11) | node() {
      method node (line 19) | node(int _val) {
    method size (line 31) | int size(pnode v) { return v ? v->sz : 0; }
    method update_size (line 32) | void update_size(pnode &v) {
    method reset (line 37) | void reset(pnode &v) {
    method combine (line 43) | void combine(pnode &v, pnode l, pnode r) {
    method operation (line 56) | void operation(pnode &v) {
    method merge (line 66) | void merge(pnode &t, pnode l, pnode r) {
    method split (line 86) | void split(pnode t, pnode &l, pnode &r, int k, int add = 0) {
    method implicit_treap (line 105) | implicit_treap() { root = nullptr; }
    method insert (line 107) | void insert(int pos, int val) {
    method query_max (line 121) | int query_max(int qL, int qR) {

FILE: old_impl/data_structures/max_count_segment_tree.cpp
  type count_max_segment_tree (line 5) | struct count_max_segment_tree {
    type node (line 6) | struct node {
      method node (line 8) | node() { mx = -(int)1e9, cnt = 0, lazy = 0; }
      method node (line 9) | node(int v) {
    method node (line 16) | node merge(node a, node b) {
      method node (line 8) | node() { mx = -(int)1e9, cnt = 0, lazy = 0; }
      method node (line 9) | node(int v) {
    method push (line 33) | void push(int l, int r, int idx) {
    method init (line 44) | void init(int l, int r, int idx) {
    method add (line 57) | void add(int ql, int qr, int v, int l, int r, int idx) {
    method node (line 77) | node query(int ql, int qr, int l, int r, int idx) {
      method node (line 8) | node() { mx = -(int)1e9, cnt = 0, lazy = 0; }
      method node (line 9) | node(int v) {
    method walk (line 95) | void walk(int l, int r, int idx) {

FILE: old_impl/data_structures/merging_segment_tree.cpp
  type node (line 4) | struct node {
    method node (line 8) | node() {
    method node (line 12) | node(int _s) {
  function size (line 20) | inline int size(pnode p) { return p ? p->sz : 0; }
  function update_size (line 22) | inline void update_size(pnode &p) {
  function pnode (line 29) | pnode init(int val, int l, int r) {
  function pnode (line 45) | pnode merge(pnode l, pnode r) {
  function split (line 60) | pair<pnode, pnode> split(pnode &t, int k) {
  function kth (line 86) | int kth(pnode t, int k, int l, int r) {

FILE: old_impl/data_structures/min_segment_tree.cpp
  function chkmin (line 11) | int chkmin(T &x, const T1 &y) { return x > y ? x = y, 1 : 0; }
  function chkmax (line 12) | int chkmax(T &x, const T1 &y) { return x < y ? x = y, 1 : 0; }
  type segment_tree_min (line 15) | struct segment_tree_min {
    type node (line 16) | struct node {
      method node (line 18) | node() {
      method node (line 23) | node(int v, int i) {
    method node (line 29) | node merge(node a, node b) {
      method node (line 18) | node() {
      method node (line 23) | node(int v, int i) {
    method init (line 37) | void init(int l, int r, int idx) {
    method update (line 49) | void update(int pos, int v, int l, int r, int idx) {
    method node (line 61) | node query(int ql, int qr, int l, int r, int idx) {
      method node (line 18) | node() {
      method node (line 23) | node(int v, int i) {
  function read (line 76) | void read() {
  function solve (line 80) | void solve() {
  function main (line 84) | int main() {

FILE: old_impl/data_structures/monotonous_queue.cpp
  function chkmax (line 5) | inline void chkmax(T &x, const T2 &y) { if(x < y) x = y; }
  function chkmin (line 6) | inline void chkmin(T &x, const T2 &y) { if(x > y) x = y; }
  type monotonous_queue_max (line 10) | struct monotonous_queue_max
    method monotonous_queue_max (line 15) | monotonous_queue_max() { Q.clear(); current_position = 0; len = 0; }
    method init (line 17) | void init(int _l)
    method push_back (line 24) | void push_back(T x)
    method T (line 31) | T query()
  type monotonous_queue_min (line 39) | struct monotonous_queue_min
    method monotonous_queue_min (line 44) | monotonous_queue_min() { Q.clear(); current_position = 0; len = 0; }
    method init (line 46) | void init(int _l)
    method push_back (line 53) | void push_back(T x)
    method T (line 60) | T query()
  function read (line 67) | void read()
  function solve (line 72) | void solve()
  function main (line 77) | int main()

FILE: old_impl/data_structures/persistent_segment_tree.cpp
  type node (line 7) | struct node {
    method node (line 10) | node() {
    method node (line 15) | node(int x) {
  function node (line 22) | node* merge(node* l, node* r) {
    method node (line 10) | node() {
    method node (line 15) | node(int x) {
  function node (line 30) | node* init(int l, int r) {
    method node (line 10) | node() {
    method node (line 15) | node(int x) {
  function node (line 39) | node* update(int pos, int val, int l, int r, node* nd) {
    method node (line 10) | node() {
    method node (line 15) | node(int x) {
  function query (line 53) | int query(int qL, int qR, int l, int r, node* nd) {
  function get_kth (line 65) | int get_kth(int k, int l, int r, node* nd) {
  function read (line 78) | void read() {}
  function solve (line 82) | void solve() {}
  function main (line 84) | int main() {

FILE: old_impl/data_structures/persistent_segment_tree_lazy.cpp
  function chkmax (line 6) | inline void chkmax(T &x, const T2 &y) {
  function chkmin (line 12) | inline void chkmin(T &x, const T2 &y) {
  type node (line 22) | struct node {
    method node (line 26) | node() {
    method node (line 30) | node(int64_t val) {
  function pnode (line 39) | pnode merge(pnode a, pnode b) {
  function pnode (line 49) | pnode cop(pnode b) {
  function push (line 63) | void push(int l, int r, pnode &ver) {
  function pnode (line 81) | pnode init(int l, int r) {
  function pnode (line 89) | pnode update(int qL, int qR, int val, int l, int r, pnode prv) {
  function query (line 110) | int64_t query(int qL, int qR, int l, int r, pnode nd) {
  function read (line 123) | void read() {
  function solve (line 132) | void solve() { root[1] = init(0, n - 1); }
  function main (line 134) | int main() {

FILE: old_impl/data_structures/persistent_treap.cpp
  type persistent_treap (line 10) | struct persistent_treap
    type node (line 12) | struct node
      method node (line 16) | node() { sz = 0; mx = 0; val = 0; l = nullptr; r = nullptr; }
      method node (line 17) | node(int _val) { val = _val; mx = val; sz = 1; l = nullptr; r = null...
    method pnode (line 22) | pnode copy_node(pnode prv)
    method size (line 35) | int size(pnode v) { return v ? v->sz : 0; }
    method update_size (line 36) | void update_size(pnode &v) { if(v) v->sz = size(v->l) + size(v->r) + 1; }
    method reset (line 37) | void reset(pnode &v) { if(v) v->mx = v->val; }
    method hey (line 38) | bool hey(int a, int b) { return (int)mt() % (a + b) < a; }
    method combine (line 40) | void combine(pnode &v, pnode l, pnode r)
    method operation (line 48) | void operation(pnode &v)
    method merge (line 57) | void merge(pnode &t, pnode l, pnode r)
    method split (line 77) | void split(pnode t, pnode &l, pnode &r, int k, int add = 0)
    method persistent_treap (line 102) | persistent_treap() { root = nullptr; }
    method insert (line 104) | void insert(int pos, int val)
    method query_max (line 120) | int query_max(int qL, int qR)
  function read (line 137) | void read()
  function solve (line 142) | void solve()
  function main (line 147) | int main()

FILE: old_impl/data_structures/persistent_treap_lazy.cpp
  type persistent_treap (line 10) | struct persistent_treap
    type node (line 12) | struct node
      method node (line 16) | node() { sz = 0; mx = 0; lazy = 0; val = 0; l = nullptr; r = nullptr; }
      method node (line 17) | node(int _val) { lazy = 0; val = _val; mx = val; sz = 1; l = nullptr...
    method pnode (line 22) | pnode copy_node(pnode prv)
    method size (line 36) | int size(pnode v) { return v ? v->sz : 0; }
    method update_size (line 37) | void update_size(pnode &v) { if(v) v->sz = size(v->l) + size(v->r) + 1; }
    method reset (line 38) | void reset(pnode &v) { if(v) v->mx = v->val; }
    method hey (line 39) | bool hey(int a, int b) { return (int)mt() % (a + b) < a; }
    method push (line 41) | void push(pnode &t)
    method combine (line 53) | void combine(pnode &v, pnode l, pnode r)
    method operation (line 61) | void operation(pnode &v)
    method merge (line 73) | void merge(pnode &t, pnode l, pnode r)
    method split (line 95) | void split(pnode t, pnode &l, pnode &r, int k, int add = 0)
    method persistent_treap (line 122) | persistent_treap() { root = nullptr; }
    method insert (line 124) | void insert(int pos, int val)
    method query_max (line 140) | int query_max(int qL, int qR)
  function read (line 157) | void read()
  function solve (line 162) | void solve()
  function main (line 167) | int main()

FILE: old_impl/data_structures/segment_tree.cpp
  type node (line 10) | struct node {
    method node (line 12) | node() { sum = 0; }
    method node (line 13) | node(int val) {
  function node (line 18) | node merge(node l, node r) {
    method node (line 12) | node() { sum = 0; }
    method node (line 13) | node(int val) {
  type segment_tree (line 24) | struct segment_tree {
    method init (line 27) | void init(int l, int r, int idx) {
    method update (line 40) | void update(int pos, int val, int l, int r, int idx) {
    method node (line 56) | node query(int qL, int qR, int l, int r, int idx) {
  function read (line 70) | void read()
  function solve (line 79) | void solve()
  function main (line 91) | int main()

FILE: old_impl/data_structures/segment_tree_AP.cpp
  type node_ap (line 10) | struct node_ap
    method node_ap (line 14) | node_ap() {sum = 0; lazy = 0; lazy_ap = 0;}
    method node_ap (line 15) | node_ap(int val)
  function node_ap (line 25) | node_ap merge(node_ap l, node_ap r)
    method node_ap (line 14) | node_ap() {sum = 0; lazy = 0; lazy_ap = 0;}
    method node_ap (line 15) | node_ap(int val)
  type segment_tree_ap (line 33) | struct segment_tree_ap
    method update (line 37) | void update(int l, int r, int idx)
    method init (line 68) | void init(int l, int r, int idx)
    method update (line 83) | void update(int qL, int qR, int val, int prog, int l, int r, int idx)
    method node_ap (line 105) | node_ap query(int qL, int qR, int l, int r, int idx)
  function read (line 120) | void read()
  function solve (line 127) | void solve()
  function main (line 133) | int main()

FILE: old_impl/data_structures/segment_tree_add_mult.cpp
  function chkmax (line 8) | inline int chkmax(T &x, const T2 &y) { return x < y ? x = y, 1 : 0; }
  function chkmin (line 9) | inline int chkmin(T &x, const T2 &y) { return x > y ? x = y, 1 : 0; }
  type node (line 13) | struct node
    method node (line 17) | node() {sum = 0; mult = 1; lazy = 0;}
    method node (line 18) | node(int val)
  function node (line 28) | node merge(node l, node r)
    method node (line 17) | node() {sum = 0; mult = 1; lazy = 0;}
    method node (line 18) | node(int val)
  type segment_tree (line 36) | struct segment_tree
    method push (line 40) | void push(int l, int r, int idx)
    method init (line 73) | void init(int l, int r, int idx)
    method mult (line 88) | void mult(int qL, int qR, int x, int l, int r, int idx)
    method add (line 108) | void add(int qL, int qR, int x, int l, int r, int idx)
    method node (line 128) | node query(int qL, int qR, int l, int r, int idx)
  function read (line 143) | void read()
  function solve (line 148) | void solve()
  function main (line 153) | int main()

FILE: old_impl/data_structures/segment_tree_fast.cpp
  type node (line 7) | struct node {
    method node (line 9) | node() { mx = -1e9; }
    method node (line 10) | node(int val) { mx = val; }
  function node (line 15) | node merge(node l, node r) {
    method node (line 9) | node() { mx = -1e9; }
    method node (line 10) | node(int val) { mx = val; }
  type segment_tree (line 20) | struct segment_tree {
    method init (line 24) | void init(int sz) {
    method modify (line 34) | void modify(int p, const node &value) {
    method node (line 40) | node query(int l, int r) {
  function read (line 55) | void read() {}
  function solve (line 59) | void solve() {}
  function main (line 61) | int main() {

FILE: old_impl/data_structures/segment_tree_lazy_min.cpp
  class segment_tree_min (line 6) | class segment_tree_min {
    type node (line 10) | struct node {
      method node (line 14) | node() {
      method node (line 19) | node(T val, int p) {
    method node (line 25) | node merge(node l, node r) {
      method node (line 14) | node() {
      method node (line 19) | node(T val, int p) {
    method push (line 37) | void push(int l, int r, int idx) {
    method init (line 54) | void init(int l, int r, int idx, const vector<T> &a) {
    method update (line 67) | void update(int qL, int qR, T val, int l, int r, int idx) {
    method node (line 87) | node query(int qL, int qR, int l, int r, int idx) {
      method node (line 14) | node() {
      method node (line 19) | node(T val, int p) {
    method init (line 106) | void init(const vector<T> &a) {
    method update (line 113) | void update(int qL, int qR, int val) {
    method node (line 120) | node query(int qL, int qR) {
      method node (line 14) | node() {
      method node (line 19) | node(T val, int p) {
  function read (line 132) | void read() {
  function solve (line 142) | void solve() {}
  function main (line 144) | int main() {

FILE: old_impl/data_structures/segment_tree_lazy_sum.cpp
  class segment_tree_sum (line 5) | class segment_tree_sum {
    type node (line 7) | struct node {
      method node (line 10) | node() { sum = 0; }
      method node (line 11) | node(T val) { sum = val; }
    method node (line 14) | node merge(node l, node r) {
      method node (line 10) | node() { sum = 0; }
      method node (line 11) | node(T val) { sum = val; }
    method push (line 20) | void push(int l, int r, int idx) {
    method init (line 37) | void init(int l, int r, int idx, const vector<T> &a) {
    method update (line 50) | void update(int qL, int qR, T val, int l, int r, int idx) {
    method node (line 70) | node query(int qL, int qR, int l, int r, int idx) {
      method node (line 10) | node() { sum = 0; }
      method node (line 11) | node(T val) { sum = val; }
    method init (line 89) | void init(vector<T> a) {
    method update (line 96) | void update(int qL, int qR, int val) {
    method node (line 103) | node query(int qL, int qR) {
      method node (line 10) | node() { sum = 0; }
      method node (line 11) | node(T val) { sum = val; }
  function read (line 115) | void read() {
  function solve (line 125) | void solve() {}
  function main (line 127) | int main() {

FILE: old_impl/data_structures/segment_tree_nonzero.cpp
  type segment_tree (line 7) | struct segment_tree
    method init (line 11) | void init(int l, int r, int idx)
    method update (line 28) | void update(int qL, int qR, int val, int l, int r, int idx)
  function read (line 50) | void read()
  function solve (line 57) | void solve()
  function main (line 62) | int main()

FILE: old_impl/data_structures/segment_tree_with_binary_search.cpp
  function chkmax (line 5) | inline void chkmax(T &x, const T2 &y) { if(x < y) x = y; }
  function chkmin (line 6) | inline void chkmin(T &x, const T2 &y) { if(x > y) x = y; }
  type node (line 10) | struct node
    method node (line 13) | node() { mn = inf; }
    method node (line 14) | node(int val) { mn = val; }
  function node (line 19) | node merge(node l, node r)
    method node (line 13) | node() { mn = inf; }
    method node (line 14) | node(int val) { mn = val; }
  type segment_tree (line 26) | struct segment_tree
    method init (line 30) | void init(int l, int r, int idx)
    method update (line 47) | void update(int pos, int val, int l, int r, int idx)
    method get_nodes (line 65) | void get_nodes(int qL, int qR, int l, int r, int idx, vector<int> &li)
    method get_right (line 79) | int get_right(int l, int r, int idx, int X)
    method get_left (line 87) | int get_left(int l, int r, int idx, int X)
  function get_left (line 99) | int get_left(int pos, int val)
  function get_right (line 112) | int get_right(int pos, int val)
  function read (line 125) | void read()
  function solve (line 130) | void solve()
  function main (line 135) | int main()

FILE: old_impl/data_structures/treap.cpp
  type node (line 7) | struct node {
    method node (line 10) | node() {
    method node (line 17) | node(int v) {
  function size (line 28) | inline int size(pnode v) { return v ? v->sz : 0; }
  function pull (line 30) | void pull(pnode &v) {
  function merge (line 37) | void merge(pnode &t, pnode l, pnode r) {
  function split (line 56) | void split(pnode t, pnode &l, pnode &r, int k) {
  function merge_op (line 72) | void merge_op(pnode &t, pnode l, pnode r) {
  function split_sz (line 95) | void split_sz(pnode t, pnode &l, pnode &r, int k, int add = 0) {
  function read (line 112) | void read() {}
  function solve (line 114) | void solve() {}
  function main (line 116) | int main() {

FILE: old_impl/geometry/closest_points.cpp
  type point (line 11) | struct point
    method point (line 15) | point() {x = 0; y = 0;}
    method point (line 16) | point(int _x, int _y)
  function cmpbyx (line 23) | bool cmpbyx(point a, point b)
  function cmpbyy (line 29) | bool cmpbyy(point a, point b)
  function read (line 38) | void read()
  function dist (line 46) | int dist(point p_i, point p_j) { return (p_i.x - p_j.x) * (p_i.x - p_j.x...
  function rec (line 48) | int rec(int l, int r)
  function solve (line 74) | void solve()
  function main (line 90) | int main()

FILE: old_impl/geometry/convex_hull.cpp
  type point (line 11) | struct point {
    method point (line 13) | point() {x = 0; y = 0;}
    method point (line 14) | point(double _x, double _y) {
  function cmp (line 20) | bool cmp(point a, point b) {
  function slope (line 25) | double slope(point a, point b) {
  type convex_hull (line 33) | struct convex_hull {
    method convex_hull (line 35) | convex_hull() {st.clear();}
    method compute_hull (line 36) | void compute_hull(vector<point> vec) {
  function read (line 61) | void read()
  function solve (line 75) | void solve()
  function main (line 80) | int main()

FILE: old_impl/geometry/dynamic_upper_hull.cpp
  function chkmin (line 11) | int chkmin(T &x, const T1 &y) { return x > y ? x = y, 1 : 0; }
  function chkmax (line 12) | int chkmax(T &x, const T1 &y) { return x < y ? x = y, 1 : 0; }
  type PT (line 15) | struct PT
    method PT (line 18) | PT() { x = y = 0; }
    method PT (line 19) | PT(int _x, int _y) { x = _x; y = _y; }
    method PT (line 22) | PT operator+(const PT &other) const { return PT(x + other.x, y + other...
    method PT (line 23) | PT operator-(const PT &other) const { return PT(x - other.x, y - other...
  function eval (line 29) | int64_t eval(PT L, PT R) { return (L.y + R.y) * 1ll * (R.x - L.x); }
  type node (line 31) | struct node
    method node (line 38) | node() { sz = 0; answer = prior = 0; leftmost = rightmost = prv = l = ...
    method node (line 39) | node(PT a) {leftmost = rightmost = this; sz = 1; answer = 0; pnt = a; ...
  function size (line 44) | inline int size(pnode &t) { return t ? t->sz : 0; }
  function pull (line 46) | void pull(pnode &t)
  function merge (line 72) | void merge(pnode &t, pnode l, pnode r)
  function split_x (line 85) | void split_x(pnode t, pnode &l, pnode &r, int k)
  function split_sz (line 97) | void split_sz(pnode t, pnode &l, pnode &r, int k, int add = 0)
  function read (line 114) | void read()
  function add (line 144) | void add(int ql, int qr, int i, int l, int r, int idx)
  function cww (line 160) | int64_t cww(const PT &a, const PT &b, const PT &c) { return (b - a) & (c...
  function find_pref (line 162) | int find_pref(pnode t, PT R)
  function find_suff (line 171) | int find_suff(pnode t, PT L)
  function add (line 186) | pair<bool, pnode> add(pnode &t, PT pnt)
  function solve (line 217) | void solve(int l, int r, int idx)
  function solve (line 249) | void solve()
  function main (line 262) | int main()

FILE: old_impl/geometry/kd-tree.cpp
  function sq (line 8) | inline int64_t sq(int x) { return x * 1ll * x; }
  type point (line 10) | struct point
    method point (line 13) | point() { }
  type cmp (line 16) | struct cmp
    method cmp (line 19) | cmp() { current_d = 0; }
    method cmp (line 20) | cmp(int d) { current_d = d; }
  function sq_dist (line 24) | int64_t sq_dist(point a, point b, int d)
  type kd_tree (line 33) | struct kd_tree
    type node (line 35) | struct node
      method node (line 39) | node() { L = -1; R = -1; }
      method node (line 40) | node(point _p) { L = -1; R = -1; p = _p; }
    method kd_tree (line 46) | kd_tree() { D = 0; psz = 0; }
    method kd_tree (line 47) | kd_tree(int d) { D = d; psz = 0; }
    method new_node (line 49) | int new_node() { return psz++; }
    method build (line 51) | int build(point *from, point *to, int axis)
    method init (line 71) | void init(point *from, point *to, int d)
    method query (line 78) | void query(int idx, point q, int64_t &answer)
    method nearest_neigbhor (line 95) | double nearest_neigbhor(point q)
  function read (line 106) | void read()
  function solve (line 116) | void solve()
  function main (line 132) | int main()

FILE: old_impl/geometry/rectangle_union.cpp
  type edge (line 11) | struct edge
    method edge (line 14) | edge() {x = -1; y1 = -1; y2 = -1; val = -1;}
    method edge (line 15) | edge(int _x, int _y1, int _y2, int _val)
  function read (line 32) | void read()
  function compress (line 55) | void compress()
  type segment_tree (line 82) | struct segment_tree
    type node (line 84) | struct node
      method node (line 87) | node() {lazy = 0, ans = 0;}
      method node (line 88) | node(int v) { ans = v; lazy = 0;}
    method update (line 93) | void update(int qL, int qR, int val, int l, int r, int idx)
  function mabs (line 120) | inline int mabs(int x) { return x < 0 ? -x : x; }
  function rectangle_union (line 122) | int rectangle_union()
  function solve (line 138) | void solve()
  function main (line 144) | int main()

FILE: old_impl/graph/dsu_bipartite.cpp
  function read (line 10) | void read() {
  function root (line 18) | int root(int u) {
  function unite (line 23) | void unite(int u, int v) {
  function solve (line 43) | void solve() {
  function main (line 52) | int main() {

FILE: old_impl/graph/eulerian_path.cpp
  function chkmin (line 6) | int chkmin(T &x, const T1 &y) {
  function chkmax (line 11) | int chkmax(T &x, const T1 &y) {
  function ostream (line 16) | ostream &operator<<(ostream &out, const pair<T1, T2> &x) {
  function istream (line 21) | istream &operator>>(istream &in, pair<T1, T2> &x) {
  function istream (line 26) | istream &operator>>(istream &in, vector<T> &a) {
  function ostream (line 34) | ostream &operator<<(ostream &out, vector<T> &a) {
  function read (line 58) | void read() {
  function dfs (line 77) | void dfs(int u) {
  function get_edge (line 88) | pair<int, int> get_edge(int edge_i) {
  function dfs_visit_nodes (line 96) | void dfs_visit_nodes(int u, vector<bool> &visited, vector<int> &nodes) {
  function solve (line 106) | void solve() {
  function main (line 211) | int main() {

FILE: old_impl/graph/max_anticlique.cpp
  function get_deg (line 13) | int get_deg(int u) {
  function dfs (line 21) | void dfs(int u) {
  function brute (line 29) | int brute() {
  function rec (line 53) | int rec() {
  function max_anticlique (line 80) | int max_anticlique() {
  function read (line 85) | void read() {}
  function solve (line 87) | void solve() {}
  function main (line 89) | int main() {

FILE: old_impl/graph/maximum_closure.cpp
  function chkmax (line 5) | inline void chkmax(T &x, const T2 &y) { if(x < y) x = y; }
  function chkmin (line 6) | inline void chkmin(T &x, const T2 &y) { if(x > y) x = y; }
  type max_flow (line 10) | struct max_flow
    type edge (line 15) | struct edge
      method edge (line 19) | edge() { flow = 0; cap = 0; rev = 0; idx = 0; to = 0; }
      method edge (line 20) | edge(int _to, int _rev, FlowT _flow, FlowT _cap, int _idx)
    method bfs (line 31) | bool bfs(int s, int t)
    method FlowT (line 58) | FlowT dfs(int u, int t, FlowT fl = finf)
    method init (line 81) | void init(int _n) { n = _n; for(int i = 0; i <= n; i++) G[i].clear(); }
    method add_edge (line 83) | void add_edge(int u, int v, FlowT w, int idx = -1)
    method FlowT (line 89) | FlowT flow(int s, int t)
  type maximum_closure (line 103) | struct maximum_closure
    method init (line 110) | void init(int _n)
    method add_clause (line 117) | void add_clause(int i, int j) { adj[i].push_back(j); }
    method dfs_tarjan (line 123) | void dfs_tarjan(int u)
    method T (line 154) | T solve()
  function read (line 187) | void read()
  function solve (line 192) | void solve()
  function main (line 197) | int main()

FILE: old_impl/graph/mincost_maxflow.cpp
  type edge (line 10) | struct edge {
    method edge (line 12) | edge() {
    method edge (line 19) | edge(int _to, int _rev, int _flow, int _cap, int _cost) {
  function add_edge (line 31) | void add_edge(int u, int v, int w, int cost) {
  function spfa (line 42) | bool spfa() {
  function min_cost_flow (line 82) | pair<int, int> min_cost_flow(int flow) {
  function read (line 107) | void read() {}
  function solve (line 109) | void solve() {}
  function main (line 111) | int main() {
  function next_char (line 124) | void next_char() {
  function read_int (line 130) | int read_int() {

FILE: old_impl/graph/persistent_dsu.cpp
  type persistent_dsu (line 7) | struct persistent_dsu
    type state (line 9) | struct state
      method state (line 12) | state() {u = -1; v = -1; rnkv = -1; rnku = -1;}
      method state (line 13) | state(int _u, int _rnku, int _v, int _rnkv)
    method persistent_dsu (line 24) | persistent_dsu() {memset(par, -1, sizeof(par)); memset(depth, 0, sizeo...
    method root (line 26) | int root(int x)
    method init (line 32) | void init(int n)
    method connected (line 41) | bool connected(int x, int y)
    method unite (line 46) | void unite(int x, int y)
    method backtrack (line 62) | void backtrack(int c)
  function read (line 76) | void read()
  function solve (line 83) | void solve()
  function main (line 88) | int main()

FILE: old_impl/graph/scc_tarjan.cpp
  function read (line 10) | void read()
  function dfs (line 29) | void dfs(int u)
  function tarjan (line 68) | void tarjan()
  function solve (line 89) | void solve()
  function main (line 94) | int main()

FILE: old_impl/graph/st_numbering.cpp
  function chkmax (line 8) | inline int chkmax(T &x, const T2 &y) { return x < y ? x = y, 1 : 0; }
  function chkmin (line 9) | inline int chkmin(T &x, const T2 &y) { return x > y ? x = y, 1 : 0; }
  function read (line 15) | void read() {
  function tarjan_check (line 28) | bool tarjan_check(int u, int pr = -1) {
  function tarjan (line 47) | void tarjan(int u, int pr = -1) {
  function st_numbering (line 64) | vector<int> st_numbering() {
  function solve (line 105) | void solve() {
  function main (line 111) | int main() {

FILE: old_impl/math/combinatorics.cpp
  function T (line 6) | T pw(T a, int pw) {
  class modint_t (line 20) | class modint_t {
    method modint_t (line 25) | modint_t() { x = 0; }
    method modint_t (line 26) | modint_t(unsigned _x) { x = _x; }
    method modint_t (line 32) | modint_t operator+=(const modint_t& m) {
    method modint_t (line 36) | modint_t operator-=(const modint_t& m) {
    method modint_t (line 40) | modint_t operator*=(const modint_t& m) {
    method modint_t (line 45) | modint_t operator+=(const int32_t m) {
    method modint_t (line 49) | modint_t operator-=(const int32_t m) {
    method modint_t (line 53) | modint_t operator*=(const int32_t m) {
    method modint_t (line 58) | modint_t operator+=(const int64_t m) {
    method modint_t (line 62) | modint_t operator-=(const int64_t m) {
    method modint_t (line 66) | modint_t operator*=(const int64_t m) {
    method modint_t (line 71) | modint_t operator+(const modint_t& m) const { return modint_t(*this) +...
    method modint_t (line 72) | modint_t operator-(const modint_t& m) const { return modint_t(*this) -...
    method modint_t (line 73) | modint_t operator*(const modint_t& m) const { return modint_t(*this) *...
    method modint_t (line 75) | modint_t operator+(const int32_t m) const { return modint_t(*this) += ...
    method modint_t (line 76) | modint_t operator-(const int32_t m) const { return modint_t(*this) -= ...
    method modint_t (line 77) | modint_t operator*(const int32_t m) const { return modint_t(*this) *= ...
    method modint_t (line 79) | modint_t operator+(const int64_t m) const { return modint_t(*this) += ...
    method modint_t (line 80) | modint_t operator-(const int64_t m) const { return modint_t(*this) -= ...
    method modint_t (line 81) | modint_t operator*(const int64_t m) const { return modint_t(*this) *= ...
    method modint_t (line 83) | modint_t inv() { return pw(modint_t(*this), mod - 2); }
  function precompute (line 90) | void precompute(int bound) {
  function mint (line 110) | mint C(int n, int k) {
  function main (line 117) | int main() {

FILE: old_impl/math/fft.cpp
  type complex_base (line 8) | struct complex_base
    method complex_base (line 11) | complex_base(double _x = 0, double _y = 0) { x = _x; y = _y; }
    method complex_base (line 12) | complex_base operator-(const complex_base &a, const complex_base &b) {...
    method complex_base (line 13) | complex_base operator+(const complex_base &a, const complex_base &b) {...
    method complex_base (line 14) | complex_base operator*(const complex_base &a, const complex_base &b) {...
  function fft (line 22) | void fft(complex_base *a, int lg)
  function inv_fft (line 53) | void inv_fft(complex_base *a, int lg)
  function mult (line 89) | vector<int> mult(vector<int> a, vector<int> b)
  function read (line 118) | void read()
  function solve (line 123) | void solve()
  function main (line 128) | int main()

FILE: old_impl/math/fft_mod.cpp
  function chkmax (line 5) | inline void chkmax(T &x, const T2 &y) { if(x < y) x = y; }
  function chkmin (line 6) | inline void chkmin(T &x, const T2 &y) { if(x > y) x = y; }
  function addmod (line 11) | inline void addmod(int& x, int y, int mod) { (x += y) >= mod && (x -= mo...
  function mulmod (line 12) | inline int mulmod(int x, int y, int mod) { return x * 1ll * y % mod; }
  type complex_base (line 14) | struct complex_base
    method complex_base (line 17) | complex_base(double _x = 0, double _y = 0) { x = _x; y = _y; }
    method complex_base (line 18) | complex_base operator-(const complex_base &a, const complex_base &b) {...
    method complex_base (line 19) | complex_base operator+(const complex_base &a, const complex_base &b) {...
    method complex_base (line 20) | complex_base operator*(const complex_base &a, const complex_base &b) {...
  function fft (line 28) | void fft(complex_base *a, int lg)
  function inv_fft (line 59) | void inv_fft(complex_base *a, int lg)
  function mult (line 95) | vector<int> mult(const vector<int> &a, const vector<int> &b)
  function mult_mod (line 124) | vector<int> mult_mod(const vector<int> &a, const vector<int> &b)
  function read (line 177) | void read()
  function solve (line 182) | void solve()
  function main (line 187) | int main()

FILE: old_impl/math/fft_xor.cpp
  function fft (line 11) | void fft(polynomial &a, int low, int high)
  function inv_fft (line 30) | void inv_fft(polynomial &a, int low, int high)
  function read (line 50) | void read()
  function solve (line 55) | void solve()
  function main (line 61) | int main()

FILE: old_impl/math/fft_xor_mod.cpp
  function pow (line 14) | int pow(int x, int p)
  function inv (line 27) | int inv(int x, int mod) { return pow(x, mod - 2); }
  function fft (line 29) | void fft(polynomial &a, int low, int high)
  function inv_fft (line 48) | void inv_fft(polynomial &a, int low, int high)
  function read (line 68) | void read()
  function solve (line 73) | void solve()
  function main (line 80) | int main()

FILE: old_impl/math/gauss_elimination_equations.cpp
  function gauss (line 8) | vector<double> gauss(vector<vector<double>> &a)
  function read (line 55) | void read()
  function solve (line 60) | void solve()
  function main (line 65) | int main()

FILE: old_impl/math/gauss_elimination_equations_mod.cpp
  function pow (line 8) | int64_t pow(int64_t base, int64_t p, int64_t MOD)
  function inv (line 15) | int64_t inv(int64_t x, int64_t MOD) { return pow(x, MOD - 2, MOD); }
  function gauss (line 17) | vector<int64_t> gauss(vector<vector<int64_t>> &a, int64_t MOD)
  function read (line 69) | void read()
  function solve (line 74) | void solve()
  function main (line 79) | int main()

FILE: old_impl/math/gauss_elimination_equations_mod_number_solutions.cpp
  function pow (line 8) | int64_t pow(int64_t base, int64_t p, int64_t MOD)
  function inv (line 15) | int64_t inv(int64_t x, int64_t MOD) { return pow(x, MOD - 2, MOD); }
  function gauss (line 17) | int64_t gauss(vector<vector<int64_t>> &a, int64_t MOD)
  function read (line 71) | void read()
  function solve (line 76) | void solve()
  function main (line 81) | int main()

FILE: old_impl/math/matrix_exponential.cpp
  type matrix (line 10) | struct matrix
    method matrix (line 15) | matrix(int _n, T val) {n = _n; t.assign(n, vector<T>(n, val)); }
    method matrix (line 16) | matrix(int _n) {n = _n; t.assign(n, vector<T>(n, 0)); }
    method matrix (line 17) | matrix() { n = 0; t.clear(); }
    method matrix (line 19) | matrix operator * (matrix b)
    method matrix (line 69) | matrix operator & (matrix b)
  function pow_min (line 82) | matrix<T> pow_min(matrix<T> base, int64_t p)
  function pow_max (line 96) | matrix<T> pow_max(matrix<T> base, int64_t p)
  function pow (line 110) | matrix<T> pow(matrix<T> base, int64_t p)
  function print (line 124) | void print(matrix<T> mat)
  function read (line 134) | void read()
  function solve (line 139) | void solve()
  function main (line 144) | int main()

FILE: old_impl/math/number_theory.cpp
  function pow (line 9) | int64_t pow(int64_t x, int64_t p, int64_t MOD)
  function get_divs (line 21) | vector<T> get_divs(T x)
  function gcd (line 38) | int64_t gcd(int64_t a, int64_t b, int64_t &x, int64_t &y)
  function prepare (line 54) | void prepare()
  function gcd (line 67) | int64_t gcd(int64_t a, int64_t b)
  function get_phi (line 73) | int64_t get_phi(int64_t x)
  function pinv (line 88) | int64_t pinv(int64_t x, int64_t MOD) { return pow(x, MOD - 2, MOD); }
  function inv (line 90) | int64_t inv(int64_t x, int64_t MOD)
  function read (line 97) | void read()
  function solve (line 102) | void solve()
  function main (line 107) | int main()

FILE: old_impl/strings/aho_corasick.cpp
  type aho_corasick (line 7) | struct aho_corasick
    method clear (line 12) | void clear()
    method aho_corasick (line 21) | aho_corasick() { psz = MAXN - 2; clear(); }
    method add_word (line 23) | void add_word(string s)
    method push_links (line 35) | void push_links()
  function read (line 68) | void read()
  function solve (line 77) | void solve()
  function main (line 85) | int main()

FILE: old_impl/strings/aho_corasick_dynamic.cpp
  type aho_corasick_static (line 7) | struct aho_corasick_static
    method clear (line 12) | void clear()
    method aho_corasick_static (line 22) | aho_corasick_static() { psz = MAXN - 2; clear(); }
    method add_word (line 24) | void add_word(string s)
    method push_links (line 36) | void push_links()
    method count (line 66) | int count(string p)
  type aho_corasick (line 81) | struct aho_corasick
    method clear (line 86) | void clear()
    method aho_corasick (line 95) | aho_corasick() { clear(); }
    method add_word (line 97) | void add_word(string s)
    method count (line 125) | int count(string s)
  function read (line 138) | void read()
  function solve (line 147) | void solve()
  function main (line 157) | int main()

FILE: old_impl/strings/kmp.cpp
  function read (line 9) | void read() {
  function failure_function (line 14) | vector<int> failure_function(string p) {
  function match (line 38) | void match(vector<int> f, string p, string s) {
  function solve (line 62) | void solve() {
  function main (line 67) | int main() {

FILE: old_impl/strings/palindromic_tree.cpp
  type palindromic_tree (line 7) | struct palindromic_tree
    method clear (line 13) | void clear()
    method get_link (line 21) | int get_link(int v)
    method add_letter (line 28) | void add_letter(char c)
  function read (line 44) | void read()
  function solve (line 49) | void solve()
  function main (line 54) | int main()

FILE: old_impl/strings/rabin_karp.cpp
  type rabin_karp (line 9) | struct rabin_karp
    method init (line 14) | void init(string s, int _base, int _mod)
    method get_hash (line 29) | int get_hash(int l, int r)
  function read (line 36) | void read()
  function solve (line 41) | void solve()
  function main (line 47) | int main()

FILE: old_impl/strings/suffix_array.cpp
  type suffix_array (line 8) | struct suffix_array {
    method suffix_array (line 12) | suffix_array() {
    method suffix_array (line 18) | suffix_array(const string &s) : n(s.size()) {
    method lcp (line 46) | int lcp(int x, int y) {
  function read (line 63) | void read() { cin >> s; }
  function solve (line 65) | void solve() {
  function main (line 72) | int main() {

FILE: old_impl/strings/suffix_array_hash.cpp
  type rabin_karp (line 9) | struct rabin_karp
    method init (line 14) | void init(string s, int _mod, int _base)
    method get_hash (line 31) | int get_hash(int l, int r)
  function cmp (line 42) | bool cmp(int i, int j)
  function kasai (line 64) | vector<int> kasai(string s, vector<int> sa)
  function build (line 92) | vector<int> build(string s)
  function read (line 112) | void read()
  function solve (line 120) | void solve()
  function main (line 137) | int main()

FILE: old_impl/strings/suffix_array_log2.cpp
  function read (line 10) | void read()
  function cmp (line 18) | bool cmp(int i, int j)
  function build_suffix_array (line 24) | void build_suffix_array()
  function build_lcp (line 49) | void build_lcp()
  function sparse_table (line 73) | void sparse_table()
  function LCP (line 87) | int LCP(int l, int r)
  function prepare (line 94) | void prepare()
  function solve (line 101) | void solve()
  function main (line 106) | int main()

FILE: old_impl/strings/suffix_automaton.cpp
  type suffix_automaton (line 7) | struct suffix_automaton {
    method add_letter (line 12) | void add_letter(char c) {
    method clear (line 65) | void clear() {
    method init (line 73) | void init(string s) {
    method suffix_automaton (line 80) | suffix_automaton() {
  function read (line 86) | void read() {}
  function solve (line 90) | void solve() { sa.clear(); }
  function main (line 92) | int main() {

FILE: old_impl/strings/trie.cpp
  type trie (line 5) | struct trie {
    method trie (line 9) | trie() { clear(); }
    method clear (line 11) | void clear() {
    method add (line 17) | void add(string s) {
    method del (line 31) | void del(string s) {
    method count (line 42) | int count(string s) {
  function read (line 57) | void read() {}
  function solve (line 59) | void solve() {}
  function main (line 61) | int main() {

FILE: old_impl/tree/centroid_decomposition.cpp
  function read (line 10) | void read() {
  function pre_dfs (line 23) | void pre_dfs(int u, int pr) {
  function centroid (line 34) | int centroid(int u, int pr) {
  function decompose (line 46) | void decompose(int u, int pr = -1) {
  function solve (line 61) | void solve() {}
  function main (line 63) | int main() {

FILE: old_impl/tree/dsu_on_tree.cpp
  function read (line 10) | void read() {
  function pre_dfs (line 24) | void pre_dfs(int u, int pr) {
  function add_vertex (line 34) | void add_vertex(int u) {}
  function clear (line 36) | void clear(int u, int pr) {}
  function add (line 38) | void add(int u, int pr) {
  function dfs (line 47) | void dfs(int u, int pr, int keep) {
  function solve (line 79) | void solve() {
  function main (line 84) | int main() {

FILE: old_impl/tree/hld.cpp
  function chkmax (line 3) | inline int chkmax(T &x, const T2 &y) { return x < y ? x = y, 1 : 0; }
  function chkmin (line 4) | inline int chkmin(T &x, const T2 &y) { return x > y ? x = y, 1 : 0; }
  function read (line 10) | void read()
  function pre_dfs (line 24) | int pre_dfs(int u, int pr)
  function decompose (line 36) | void decompose(int u, int pr, int head)
  function upper (line 61) | inline int upper(int u, int v) { return st[u] <= st[v] && en[v] <= en[u]...
  function lca (line 63) | int lca(int u, int v)
  function hld_precompute (line 75) | void hld_precompute(int root)
  function get_path_up (line 81) | vector<pair<int, int> > get_path_up(int u, int anc)
  function get_path (line 93) | vector<pair<int, int> > get_path(int u, int v)
  function solve (line 112) | void solve()
  function main (line 117) | int main()

FILE: old_impl/tree/lca-seg3.cpp
  function read (line 11) | void read()
  function pre_dfs (line 28) | void pre_dfs(int u, int pr)
  function upper (line 47) | inline bool upper(int u, int v) { return st[u] <= st[v] && en[v] <= en[u...
  function lca (line 49) | int lca(int u, int v)
  function get_path_up (line 61) | int get_path_up(int u, int anc)
  function get_path (line 76) | int get_path(int u, int v)
  function lca_precompute (line 83) | void lca_precompute(int root)
  function solve (line 89) | void solve()
  function main (line 94) | int main()

FILE: old_impl/tree/link_cut_tree.cpp
  type node (line 8) | struct node {
    method node (line 11) | node() {
    method node (line 21) | node(int v) {
  function size (line 33) | int size(node *v) { return v ? v->sz : 0; }
  function push (line 35) | void push(node *&t) {
  function pull (line 51) | void pull(node *&v) {
  function merge (line 77) | void merge(node *&t, node *l, node *r) {
  function split (line 97) | void split(node *t, node *&l, node *&r, int k, int add = 0) {
  function node (line 115) | node *get_root(node *t) {
    method node (line 11) | node() {
    method node (line 21) | node(int v) {
  function node (line 125) | node *remove_right(node *t) {
    method node (line 11) | node() {
    method node (line 21) | node(int v) {
  function node (line 154) | node *remove_left(node *t) {
    method node (line 11) | node() {
    method node (line 21) | node(int v) {
  function node (line 179) | node *merge_trees(node *u, node *t) {
    method node (line 11) | node() {
    method node (line 21) | node(int v) {
  type link_cut_tree (line 188) | struct link_cut_tree {
    method node (line 191) | node *access(node *t) {
    method node (line 202) | node *find_root(node *u) {
    method make_root (line 212) | void make_root(node *u) {
    method link (line 218) | void link(node *u, node *w) {
    method cut (line 224) | void cut(node *p) {
    method depth (line 229) | int depth(node *u) {
    method node (line 234) | node *lca(node *u, node *v) {
    method init (line 249) | void init(int c) {
    method lca (line 254) | inline int lca(int u, int v) { return lca(ver[u], ver[v])->id; }
    method root (line 255) | inline int root(int u) { return find_root(ver[u])->id; }
    method link (line 256) | inline void link(int u, int v) { link(ver[u], ver[v]); }
    method make_root (line 257) | inline void make_root(int u) { make_root(ver[u]); }
    method depth (line 258) | inline int depth(int u) { return depth(ver[u]); }
    method cut (line 259) | inline void cut(int u) { cut(ver[u]); }
  function read (line 264) | void read() { cin >> n >> m; }
  function solve (line 268) | void solve() {
  function main (line 294) | int main() {

FILE: old_impl/tree/virtual_tree.cpp
  function read (line 9) | void read() {
  function dfs_lca (line 23) | void dfs_lca(int u, int pr, int &dfs_time) {
  function upper (line 41) | inline bool upper(int u, int v) {
  function lca (line 45) | int lca(int u, int v) {
  function lca_precompute (line 63) | void lca_precompute(int root) {
  function build_tree (line 73) | int build_tree(vector<int> vec) {
  function solve (line 119) | void solve() {
  function main (line 139) | int main() {

FILE: other/bits/bit_trie.hpp
  class BitTrie (line 5) | class BitTrie {
    type node (line 7) | struct node {
      method node (line 11) | node() {
    method clear (line 19) | void clear() { trie = {node()}; }
    method BitTrie (line 21) | BitTrie() { clear(); }
    method add (line 23) | void add(T x, int cnt) {
    method T (line 37) | T max_xor(T x) {

FILE: other/bits/xor_basis.hpp
  class XorBasis (line 5) | class XorBasis {
    method clear (line 10) | void clear() {
    method XorBasis (line 14) | XorBasis() { clear(); }
    method add (line 16) | void add(T val) {
    method size (line 30) | inline int size() { return sz; }
    method T (line 32) | T max_xor() {
    method can_create (line 43) | bool can_create(T val) {
    method get_basis (line 52) | vector<T> get_basis() {
    method merge (line 62) | XorBasis<T, num_bits> merge(const XorBasis<T, num_bits>& other) {
    method get_bit (line 81) | typename enable_if<is_integral<U>::value, bool>::type get_bit(
    method is_zero (line 88) | typename enable_if<is_integral<U>::value, bool>::type is_zero(const T&...
    method xor_op (line 94) | typename enable_if<is_integral<U>::value, T>::type xor_op(
    method get_bit (line 102) | typename enable_if<is_same<U, bitset<N>>::value, bool>::type get_bit(
    method is_zero (line 109) | typename enable_if<is_same<U, bitset<N>>::value, bool>::type is_zero(
    method xor_op (line 116) | typename enable_if<is_same<U, bitset<N>>::value, bitset<N>>::type xor_op(

FILE: other/dp_optimizations/LiChao_dynamic.cpp
  type LiChao_max (line 8) | struct LiChao_max
    type line (line 10) | struct line
      method line (line 13) | line() { a = 0; b = 0; }
      method line (line 14) | line(int _a, int _b) { a = _a; b = _b; }
      method eval (line 15) | int64_t eval(int x) { return a * 1ll * x + (int64_t)b; }
    type node (line 18) | struct node
      method node (line 22) | node() { f = line(); l = nullptr; r = nullptr; }
      method node (line 23) | node(int a, int b) { f = line(a, b); l = nullptr; r = nullptr; }
      method node (line 24) | node(line v) { f = v; l = nullptr; r = nullptr; }
    method init (line 30) | void init(int _sz) { sz = _sz + 1; root = nullptr; }
    method add_line (line 32) | void add_line(int a, int b) { line v = line(a, b); insert(v, -sz, sz, ...
    method query (line 33) | int64_t query(int x) { return query(x, -sz, sz, root); }
    method insert (line 35) | void insert(line &v, int l, int r, pnode &nd)
    method query (line 51) | int64_t query(int x, int l, int r, pnode &nd)
  type LiChao_min (line 62) | struct LiChao_min
    type line (line 64) | struct line
      method line (line 67) | line() { a = 0; b = 0; }
      method line (line 68) | line(int _a, int _b) { a = _a; b = _b; }
      method eval (line 69) | int64_t eval(int x) { return a * 1ll * x + (int64_t)b; }
    type node (line 72) | struct node
      method node (line 76) | node() { f = line(); l = nullptr; r = nullptr; }
      method node (line 77) | node(int a, int b) { f = line(a, b); l = nullptr; r = nullptr; }
      method node (line 78) | node(line v) { f = v; l = nullptr; r = nullptr; }
    method init (line 84) | void init(int _sz) { sz = _sz + 1; root = nullptr; }
    method add_line (line 86) | void add_line(int a, int b) { line v = line(a, b); insert(v, -sz, sz, ...
    method query (line 87) | int64_t query(int x) { return query(x, -sz, sz, root); }
    method insert (line 89) | void insert(line &v, int l, int r, pnode &nd)
    method query (line 105) | int64_t query(int x, int l, int r, pnode &nd)
  function read (line 116) | void read()
  function solve (line 121) | void solve()
  function main (line 126) | int main()

FILE: other/dp_optimizations/LiChao_parabolic.cpp
  type LiChao_parabolic_min (line 9) | struct LiChao_parabolic_min {
    type Parabol (line 10) | struct Parabol {
      method Parabol (line 12) | Parabol() {a = 0; b = 0; c = inf;}
      method Parabol (line 13) | Parabol(T a, T b, T c) : a(a), b(b), c(c) {}
      method Parabol (line 14) | Parabol(const Parabol& rhs) {
      method T (line 19) | T query(T x) {
    type Node (line 23) | struct Node {
      method Node (line 26) | Node() : l(0), r(0) {}
      method T (line 27) | T query(T x) {
    method LiChao_parabolic_min (line 36) | LiChao_parabolic_min() : rt(0), offset(0) {}
    method Node (line 38) | Node* upd(Node* p, int l, int r, int L, int R, Parabol prb) {
      method Node (line 26) | Node() : l(0), r(0) {}
      method T (line 27) | T query(T x) {
    method T (line 75) | T query(Node* p, int i, int L, int R) {
    method upd (line 86) | void upd(T a, T b, T c) {
    method T (line 90) | T query(int i) {
  function read (line 95) | void read()
  function solve (line 100) | void solve()
  function main (line 105) | int main()

FILE: other/dp_optimizations/LiChao_segment_tree_offline.cpp
  type LiChao_max (line 8) | struct LiChao_max
    type line (line 10) | struct line
      method line (line 13) | line() { a = 0; b = 0; }
      method line (line 14) | line(double _a, double _b) { a = _a; b = _b; }
      method eval (line 15) | double eval(int x) { return a * x + b; }
    method init (line 23) | void init(int l, int r, int idx)
    method init (line 35) | void init(vector<int> Q)
    method add_line (line 47) | void add_line(double a, double b) { line v = line(a, b); insert(v, 1, ...
    method query (line 48) | double query(int x) { return query(x, 1, sz, 0); }
    method insert (line 50) | void insert(line &v, int l, int r, int idx)
    method query (line 65) | double query(int x, int l, int r, int idx)
  type LiChao_min (line 76) | struct LiChao_min
    type line (line 78) | struct line
      method line (line 81) | line() { a = 0; b = 0; }
      method line (line 82) | line(double _a, double _b) { a = _a; b = _b; }
      method eval (line 83) | double eval(int x) { return a * x + b; }
    method init (line 91) | void init(int l, int r, int idx)
    method init (line 103) | void init(vector<int> Q)
    method add_line (line 115) | void add_line(double a, double b) { line v = line(a, b); insert(v, 1, ...
    method query (line 116) | double query(int x) { return query(x, 1, sz, 0); }
    method insert (line 118) | void insert(line &v, int l, int r, int idx)
    method query (line 133) | double query(int x, int l, int r, int idx)
  function read (line 144) | void read()
  function solve (line 149) | void solve()
  function main (line 154) | int main()

FILE: other/dp_optimizations/convex_hull_trick_max.cpp
  type convex_hull_trick_max (line 8) | struct convex_hull_trick_max
    type line (line 10) | struct line
      method line (line 16) | line() {m = 0; b = 0; line_x = 0; is_query = 0; }
      method line (line 17) | line(int64_t _m, int64_t _b) {m = _m; b = _b; line_x = 0; is_query =...
      method value_at (line 25) | int64_t value_at(int64_t x) const { return m * x + b; }
    method parallel (line 28) | bool parallel(const line &l1, const line &l2) { return l1.m == l2.m; }
    method intersect_x (line 30) | double intersect_x(const line &l1, const line &l2)
    method clear (line 37) | void clear() { hull.clear(); }
    method init (line 38) | void init() { clear(); }
    method has_next (line 40) | bool has_next(set<line>::iterator it) { return it != hull.end() && nex...
    method has_prev (line 41) | bool has_prev(set<line>::iterator it) { return it != hull.end() && it ...
    method irrelevant (line 43) | bool irrelevant(const line &l1, const line &l2, const line &l3) { retu...
    method irrelevant (line 44) | bool irrelevant(set<line>::iterator it) { return has_prev(it) && has_n...
    method update_border (line 46) | set<line>::iterator update_border(set<line>::iterator it)
    method add_line (line 61) | void add_line(int64_t m, int64_t b)
    method query (line 87) | int64_t query(int64_t x)
  function read (line 101) | void read()
  function solve (line 108) | void solve()
  function main (line 114) | int main()

FILE: other/dp_optimizations/convex_hull_trick_min.cpp
  type convex_hull_trick_min (line 8) | struct convex_hull_trick_min
    type line (line 10) | struct line
      method line (line 16) | line() {m = 0; b = 0; line_x = 0; is_query = 0; }
      method line (line 17) | line(int64_t _m, int64_t _b) {m = _m; b = _b; line_x = 0; is_query =...
      method value_at (line 25) | int64_t value_at(int64_t x) const { return m * x + b; }
    method parallel (line 28) | bool parallel(const line &l1, const line &l2) { return l1.m == l2.m; }
    method intersect_x (line 30) | double intersect_x(const line &l1, const line &l2)
    method clear (line 37) | void clear() { hull.clear(); }
    method init (line 38) | void init() { clear(); }
    method has_next (line 40) | bool has_next(set<line>::iterator it) { return it != hull.end() && nex...
    method has_prev (line 41) | bool has_prev(set<line>::iterator it) { return it != hull.end() && it ...
    method irrelevant (line 43) | bool irrelevant(const line &l1, const line &l2, const line &l3) { retu...
    method irrelevant (line 44) | bool irrelevant(set<line>::iterator it) { return has_prev(it) && has_n...
    method update_border (line 46) | set<line>::iterator update_border(set<line>::iterator it)
    method add_line (line 61) | void add_line(int64_t m, int64_t b)
    method query (line 87) | int64_t query(int64_t x)
  function read (line 101) | void read()
  function solve (line 108) | void solve()
  function main (line 114) | int main()

FILE: other/dp_optimizations/divide_and_conquer_optimization.cpp
  function read (line 12) | void read()
  function rec (line 19) | void rec(int l, int r, int opt_l, int opt_r, int k)
  function solve (line 47) | void solve()
  function main (line 55) | int main()
  function Next (line 69) | void Next() { if(++pos_ind == maxl) fread(sir, 1, maxl, stdin), pos_ind ...
  function Read (line 70) | void Read(int &x)

FILE: other/dp_optimizations/slope_trick.cpp
  function chkmin (line 11) | int chkmin(T &x, const T1 &y) { return x > y ? x = y, 1 : 0; }
  function chkmax (line 12) | int chkmax(T &x, const T1 &y) { return x < y ? x = y, 1 : 0; }
  type slope_trick (line 16) | struct slope_trick {
    method slope_trick (line 21) | slope_trick() {
    method T (line 27) | T zero_start() {
    method T (line 35) | T zero_end() {
    method size (line 43) | inline size_t size() {
    method add_simple (line 48) | void add_simple(const T &center, const T &height = 0) {
    method prefix_min (line 70) | void prefix_min() {
    method suffix_min (line 76) | void suffix_min() {
    method local_min (line 82) | void local_min(const T &strip_width) {
    method add (line 92) | void add(const slope_trick &other) {
    method add_with_destroy (line 96) | void add_with_destroy(slope_trick &other) {
  function read (line 104) | void read() {
  function solve (line 111) | void solve() {
  function main (line 122) | int main() {

FILE: other/dp_optimizations/slope_trick_priority_queue.cpp
  function chkmin (line 11) | int chkmin(T &x, const T1 &y) { return x > y ? x = y, 1 : 0; }
  function chkmax (line 12) | int chkmax(T &x, const T1 &y) { return x < y ? x = y, 1 : 0; }
  type slope_trick (line 16) | struct slope_trick {
    method slope_trick (line 21) | slope_trick() {
    method T (line 27) | T zero_start() {
    method T (line 35) | T zero_end() {
    method add_simple (line 44) | void add_simple(const T &center, const T &height = 0) {
    method prefix_min (line 66) | void prefix_min() {
    method suffix_min (line 74) | void suffix_min() {
    method local_min (line 82) | void local_min(const T &strip_width) {
  function read (line 96) | void read() {
  function solve (line 103) | void solve() {
  function main (line 114) | int main() {

FILE: other/queries/mo.cpp
  type query (line 7) | struct query
    method query (line 12) | query() {l = -1; r = -1; block = -1; idx = -1;}
    method query (line 13) | query(int _l, int _r, int i)
  function cmp (line 21) | bool cmp(query a, query b)
  function read (line 29) | void read()
  function add (line 37) | void add(int idx)
  function del (line 42) | void del(int idx)
  function solve (line 49) | void solve()
  function main (line 80) | int main()

FILE: other/queries/mo_dsu.cpp
  type query (line 7) | struct query
    method query (line 10) | query() {l = 0; r = 0; idx = 0;}
    method query (line 11) | query(int _l, int _r, int _idx)
  type persistent_dsu (line 19) | struct persistent_dsu
    type state (line 21) | struct state
      method state (line 24) | state() {u = 0; ru = 0; v = 0; rv = 0;}
      method state (line 25) | state(int _u, int _ru, int _v, int _rv)
    method persistent_dsu (line 38) | persistent_dsu()
    method init (line 46) | void init(int _sz)
    method root (line 53) | int root(int x)
    method connected (line 59) | bool connected(int x, int y)
    method unite (line 64) | void unite(int x, int y)
    method snapshot (line 80) | void snapshot() { st.push(state(-1, -1, -1, -1)); }
    method rollback (line 82) | void rollback()
  type edge (line 99) | struct edge
    method edge (line 102) | edge() {u = 0; v = 0;}
    method edge (line 103) | edge(int _u, int _v)
  function read (line 114) | void read()
  function cmp (line 129) | bool cmp(query fir, query sec)
  function add (line 136) | void add(int idx) { d.unite(a[idx].u, a[idx].v); }
  function solve (line 138) | void solve()
  function main (line 192) | int main()

FILE: other/queries/mo_online.cpp
  function read (line 11) | void read()
  type my_set (line 18) | struct my_set
    method my_set (line 22) | my_set() { answer = 0; cnt.clear(); }
    method insert (line 24) | void insert(int val)
    method erase (line 30) | void erase(int val)
    method clear (line 36) | void clear()
    method query (line 42) | int query() { return answer; }
  function query (line 49) | int query(int l, int r)
  function update (line 75) | void update(int mid, int pos, int val)
  function solve (line 81) | void solve()
  function main (line 125) | int main()

FILE: other/queries/offline_centroid_queries.cpp
  function chkmin (line 8) | int chkmin(T &x, const T1 &y) {
  function chkmax (line 13) | int chkmax(T &x, const T1 &y) {
  function ostream (line 18) | ostream &operator<<(ostream &out, const pair<T1, T2> &x) {
  function istream (line 23) | istream &operator>>(istream &in, pair<T1, T2> &x) {
  function istream (line 28) | istream &operator>>(istream &in, vector<T> &a) {
  function ostream (line 36) | ostream &operator<<(ostream &out, vector<T> &a) {
  type basis (line 44) | struct basis {
    method init (line 48) | void init(int _max_log) {
    method add (line 53) | void add(T val) {
    method size (line 66) | inline int size() {
    method T (line 74) | T max_xor() {
    method can_create (line 85) | bool can_create(T val) {
    method get_basis (line 95) | vector<T> get_basis() {
    method merge (line 105) | basis<T> merge(basis<T> other) {
  function read (line 126) | void read() {
  function get_size (line 145) | int get_size(int v, int p) {
  function dfs_basis (line 155) | void dfs_basis(int v, int p, basis<int> pref_bs) {
  function dfs_marker (line 166) | void dfs_marker(int v, int p, int mark) {
  function decompose (line 175) | void decompose(int u, vector<int> qidx) {
  function solve (line 236) | void solve() {
  function main (line 266) | int main() {

FILE: other/utils/count_inversions.cpp
  function count_inversions (line 4) | int64_t count_inversions(int *start, int *end) {

FILE: strings/aho_corasick.hpp
  class AhoCorasick (line 5) | class AhoCorasick {
    type State (line 11) | struct State {
      method State (line 15) | State() : link(0), word_id(-1) {}
    method AhoCorasick (line 21) | AhoCorasick() { clear(); }
    method clear (line 23) | void clear() {
    method add_word (line 28) | void add_word(const T& word, int id = -1) {
    method build (line 40) | void build() {
    method go (line 64) | int go(int u, const G& c) const {
    method link (line 71) | int link(int u) const { return states[u].link; }
    method word_id (line 72) | int word_id(int u) const { return states[u].word_id; }
    method size (line 73) | int size() const { return states.size(); }
    method traverse (line 75) | vector<int> traverse(const T& text) const {
    method build_link_tree (line 86) | vector<vector<int>> build_link_tree() const {

FILE: strings/hashing.hpp
  class HashMeta (line 4) | class HashMeta {
    method set_random_base (line 6) | void set_random_base() {
    method precompute_base_pow (line 18) | void precompute_base_pow(size_t n) {
    method add (line 26) | static constexpr uint64_t add(uint64_t a, uint64_t b) {
    method sub (line 32) | static constexpr uint64_t sub(uint64_t a, uint64_t b) {
    method mul (line 36) | static constexpr uint64_t mul(uint64_t a, uint64_t b) {
    class hash_t (line 47) | class hash_t {
      method hash_t (line 51) | hash_t() : h(0) {}
      method hash_t (line 52) | hash_t(uint64_t h) : h(h) {}
      method hash_t (line 55) | hash_t& operator+=(const hash_t& other) {
      method hash_t (line 60) | hash_t& operator-=(const hash_t& other) {
      method hash_t (line 65) | hash_t& operator*=(const hash_t& other) {
      method hash_t (line 70) | hash_t operator+(const hash_t& other) const {
      method hash_t (line 73) | hash_t operator-(const hash_t& other) const {
      method hash_t (line 76) | hash_t operator*(const hash_t& other) const {
    method init (line 91) | void init(size_t n) {
    method rabin_karp (line 97) | vector<hash_t> rabin_karp(const T& container) {
    method hash_t (line 106) | hash_t hash_range(int l, int r, const vector<hash_t>& h) {
      method hash_t (line 51) | hash_t() : h(0) {}
      method hash_t (line 52) | hash_t(uint64_t h) : h(h) {}
      method hash_t (line 55) | hash_t& operator+=(const hash_t& other) {
      method hash_t (line 60) | hash_t& operator-=(const hash_t& other) {
      method hash_t (line 65) | hash_t& operator*=(const hash_t& other) {
      method hash_t (line 70) | hash_t operator+(const hash_t& other) const {
      method hash_t (line 73) | hash_t operator-(const hash_t& other) const {
      method hash_t (line 76) | hash_t operator*(const hash_t& other) const {

FILE: strings/suffix_array.hpp
  class SuffixArray (line 5) | class SuffixArray {
    method build_sa (line 11) | void build_sa(const T& s) {
    method build_lcp (line 45) | void build_lcp(const T& s) {
    method SuffixArray (line 69) | SuffixArray() : n(0) {}
    method SuffixArray (line 70) | SuffixArray(const T& s) { init(s); }
    method clear (line 72) | void clear() {
    method init (line 79) | void init(const T& s) {

FILE: strings/suffix_automaton.hpp
  class SuffixAutomaton (line 5) | class SuffixAutomaton {
    type State (line 11) | struct State {
      method State (line 15) | State(int l = 0, int lnk = -1) : len(l), link(lnk) {}
    method check_replace_with_clone (line 18) | int check_replace_with_clone(int p, G c) {
    method SuffixAutomaton (line 39) | SuffixAutomaton() : last(0) { clear(); }
    method SuffixAutomaton (line 40) | SuffixAutomaton(const T& s) { init(s); }
    method add_letter (line 42) | void add_letter(G c) {
    method add_string (line 67) | void add_string(const T& s) {
    method clear (line 74) | void clear() {
    method init (line 80) | void init(const T& s) {
    method build_suffix_link_tree (line 85) | vector<vector<int>> build_suffix_link_tree() {
    method states_by_length (line 93) | vector<vector<int>> states_by_length() {

FILE: tree/centroid_decomposition.hpp
  class CentroidDecomposition (line 6) | class CentroidDecomposition {
    method dfs (line 13) | int dfs(int u, int pr) {
    method find_centroid (line 23) | int find_centroid(int u, int pr, int n) {
    method CentroidDecomposition (line 35) | CentroidDecomposition(vector<vector<int>> adj = {}, int root = 0)
    method decompose (line 47) | void decompose(int u, int prev_cen = -1, int depth = 0) {

FILE: tree/euler_order_segment_tree.cpp
  function chkmin (line 4) | int chkmin(T &x, const T1 &y) {
  function chkmax (line 8) | int chkmax(T &x, const T1 &y) {
  function read (line 17) | void read() {
  function pre_dfs (line 29) | void pre_dfs(int u, int pr, int d = 0) {
  type segment_tree (line 46) | struct segment_tree {
    type node (line 47) | struct node {
      method node (line 49) | node() { l = m = r = lm = mr = lmr = -inf; }
      method node (line 51) | node(int d) {
    method node (line 61) | node merge(node a, node b) {
      method node (line 49) | node() { l = m = r = lm = mr = lmr = -inf; }
      method node (line 51) | node(int d) {
    method push (line 81) | void push(int l, int r, int idx) {
    method init (line 91) | void init(int l, int r, int idx, const vector<array<int, 1>> &dat) {
    method update (line 104) | void update(int pos, int l, int r, int idx) {
    method update (line 120) | void update(int ql, int qr, int l, int r, int idx) {
  function solve (line 141) | void solve() {
  function main (line 146) | int main() {

FILE: tree/lca.hpp
  class LCAUtils (line 4) | class LCAUtils {
    method dfs_lca (line 9) | void dfs_lca(int u, int pr, int& dfs_time) {
    method LCAUtils (line 30) | LCAUtils() : n(0) {}
    method LCAUtils (line 31) | LCAUtils(int _n) { init(_n); }
    method LCAUtils (line 32) | LCAUtils(int _n, const vector<vector<int>>& _adj, int root = 0) {
    method init (line 38) | void init(int _n) {
    method add_edge (line 43) | void add_edge(int u, int v) {
    method prepare (line 48) | void prepare(int root = 1) {
    method lca (line 62) | int lca(int u, int v) {
    method upper (line 80) | inline bool upper(int u, int v) {

FILE: tree/lca_sparse_table.hpp
  class LCAUtilsRMQ (line 5) | class LCAUtilsRMQ {
    method _min_custom (line 7) | static pair<int, int> _min_custom(pair<int, int> a, pair<int, int> b) {
    method pre_dfs (line 15) | void pre_dfs(int u, int pr = -1, int d = 0) {
    method LCAUtilsRMQ (line 32) | LCAUtilsRMQ() { n = 0; }
    method LCAUtilsRMQ (line 33) | LCAUtilsRMQ(int _n) { init(_n); }
    method LCAUtilsRMQ (line 34) | LCAUtilsRMQ(int _n, const vector<vector<int>>& _adj) {
    method add_edge (line 39) | void add_edge(int u, int v) {
    method init (line 44) | void init(int _n) {
    method prepare (line 50) | void prepare(int root = 0) {
    method lca (line 58) | int lca(int u, int v) {
    method dist (line 65) | int dist(int u, int v) { return dep[u] + dep[v] - 2 * dep[lca(u, v)]; }

FILE: tree/line_tree.hpp
  class LineTree (line 6) | class LineTree {
    method LineTree (line 16) | LineTree() {}
    method LineTree (line 17) | LineTree(
    method init (line 23) | void init(
    method min_value (line 57) | int min_value(int u, int v) { return vals[helper_lca.lca(u, v)]; }
    method min_node (line 59) | int min_node(int u, int v) { return helper_lca.lca(u, v); }

FILE: tree/link_cut_tree.hpp
  class LinkCutTree (line 10) | class LinkCutTree {
    type Node (line 14) | struct Node {
      method Node (line 23) | Node(T val = e(), int id = -1)
    method push (line 36) | void push(Node* x) {
    method pull (line 63) | void pull(Node* x) {
    method state (line 79) | inline int state(Node* n) {
    method is_root (line 92) | bool is_root(Node* x) { return state(x) == 0; }
    method rotate (line 94) | void rotate(Node* x) {
    method splay (line 124) | void splay(Node* x) {
    method Node (line 147) | Node* expose(Node* x) {
      method Node (line 23) | Node(T val = e(), int id = -1)
    method apply_lazy_to_node (line 165) | void apply_lazy_to_node(Node* node, const G& lazy_val) {
    method add_light (line 173) | void add_light(Node* c, Node* light) {
    method erase_light (line 177) | void erase_light(Node* c, Node* light) {
    method LinkCutTree (line 182) | LinkCutTree(int n) : nodes(n) {
    method LinkCutTree (line 188) | LinkCutTree(const vector<T>& values) : nodes(values.size()) {
    method Node (line 194) | Node* access(int x) {
      method Node (line 23) | Node(T val = e(), int id = -1)
    method reroot (line 200) | void reroot(int x) {
    method link (line 206) | void link(int u, int v) {
    method cut (line 215) | void cut(int u, int v) {
    method connected (line 224) | bool connected(int u, int v) {
    method lca (line 233) | int lca(int u, int v) {
    method T (line 242) | T path_query(int u, int v) {
    method update (line 248) | void update(int u, const T& val) {
    method path_update (line 254) | void path_update(int u, int v, const G& lazy_val) {
    method T (line 260) | T get(int u) {
    method get_root (line 265) | int get_root(int u) {
    method jump (line 277) | int jump(int u, int v, int k) {
    method Node (line 299) | Node* get_node(int idx) { return &nodes[idx]; }
      method Node (line 23) | Node(T val = e(), int id = -1)
    method size (line 301) | int size() const { return nodes.size(); }
    method change_light (line 304) | void change_light(Node* pp, Node* p, Node* x) {
    method print_node (line 309) | void print_node(Node* node, int indent = 0) {
    method print_tree (line 324) | void print_tree(Node* node, int indent = 0) {

FILE: tree/vertex_add_path_sum.hpp
  class VertexAddPathSum (line 7) | class VertexAddPathSum : LCAUtils {
    method VertexAddPathSum (line 12) | VertexAddPathSum() {}
    method prepare (line 14) | void prepare(int root = 1) {
    method query (line 19) | int query(int u, int v) {
    method update (line 30) | void update(int u, int x) { ft.update(in_time[u], out_time[u], x); }

FILE: tree/virtual_tree.hpp
  class VirtualTree (line 5) | class VirtualTree : public LCAUtils {
    method VirtualTree (line 7) | VirtualTree() : LCAUtils() {}
    method VirtualTree (line 8) | VirtualTree(int n) : LCAUtils(n) {}
    method VirtualTree (line 9) | VirtualTree(int n, const vector<vector<int>>& adj, int root = 0)
    method add_edge (line 14) | void add_edge(int u, int v) { LCAUtils::add_edge(u, v); }
    method build (line 16) | pair<vector<vector<int>>, vector<int>> build(const vector<int>& vertic...
Condensed preview — 132 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (362K chars).
[
  {
    "path": "README.md",
    "chars": 876,
    "preview": "# Coding-Library\n\nThis is a collection of implementations of various data structures and algorithms, intended for compet"
  },
  {
    "path": "data_structures/clever_adding_intervals_set.hpp",
    "chars": 1185,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\ntemplate<class T>\nstruct clever_set {\n    map<pair<int, int>, T> value;\n\n"
  },
  {
    "path": "data_structures/compressed_fenwick.hpp",
    "chars": 647,
    "preview": "#include <bits/stdc++.h>\n#include <coding_library/data_structures/fenwick.hpp>\nusing namespace std;\n\ntemplate<class T>\ns"
  },
  {
    "path": "data_structures/decremental_constant_set.hpp",
    "chars": 3478,
    "preview": "#include <bits/stdc++.h>\n#include <coding_library/graph/dsu.hpp>\nusing namespace std;\n\n/*\nThe structures resembles a set"
  },
  {
    "path": "data_structures/fenwick.hpp",
    "chars": 976,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\ntemplate<class T>\nclass Fenwick {\n  private:\n    int sz, log_size;\n    ve"
  },
  {
    "path": "data_structures/fenwick_2d.hpp",
    "chars": 1704,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\ntemplate<class T, T (*merge)(T, T), T (*identity)()>\nclass Fenwick2d {\n  "
  },
  {
    "path": "data_structures/fenwick_range_update.hpp",
    "chars": 688,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\ntemplate<class T>\nclass FenwickRangeUpdate { \n  private:\n    int sz;\n    "
  },
  {
    "path": "data_structures/fenwick_range_update_range_query.hpp",
    "chars": 619,
    "preview": "#include <bits/stdc++.h>\n#include \"coding_library/data_structures/fenwick_range_update.hpp\"\nusing namespace std;\n\ntempla"
  },
  {
    "path": "data_structures/heap.hpp",
    "chars": 2181,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\ntemplate<class T, bool (*cmp)(T, T)>\nclass Heap {\n  private:\n    vector<T"
  },
  {
    "path": "data_structures/meldable_heap.hpp",
    "chars": 2126,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\ntemplate<class T = int>\nclass MeldableHeap {\n  private:\n    static uint32"
  },
  {
    "path": "data_structures/merge_sort_tree.hpp",
    "chars": 1860,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\n// InnerOrderedSet should implement:\n//     1) insert(x), which adds one "
  },
  {
    "path": "data_structures/monoids_lazy.hpp",
    "chars": 5158,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\ntemplate<class T>\nclass MonoidMin {\n  public:\n    struct MinVal {\n       "
  },
  {
    "path": "data_structures/nonintersecting_range_tree.hpp",
    "chars": 1966,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\n/* Based on https://codeforces.com/contest/2063/problem/F2. Main idea is "
  },
  {
    "path": "data_structures/offline_segment_tree_2d.hpp",
    "chars": 2564,
    "preview": "#include <bits/stdc++.h>\n#include <coding_library/data_structures/fenwick.hpp>\n\nusing namespace std;\n\ntemplate<class T>\n"
  },
  {
    "path": "data_structures/rmq2d.hpp",
    "chars": 2745,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\nstruct rmq1d {\n    vector<int> rmq;\n    int n;\n    void init(int N) {\n   "
  },
  {
    "path": "data_structures/segment_tree.hpp",
    "chars": 3263,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\n// Motivated by atcoder library, but adapted to my style. All ranges are\n"
  },
  {
    "path": "data_structures/segment_tree_lazy.hpp",
    "chars": 5105,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\n// Motivated by atcoder library, but adapted to my style. All ranges are\n"
  },
  {
    "path": "data_structures/set_lazy.hpp",
    "chars": 2746,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\ntemplate<typename T, template<typename...> class Container = multiset>\ncl"
  },
  {
    "path": "data_structures/sparse_table.hpp",
    "chars": 964,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\ntemplate<class T, T (*merge)(T, T)>\nclass SparseTable {\n  private:\n    in"
  },
  {
    "path": "data_structures/sparse_table_disjoint.hpp",
    "chars": 1591,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\ntemplate<class T, T (*merge)(T, T)>\nclass SparseTableDisjoint {\n  private"
  },
  {
    "path": "data_structures/treap.hpp",
    "chars": 6821,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\ntemplate<class KeyT, class T, T (*merge_func)(T, T), uint64_t (*rng)()>\ns"
  },
  {
    "path": "data_structures/treap_lazy.hpp",
    "chars": 7813,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\ntemplate<\n    class KeyT, class T, T (*merge_func)(T, T), class LazyT, ui"
  },
  {
    "path": "data_structures/wavelet_tree.hpp",
    "chars": 2152,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\n// wvlt = new WaveletTree();\n// wvlt->init(arr, 0, n);                   "
  },
  {
    "path": "dp_optimizations/convex_hull_trick.hpp",
    "chars": 1689,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\ntemplate<class T, bool maximum = true>\nclass ConvexHullTrick {\n  public:\n"
  },
  {
    "path": "geometry/dynamic_convex_hull.hpp",
    "chars": 3158,
    "preview": "#include <bits/stdc++.h>\n#include <coding_library/geometry/point.hpp>\nusing namespace std;\n\n// Tested on problem 277 fro"
  },
  {
    "path": "geometry/halfplane_intersection.hpp",
    "chars": 2767,
    "preview": "#include <bits/stdc++.h>\n#include <coding_library/geometry/point.hpp>\n\nusing namespace std;\n\nusing Line = pair<Point, Po"
  },
  {
    "path": "geometry/point.hpp",
    "chars": 5699,
    "preview": "#ifndef POINT_HPP\n#define POINT_HPP\n\n#include <bits/stdc++.h>\nusing namespace std;\n\nusing coord_t = double;\n\nstruct Poin"
  },
  {
    "path": "geometry/polygon.hpp",
    "chars": 5270,
    "preview": "#ifndef POLYGON_HPP\n#define POLYGON_HPP\n\n#include <bits/stdc++.h>\n#include <coding_library/geometry/point.hpp>\nusing nam"
  },
  {
    "path": "geometry/voronoi.hpp",
    "chars": 4860,
    "preview": "#ifndef VORONOI_HPP\n#define VORONOI_HPP\n\n#include <bits/stdc++.h>\n#include <coding_library/geometry/point.hpp>\nusing nam"
  },
  {
    "path": "graph/bcc.hpp",
    "chars": 2523,
    "preview": "#include <bits/stdc++.h>\n\nusing namespace std;\n\nclass biconnected_components {\n  private:\n    vector<int> low, disc;\n\n  "
  },
  {
    "path": "graph/bipartite_coloring.hpp",
    "chars": 7976,
    "preview": "#include <bits/stdc++.h>\n#include <coding_library/graph/hopcroft_karp.hpp>\nusing namespace std;\n\nstruct Edge {\n    int u"
  },
  {
    "path": "graph/bipartite_matching.hpp",
    "chars": 2497,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\nclass BipartiteMatching {\n  private:\n    int n, m, visited_timer;\n    vec"
  },
  {
    "path": "graph/dijkstra_vlog.hpp",
    "chars": 937,
    "preview": "#include <bits/stdc++.h>\n#include <coding_library/data_structures/heap.hpp>\n\nusing namespace std;\n\ntemplate<typename T>\n"
  },
  {
    "path": "graph/directed_cactus.hpp",
    "chars": 2019,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\nclass DirectedCactus {\n  private:\n    int n;\n    vector<vector<int>> adj;"
  },
  {
    "path": "graph/dsu.hpp",
    "chars": 945,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\nclass DSU {\n  public:\n    int n;\n    vector<int> par;\n    vector<int> sz;"
  },
  {
    "path": "graph/eppstein_shortest_paths.hpp",
    "chars": 4631,
    "preview": "#include <bits/stdc++.h>\n#include <coding_library/data_structures/meldable_heap.hpp>\nusing namespace std;\n\ntemplate<clas"
  },
  {
    "path": "graph/eulerian_paths.hpp",
    "chars": 3975,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\n// This implementation find cnt_odd_vertices / 2 eulerian paths that cove"
  },
  {
    "path": "graph/graph.hpp",
    "chars": 1381,
    "preview": "#include <bits/stdc++.h>\n#include <coding_library/graph/dsu.hpp>\nusing namespace std;\n\nclass UndirectedGraph {\n  public:"
  },
  {
    "path": "graph/hopcroft_karp.hpp",
    "chars": 3134,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\n// Hopcroft-Karp algorithm for bipartite matching that runs in O(E sqrt(V"
  },
  {
    "path": "graph/hungarian_algorithm.hpp",
    "chars": 2436,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\n// Based on http://e-maxx.ru/algo/assignment_hungary#6 but wrapped in a c"
  },
  {
    "path": "graph/maxflow.hpp",
    "chars": 2029,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\ntemplate<class T>\nclass MaxFlow {\n  private:\n    struct Edge {\n        T "
  },
  {
    "path": "graph/mincost_circulation.hpp",
    "chars": 4058,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\n// In some rare cases, we might want to find the min cost circulation ins"
  },
  {
    "path": "graph/mincost_flow.hpp",
    "chars": 3715,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\n// Based on Ormlis' implementation\n\ntemplate<typename T>\nclass MinCostFlo"
  },
  {
    "path": "graph/scc.hpp",
    "chars": 1413,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\nclass StronglyConnectedComponents {\n  private:\n    vector<bool> visited;\n"
  },
  {
    "path": "graph/st_numbering.hpp",
    "chars": 3219,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\nclass STNumbering {\n  private:\n    vector<int> low, disc, par, sign;\n    "
  },
  {
    "path": "graph/two_sat.hpp",
    "chars": 1762,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\nclass TwoSat {\n  private:\n    vector<bool> visited;\n\n    void dfs1(int u)"
  },
  {
    "path": "math/gauss_bitset.hpp",
    "chars": 1927,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\ntemplate<size_t N>\nclass GaussBitset {\n  public:\n    int n_var;\n    vecto"
  },
  {
    "path": "old_impl/data_structures/implicit_treap.hpp",
    "chars": 5492,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\nrandom_device rd;\nmt19937 mt(rd());\n\nstruct implicit_treap {\n    struct n"
  },
  {
    "path": "old_impl/data_structures/implicit_treap_basic.hpp",
    "chars": 2563,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\nrandom_device rd;\nmt19937 mt(rd());\n\nstruct implicit_treap {\n    struct n"
  },
  {
    "path": "old_impl/data_structures/max_count_segment_tree.cpp",
    "chars": 2531,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\nconst int MAXN = (1 << 20);\n\nstruct count_max_segment_tree {\n    struct no"
  },
  {
    "path": "old_impl/data_structures/merging_segment_tree.cpp",
    "chars": 1715,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\nstruct node {\n    int sz;\n    node *l, *r;\n\n    node() {\n        sz = 0;\n"
  },
  {
    "path": "old_impl/data_structures/min_segment_tree.cpp",
    "chars": 1649,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\n#define SZ(x) ((int)x.size())\n#define ALL(V) V.begin(), V.end()\n#define L_B "
  },
  {
    "path": "old_impl/data_structures/monotonous_queue.cpp",
    "chars": 1468,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\ntemplate<class T, class T2> inline void chkmax(T &x, co"
  },
  {
    "path": "old_impl/data_structures/persistent_segment_tree.cpp",
    "chars": 1603,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\n\nstruct node {\n    int sum;"
  },
  {
    "path": "old_impl/data_structures/persistent_segment_tree_lazy.cpp",
    "chars": 2370,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\ntemplate<class T, class T2>\ninline void chkmax(T &x, co"
  },
  {
    "path": "old_impl/data_structures/persistent_treap.cpp",
    "chars": 2387,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\n\nrandom_device rd;\nmt19937 "
  },
  {
    "path": "old_impl/data_structures/persistent_treap_lazy.cpp",
    "chars": 2732,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\n\nrandom_device rd;\nmt19937 "
  },
  {
    "path": "old_impl/data_structures/segment_tree.cpp",
    "chars": 1518,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 18);\n\nint n, m;\nint a[MAXN];\n\nst"
  },
  {
    "path": "old_impl/data_structures/segment_tree_AP.cpp",
    "chars": 2233,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 18);\n\nint n, m;\nint a[MAXN];\n\nst"
  },
  {
    "path": "old_impl/data_structures/segment_tree_add_mult.cpp",
    "chars": 2959,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\n//#pragma GCC optimize (\"O3\")\n//#pragma GCC target (\"sse4\")\n\nusing namespace"
  },
  {
    "path": "old_impl/data_structures/segment_tree_fast.cpp",
    "chars": 1206,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\n\nstruct node {\n    int mx;\n"
  },
  {
    "path": "old_impl/data_structures/segment_tree_lazy_min.cpp",
    "chars": 2930,
    "preview": "#include <bits/stdc++.h>\n#include <limits>\nusing namespace std;\n\ntemplate<class T>\nclass segment_tree_min {\n  private:\n "
  },
  {
    "path": "old_impl/data_structures/segment_tree_lazy_sum.cpp",
    "chars": 2604,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\ntemplate<class T>\nclass segment_tree_sum {\n  private:\n    struct node {\n "
  },
  {
    "path": "old_impl/data_structures/segment_tree_nonzero.cpp",
    "chars": 1090,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\n\nstruct segment_tree\n{\n\tint"
  },
  {
    "path": "old_impl/data_structures/segment_tree_with_binary_search.cpp",
    "chars": 2509,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\ntemplate<class T, class T2> inline void chkmax(T &x, co"
  },
  {
    "path": "old_impl/data_structures/treap.cpp",
    "chars": 1927,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\nrandom_device rd;\nmt19937 mt(rd());\n\nstruct node {\n    int sz, prior, val"
  },
  {
    "path": "old_impl/geometry/closest_points.cpp",
    "chars": 1488,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\n#define int long long\n\nusing namespace std;\nconst int MAXN = (1 << 20);\ncons"
  },
  {
    "path": "old_impl/geometry/convex_hull.cpp",
    "chars": 1539,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\n#define double long double\n\nusing namespace std;\nconst int MAXN = (1 << 20);"
  },
  {
    "path": "old_impl/geometry/dynamic_upper_hull.cpp",
    "chars": 5118,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\n#define SZ(x) ((int)x.size())\n#define ALL(V) V.begin(), V.end()\n#define L_B "
  },
  {
    "path": "old_impl/geometry/kd-tree.cpp",
    "chars": 2453,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (int)1e5 + 42 + 17;\nconst int MAXD = 5"
  },
  {
    "path": "old_impl/geometry/rectangle_union.cpp",
    "chars": 2501,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\n#define int long long\n\nusing namespace std;\nconst int MAXN = (1 << 21);\ncons"
  },
  {
    "path": "old_impl/graph/dsu_bipartite.cpp",
    "chars": 999,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\n\nint n, m;\npair<int, int> e"
  },
  {
    "path": "old_impl/graph/eulerian_path.cpp",
    "chars": 5443,
    "preview": "#include <bits/stdc++.h>\n\nusing namespace std;\n\ntemplate<class T, class T1>\nint chkmin(T &x, const T1 &y) {\n    return x"
  },
  {
    "path": "old_impl/graph/max_anticlique.cpp",
    "chars": 1745,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (52);\n\nint G[MAXN][MAXN], n;\nint mn_de"
  },
  {
    "path": "old_impl/graph/maximum_closure.cpp",
    "chars": 3944,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\ntemplate<class T, class T2> inline void chkmax(T &x, co"
  },
  {
    "path": "old_impl/graph/mincost_maxflow.cpp",
    "chars": 3019,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 10);\nconst int inf = (int)1e9 + "
  },
  {
    "path": "old_impl/graph/persistent_dsu.cpp",
    "chars": 1336,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\n\nstruct persistent_dsu\n{\n\ts"
  },
  {
    "path": "old_impl/graph/scc_tarjan.cpp",
    "chars": 1455,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\n\nint n, m;\nvector<int> G[MA"
  },
  {
    "path": "old_impl/graph/st_numbering.cpp",
    "chars": 2485,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\n//#pragma GCC optimize (\"O3\")\n//#pragma GCC target (\"sse4\")\n\nusing namespace"
  },
  {
    "path": "old_impl/math/combinatorics.cpp",
    "chars": 3200,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\nconst int mod = (int)1e9 + 7;\n\ntemplate<class T>\nT pw(T a, int pw) {\n    T"
  },
  {
    "path": "old_impl/math/fft.cpp",
    "chars": 3097,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst double PI = acos(-1);\nconst int MAXN = (1 << 21);"
  },
  {
    "path": "old_impl/math/fft_mod.cpp",
    "chars": 4650,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\ntemplate<class T, class T2> inline void chkmax(T &x, co"
  },
  {
    "path": "old_impl/math/fft_xor.cpp",
    "chars": 902,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\n#define int long long\n\nusing namespace std;\nconst int MAXN = (1 << 20);\n\ntyp"
  },
  {
    "path": "old_impl/math/fft_xor_mod.cpp",
    "chars": 1284,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\n#define int long long\n#define pow mypow\n\nusing namespace std;\nconst int MAXN"
  },
  {
    "path": "old_impl/math/gauss_elimination_equations.cpp",
    "chars": 1269,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\nconst double eps = 1e-9;\n\nv"
  },
  {
    "path": "old_impl/math/gauss_elimination_equations_mod.cpp",
    "chars": 1767,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\nconst int64_t mod = (int64_"
  },
  {
    "path": "old_impl/math/gauss_elimination_equations_mod_number_solutions.cpp",
    "chars": 1807,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\nconst int64_t mod = (int64_"
  },
  {
    "path": "old_impl/math/matrix_exponential.cpp",
    "chars": 2689,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\nconst int mod = (int)1e9 + "
  },
  {
    "path": "old_impl/math/number_theory.cpp",
    "chars": 2165,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\nconst int bound = 1000000;\n"
  },
  {
    "path": "old_impl/strings/aho_corasick.cpp",
    "chars": 1205,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\n\nstruct aho_corasick\n{\n\tint"
  },
  {
    "path": "old_impl/strings/aho_corasick_dynamic.cpp",
    "chars": 2221,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\n\nstruct aho_corasick_static"
  },
  {
    "path": "old_impl/strings/kmp.cpp",
    "chars": 1314,
    "preview": "#include <bits/stdc++.h>\r\n#define endl '\\n'\r\n\r\nusing namespace std;\r\nconst int MAXN = (1 << 20);\r\n\r\nstring str, pat;\r\n\r\n"
  },
  {
    "path": "old_impl/strings/palindromic_tree.cpp",
    "chars": 746,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\n\nstruct palindromic_tree\n{\n"
  },
  {
    "path": "old_impl/strings/rabin_karp.cpp",
    "chars": 751,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\n#define int long long\n\nusing namespace std;\nconst int MAXN = (1 << 20);\n\nstr"
  },
  {
    "path": "old_impl/strings/suffix_array.cpp",
    "chars": 1721,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (int)1e5 + 42;\nconst int MAXLOG = 20;\n"
  },
  {
    "path": "old_impl/strings/suffix_array_hash.cpp",
    "chars": 2229,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\n#define int long long\n\nusing namespace std;\nconst int MAXN = (1 << 20);\n\nstr"
  },
  {
    "path": "old_impl/strings/suffix_array_log2.cpp",
    "chars": 1647,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\n\nint n;\nstring s;\n\nvoid rea"
  },
  {
    "path": "old_impl/strings/suffix_automaton.cpp",
    "chars": 1848,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\n\nstruct suffix_automaton {\n"
  },
  {
    "path": "old_impl/strings/trie.cpp",
    "chars": 1183,
    "preview": "#include <bits/stdc++.h>\n\nusing namespace std;\n\nstruct trie {\n    vector<int> cnt, len;\n    vector<map<char, int>> to;\n\n"
  },
  {
    "path": "old_impl/tree/centroid_decomposition.cpp",
    "chars": 1147,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\n\nint n;\nvector<int> adj[MAX"
  },
  {
    "path": "old_impl/tree/dsu_on_tree.cpp",
    "chars": 1366,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\n\nint n;\nvector<int> G[MAXN]"
  },
  {
    "path": "old_impl/tree/hld.cpp",
    "chars": 2143,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\ntemplate<class T, class T2> inline int chkmax(T &x, const T2 &y) { return "
  },
  {
    "path": "old_impl/tree/lca-seg3.cpp",
    "chars": 1582,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\nconst int MAXLOG = 20;\n\nint"
  },
  {
    "path": "old_impl/tree/link_cut_tree.cpp",
    "chars": 5367,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\nconst int MAXN = (1 << 20);\n\nrandom_device rd;\nmt19937_64 mt(rd());\n\nstruc"
  },
  {
    "path": "old_impl/tree/virtual_tree.cpp",
    "chars": 2823,
    "preview": "#include <bits/stdc++.h>\n\nusing namespace std;\nconst int MAXLOG = 20;\n\nint n;\nvector<vector<int>> adj;\n\nvoid read() {\n  "
  },
  {
    "path": "other/bits/bit_trie.hpp",
    "chars": 1142,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\ntemplate<class T, int num_bits>\nclass BitTrie {\n  public:\n    struct node"
  },
  {
    "path": "other/bits/xor_basis.hpp",
    "chars": 2841,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\ntemplate<class T, int num_bits>\nclass XorBasis {\n  public:\n    int sz;\n  "
  },
  {
    "path": "other/dp_optimizations/LiChao_dynamic.cpp",
    "chars": 2971,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\nconst int64_t inf = (int64_"
  },
  {
    "path": "other/dp_optimizations/LiChao_parabolic.cpp",
    "chars": 2326,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\nconst int inf = (int)1e9 + "
  },
  {
    "path": "other/dp_optimizations/LiChao_segment_tree_offline.cpp",
    "chars": 3451,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\nconst double inf = (double)"
  },
  {
    "path": "other/dp_optimizations/convex_hull_trick_max.cpp",
    "chars": 2543,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\nconst int64_t inf = (int64_"
  },
  {
    "path": "other/dp_optimizations/convex_hull_trick_min.cpp",
    "chars": 2543,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\nconst int64_t inf = (int64_"
  },
  {
    "path": "other/dp_optimizations/divide_and_conquer_optimization.cpp",
    "chars": 1354,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (int)4e3 + 42;\nconst int inf = (int)1e"
  },
  {
    "path": "other/dp_optimizations/slope_trick.cpp",
    "chars": 2794,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\n#define SZ(x) ((int)x.size())\n#define ALL(V) V.begin(), V.end()\n#define lb l"
  },
  {
    "path": "other/dp_optimizations/slope_trick_priority_queue.cpp",
    "chars": 2605,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\n#define SZ(x) ((int)x.size())\n#define ALL(V) V.begin(), V.end()\n#define lb l"
  },
  {
    "path": "other/queries/mo.cpp",
    "chars": 1125,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n\nusing namespace std;\nconst int MAXN = (1 << 20);\n\nstruct query\n{\n\tint l, r, "
  },
  {
    "path": "other/queries/mo_dsu.cpp",
    "chars": 2892,
    "preview": "#include <bits/stdc++.h>\n#define endl '\\n'\n \nusing namespace std;\nconst int MAXN = (1 << 20);\n \nstruct query\n{\n\tint l, r"
  },
  {
    "path": "other/queries/mo_online.cpp",
    "chars": 2486,
    "preview": "#include <bits/stdc++.h>\r\n#define endl '\\n'\r\n\r\nusing namespace std;\r\nconst int MAXN = (int)1e5 + 42;\r\nconst int B = 2172"
  },
  {
    "path": "other/queries/offline_centroid_queries.cpp",
    "chars": 5707,
    "preview": "// This is from https://codeforces.com/contest/1902/problem/F\n\n#include <bits/stdc++.h>\n\nusing namespace std;\n\ntemplate<"
  },
  {
    "path": "other/utils/count_inversions.cpp",
    "chars": 695,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\nint64_t count_inversions(int *start, int *end) {\n    if(end - start <= 1)"
  },
  {
    "path": "strings/aho_corasick.hpp",
    "chars": 2291,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\ntemplate<class T = string>\nclass AhoCorasick {\n  private:\n    using G = c"
  },
  {
    "path": "strings/hashing.hpp",
    "chars": 3232,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\nclass HashMeta {\n  private:\n    void set_random_base() {\n        seed_seq"
  },
  {
    "path": "strings/suffix_array.hpp",
    "chars": 2006,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\ntemplate<class T = string>\nclass SuffixArray {\n  private:\n    using G = c"
  },
  {
    "path": "strings/suffix_automaton.hpp",
    "chars": 2400,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\ntemplate<class T = string>\nclass SuffixAutomaton {\n  private:\n    using G"
  },
  {
    "path": "tree/centroid_decomposition.hpp",
    "chars": 3258,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\ntemplate<\n    void (*process)(int, const vector<vector<int>> &, const vec"
  },
  {
    "path": "tree/euler_order_segment_tree.cpp",
    "chars": 3316,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\ntemplate<class T, class T1>\nint chkmin(T &x, const T1 &y) {\n    return x >"
  },
  {
    "path": "tree/lca.hpp",
    "chars": 1759,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\nclass LCAUtils {\n  protected:\n    int max_log, dfs_time;\n    vector<vecto"
  },
  {
    "path": "tree/lca_sparse_table.hpp",
    "chars": 1490,
    "preview": "#include <bits/stdc++.h>\n#include <coding_library/data_structures/sparse_table.hpp>\nusing namespace std;\n\nclass LCAUtils"
  },
  {
    "path": "tree/line_tree.hpp",
    "chars": 1563,
    "preview": "#include <bits/stdc++.h>\n#include <coding_library/graph/dsu.hpp>\n#include <coding_library/tree/lca_sparse_table.hpp>\nusi"
  },
  {
    "path": "tree/link_cut_tree.hpp",
    "chars": 8578,
    "preview": "#include <bits/stdc++.h>\nusing namespace std;\n\n// Mine was slow, so based it on maspy's implementation:\n// https://codef"
  },
  {
    "path": "tree/vertex_add_path_sum.hpp",
    "chars": 724,
    "preview": "#include <bits/stdc++.h>\n#include \"coding_library/data_structures/fenwick_range_update.hpp\"\n#include \"coding_library/tre"
  },
  {
    "path": "tree/virtual_tree.hpp",
    "chars": 1647,
    "preview": "#include <bits/stdc++.h>\n#include <coding_library/tree/lca.hpp>\nusing namespace std;\n\nclass VirtualTree : public LCAUtil"
  }
]

About this extraction

This page contains the full source code of the radoslav11/Coding-Library GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 132 files (324.3 KB), approximately 106.6k tokens, and a symbol index with 1510 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!