├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── CMakeUserPresets.json ├── README.md ├── aho_corasick.h ├── arbitrary_ntt.h ├── avl.h ├── barrett.h ├── binom.h ├── binom_sum.h ├── binpow.h ├── bit_rmq.h ├── build.sh ├── cap_scaling_min_cost_flow.h ├── cartesian.h ├── char_poly.h ├── conanfile.txt ├── dag_dom_tree.h ├── debug.h ├── det_f2.h ├── directed_eulerian_tour.h ├── dom_tree.h ├── doubling_lca_base.h ├── dsu.h ├── dyn_inv_table.h ├── dyn_mod.h ├── egz.h ├── empty_class.h ├── entombed.h ├── eulerian_tour.h ├── fast_io.h ├── fixed_power_table.h ├── fixed_size_matrix.h ├── fixed_size_upper_matrix.h ├── free_queue.h ├── gaussian_elimination.h ├── gaussian_field.h ├── gen.h ├── heavy_light_decomp.h ├── heavy_light_decomp_base.h ├── heavy_light_decomp_subtree.h ├── hilbert.h ├── inv.h ├── inv_table.h ├── io.d ├── io.h ├── io.rs ├── io_base.h ├── is_specialization_of.h ├── itoa └── jeaiii_to_text.h ├── kmp.h ├── lca.h ├── longest_path_decomp.h ├── matrix.h ├── min_plus_conv.h ├── mod.h ├── mod_wrapper.h ├── monoid_dsu.h ├── mont.h ├── nd_array.h ├── nim.h ├── north_east_lattic_path.h ├── ntt.h ├── parity_dsu.h ├── path_compression_dsu.h ├── point.h ├── poly.h ├── poly_compose.h ├── poly_conv.h ├── poly_div.h ├── poly_exp.h ├── poly_gen.h ├── poly_gen_dyn.h ├── poly_interpolate.h ├── poly_inv.h ├── poly_log.h ├── poly_multieval.h ├── poly_op.h ├── poly_pow.h ├── poly_prod.h ├── power_table.h ├── pq_util.h ├── prefix_table.h ├── primality_test.h ├── prime_count.h ├── primitive_root.h ├── quick_gcd.h ├── range_dsu.h ├── reroot_dp.h ├── rolling_hash.h ├── sa.h ├── sa_doubling.h ├── sam.h ├── segment_cover.h ├── segment_tree.h ├── sieve.h ├── singleton.h ├── smawk.h ├── snippets ├── YESNO.h ├── all.h ├── discretization.h ├── group.h ├── min_pow_of_two.h ├── min_pq.h ├── oneshot_discretization.h ├── ranges.h ├── u64.h ├── update_max.h └── update_min.h ├── sparse_table.h ├── splay.h ├── suffix_xor_basis.h ├── tarjan.h ├── test ├── CMakeLists.txt ├── arbitrary_ntt.hpp ├── asm_factor.hpp ├── benchmark.cc ├── binpow.hpp ├── debug.hpp ├── io.hpp ├── lca.hpp ├── mod.hpp ├── nd_vector.hpp ├── poly.hpp ├── poly_gen.hpp ├── poly_gen_dyn.hpp ├── poly_interpolate.hpp ├── rmq.hpp ├── rolling_hash.hpp ├── segment_tree.hpp ├── smawk.hpp ├── tests.cc ├── universal_euclidean.hpp ├── y_combinator.hpp └── zip_with.hpp ├── tmdc.h ├── top_tree.h ├── treap.h ├── tri_edge_connected.h ├── trie.h ├── trygub.h ├── types ├── compare.h ├── graph.h ├── graph │ ├── adjacent_list.h │ ├── adjacent_list_base.h │ ├── forward_star.h │ └── vector.h ├── matrix_2d.h ├── monoid.h ├── topo_graph.h └── tree_monoid.h ├── uint128_shim.h ├── universal_euclidean.h ├── util.h ├── y_combinator.h └── zip_with.h /.gitignore: -------------------------------------------------------------------------------- 1 | /.cache 2 | /.ccls-cache 3 | /Build 4 | /compile_commands.json 5 | /todo 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "picobench"] 2 | path = picobench 3 | url = https://github.com/iboB/picobench.git 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14 FATAL_ERROR) 2 | 3 | project(shoka LANGUAGES CXX) 4 | 5 | set(CMAKE_CXX_STANDARD 20) 6 | set(CMAKE_CXX_EXTENSIONS OFF) 7 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 8 | 9 | # include(${CMAKE_BINARY_DIR}/conan_paths.cmake) 10 | 11 | find_package(Catch2 3 REQUIRED) 12 | 13 | include(CTest) 14 | include(Catch) 15 | add_subdirectory(test) 16 | -------------------------------------------------------------------------------- /CMakeUserPresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 4, 3 | "vendor": { 4 | "conan": {} 5 | }, 6 | "include": [ 7 | "/home/ftiasch/Documents/shoka/Build/CMakePresets.json" 8 | ] 9 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Build 2 | 3 | ```shell 4 | cmake --build Build && (cd Build && ctest .) 5 | ``` 6 | 7 | # Convention 8 | 9 | ## Naming 10 | 11 | ## Structure 12 | 13 | - namespace `xxx_details` 14 | 15 | ```c++ 16 | class C { 17 | // private members 18 | public: 19 | // public members 20 | }; 21 | ``` 22 | -------------------------------------------------------------------------------- /aho_corasick.h: -------------------------------------------------------------------------------- 1 | #include "empty_class.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | template struct AhoCorasick { 8 | struct Node : public BaseNode { 9 | Node() { std::fill(go.begin(), go.end(), nullptr); } 10 | 11 | Node *fail; 12 | std::array go; 13 | }; 14 | 15 | explicit AhoCorasick(int n) : node_count{1}, nodes(1 + n) {} 16 | 17 | Node *root() { return nodes.data(); } 18 | 19 | Node *extend(Node *p, int c) { 20 | if (p->go[c] == nullptr) { 21 | p->go[c] = new (nodes.data() + (node_count++)) Node(); 22 | } 23 | return p->go[c]; 24 | } 25 | 26 | auto build() { 27 | std::vector queue; 28 | auto r = root(); 29 | for (int c = 0; c < C; c++) { 30 | auto &v = r->go[c]; 31 | if (v != nullptr) { 32 | queue.push_back(v); 33 | } 34 | (v != nullptr ? v->fail : v) = r; 35 | } 36 | for (int hd = 0; hd < queue.size(); hd++) { 37 | auto u = queue[hd]; 38 | for (int c = 0; c < C; c++) { 39 | auto &v = u->go[c]; 40 | if (v != nullptr) { 41 | queue.push_back(v); 42 | } 43 | (v != nullptr ? v->fail : v) = u->fail->go[c]; 44 | } 45 | } 46 | return queue; 47 | } 48 | 49 | protected: 50 | int node_count; 51 | std::vector nodes; 52 | }; 53 | -------------------------------------------------------------------------------- /arbitrary_ntt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "snippets/min_pow_of_two.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | template struct ArbitraryNTT { 11 | std::vector operator()(const std::vector &a_, 12 | const std::vector &b_) { 13 | int deg_plus_1 = a_.size() + b_.size() - 1; 14 | int n = min_pow_of_two(deg_plus_1); 15 | if (max_n < n) { 16 | max_n = n; 17 | twiddles.resize(max_n + 1); 18 | static const double PI = acos(-1); 19 | for (int i = 0; i <= max_n; i++) { 20 | twiddles[i] = Complex{cos(2 * i * PI / max_n), sin(2 * i * PI / max_n)}; 21 | } 22 | for (int i = 0; i < NUMBER_OF_BUFFER; i++) { 23 | buffers[i].resize(max_n); 24 | } 25 | } 26 | auto a = buffers[0].data(); 27 | auto b = buffers[1].data(); 28 | auto c = buffers[2].data(); 29 | auto d = buffers[3].data(); 30 | radix_split(n, a, a_); 31 | radix_split(n, b, b_); 32 | dif(n, a); 33 | dif(n, b); 34 | for (int m = 1; m <= n; m <<= 1) { 35 | for (int i = m >> 1; i < m; i++) { 36 | auto coef = .5 * b[i]; 37 | auto j = m + (m >> 1) - 1 - i; 38 | auto t = a[i] - std::conj(a[j]); 39 | c[i] = coef * Complex{t.imag(), -t.real()}; 40 | d[i] = coef * (a[i] + std::conj(a[j])); 41 | } 42 | } 43 | dit(n, c); 44 | dit(n, d); 45 | std::vector out(deg_plus_1); 46 | Mod M{1 << B}, M2{M * M}; 47 | for (int i = 0; i < deg_plus_1; ++i) { 48 | auto da = Mod::normalize(static_cast(c[i].imag() / n + 0.5)); 49 | auto db = Mod::normalize(static_cast(c[i].real() / n + 0.5)); 50 | auto dc = Mod::normalize(static_cast(d[i].imag() / n + 0.5)); 51 | auto dd = Mod::normalize(static_cast(d[i].real() / n + 0.5)); 52 | out[i] = dd * M2 + (db + dc) * M + da; 53 | } 54 | return out; 55 | } 56 | 57 | private: 58 | using Complex = std::complex; 59 | 60 | static constexpr int B = 15; 61 | static constexpr int NUMBER_OF_BUFFER = 4; 62 | 63 | void radix_split(int n, Complex *b, const std::vector &a) { 64 | for (int i = 0; i < a.size(); i++) { 65 | auto got = a[i].get(); 66 | b[i] = Complex{static_cast(got >> B), 67 | static_cast(got & ((1 << B) - 1))}; 68 | } 69 | std::fill(b + a.size(), b + n, Complex{}); 70 | } 71 | 72 | void dit(int n, Complex *a) { 73 | for (int m = 1; m < n; m <<= 1) { 74 | auto step = max_n / (m << 1); 75 | for (int i = 0; i < n; i += m << 1) { 76 | int tid = 0; 77 | for (int r = i; r < i + m; r++) { 78 | auto tmp = twiddles[tid] * a[r + m]; 79 | a[r + m] = a[r]; 80 | a[r + m] -= tmp; 81 | a[r] += tmp; 82 | tid += step; 83 | } 84 | } 85 | } 86 | } 87 | 88 | void dif(int n, Complex *a) { 89 | for (int m = n; m >>= 1;) { 90 | auto step = max_n / (m << 1); 91 | for (int i = 0; i < n; i += m << 1) { 92 | int tid = max_n; 93 | for (int r = i; r < i + m; r++) { 94 | auto tmp = a[r]; 95 | tmp -= a[r + m]; 96 | a[r] += a[r + m]; 97 | a[r + m] = twiddles[tid] * tmp; 98 | tid -= step; 99 | } 100 | } 101 | } 102 | } 103 | 104 | int max_n = 0; 105 | std::vector twiddles; 106 | std::array, NUMBER_OF_BUFFER> buffers; 107 | }; 108 | -------------------------------------------------------------------------------- /avl.h: -------------------------------------------------------------------------------- 1 | #include "free_queue.h" 2 | 3 | #include 4 | #include 5 | 6 | template struct AVLTreeBase { 7 | struct Node : public NodeBase { 8 | int height; 9 | size_t size; 10 | Node *left, *right; 11 | }; 12 | 13 | explicit AVLTreeBase(int n_) : nodes(n_ << 1), free_queue(n_ << 1) { 14 | assert(free_queue.allocate() == 0); 15 | auto n = null_node(); 16 | n->height = 0; 17 | n->size = 0; 18 | n->left = n->right = null_node(); 19 | } 20 | 21 | Node *null_node() { return nodes.data(); } 22 | 23 | Node *new_leaf() { 24 | auto n = new_node(); 25 | n->height = 0; 26 | n->size = 1; 27 | n->left = n->right = null_node(); 28 | return n; 29 | } 30 | 31 | Node *merge(Node *u, Node *v) { 32 | if (u == null_node()) { 33 | return v; 34 | } 35 | if (v == null_node()) { 36 | return u; 37 | } 38 | if (std::abs(u->height - v->height) <= 1) { 39 | return new_node(u, v); 40 | } 41 | Impl::propagate(v); 42 | if (u->height + 2 == v->height && v->right->height + 2 == v->height) { 43 | auto [vl, vr] = destruct(v); 44 | auto [vll, vlr] = destruct(vl); 45 | return new_node(new_node(u, vll), new_node(vlr, vr)); 46 | } 47 | if (u->height < v->height) { 48 | auto [vl, vr] = destruct(v); 49 | return merge(merge(u, vl), vr); 50 | } else { 51 | auto [ul, ur] = destruct(u); 52 | return merge(ul, merge(ur, v)); 53 | } 54 | } 55 | 56 | std::pair split(Node *u, size_t k) { 57 | if (k == 0) { 58 | return {null_node(), u}; 59 | } 60 | if (k == u->size) { 61 | return {u, null_node()}; 62 | } 63 | auto [ul, ur] = destruct(u); 64 | if (k <= ul->size) { 65 | auto [a, b] = split(ul, k); 66 | return {a, merge(b, ur)}; 67 | } else { 68 | auto [a, b] = split(ur, k - ul->size); 69 | return {merge(ul, a), b}; 70 | } 71 | } 72 | 73 | private: 74 | Node *collect(Node *n) { 75 | n->height = std::max(n->left->height, n->right->height) + 1; 76 | n->size = n->left->size + n->right->size; 77 | Impl::collect(n); 78 | return n; 79 | } 80 | 81 | Node *new_node() { return new (nodes.data() + free_queue.allocate()) Node(); } 82 | 83 | Node *new_node(Node *l, Node *r) { 84 | auto n = new_node(); 85 | n->left = l; 86 | n->right = r; 87 | return collect(n); 88 | } 89 | 90 | std::pair destruct(Node *u) { 91 | Impl::propagate(u); 92 | free_node(u); 93 | return {u->left, u->right}; 94 | } 95 | 96 | void free_node(Node *n) { free_queue.free(n - nodes.data()); } 97 | 98 | std::vector nodes; 99 | FreeQueue free_queue; 100 | }; 101 | -------------------------------------------------------------------------------- /barrett.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "mod_wrapper.h" 4 | 5 | namespace mod { 6 | 7 | template struct BarrettBaseT { 8 | using M = M_; 9 | 10 | void set_mod(M mod_) { 11 | mod = mod_; 12 | inv_mod = static_cast(-1) / mod; 13 | } 14 | 15 | M get_mod() const { return mod; } 16 | 17 | private: 18 | using M2 = m2_t; 19 | 20 | public: 21 | M reduce(M2 x) { 22 | auto q = MultiplierT::mul_hi(x, inv_mod); 23 | auto r = x - q * mod; 24 | return r >= mod ? r - mod : r; 25 | } 26 | 27 | private: 28 | M mod; 29 | M2 inv_mod; 30 | }; 31 | 32 | template 33 | using Barrett64T = ModWrapperT>; 34 | template 35 | using BarrettT = ModWrapperT>; 36 | 37 | } // namespace mod 38 | 39 | using mod::Barrett64T; 40 | using mod::BarrettT; 41 | -------------------------------------------------------------------------------- /binom.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template struct Binom { 4 | explicit Binom(int n) : fact(n), inv_fact(n) { 5 | fact[0] = inv_fact[0] = inv_fact[1] = Mod{1}; 6 | for (int i = 2; i < n; ++i) { 7 | inv_fact[i] = -Mod{Mod::mod() / i} * inv_fact[Mod::mod() % i]; 8 | } 9 | for (int i = 1; i < n; ++i) { 10 | fact[i] = Mod{i} * fact[i - 1]; 11 | inv_fact[i] *= inv_fact[i - 1]; 12 | } 13 | } 14 | 15 | Mod operator()(int n, int k) const { 16 | return k < 0 || k > n ? Mod{0} : fact[n] * inv_fact[n - k] * inv_fact[k]; 17 | } 18 | 19 | std::vector fact, inv_fact; 20 | }; 21 | -------------------------------------------------------------------------------- /binom_sum.h: -------------------------------------------------------------------------------- 1 | #include "dyn_inv_table.h" 2 | 3 | #include 4 | #include 5 | 6 | template struct BinomialSum { 7 | // c0 * x^n mod (x - 1)^{k + 1} 8 | static std::vector monomial_mod(Mod n, int k, Mod c0 = Mod{1}) { 9 | std::vector result(k + 1); 10 | if (n.get() <= k) { 11 | result[n.get()] = c0; 12 | } else { 13 | result[0] = Mod{1}; 14 | for (int i = 0; i < k; i++) { 15 | result[i + 1] = result[i] * (n - Mod{i}) * inv(i + 1); 16 | } 17 | Mod c{c0}; 18 | for (int i = k; i >= 0; i--) { 19 | result[i] *= c; 20 | c = -c * (n - Mod{i}) * inv(k - i + 1); 21 | } 22 | } 23 | return result; 24 | } 25 | 26 | // Q * F(z) = P 27 | // Computes F(z) mod (z - 1)^{k + 1} 28 | // where P is given in sparse form, i.e. (i, c) stands for c * z^i 29 | static std::vector 30 | rational_gf_mod(const std::vector &Q, 31 | const std::vector> &P, int k) { 32 | auto d = static_cast(Q.size()) - 1; 33 | // Q(t + 1) 34 | std::vector Q_in_t(d + 1); 35 | for (int i = 0; i <= d; i++) { 36 | Mod c = Q[i]; 37 | for (int j = 0; j <= i; j++) { 38 | // Q_in_t[j] += Q[i] * binom(i, j); 39 | Q_in_t[j] += c; 40 | c *= Mod{i - j} * inv(j + 1); 41 | } 42 | } 43 | assert(Q_in_t[0].get()); 44 | // P(t + 1) mod t^{k + 1} 45 | std::vector F_in_t(k + 1); 46 | for (auto &&[i, pi] : P) { 47 | Mod c = pi; 48 | for (int j = 0; j <= k && c.get(); j++) { 49 | F_in_t[j] += c; 50 | c *= (i - Mod{j}) * inv(j + 1); 51 | } 52 | } 53 | { 54 | auto inv_Q0 = Q_in_t[0].inv(); 55 | for (int i = 0; i <= k; i++) { 56 | Mod t{F_in_t[i]}; 57 | for (int j = 1; j <= d && j <= i; j++) { 58 | t -= Q_in_t[j] * F_in_t[i - j]; 59 | } 60 | F_in_t[i] = inv_Q0 * t; 61 | } 62 | } 63 | std::vector F_in_u(k + 1); 64 | for (auto &&[i, pi] : P) { 65 | if (i.get() <= k) { 66 | F_in_u[i.get()] += pi; 67 | } else { 68 | auto c = monomial_mod(i, k, pi); 69 | for (int j = 0; j <= k; j++) { 70 | F_in_u[j] += c[j]; 71 | } 72 | } 73 | } 74 | // offset terms 75 | for (int i = 1; i <= d; i++) { 76 | // t^{k + i} 77 | Mod c{0}; 78 | for (int j = i; j <= d; j++) { 79 | c += Q_in_t[j] * F_in_t[k + i - j]; 80 | } 81 | // (u - 1)^{k + i} 82 | if ((k + i) & 1) { 83 | c = -c; 84 | } 85 | for (int j = 0; j <= k && c.get(); j++) { 86 | F_in_u[j] += c; 87 | c = -c * Mod{k + i - j} * inv(j + 1); 88 | } 89 | } 90 | { 91 | auto inv_Q0 = Q[0].inv(); 92 | for (int i = 0; i <= k; i++) { 93 | Mod t{F_in_u[i]}; 94 | for (int j = 1; j <= d && j <= i; j++) { 95 | t -= Q[j] * F_in_u[i - j]; 96 | } 97 | F_in_u[i] = inv_Q0 * t; 98 | } 99 | } 100 | return F_in_u; 101 | } 102 | }; 103 | -------------------------------------------------------------------------------- /binpow.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | template 7 | static constexpr T binpow(T a, N n) { 8 | static_assert(std::is_integral_v); 9 | auto result = T::mul_id(); 10 | while (n) { 11 | if (n & 1) { 12 | result *= a; 13 | } 14 | a *= a; 15 | n >>= 1; 16 | } 17 | return result; 18 | } 19 | -------------------------------------------------------------------------------- /bit_rmq.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sparse_table.h" 4 | 5 | #include 6 | 7 | template > struct BitRmqT { 8 | using T = T_; 9 | using Semilattice = SemilatticeT; 10 | 11 | explicit BitRmqT(std::vector &&values_) 12 | : n{static_cast(values_.size())}, m{block_id(n - 1) + 1}, 13 | values{std::move(values_)}, 14 | block_meet{compute_block_meet(n, m, values)}, inter{block_meet} { 15 | block.reserve(m); 16 | for (int i = 0, s = 0; i < m; ++i, s += 64) { 17 | block.emplace_back(values.data() + s, std::min(n - s, 64)); 18 | } 19 | } 20 | 21 | T operator()(int l, int r) const { 22 | if (l == r) { 23 | return Semilattice::id; 24 | } 25 | r--; 26 | int lb = block_id(l); 27 | int rb = block_id(r); 28 | if (lb == rb) { 29 | return block[lb](l & 63, r & 63); 30 | } 31 | T pre_suf = 32 | Semilattice::meet(block[lb].suffix[l & 63], block[rb].prefix[r & 63]); 33 | return (lb + 1 <= rb - 1) 34 | ? Semilattice::meet(pre_suf, inter(lb + 1, rb - 1)) 35 | : pre_suf; 36 | } 37 | 38 | private: 39 | static constexpr int block_id(int index) { return index >> 6; } 40 | 41 | struct Block { 42 | explicit Block(const T *a_, int n) { 43 | a = a_; 44 | uint64_t current_stack = 0; 45 | T minimum = Semilattice::id; 46 | for (int i = 0; i < n; ++i) { 47 | while (current_stack && 48 | Compare{}(a[i], a[highest_bit(current_stack)])) { 49 | current_stack ^= 1ULL << highest_bit(current_stack); 50 | } 51 | current_stack |= 1ULL << i; 52 | stack[i] = current_stack; 53 | minimum = Semilattice::meet(minimum, a[i]); 54 | prefix[i] = minimum; 55 | } 56 | suffix[n - 1] = a[n - 1]; 57 | for (int i = n - 1; i--;) { 58 | suffix[i] = Semilattice::meet(suffix[i + 1], a[i]); 59 | } 60 | } 61 | 62 | T operator()(int l, int r) const { 63 | return a[__builtin_ctzll(stack[r] & ~((1ULL << l) - 1))]; 64 | } 65 | 66 | std::array prefix, suffix; 67 | 68 | private: 69 | static int highest_bit(uint64_t mask) { return 63 - __builtin_clzll(mask); } 70 | 71 | const T *a; 72 | 73 | std::array stack; 74 | }; 75 | 76 | static std::vector compute_block_meet(int n, int m, 77 | const std::vector &values) { 78 | std::vector meet(m, Semilattice::id); 79 | for (int i = 0; i < n; ++i) { 80 | meet[block_id(i)] = Semilattice::meet(meet[block_id(i)], values[i]); 81 | } 82 | return meet; 83 | } 84 | 85 | int n, m; 86 | const std::vector values; 87 | std::vector block_meet; 88 | SparseTableT inter; 89 | std::vector block; 90 | }; 91 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o errexit 3 | 4 | conan install . --output-folder=Build --build=missing 5 | (cd Build && cmake -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=1 ..) 6 | cmake --build Build 7 | -------------------------------------------------------------------------------- /cap_scaling_min_cost_flow.h: -------------------------------------------------------------------------------- 1 | #include "snippets/min_pow_of_two.h" 2 | #include "snippets/min_pq.h" 3 | #include "types/graph/adjacent_list_base.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | template 11 | class CapScalingMinCostFlow 12 | : public AdjacentListBase> { 13 | using Base = AdjacentListBase>; 14 | using Base::edges; 15 | 16 | using OutFn = std::function; 17 | 18 | void update(int u, int v, int i, CapT delta) { 19 | excess[u] -= delta; 20 | excess[v] += delta; 21 | std::get<1>(edges[i]) -= delta; 22 | std::get<1>(edges[i ^ 1]) += delta; 23 | } 24 | 25 | bool augment(int s, int delta, const OutFn &output) { 26 | std::ranges::fill(visited, false); 27 | std::ranges::fill(dist, std::numeric_limits::max()); 28 | while (!pq.empty()) { 29 | pq.pop(); 30 | } 31 | pq.emplace(dist[s] = 0, s); 32 | while (!pq.empty()) { 33 | auto [du, u] = pq.top(); 34 | pq.pop(); 35 | if (du == dist[u]) { 36 | visited[u] = true; 37 | if (excess[u] <= -delta) { 38 | // augment along the path s->t 39 | auto t = u; 40 | output(delta, dist[t] + pi[s] - pi[t]); 41 | for (int u = 0; u < n; u++) { 42 | if (visited[u]) { 43 | pi[u] = pi[u] - dist[u] + dist[t]; 44 | } 45 | } 46 | for (int v = t; v != s;) { 47 | auto i = pre[v]; 48 | assert(~i); 49 | auto u = std::get<0>(edges[i ^ 1]); 50 | update(u, v, i, delta); 51 | v = u; 52 | } 53 | return true; 54 | } 55 | for (int i = Base::head[u]; ~i; i = Base::next[i]) { 56 | auto [v, c, w] = edges[i]; 57 | auto rw = w - pi[u] + pi[v]; 58 | if (c >= delta && dist[v] > dist[u] + rw) { 59 | pre[v] = i; 60 | pq.emplace(dist[v] = dist[u] + rw, v); 61 | } 62 | } 63 | } 64 | } 65 | return false; 66 | } 67 | 68 | int n; 69 | CapT maxc = 1; 70 | std::vector visited, pre; 71 | MinPQ> pq; 72 | std::vector excess; 73 | std::vector pi, dist; 74 | 75 | public: 76 | explicit CapScalingMinCostFlow(int n_) 77 | : Base{n_}, n{n_}, visited(n), pre(n), excess(n), pi(n), dist(n) {} 78 | 79 | void add_edge(int u, int v, CapT c, CostT w) { 80 | Base::add(u, v, c, w); 81 | Base::add(v, u, 0, -w); 82 | maxc = std::max(maxc, c); 83 | } 84 | 85 | CapT operator()(int source, int sink, const OutFn &output) { 86 | auto delta = min_pow_of_two(maxc + 1) >> 1; 87 | CapT flow{0}; 88 | while (delta) { 89 | for (int i = 0; i < static_cast(edges.size()); i++) { 90 | auto &[v, c, w] = edges[i]; 91 | auto u = std::get<0>(edges[i ^ 1]); 92 | if (c >= delta && w - pi[u] + pi[v] < 0) { 93 | update(u, v, i, delta); 94 | output(delta, w); 95 | } 96 | } 97 | for (int s = 0; s < n; s++) { 98 | while (excess[s] >= delta) { 99 | assert(augment(s, delta, output)); 100 | } 101 | } 102 | do { 103 | flow += delta; 104 | excess[source] += delta; 105 | excess[sink] -= delta; 106 | } while (augment(source, delta, output)); 107 | flow -= delta; 108 | excess[source] -= delta; 109 | excess[sink] += delta; 110 | delta >>= 1; 111 | } 112 | return flow; 113 | } 114 | }; 115 | -------------------------------------------------------------------------------- /cartesian.h: -------------------------------------------------------------------------------- 1 | #include "types/compare.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | template > 9 | requires IsComparator 10 | class MaxCartesianTree { 11 | int n; 12 | std::vector stack; 13 | 14 | public: 15 | explicit MaxCartesianTree(std::ranges::random_access_range auto a, 16 | C compare = {}) 17 | : n(std::ranges::size(a)), stack(n), root{-1}, child(n) { 18 | int top = -1; 19 | for (int i = 0; i < n; i++) { 20 | while (~top && compare(a[stack[top]], a[i])) { 21 | top--; 22 | } 23 | int &r = ~top ? child[stack[top]][1] : root; 24 | child[i] = {r, -1}; 25 | r = i; 26 | stack[++top] = i; 27 | } 28 | } 29 | 30 | int root; // virtually child[-1][1] 31 | std::vector> child; 32 | }; 33 | -------------------------------------------------------------------------------- /char_poly.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | std::vector char_poly(int n, std::vector> a) { 6 | // Hessenberg reduction 7 | for (int r = 1; r < n; r++) { 8 | // a[>= r][r - 1] 9 | int pivot = r; 10 | while (pivot < n && !a[pivot][r - 1].get()) { 11 | pivot++; 12 | } 13 | if (pivot < n) { 14 | std::swap(a[r], a[pivot]); 15 | for (int i = 0; i < n; i++) { 16 | std::swap(a[i][r], a[i][pivot]); 17 | } 18 | auto inv = a[r][r - 1].inv(); 19 | for (int k = r + 1; k < n; k++) { 20 | if (a[k][r - 1].get()) { 21 | auto t = a[k][r - 1] * inv; 22 | for (int j = 0; j < n; j++) { 23 | a[k][j] -= t * a[r][j]; 24 | } 25 | for (int i = 0; i < n; i++) { 26 | a[i][r] += t * a[i][k]; 27 | } 28 | } 29 | } 30 | } 31 | } 32 | // char poly of Hessenberg matrix 33 | std::vector chi(n + 1, std::vector{}); 34 | chi[0].emplace_back(1); 35 | for (int i = 1; i <= n; i++) { 36 | // compute chi[i] 37 | chi[i].resize(i + 1); 38 | for (int j = 0; j < i; j++) { 39 | chi[i][j] -= a[i - 1][i - 1] * chi[i - 1][j]; 40 | chi[i][j + 1] += chi[i - 1][j]; 41 | } 42 | Mod coef{1}; 43 | for (int k = 2; k <= i; k++) { 44 | coef *= a[i - k + 1][i - k]; 45 | auto c = coef * a[i - k][i - 1]; 46 | for (int j = 0; j <= i - k; j++) { 47 | chi[i][j] -= c * chi[i - k][j]; 48 | } 49 | } 50 | } 51 | return chi[n]; 52 | } 53 | -------------------------------------------------------------------------------- /conanfile.txt: -------------------------------------------------------------------------------- 1 | [requires] 2 | catch2/3.5.3 3 | 4 | [generators] 5 | CMakeDeps 6 | CMakeToolchain 7 | -------------------------------------------------------------------------------- /dag_dom_tree.h: -------------------------------------------------------------------------------- 1 | #include "doubling_lca_base.h" 2 | #include "types/topo_graph.h" 3 | 4 | template class DagDomTree : public DoublingLcaBase { 5 | public: 6 | explicit DagDomTree(const TopoGraph &dag) 7 | : DoublingLcaBase(dag.size()), idom(dag.size(), -1) { 8 | for (int u : dag.rorder | std::views::reverse) { 9 | if (~idom[u]) { 10 | add_leaf(u, idom[u]); 11 | } 12 | for (int v : dag[u]) { 13 | idom[v] = ~idom[v] ? lca(idom[v], u) : u; 14 | } 15 | } 16 | } 17 | 18 | std::vector idom; 19 | }; 20 | -------------------------------------------------------------------------------- /debug.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | template struct Binary { 17 | static_assert(std::is_integral_v); 18 | 19 | explicit Binary(T value_, int length_ = std::numeric_limits::digits) 20 | : value{value_}, length{length_} {} 21 | 22 | T value; 23 | int length; 24 | }; 25 | 26 | namespace std { 27 | 28 | template 29 | ostream &operator<<(ostream &out, const tuple &t) { 30 | out << '('; 31 | std::apply( 32 | [&out](const T &...args) { 33 | int index = 0; 34 | ((out << args << (++index != sizeof...(T) ? ", " : "")), ...); 35 | }, 36 | t); 37 | return out << ')'; 38 | } 39 | 40 | template 41 | ostream &operator<<(ostream &out, const pair &v) { 42 | return out << tuple(v.first, v.second); 43 | } 44 | 45 | template ostream &operator<<(ostream &out, const Binary &b) { 46 | out << "("; 47 | for (auto i : std::ranges::iota_view(0, b.length)) { 48 | out << (b.value >> i & 1); 49 | } 50 | return out << ")_2"; 51 | } 52 | 53 | template 54 | ostream &operator<<(ostream &out, Range &&range) 55 | requires(!same_as, char>) 56 | { 57 | out << "["; 58 | bool first = true; 59 | for (auto &&elem : range) { 60 | if (first) { 61 | first = false; 62 | } else { 63 | out << ", "; 64 | } 65 | out << elem; 66 | } 67 | return out << "]"; 68 | } 69 | 70 | template 71 | ostream &operator<<(ostream &out, priority_queue pq) { 72 | vector v; 73 | while (!pq.empty()) { 74 | v.push_back(pq.top()); 75 | pq.pop(); 76 | } 77 | return out << v; 78 | } 79 | 80 | } // namespace std 81 | 82 | struct DebugLine { 83 | explicit DebugLine(int lineno) { std::cerr << lineno << "L "; } 84 | 85 | ~DebugLine() { std::cerr << std::endl; } 86 | 87 | template DebugLine &operator<<(T &&v) { 88 | std::cerr << std::forward(v); 89 | return *this; 90 | } 91 | }; 92 | 93 | #define KV(x) #x "=" << (x) << ";" 94 | #define DEBUG DebugLine(__LINE__) 95 | -------------------------------------------------------------------------------- /det_f2.h: -------------------------------------------------------------------------------- 1 | #include "char_poly.h" 2 | 3 | #include 4 | #include 5 | 6 | template 7 | std::vector det_f2(int n, std::vector>> a) { 8 | // a[0] + a[1] * x 9 | int shift = 0; 10 | Mod scale{1}; 11 | for (int j = 0; j < n; j++) { 12 | // Make a[j][j][1] == 1 13 | int pivot; 14 | while (true) { 15 | pivot = j; 16 | while (pivot < n && !a[j][pivot][1].get()) { 17 | pivot++; 18 | } 19 | if (pivot < n) { 20 | break; 21 | } 22 | if (++shift > n) { 23 | return std::vector(n + 1, Mod{0}); 24 | } 25 | // *= x 26 | for (int k = 0; k < n; k++) { 27 | a[j][k] = {Mod{0}, a[j][k][0]}; 28 | } 29 | for (int k = 0; k < j; k++) { 30 | auto t = a[j][k][1]; 31 | if (t.get()) { 32 | for (int p = 0; p < n; p++) { 33 | a[j][p][0] -= t * a[k][p][0]; 34 | a[j][p][1] -= t * a[k][p][1]; 35 | } 36 | } 37 | } 38 | } 39 | if (j < pivot) { 40 | scale = -scale; 41 | for (int i = 0; i < n; i++) { 42 | std::swap(a[i][j], a[i][pivot]); 43 | } 44 | } 45 | scale *= a[j][j][1]; 46 | { 47 | auto t = a[j][j][1].inv(); 48 | for (int k = 0; k < n; k++) { 49 | a[j][k][0] *= t; 50 | a[j][k][1] *= t; 51 | } 52 | } 53 | for (int i = 0; i < n; i++) { 54 | auto t = a[i][j][1]; 55 | if (i != j && t.get()) { 56 | for (int p = 0; p < n; p++) { 57 | a[i][p][0] -= t * a[j][p][0]; 58 | a[i][p][1] -= t * a[j][p][1]; 59 | } 60 | } 61 | } 62 | } 63 | std::vector b(n, std::vector(n)); 64 | for (int i = 0; i < n; i++) { 65 | for (int j = 0; j < n; j++) { 66 | b[i][j] = -a[i][j][0]; 67 | } 68 | } 69 | auto chi = char_poly(n, b); 70 | std::vector result(n + 1); 71 | for (int i = 0; i + shift <= n; i++) { 72 | result[i] = scale * chi[i + shift]; 73 | } 74 | return result; 75 | } 76 | -------------------------------------------------------------------------------- /directed_eulerian_tour.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // TODO: Unverified 5 | struct DirectedEulerianTour : public std::vector { 6 | explicit DirectedEulerianTour(int n_, int s, 7 | const std::vector> &edges_) 8 | : n{n_}, m(edges_.size()), head(n, -1), next(m), edges{edges_} { 9 | for (int i = 0; i < m; ++i) { 10 | auto [u, v] = edges[i]; 11 | next[i] = head[v]; 12 | head[u] = i; 13 | } 14 | dfs(s); 15 | } 16 | 17 | private: 18 | void dfs(int v) { 19 | while (~head[v]) { 20 | int u = edges[head[v]].first; 21 | head[v] = next[head[v]]; 22 | dfs(u); 23 | } 24 | push_back(v); 25 | } 26 | 27 | int n, m; 28 | std::vector head, next; 29 | const std::vector> &edges; 30 | }; 31 | -------------------------------------------------------------------------------- /dom_tree.h: -------------------------------------------------------------------------------- 1 | #include "types/graph.h" 2 | 3 | #include 4 | #include 5 | 6 | template class DomTree { 7 | void prepare(int u) { 8 | visited[u] = true; 9 | dfn[u] = order.size(); 10 | order.push_back(u); 11 | for (int v : graph[u]) { 12 | if (!visited[v]) { 13 | parent[v] = u; 14 | prepare(v); 15 | } 16 | } 17 | } 18 | 19 | int mplus(int u, int v) const { return sdom_dfn[u] < sdom_dfn[v] ? u : v; } 20 | 21 | int find(int u) { 22 | auto p = dsu[u].first; 23 | if (p != u) { 24 | find(p); 25 | dsu[u] = {dsu[p].first, mplus(dsu[p].second, dsu[u].second)}; 26 | } 27 | return dsu[u].second; 28 | } 29 | 30 | const Graph &graph; 31 | int n; 32 | std::vector visited; 33 | std::vector parent, dfn, sdom_dfn, sdom_head, sdom_next; 34 | std::vector> dsu; 35 | 36 | public: 37 | explicit DomTree(const Graph &graph_, const Graph &rgraph, int source = 0) 38 | : graph{graph_}, n(graph.size()), visited(n), parent(n, -1), dfn(n), 39 | sdom_dfn(n, n), sdom_head(n, -1), sdom_next(n), dsu(n), idom(n, -1) { 40 | order.reserve(n); 41 | prepare(source); 42 | sdom_dfn[source] = n; 43 | for (int i = 0; i < n; i++) { 44 | dsu[i] = {i, source}; 45 | } 46 | for (int v : order | std::views::drop(1) | std::views::reverse) { 47 | for (int u : rgraph[v]) { 48 | if (visited[u]) { 49 | sdom_dfn[v] = std::min(sdom_dfn[v], 50 | dfn[u] <= dfn[v] ? dfn[u] : sdom_dfn[find(u)]); 51 | } 52 | } 53 | dsu[v] = {parent[v], v}; 54 | // add sdom[v] -> v 55 | auto sdom = order[sdom_dfn[v]]; 56 | sdom_next[v] = sdom_head[sdom]; 57 | sdom_head[sdom] = v; 58 | for (int u = sdom_head[parent[v]]; ~u; u = sdom_next[u]) { 59 | idom[u] = find(u); 60 | } 61 | sdom_head[parent[v]] = -1; 62 | } 63 | for (int v : order | std::views::drop(1)) { 64 | idom[v] = 65 | sdom_dfn[v] <= sdom_dfn[idom[v]] ? order[sdom_dfn[v]] : idom[idom[v]]; 66 | } 67 | } 68 | 69 | std::vector order, idom; 70 | }; 71 | -------------------------------------------------------------------------------- /doubling_lca_base.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "snippets/min_pow_of_two.h" 4 | 5 | #include 6 | 7 | class DoublingLcaBase { 8 | int n, max_d; 9 | std::vector depth; 10 | std::vector> jump; 11 | 12 | public: 13 | explicit DoublingLcaBase(int n_) 14 | : n(n_), max_d{log_min_pow_of_two(n)}, depth(n), 15 | jump(n, std::vector(max_d, -1)) {} 16 | 17 | void add_leaf(int u, int p) { 18 | depth[u] = depth[p] + 1; 19 | jump[u][0] = p; 20 | for (int i = 0; ~jump[u][i] && i + 1 < max_d; i++) { 21 | jump[u][i + 1] = jump[jump[u][i]][i]; 22 | } 23 | } 24 | 25 | int lca(int x, int y) const { 26 | if (depth[x] > depth[y]) { 27 | std::swap(x, y); 28 | } 29 | for (int d = 0; d < max_d; d++) { 30 | if ((depth[y] - depth[x]) >> d & 1) { 31 | y = jump[y][d]; 32 | } 33 | } 34 | if (x == y) { 35 | return x; 36 | } 37 | for (int d = max_d; d--;) { 38 | if (jump[x][d] != jump[y][d]) { 39 | x = jump[x][d]; 40 | y = jump[y][d]; 41 | } 42 | } 43 | return jump[x][0]; 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /dsu.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class Dsu { 4 | struct Node { 5 | int p, r; 6 | }; 7 | 8 | std::vector node; 9 | 10 | public: 11 | explicit Dsu(int n) : node(n) { 12 | for (int i = 0; i < n; i++) { 13 | node[i] = {i, 0}; 14 | } 15 | } 16 | 17 | int find(int u) { 18 | while (node[u].p != u) { 19 | u = node[u].p = node[node[u].p].p; 20 | } 21 | return u; 22 | } 23 | 24 | bool merge(int a, int b) { 25 | a = find(a), b = find(b); 26 | if (a == b) { 27 | return false; 28 | } 29 | if (node[a].r < node[b].r) { 30 | std::swap(a, b); 31 | } 32 | node[b].p = a; 33 | node[a].r += node[a].r == node[b].r; 34 | return true; 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /dyn_inv_table.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "singleton.h" 4 | 5 | #include 6 | 7 | template struct DynInvTable { 8 | explicit DynInvTable() : b(2) { b[1] = Mod{1}; } 9 | 10 | Mod operator[](int i) { 11 | for (int j = b.size(); j <= i; j++) { 12 | b.push_back(-Mod{Mod::mod() / j} * b[Mod::mod() % j]); 13 | } 14 | return b[i]; 15 | } 16 | 17 | std::vector b; 18 | }; 19 | 20 | template static Mod inv(int a) { 21 | return singleton>()[a]; 22 | } 23 | -------------------------------------------------------------------------------- /dyn_mod.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "mod_wrapper.h" 4 | 5 | #include 6 | #include 7 | 8 | namespace mod { 9 | 10 | template struct DynModBaseT { 11 | using M = M_; 12 | 13 | void set_mod(M mod_) { mod = mod_; } 14 | 15 | M get_mod() const { return mod; } 16 | 17 | private: 18 | using M2 = m2_t; 19 | 20 | public: 21 | M reduce(M2 x) { return x % mod; } 22 | 23 | private: 24 | M mod; 25 | }; 26 | 27 | template 28 | using DynMod64T = ModWrapperT>; 29 | template 30 | using DynModT = ModWrapperT>; 31 | 32 | } // namespace mod 33 | 34 | using mod::DynMod64T; 35 | using mod::DynModT; 36 | -------------------------------------------------------------------------------- /egz.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | template std::vector egz(const std::vector &a) { 7 | int n = a.size(); 8 | assert(n & 1); 9 | auto p = (n + 1) >> 1; 10 | Mod::set_mod(p); 11 | std::vector> sorted_a(n); 12 | for (int i = 0; i < n; ++i) { 13 | sorted_a[i] = {a[i] % p, i}; 14 | } 15 | std::sort(sorted_a.begin(), sorted_a.end()); 16 | for (int i = 0; i + p - 1 < n; ++i) { 17 | if (sorted_a[i].first == sorted_a[i + p - 1].first) { 18 | std::vector plan(p); 19 | for (int j = 0; j < p; ++j) { 20 | plan[j] = sorted_a[i + j].second; 21 | } 22 | return plan; 23 | } 24 | } 25 | auto offset = -Mod{sorted_a[0].first}; 26 | std::vector from(p, -1); 27 | from[0] = 0; 28 | int last = p - 1; 29 | for (int i = 1; i + p - 1 < n; ++i) { 30 | offset -= Mod{sorted_a[i].first}; 31 | Mod d{sorted_a[i + p - 1].first - sorted_a[i].first}; 32 | while (~last && ~from[last]) { 33 | last--; 34 | } 35 | assert(~last); 36 | int low = 0, high = (Mod{last} * d.inv()).get(); 37 | while (low + 1 < high) { 38 | int middle = (low + high) >> 1; 39 | if (~from[(Mod{middle} * d).get()]) { 40 | low = middle; 41 | } else { 42 | high = middle; 43 | } 44 | } 45 | auto x = Mod{low} * d; 46 | assert(~from[x.get()]); 47 | assert(!~from[(x + d).get()]); 48 | from[(x + d).get()] = i; 49 | } 50 | std::vector picked(p); 51 | while (offset.get()) { 52 | int i = from[offset.get()]; 53 | picked[i] = true; 54 | offset -= Mod{sorted_a[i + p - 1].first - sorted_a[i].first}; 55 | } 56 | std::vector plan{sorted_a[0].second}; 57 | plan.reserve(p); 58 | for (int i = 1; i + p - 1 < n; ++i) { 59 | plan.push_back(sorted_a[picked[i] ? i + p - 1 : i].second); 60 | } 61 | return plan; 62 | } 63 | -------------------------------------------------------------------------------- /empty_class.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct EmptyClass {}; 4 | -------------------------------------------------------------------------------- /entombed.h: -------------------------------------------------------------------------------- 1 | // [Explaining the Entombed Algorithm](https://arxiv.org/pdf/2104.09982.pdf) 2 | -------------------------------------------------------------------------------- /eulerian_tour.h: -------------------------------------------------------------------------------- 1 | #include "types/graph/adjacent_list_base.h" 2 | 3 | #include 4 | #include 5 | 6 | class Eulerian : public AdjacentListBase { 7 | void dfs(int u) { 8 | while (~head[u]) { 9 | int i = head[u]; 10 | head[u] = next[head[u]]; 11 | if (!used[i >> 1]) { 12 | used[i >> 1] = true; 13 | dfs(edges[i]); 14 | } 15 | } 16 | tour.push_back(u); 17 | } 18 | 19 | int n; 20 | std::vector used; 21 | 22 | public: 23 | explicit Eulerian(int n, int s, const std::vector> &edges) 24 | : AdjacentListBase{n, static_cast(edges.size()) << 1}, n{n}, 25 | used(edges.size() << 1) { 26 | for (auto [a, b] : edges) { 27 | add(a, b); 28 | add(b, a); 29 | } 30 | dfs(s); 31 | } 32 | 33 | std::vector tour; 34 | }; 35 | -------------------------------------------------------------------------------- /fast_io.h: -------------------------------------------------------------------------------- 1 | #include "io_base.h" 2 | 3 | #include 4 | #include 5 | 6 | struct FastIO : public IOBaseT { 7 | friend class IOBaseT; 8 | 9 | explicit FastIO(std::FILE *inf_ = stdin, std::FILE *ouf_ = stdout) 10 | : inf{inf_}, ouf{ouf_} {} 11 | 12 | ~FastIO() { 13 | if (orear) { 14 | fwrite(obuf, 1, orear, ouf); 15 | } 16 | } 17 | 18 | private: 19 | static const size_t BUF_SIZE = 1 << 16; 20 | 21 | char getc() { 22 | if (ihead == irear) { 23 | ihead = 0; 24 | irear = fread(ibuf, 1, BUF_SIZE, inf); 25 | } 26 | return ihead < irear ? ibuf[ihead++] : '\0'; 27 | } 28 | 29 | void putc(char c) { 30 | if (orear == BUF_SIZE) { 31 | fwrite(obuf, 1, BUF_SIZE, ouf); 32 | orear = 0; 33 | } 34 | obuf[orear++] = c; 35 | } 36 | 37 | template void read1(T &&v) { 38 | using DecayedT = std::decay_t; 39 | if constexpr (std::is_same_v) { 40 | v = getc(); 41 | } else if constexpr (std::is_integral_v) { 42 | char c = getc(); 43 | while (!std::isdigit(c) && c != '-') { 44 | c = getc(); 45 | } 46 | bool is_neg = false; 47 | if (c == '-') { 48 | is_neg = true; 49 | c = getc(); 50 | } 51 | std::decay_t r = 0; 52 | for (; std::isdigit(c); c = getc()) { 53 | r = r * 10 + (c - '0'); 54 | } 55 | v = is_neg ? -r : r; 56 | } else { 57 | static_assert(!sizeof(T *)); 58 | } 59 | } 60 | 61 | template void write1(T &&v) { 62 | using DecayedT = std::decay_t; 63 | if constexpr (std::is_same_v) { 64 | putc(v); 65 | } else if constexpr (std::is_integral_v) { 66 | sprintf(text, "%lld", static_cast(v)); 67 | for (int i = 0; text[i]; i++) { 68 | putc(text[i]); 69 | } 70 | } else if constexpr (std::is_same_v || 71 | std::is_same_v) { 72 | for (int i = 0; v[i]; i++) { 73 | putc(v[i]); 74 | } 75 | } else { 76 | static_assert(!sizeof(T *)); 77 | } 78 | } 79 | 80 | std::FILE *inf, *ouf; 81 | 82 | char ibuf[BUF_SIZE], obuf[BUF_SIZE], text[32]; 83 | size_t ihead = 0, irear = 0, orear = 0; 84 | }; 85 | -------------------------------------------------------------------------------- /fixed_power_table.h: -------------------------------------------------------------------------------- 1 | #include "binpow.h" 2 | #include "sieve.h" 3 | 4 | #include 5 | 6 | template struct FixedPowerTable : public std::vector { 7 | explicit FixedPowerTable(int n, int k) : std::vector(n) { 8 | (*this)[0] = Mod{0}; 9 | if (1 < n) { 10 | (*this)[1] = Mod{1}; 11 | } 12 | PrimeGen primes(n); 13 | for (int i = 2; i < n; ++i) { 14 | auto p = primes.min_div(i); 15 | (*this)[i] = p == i ? binpow(Mod{i}, k) : (*this)[i / p] * (*this)[p]; 16 | } 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /fixed_size_matrix.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | template 10 | struct FixedSizeMatrixT : std::array, N> { 11 | using Row = std::array; 12 | 13 | using std::array::array; 14 | 15 | explicit FixedSizeMatrixT(std::initializer_list rows) 16 | : std::array{ 17 | reinterpret_cast &>(*rows.begin())} {} 18 | 19 | static FixedSizeMatrixT mul_id() { 20 | FixedSizeMatrixT e; 21 | for (int i = 0; i < N; ++i) { 22 | e[i][i] = T::mul_id(); 23 | } 24 | return e; 25 | } 26 | 27 | FixedSizeMatrixT &operator+=(const FixedSizeMatrixT &o) { 28 | for (int i = 0; i < N; ++i) { 29 | for (int j = 0; j < N; ++j) { 30 | (*this)[i][j] += o[i][j]; 31 | } 32 | } 33 | return *this; 34 | } 35 | 36 | FixedSizeMatrixT operator+(const FixedSizeMatrixT &o) const { 37 | return FixedSizeMatrixT(*this) += o; 38 | } 39 | 40 | FixedSizeMatrixT &operator-=(const FixedSizeMatrixT &o) { 41 | for (int i = 0; i < N; ++i) { 42 | for (int j = 0; j < N; ++j) { 43 | (*this)[i][j] -= o[i][j]; 44 | } 45 | } 46 | return *this; 47 | } 48 | 49 | FixedSizeMatrixT operator-(const FixedSizeMatrixT &o) const { 50 | return FixedSizeMatrixT(*this) -= o; 51 | } 52 | 53 | FixedSizeMatrixT operator*(const FixedSizeMatrixT &o) const { 54 | static T buffer[N]; 55 | FixedSizeMatrixT result; 56 | for (int j = 0; j < N; ++j) { 57 | for (int i = 0; i < N; ++i) { 58 | buffer[i] = o[i][j]; 59 | } 60 | for (int i = 0; i < N; ++i) { 61 | for (int k = 0; k < N; ++k) { 62 | result[i][j] += (*this)[i][k] * buffer[k]; 63 | } 64 | } 65 | } 66 | return result; 67 | } 68 | 69 | FixedSizeMatrixT &operator*=(const FixedSizeMatrixT &o) { 70 | return *this = *this * o; 71 | } 72 | }; 73 | 74 | template 75 | auto operator*(const typename FixedSizeMatrixT::Row &r, 76 | const FixedSizeMatrixT &o) { 77 | typename FixedSizeMatrixT::Row result; 78 | for (int k = 0; k < N; k++) { 79 | for (int j = 0; j < N; j++) { 80 | result[j] += r[k] * o[k][j]; 81 | } 82 | } 83 | return result; 84 | } 85 | -------------------------------------------------------------------------------- /fixed_size_upper_matrix.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | template 8 | struct FixedSizeUpperMatrixT : std::array, N> { 9 | using Row = std::array; 10 | 11 | using std::array::array; 12 | 13 | explicit FixedSizeUpperMatrixT(std::initializer_list rows) 14 | : std::array{ 15 | reinterpret_cast &>(*rows.begin())} {} 16 | 17 | static FixedSizeUpperMatrixT mul_id() { 18 | FixedSizeUpperMatrixT e; 19 | for (int i = 0; i < N; ++i) { 20 | e[i][i] = T::mul_id(); 21 | } 22 | return e; 23 | } 24 | 25 | FixedSizeUpperMatrixT &operator+=(const FixedSizeUpperMatrixT &o) { 26 | for (int i = 0; i < N; ++i) { 27 | for (int j = i; j < N; ++j) { 28 | (*this)[i][j] += o[i][j]; 29 | } 30 | } 31 | return *this; 32 | } 33 | 34 | FixedSizeUpperMatrixT operator+(const FixedSizeUpperMatrixT &o) const { 35 | return FixedSizeUpperMatrixT(*this) += o; 36 | } 37 | 38 | FixedSizeUpperMatrixT &operator-=(const FixedSizeUpperMatrixT &o) { 39 | for (int i = 0; i < N; ++i) { 40 | for (int j = i; j < N; ++j) { 41 | (*this)[i][j] -= o[i][j]; 42 | } 43 | } 44 | return *this; 45 | } 46 | 47 | FixedSizeUpperMatrixT operator-(const FixedSizeUpperMatrixT &o) const { 48 | return FixedSizeUpperMatrixT(*this) -= o; 49 | } 50 | 51 | FixedSizeUpperMatrixT operator*(const FixedSizeUpperMatrixT &o) const { 52 | static T buffer[N]; 53 | FixedSizeUpperMatrixT result; 54 | for (int j = 0; j < N; ++j) { 55 | for (int i = 0; i < N; ++i) { 56 | buffer[i] = o[i][j]; 57 | } 58 | for (int i = 0; i <= j; ++i) { 59 | for (int k = i; k <= j; ++k) { 60 | result[i][j] += (*this)[i][k] * buffer[k]; 61 | } 62 | } 63 | } 64 | return result; 65 | } 66 | 67 | FixedSizeUpperMatrixT &operator*=(const FixedSizeUpperMatrixT &o) { 68 | return *this = *this * o; 69 | } 70 | }; 71 | 72 | template 73 | auto operator*(const typename FixedSizeUpperMatrixT::Row &r, 74 | const FixedSizeUpperMatrixT &o) { 75 | typename FixedSizeUpperMatrixT::Row result; 76 | for (int k = 0; k < N; k++) { 77 | for (int j = k; j < N; j++) { 78 | result[j] += r[k] * o[k][j]; 79 | } 80 | } 81 | return result; 82 | } 83 | -------------------------------------------------------------------------------- /free_queue.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | struct FreeQueue { 7 | explicit FreeQueue(int size_) : size(size_), head(0), rear(0), queue(size) { 8 | std::iota(queue.begin(), queue.end(), 0); 9 | } 10 | 11 | int allocate() { 12 | int index = queue[head++]; 13 | if (head == size) { 14 | head = 0; 15 | } 16 | return index; 17 | } 18 | 19 | void free(int index) { 20 | queue[rear++] = index; 21 | if (rear == size) { 22 | rear = 0; 23 | } 24 | } 25 | 26 | private: 27 | int size, head, rear; 28 | std::vector queue; 29 | }; 30 | -------------------------------------------------------------------------------- /gaussian_elimination.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template struct Gaussian { 4 | static Mod det(std::vector> a) { 5 | const int n = a.size(); 6 | Mod result(1); 7 | for (int j = 0; j < n; ++j) { 8 | int pivot = j; 9 | while (pivot < n && a[pivot][j].get() == 0) { 10 | pivot++; 11 | } 12 | if (pivot == n) { 13 | return Mod(0); 14 | } 15 | if (j < pivot) { 16 | result *= Mod(Mod::mod() - 1); 17 | std::swap(a[j], a[pivot]); 18 | } 19 | Mod normalizer = a[j][j].inv(); 20 | for (int i = j + 1; i < n; ++i) { 21 | if (a[i][j].get()) { 22 | Mod scale = a[i][j] * normalizer; 23 | for (int k = j; k < n; ++k) { 24 | a[i][k] -= scale * a[j][k]; 25 | } 26 | } 27 | } 28 | result *= a[j][j]; 29 | } 30 | return result; 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /gaussian_field.h: -------------------------------------------------------------------------------- 1 | #include "singleton.h" 2 | 3 | #include 4 | #include 5 | 6 | // Fp[z] / (z^2 - alpha) 7 | template struct GaussianFieldT { 8 | constexpr GaussianFieldT(Mod x_ = {}, Mod y_ = {}) : x{x_}, y{y_} {} 9 | 10 | static Mod &a() { return singleton().alpha; } 11 | 12 | static void set_alpha(Mod a_) { a() = a_; } 13 | 14 | static constexpr GaussianFieldT mul_id() { return {Mod::mul_id(), Mod{}}; } 15 | 16 | constexpr GaussianFieldT &operator+=(const GaussianFieldT &other) { 17 | x += other.x; 18 | y += other.y; 19 | return *this; 20 | } 21 | 22 | constexpr GaussianFieldT &operator-=(const GaussianFieldT &other) { 23 | x -= other.x; 24 | y -= other.y; 25 | return *this; 26 | } 27 | 28 | constexpr GaussianFieldT operator*=(const GaussianFieldT &other) { 29 | std::tie(x, y) = std::pair{x * other.x + a() * y * other.y, 30 | x * other.y + y * other.x}; 31 | return *this; 32 | } 33 | 34 | constexpr GaussianFieldT operator+(const GaussianFieldT &other) const { 35 | GaussianFieldT copy = *this; 36 | return copy += other; 37 | } 38 | 39 | constexpr GaussianFieldT operator-() const { 40 | GaussianFieldT copy{}; 41 | copy -= *this; 42 | return copy; 43 | } 44 | 45 | constexpr GaussianFieldT operator-(const GaussianFieldT &other) const { 46 | GaussianFieldT copy = *this; 47 | return copy -= other; 48 | } 49 | 50 | constexpr GaussianFieldT operator*(const GaussianFieldT &other) const { 51 | GaussianFieldT copy = *this; 52 | return copy *= other; 53 | } 54 | 55 | constexpr GaussianFieldT inv() const { 56 | auto d = (x * x - a() * y * y).inv(); 57 | return GaussianFieldT{d * x, -d * y}; 58 | } 59 | 60 | Mod x, y; 61 | 62 | private: 63 | struct Store { 64 | Mod alpha; 65 | }; 66 | }; 67 | 68 | namespace std { 69 | 70 | template 71 | std::ostream &operator<<(std::ostream &out, GaussianFieldT e) { 72 | return out << e.x << " + " << e.y << " sqrt{" << GaussianFieldT::a() 73 | << "}"; 74 | } 75 | 76 | } // namespace std 77 | -------------------------------------------------------------------------------- /gen.h: -------------------------------------------------------------------------------- 1 | #include "testlib.h" 2 | 3 | #include 4 | 5 | std::vector rand_tree(int n, int r) { 6 | std::vector parent(n, -1); 7 | int y = r; 8 | for (int _ = 1; _ < n; ++_) { 9 | int x = rnd.next(0, n - 1); 10 | while (x == r || ~parent[x]) { 11 | y = x; 12 | x = rnd.next(0, n - 1); 13 | } 14 | parent[x] = y; 15 | y = x; 16 | } 17 | return parent; 18 | } 19 | 20 | static std::string rand_parenthesis(int n) { 21 | std::vector bits((n << 1) + 1); 22 | for (int i = 0; i <= n; ++i) { 23 | bits[i] = 1; 24 | } 25 | shuffle(bits.begin(), bits.end()); 26 | int sum = 0; 27 | std::pair best{0, 0}; 28 | for (int i = 0; i <= n << 1; ++i) { 29 | sum += bits[i] ? -1 : 1; 30 | best = std::min(best, std::make_pair(sum, i + 1)); 31 | } 32 | std::string result; 33 | for (int i = 0; i < n << 1; ++i) { 34 | result += bits[(best.second + i) % ((n << 1) + 1)] ? ')' : '('; 35 | } 36 | return result; 37 | } 38 | -------------------------------------------------------------------------------- /heavy_light_decomp.h: -------------------------------------------------------------------------------- 1 | #include "heavy_light_decomp_base.h" 2 | 3 | template 4 | struct HeavyLightDecompositionSubtree : public HeavyLightDecompositionBase { 5 | HeavyLightDecompositionSubtree(const Tree &tree, int root) 6 | : HeavyLightDecompositionBase(tree, root), path(n, nullptr) { 7 | if (BIASED) { 8 | for (int u = 0; u < n; ++u) { 9 | if (bottom[u] == u) { 10 | const int count = depth[u] - get_lowest_depth(u); 11 | std::vector vertices, weight; 12 | vertices.reserve(count); 13 | weight.reserve(count); 14 | for (int i = 0, v = u; i < count; ++i, v = parent[v]) { 15 | vertices.push_back(v); 16 | weight.push_back(size[v]); 17 | } 18 | for (int i = count; i-- > 1;) { 19 | weight[i] -= weight[i - 1]; 20 | } 21 | path[u] = new NestedT(vertices, weight); 22 | } 23 | } 24 | } else { 25 | for (int u = 0; u < n; ++u) { 26 | if (bottom[u] == u) { 27 | const int count = depth[u] - get_lowest_depth(u); 28 | std::vector vertices, weight; 29 | vertices.reserve(count); 30 | for (int i = 0, v = u; i < count; ++i, v = parent[v]) { 31 | vertices.push_back(v); 32 | } 33 | path[u] = new NestedT(vertices); 34 | } 35 | } 36 | } 37 | } 38 | 39 | ~HeavyLightDecompositionSubtree() { 40 | for (auto &&p : path) { 41 | if (p != nullptr) { 42 | delete p; 43 | } 44 | } 45 | } 46 | 47 | template 48 | Handler traverse(Handler &&h, bool include_lca, int a, int b) { 49 | while (bottom[a] != bottom[b]) { 50 | if (get_lowest_depth(a) > get_lowest_depth(b)) { 51 | const int base = depth[bottom[a]]; 52 | h.template update<0>(path[bottom[a]], base - depth[a], 53 | base - get_lowest_depth(a) - 1); 54 | a = top[a]; 55 | } else { 56 | const int base = depth[bottom[b]]; 57 | h.template update<1>(path[bottom[b]], base - depth[b], 58 | base - get_lowest_depth(b) - 1); 59 | b = top[b]; 60 | } 61 | } 62 | if (include_lca || a != b) { 63 | if (depth[a] > depth[b]) { 64 | const int base = depth[bottom[a]]; 65 | h.template update<0>(path[bottom[a]], base - depth[a], 66 | base - depth[b] - (!include_lca)); 67 | } else { 68 | const int base = depth[bottom[b]]; 69 | h.template update<1>(path[bottom[b]], base - depth[b], 70 | base - depth[a] - (!include_lca)); 71 | } 72 | } 73 | return h; 74 | } 75 | 76 | private: 77 | std::vector path; 78 | }; 79 | -------------------------------------------------------------------------------- /heavy_light_decomp_base.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct HeavyLightDecompositionBase { 5 | using Tree = std::vector>; 6 | 7 | explicit HeavyLightDecompositionBase(const Tree &tree, int root) 8 | : n(tree.size()), parent(n), size(n), depth(n), top(n), bottom(n) { 9 | parent[root] = -1; 10 | build(tree, root); 11 | for (int u = 0; u < n; ++u) { 12 | top[u] = top[bottom[u]]; 13 | } 14 | } 15 | 16 | int lca(int a, int b) const { 17 | while (bottom[a] != bottom[b]) { 18 | if (get_lowest_depth(a) > get_lowest_depth(b)) { 19 | a = top[a]; 20 | } else { 21 | b = top[b]; 22 | } 23 | } 24 | return depth[a] < depth[b] ? a : b; 25 | } 26 | 27 | int n; 28 | std::vector parent, size, depth; 29 | 30 | protected: 31 | void build(const Tree &tree, int u) { 32 | const int p = parent[u]; 33 | depth[u] = ~p ? depth[p] + 1 : 0; 34 | size[u] = 1; 35 | std::pair candidate{0, u}; 36 | for (int v : tree[u]) { 37 | if (v != p) { 38 | parent[v] = u; 39 | build(tree, v); 40 | size[u] += size[v]; 41 | candidate = std::max(candidate, std::make_pair(size[v], bottom[v])); 42 | } 43 | } 44 | bottom[u] = candidate.second; 45 | top[bottom[u]] = p; 46 | } 47 | 48 | int get_lowest_depth(int u) const { return ~top[u] ? depth[top[u]] : -1; } 49 | 50 | std::vector top, bottom; 51 | }; 52 | -------------------------------------------------------------------------------- /heavy_light_decomp_subtree.h: -------------------------------------------------------------------------------- 1 | #include "heavy_light_decomp_base.h" 2 | 3 | template 4 | struct HeavyLightDecompositionSubtree : public HeavyLightDecompositionBase { 5 | HeavyLightDecompositionSubtree(const Tree &tree, int root) 6 | : HeavyLightDecompositionBase(tree, root), position(n) { 7 | vertices.reserve(n); 8 | dfs(tree, root); 9 | sgt = new NestedT(vertices); 10 | } 11 | 12 | ~HeavyLightDecompositionSubtree() { delete sgt; } 13 | 14 | template Handler traverse_all(Handler &&h) { 15 | return sgt->template traverse_all(std::forward(h)); 16 | } 17 | 18 | template Handler traverse_subtree(Handler &&h, int u) { 19 | return sgt->template traverse( 20 | std::forward(h), position[u], position[u] + size[u] - 1); 21 | } 22 | 23 | template 24 | Handler traverse_path(Handler &&h, bool include_lca, int a, int b) { 25 | while (bottom[a] != bottom[b]) { 26 | if (get_lowest_depth(a) > get_lowest_depth(b)) { 27 | h.template update<0>(sgt, 28 | position[a] - (depth[a] - get_lowest_depth(a)) + 1, 29 | position[a]); 30 | a = top[a]; 31 | } else { 32 | h.template update<1>(sgt, 33 | position[b] - (depth[b] - get_lowest_depth(b)) + 1, 34 | position[b]); 35 | b = top[b]; 36 | } 37 | } 38 | if (include_lca || a != b) { 39 | if (depth[a] > depth[b]) { 40 | h.template update<0>(sgt, position[b] + (!include_lca), position[a]); 41 | } else { 42 | h.template update<1>(sgt, position[a] + (!include_lca), position[b]); 43 | } 44 | } 45 | return h; 46 | } 47 | 48 | private: 49 | void dfs(const Tree &tree, int u) { 50 | position[u] = vertices.size(); 51 | vertices.push_back(u); 52 | for (int v : tree[u]) { 53 | if (v != parent[u] && bottom[v] == bottom[u]) { 54 | dfs(tree, v); 55 | break; 56 | } 57 | } 58 | for (int v : tree[u]) { 59 | if (v != parent[u] && bottom[v] != bottom[u]) { 60 | dfs(tree, v); 61 | } 62 | } 63 | } 64 | 65 | std::vector vertices, position; 66 | NestedT *sgt; 67 | }; 68 | -------------------------------------------------------------------------------- /hilbert.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static inline uint64_t hilbert_rank(int x, int y, int k = 31, int rotate = 0) { 4 | if (k--) { 5 | static const int INDEX[2][2] = {{0, 3}, {1, 2}}; 6 | static const int DELTA[4] = {3, 0, 0, 1}; 7 | int index = INDEX[x >> k][y >> k] + rotate & 3; 8 | uint64_t result = hilbert_rank(x & ~(1 << k), y & ~(1 << k), k, 9 | rotate + DELTA[index] & 3); 10 | return (static_cast(index) << (k + k)) + 11 | ((index == 1 || index == 2) 12 | ? result 13 | : ((static_cast(1) << (k + k)) - 1 - result)); 14 | } 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /inv.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // a^{-1} mod m 6 | static inline constexpr uint32_t euclidean_inv(uint32_t a, uint32_t m) { 7 | return a == 1 ? 1 8 | : (1 + static_cast(a - euclidean_inv(m % a, a)) * 9 | static_cast(m)) / 10 | a; 11 | } 12 | -------------------------------------------------------------------------------- /inv_table.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | template struct InvTable : std::vector { 6 | explicit InvTable(int n) : std::vector(n) { 7 | (*this)[1] = Mod{1}; 8 | for (int i = 2; i < n; ++i) { 9 | (*this)[i] = -Mod{Mod::mod() / i} * (*this)[Mod::mod() % i]; 10 | } 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /io.d: -------------------------------------------------------------------------------- 1 | import std.stdio : readln, writeln; 2 | 3 | struct IO { 4 | import std.conv : to; 5 | import std.range : empty, front, popFront, split; 6 | 7 | string readToken() { 8 | while (tokens.empty) { 9 | tokens = readln.split; 10 | } 11 | auto token = tokens.front; 12 | tokens.popFront; 13 | return token; 14 | } 15 | 16 | int readInt() { 17 | return readToken.to!int; 18 | } 19 | 20 | string[] tokens; 21 | } 22 | -------------------------------------------------------------------------------- /io.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "io_base.h" 4 | 5 | #include 6 | #include 7 | 8 | struct IO : public IOBaseT { 9 | friend class IOBaseT; 10 | 11 | explicit IO(bool sync = false) { 12 | if (!sync) { 13 | std::ios::sync_with_stdio(false); 14 | std::cin.tie(nullptr); 15 | } 16 | std::cout << std::fixed << std::setprecision(12); 17 | } 18 | 19 | private: 20 | template void read1(T &&v) { std::cin >> v; } 21 | template void write1(T &&v) { std::cout << v; } 22 | }; 23 | -------------------------------------------------------------------------------- /io.rs: -------------------------------------------------------------------------------- 1 | use std::io::{BufWriter, stdin, stdout, Write}; 2 | 3 | #[derive(Default)] 4 | struct Scanner { 5 | buffer: Vec 6 | } 7 | 8 | impl Scanner { 9 | fn next(&mut self) -> T { 10 | loop { 11 | if let Some(token) = self.buffer.pop() { 12 | return token.parse().ok().expect("Failed parse"); 13 | } 14 | let mut input = String::new(); 15 | stdin().read_line(&mut input).expect("Failed read"); 16 | self.buffer = input.split_whitespace().rev().map(String::from).collect(); 17 | } 18 | } 19 | } 20 | 21 | fn solve(n: usize, m: u64, w: Vec) -> Vec 22 | { 23 | let mut result = Vec::new(); 24 | let mut sum: u64 = 0; 25 | for i in 0..n { 26 | if w[i] <= m { 27 | if 2 * w[i] >= m { 28 | return vec![i]; 29 | } else { 30 | result.push(i); 31 | sum += w[i]; 32 | if 2 * sum >= m { 33 | return result; 34 | } 35 | } 36 | } 37 | } 38 | return vec![]; 39 | } 40 | 41 | fn main() { 42 | let mut scan = Scanner::default(); 43 | let out = &mut BufWriter::new(stdout()); 44 | } 45 | -------------------------------------------------------------------------------- /io_base.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #ifndef YES 8 | #define YES "Yes" 9 | #endif 10 | #ifndef NO 11 | #define NO "No" 12 | #endif 13 | 14 | template struct IOBaseT { 15 | template T read() { 16 | T v; 17 | static_cast(this)->read1(v); 18 | return v; 19 | } 20 | 21 | template std::vector read_v(size_t n) { 22 | std::vector vec(n); 23 | for (auto &&v : vec) { 24 | v = read(); 25 | } 26 | return vec; 27 | } 28 | 29 | template std::tuple read_t() { 30 | std::tuple t; 31 | read_t_(t, std::make_index_sequence()); 32 | return t; 33 | } 34 | 35 | IOBaseT &operator<<(bool o) { return *this << (o ? YES : NO); } 36 | 37 | template 38 | IOBaseT &operator<<(RangeT &&o) 39 | requires(!std::same_as, char>) 40 | { 41 | bool first = true; 42 | for (auto &&v : o) { 43 | if (first) { 44 | first = false; 45 | } else { 46 | *this << ' '; 47 | } 48 | *this << v; 49 | } 50 | return *this; 51 | } 52 | 53 | template IOBaseT &operator<<(T &&o) { 54 | return static_cast(this)->write1(std::forward(o)), *this; 55 | } 56 | 57 | private: 58 | template 59 | void read_t_(Tuple &t, std::index_sequence) { 60 | (..., (std::get(t) = read>())); 61 | } 62 | }; 63 | -------------------------------------------------------------------------------- /is_specialization_of.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | template