├── .github └── workflows │ └── verify.yml ├── .verify-helper └── timestamps.remote.json ├── README.md ├── data_structure ├── bbst │ └── splay_tree.hpp ├── other │ ├── cartesian_tree_min.hpp │ ├── li_chao_tree.hpp │ └── sliding_window_aggregation.hpp ├── sequence │ ├── binary_indexed_tree.hpp │ ├── commutative_dual_segment_tree.hpp │ ├── compact_bit_vector.hpp │ ├── cumulative_sum.hpp │ ├── disjoint_sparse_table.hpp │ ├── dual_binary_indexed_tree.hpp │ ├── dual_disjoint_sparse_table.hpp │ ├── dual_invertible_binary_indexed_tree.hpp │ ├── dual_segment_tree.hpp │ ├── dual_sparse_table.hpp │ ├── invertible_binary_indexed_tree.hpp │ ├── invertible_cumulative_sum.hpp │ ├── lazy_segment_tree.hpp │ ├── segment_tree.hpp │ ├── segment_tree_beats.hpp │ ├── sparse_table.hpp │ ├── wavelet_matrix.hpp │ └── xor_segment_tree.hpp ├── tree │ └── heavy_light_decomposition.hpp └── unionfind │ └── unionfind.hpp ├── docs ├── data_structure │ ├── other │ │ └── li_chao_tree.md │ └── unionfind │ │ └── unionfind.md ├── other │ └── poker_hands.md └── string │ ├── lcp_array.md │ ├── manacher.md │ ├── suffix_array.md │ └── z_algorithm.md ├── graph ├── biconnected_components.hpp ├── block_cut_tree.hpp ├── enumerate_triangles.hpp ├── extended_block_cut_tree.hpp ├── strongly_connected_components.hpp └── two_edge_connected_components.hpp ├── old_Data_Structures ├── Bidirectional_Segment_Tree.cpp ├── Euler_Tour_Path_Query.cpp ├── Euler_Tour_Path_Query_Commutative.cpp ├── Euler_Tour_Subtree_Query.cpp ├── Heavy_Light_Decomposition.cpp ├── Heavy_Light_Decomposition_Commutative.cpp ├── Inversion_Number.cpp ├── Segment_Tree_Beats.cpp ├── Treap.cpp └── Trie.cpp ├── old_Dynamic_Programming ├── Count_Subsequences.cpp ├── Longest_Common_Subsequence.cpp ├── Longest_Increasing_Subsequence.cpp └── Matrix_Chain_Multiplication.cpp ├── old_Geometry ├── Circle.cpp ├── Line.cpp └── Point.cpp ├── old_Graph ├── All_Pairs_Shortest_Path_(Warshall_Floyd).cpp ├── Bipartite_Matching.cpp ├── Convert_to_Rooted_Tree.cpp ├── Detect_Cycle.cpp ├── Lowest_Common_Ancestor.cpp ├── Max_Flow_(Dinic).cpp ├── Max_Flow_(Ford_Fulkerson).cpp ├── Min_Cost_Flow_(Primal_Dual).cpp ├── Minimium_Cost_Arborescence.cpp ├── Minimum_Spanning_Tree_(Kruskal).cpp ├── Range_Edges.cpp ├── Rerooting.cpp ├── Rerooting_1.cpp ├── Rerooting_2.cpp ├── Single_Source_Shortest_Path_(Bellman_Ford).cpp ├── Single_Source_Shortest_Path_(Dijkstra).cpp ├── Topological_Sort.cpp ├── Tree_Diameter.cpp └── Tree_Height.cpp ├── old_Math ├── Bitwise_And_Convolution.cpp ├── Catalan_Number.cpp ├── Convolution_(FFT).cpp ├── Convolution_(NTT).cpp ├── Cycle_Decomposition.cpp ├── Euler_phi.cpp ├── Matrix_Multiplication.cpp ├── Modulo.cpp ├── Multipoint_Evaluation.cpp ├── Polynomial_Division.cpp ├── Polynomial_Inverse.cpp ├── Prime.cpp ├── Quotient_Ranges.cpp └── XOR_Convolution.cpp ├── old_Range_Queries ├── Naive.cpp ├── Point_Add_Range_Sum.cpp ├── Point_Update_Range_Max.cpp ├── Point_Update_Range_Min.cpp ├── Range_Add_Point_Value.cpp ├── Range_Add_Range_Min.cpp ├── Range_Add_Range_Sum.cpp ├── Range_Chmin_Range_Min.cpp ├── Range_Min.cpp ├── Range_Sum.cpp ├── Range_Update_Add_Range_Sum.cpp ├── Range_Update_Point_Value.cpp ├── Range_Update_Range_Min.cpp └── Range_Update_Range_Sum.cpp ├── old_String ├── LCP_Array.cpp └── Rolling_Hash.cpp ├── other ├── monoids │ ├── affine_sum.hpp │ └── linear.hpp └── poker_hands.hpp ├── string ├── lcp_array.hpp ├── manacher.hpp ├── suffix_array.hpp └── z_algorithm.hpp └── test ├── aoj ├── dsl │ ├── dsl_1_a.test.cpp │ ├── dsl_2_a.test.cpp │ ├── dsl_2_b.test.cpp │ ├── dsl_2_b_2.test.cpp │ ├── dsl_2_b_3.test.cpp │ ├── dsl_2_d.test.cpp │ ├── dsl_2_e.test.cpp │ ├── dsl_2_e_2.test.cpp │ ├── dsl_2_e_3.test.cpp │ ├── dsl_2_f.test.cpp │ ├── dsl_2_g.test.cpp │ ├── dsl_2_h.test.cpp │ ├── dsl_2_i.test.cpp │ ├── dsl_5_a.test.cpp │ ├── dsl_5_a_2.test.cpp │ └── dsl_5_a_3.test.cpp ├── grl │ ├── grl_3_a.test.cpp │ ├── grl_3_a_2.test.cpp │ ├── grl_3_b.test.cpp │ └── grl_3_c.test.cpp ├── itp │ └── itp1_6_a.test.cpp └── other │ ├── 1508.test.cpp │ ├── 1508_2.test.cpp │ ├── 2535.test.cpp │ └── 2677.test.cpp ├── library_checker ├── data_structure │ ├── line_add_get_min.test.cpp │ ├── point_add_range_sum.test.cpp │ ├── point_add_range_sum_2.test.cpp │ ├── point_add_range_sum_3.test.cpp │ ├── point_set_range_composite.test.cpp │ ├── queue_operate_all_composite.test.cpp │ ├── range_affine_point_get.test.cpp │ ├── range_affine_range_sum.test.cpp │ ├── range_chmin_chmax_add_range_sum.test.cpp │ ├── range_kth_smallest.test.cpp │ ├── segment_add_get_min.test.cpp │ ├── static_range_frequency.test.cpp │ ├── static_range_sum.test.cpp │ ├── static_range_sum_2.test.cpp │ ├── static_range_sum_3.test.cpp │ ├── staticrmq.test.cpp │ ├── staticrmq_2.test.cpp │ ├── staticrmq_3.test.cpp │ └── unionfind.test.cpp ├── graph │ ├── biconnected_components.test.cpp │ ├── biconnected_components_2.test.cpp │ ├── enumerate_triangles.test.cpp │ ├── scc.test.cpp │ └── two_edge_connected_components.test.cpp ├── string │ ├── enumerate_palindromes.test.cpp │ ├── number_of_substrings.test.cpp │ ├── suffixarray.test.cpp │ └── zalgorithm.test.cpp └── tree │ ├── cartesian_tree.test.cpp │ └── lca.test.cpp └── yukicoder ├── yuki_1326.test.cpp ├── yuki_1326_2.test.cpp ├── yuki_1891.test.cpp └── yuki_945.test.cpp /.github/workflows/verify.yml: -------------------------------------------------------------------------------- 1 | name: verify 2 | 3 | on: push 4 | 5 | jobs: 6 | verify: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/checkout@v1 11 | 12 | - name: Set up Python 13 | uses: actions/setup-python@v1 14 | 15 | - name: Install dependencies 16 | run: pip3 install -U online-judge-verify-helper 17 | 18 | - name: Run tests 19 | env: 20 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 21 | YUKICODER_TOKEN: ${{ secrets.YUKICODER_TOKEN }} 22 | GH_PAT: ${{ secrets.GH_PAT }} 23 | run: oj-verify all 24 | -------------------------------------------------------------------------------- /.verify-helper/timestamps.remote.json: -------------------------------------------------------------------------------- 1 | { 2 | "test/aoj/dsl/dsl_1_a.test.cpp": "2022-08-24 00:37:04 +0900", 3 | "test/aoj/dsl/dsl_2_a.test.cpp": "2022-07-19 22:43:05 +0900", 4 | "test/aoj/dsl/dsl_2_b.test.cpp": "2022-07-19 22:43:05 +0900", 5 | "test/aoj/dsl/dsl_2_b_2.test.cpp": "2022-07-19 22:43:05 +0900", 6 | "test/aoj/dsl/dsl_2_b_3.test.cpp": "2022-07-19 22:43:05 +0900", 7 | "test/aoj/dsl/dsl_2_d.test.cpp": "2022-07-19 22:43:05 +0900", 8 | "test/aoj/dsl/dsl_2_e.test.cpp": "2022-07-19 22:43:05 +0900", 9 | "test/aoj/dsl/dsl_2_e_2.test.cpp": "2022-07-19 22:43:05 +0900", 10 | "test/aoj/dsl/dsl_2_e_3.test.cpp": "2022-07-19 22:43:05 +0900", 11 | "test/aoj/dsl/dsl_2_f.test.cpp": "2022-07-19 22:43:05 +0900", 12 | "test/aoj/dsl/dsl_2_g.test.cpp": "2022-07-19 22:43:05 +0900", 13 | "test/aoj/dsl/dsl_2_h.test.cpp": "2022-07-19 22:43:05 +0900", 14 | "test/aoj/dsl/dsl_2_i.test.cpp": "2022-07-19 22:43:05 +0900", 15 | "test/aoj/dsl/dsl_5_a.test.cpp": "2022-07-19 22:43:05 +0900", 16 | "test/aoj/dsl/dsl_5_a_2.test.cpp": "2022-07-19 22:43:05 +0900", 17 | "test/aoj/dsl/dsl_5_a_3.test.cpp": "2022-07-19 22:43:05 +0900", 18 | "test/aoj/grl/grl_3_a.test.cpp": "2022-07-20 01:33:22 +0900", 19 | "test/aoj/grl/grl_3_a_2.test.cpp": "2022-07-24 02:46:13 +0900", 20 | "test/aoj/grl/grl_3_b.test.cpp": "2022-07-20 01:24:27 +0900", 21 | "test/aoj/grl/grl_3_c.test.cpp": "2022-07-20 01:33:22 +0900", 22 | "test/aoj/itp/itp1_6_a.test.cpp": "2022-07-19 22:43:05 +0900", 23 | "test/aoj/other/1508.test.cpp": "2022-08-05 04:50:39 +0900", 24 | "test/aoj/other/1508_2.test.cpp": "2022-08-05 04:50:39 +0900", 25 | "test/aoj/other/2535.test.cpp": "2022-08-15 03:29:29 +0900", 26 | "test/aoj/other/2677.test.cpp": "2022-08-17 04:19:08 +0900", 27 | "test/library_checker/data_structure/line_add_get_min.test.cpp": "2022-09-17 03:51:35 +0900", 28 | "test/library_checker/data_structure/point_add_range_sum.test.cpp": "2022-07-19 22:43:05 +0900", 29 | "test/library_checker/data_structure/point_add_range_sum_2.test.cpp": "2022-07-19 22:43:05 +0900", 30 | "test/library_checker/data_structure/point_add_range_sum_3.test.cpp": "2022-07-19 22:43:05 +0900", 31 | "test/library_checker/data_structure/point_set_range_composite.test.cpp": "2022-07-19 22:43:05 +0900", 32 | "test/library_checker/data_structure/queue_operate_all_composite.test.cpp": "2022-07-19 22:43:05 +0900", 33 | "test/library_checker/data_structure/range_affine_point_get.test.cpp": "2022-07-19 22:43:05 +0900", 34 | "test/library_checker/data_structure/range_affine_range_sum.test.cpp": "2022-07-19 22:43:05 +0900", 35 | "test/library_checker/data_structure/range_chmin_chmax_add_range_sum.test.cpp": "2022-07-19 22:43:05 +0900", 36 | "test/library_checker/data_structure/range_kth_smallest.test.cpp": "2022-07-19 22:43:05 +0900", 37 | "test/library_checker/data_structure/segment_add_get_min.test.cpp": "2022-09-17 03:51:35 +0900", 38 | "test/library_checker/data_structure/static_range_frequency.test.cpp": "2022-07-19 22:43:05 +0900", 39 | "test/library_checker/data_structure/static_range_sum.test.cpp": "2022-07-19 22:43:05 +0900", 40 | "test/library_checker/data_structure/static_range_sum_2.test.cpp": "2022-07-19 22:43:05 +0900", 41 | "test/library_checker/data_structure/static_range_sum_3.test.cpp": "2022-07-19 22:43:05 +0900", 42 | "test/library_checker/data_structure/staticrmq.test.cpp": "2022-08-24 04:05:14 +0900", 43 | "test/library_checker/data_structure/staticrmq_2.test.cpp": "2022-08-24 04:05:14 +0900", 44 | "test/library_checker/data_structure/staticrmq_3.test.cpp": "2022-08-24 04:05:14 +0900", 45 | "test/library_checker/data_structure/unionfind.test.cpp": "2022-08-24 00:37:04 +0900", 46 | "test/library_checker/graph/biconnected_components.test.cpp": "2022-07-20 01:33:22 +0900", 47 | "test/library_checker/graph/biconnected_components_2.test.cpp": "2022-07-24 02:46:13 +0900", 48 | "test/library_checker/graph/enumerate_triangles.test.cpp": "2022-07-20 01:50:04 +0900", 49 | "test/library_checker/graph/scc.test.cpp": "2022-08-24 04:05:14 +0900", 50 | "test/library_checker/graph/two_edge_connected_components.test.cpp": "2022-07-20 01:24:27 +0900", 51 | "test/library_checker/string/enumerate_palindromes.test.cpp": "2022-09-02 02:22:16 +0900", 52 | "test/library_checker/string/number_of_substrings.test.cpp": "2022-09-02 02:22:16 +0900", 53 | "test/library_checker/string/zalgorithm.test.cpp": "2022-09-02 02:22:16 +0900", 54 | "test/library_checker/tree/cartesian_tree.test.cpp": "2022-07-19 22:43:05 +0900", 55 | "test/library_checker/tree/lca.test.cpp": "2022-08-24 04:05:14 +0900", 56 | "test/yukicoder/yuki_1326.test.cpp": "2022-07-20 02:04:32 +0900", 57 | "test/yukicoder/yuki_1326_2.test.cpp": "2022-07-24 02:46:13 +0900", 58 | "test/yukicoder/yuki_1891.test.cpp": "2022-07-17 07:03:54 +0900", 59 | "test/yukicoder/yuki_945.test.cpp": "2022-07-17 07:03:54 +0900" 60 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Actions Status](https://github.com/SSRS-cp/Competitive_Programming/workflows/verify/badge.svg)](https://github.com/SSRS-cp/Competitive_Programming/actions) [![GitHub Pages](https://img.shields.io/static/v1?label=GitHub+Pages&message=+&color=brightgreen&logo=github)](https://SSRS-cp.github.io/cp_library/) 2 | 3 | [![SSRS](https://img.shields.io/endpoint?url=https%3A%2F%2Fatcoder-badges.now.sh%2Fapi%2Fatcoder%2Fjson%2FSSRS)](https://atcoder.jp/users/SSRS) 4 | [![SSRS_](https://img.shields.io/endpoint?url=https%3A%2F%2Fatcoder-badges.now.sh%2Fapi%2Fcodeforces%2Fjson%2FSSRS_)](https://codeforces.com/profile/SSRS_) 5 | 6 | 競プロライブラリです。 7 | 8 | verification-helper の導入のため、大規模改装中です 9 | -------------------------------------------------------------------------------- /data_structure/bbst/splay_tree.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief スプレー木 (一点更新・区間取得) 4 | */ 5 | template 6 | struct splay_tree{ 7 | struct node{ 8 | node* p; 9 | array ch; 10 | int sz; 11 | T val, sum; 12 | node(): p(nullptr), ch({nullptr, nullptr}){ 13 | } 14 | node(T x): p(nullptr), ch({nullptr, nullptr}), sz(1), val(x), sum(x){ 15 | } 16 | }; 17 | function f; 18 | T E; 19 | node* root = nullptr; 20 | splay_tree(){ 21 | } 22 | splay_tree(vector A, function f, T E): f(f), E(E){ 23 | root = build(A, 0, A.size()); 24 | } 25 | node* build(vector &A, int L, int R){ 26 | if (L == R){ 27 | return nullptr; 28 | } 29 | int m = (L + R) / 2; 30 | node* v = new node(A[m]); 31 | node* l = build(A, L, m); 32 | v->ch[0] = l; 33 | if (l != nullptr){ 34 | l->p = v; 35 | } 36 | node* r = build(A, m + 1, R); 37 | v->ch[1] = r; 38 | if (r != nullptr){ 39 | r->p = v; 40 | } 41 | update(v); 42 | return v; 43 | } 44 | bool empty(){ 45 | return root == nullptr; 46 | } 47 | int size(){ 48 | return size(root); 49 | } 50 | int size(node* v){ 51 | if (v == nullptr){ 52 | return 0; 53 | } 54 | return v->sz; 55 | } 56 | T sum(node* v){ 57 | if (v == nullptr){ 58 | return E; 59 | } 60 | return v->sum; 61 | } 62 | void update(node* v){ 63 | v->sz = size(v->ch[0]) + 1 + size(v->ch[1]); 64 | v->sum = f(f(sum(v->ch[0]), v->val), sum(v->ch[1])); 65 | } 66 | int child_id(node *v){ 67 | if (v->p == nullptr){ 68 | return -1; 69 | } else if (v->p->ch[0] == v){ 70 | return 0; 71 | } else { 72 | return 1; 73 | } 74 | } 75 | void update_child(node* v, node *w){ 76 | w->p = v->p; 77 | if (v->p == nullptr){ 78 | return; 79 | } 80 | if (v->p->ch[0] == v){ 81 | v->p->ch[0] = w; 82 | } else { 83 | v->p->ch[1] = w; 84 | } 85 | } 86 | void rotate(node* v, int c){ 87 | node* w = v->ch[c ^ 1]; 88 | update_child(v, w); 89 | v->ch[c ^ 1] = w->ch[c]; 90 | if (w->ch[c] != nullptr){ 91 | w->ch[c]->p = v; 92 | } 93 | v->p = w; 94 | w->ch[c] = v; 95 | update(v); 96 | update(w); 97 | } 98 | void splay(node* v){ 99 | while (v->p != nullptr){ 100 | node* p = v->p; 101 | node* g = p->p; 102 | int x = child_id(v); 103 | int y = child_id(p); 104 | if (y == -1){ 105 | rotate(p, x ^ 1); 106 | } else if (x == y){ 107 | rotate(g, x ^ 1); 108 | rotate(p, x ^ 1); 109 | } else { 110 | rotate(p, y); 111 | rotate(g, x); 112 | } 113 | } 114 | root = v; 115 | } 116 | node* get(node *v, int k){ 117 | while (true){ 118 | int s = size(v->ch[0]); 119 | if (k < s){ 120 | v = v->ch[0]; 121 | } else if (k == s){ 122 | splay(v); 123 | return v; 124 | } else { 125 | k -= s + 1; 126 | v = v->ch[1]; 127 | } 128 | } 129 | } 130 | node* get(int k){ 131 | return get(root, k); 132 | } 133 | T operator [](int k){ 134 | return get(root, k)->val; 135 | } 136 | node* insert(node* r, int k, node* v){ 137 | if (k == size(r)){ 138 | v->ch[0] = r; 139 | if (r != nullptr){ 140 | r->p = v; 141 | } 142 | r = v; 143 | update(v); 144 | } else { 145 | node* u = get(r, k); 146 | v->ch[0] = u->ch[0]; 147 | v->ch[1] = u; 148 | if (u->ch[0] != nullptr){ 149 | u->ch[0]->p = v; 150 | } 151 | u->ch[0] = nullptr; 152 | u->p = v; 153 | update(u); 154 | update(v); 155 | } 156 | root = v; 157 | return v; 158 | } 159 | node* insert(node *r, int k){ 160 | node* v = new node; 161 | return insert(r, k, v); 162 | } 163 | node* insert(node *r, int k, T x){ 164 | node* v = new node(x); 165 | return insert(r, k, v); 166 | } 167 | node* insert(int k, T x){ 168 | return insert(root, k, x); 169 | } 170 | void erase(node* v){ 171 | node* l = v->ch[0]; 172 | node* r = v->ch[1]; 173 | delete v; 174 | if (l == nullptr && r == nullptr){ 175 | root = nullptr; 176 | } else if (l == nullptr){ 177 | root = r; 178 | r->p = nullptr; 179 | } else if (r == nullptr){ 180 | root = l; 181 | l->p = nullptr; 182 | } else { 183 | r->p = nullptr; 184 | root = r; 185 | r = get(0); 186 | r->ch[0] = l; 187 | l->p = r; 188 | update(r); 189 | } 190 | } 191 | void erase(node *v, int k){ 192 | erase(get(v, k)); 193 | } 194 | void erase(int k){ 195 | erase(get(k)); 196 | } 197 | pair split(node* v, int k){ 198 | node* x = insert(v, k); 199 | node* l = x->ch[0]; 200 | node* r = x->ch[1]; 201 | if (l != nullptr){ 202 | l->p = nullptr; 203 | } 204 | if (r != nullptr){ 205 | r->p = nullptr; 206 | } 207 | delete x; 208 | return make_pair(l, r); 209 | } 210 | pair split(int k){ 211 | return split(root, k); 212 | } 213 | node* merge(node* l, node* r){ 214 | node* v = new node; 215 | v->ch[0] = l; 216 | v->ch[1] = r; 217 | if (l != nullptr){ 218 | l->p = v; 219 | } 220 | if (r != nullptr){ 221 | r->p = v; 222 | } 223 | erase(v); 224 | return root; 225 | } 226 | void set(node* v, T x){ 227 | v->val = x; 228 | update(v); 229 | } 230 | void set(node* v, int k, int x){ 231 | node* w = get(v, k); 232 | set(w, x); 233 | } 234 | void set(int k, int x){ 235 | node* v = get(k); 236 | set(v, x); 237 | } 238 | T query(node* v, int l, int r){ 239 | int sz = size(v->ch[0]); 240 | T ans = E; 241 | if (l == 0 && r >= sz){ 242 | ans = sum(v->ch[0]); 243 | } else if (l < sz){ 244 | ans = query(v->ch[0], l, min(r, sz)); 245 | } 246 | if (l <= sz && r > sz){ 247 | ans = f(ans, v->val); 248 | } 249 | if (l <= sz + 1 && r == v->sz){ 250 | ans = f(ans, sum(v->ch[1])); 251 | } else if (r > sz + 1){ 252 | ans = f(ans, query(v->ch[1], max(l - sz - 1, 0), r - sz - 1)); 253 | } 254 | return ans; 255 | } 256 | T query(int l, int r){ 257 | return query(root, l, r); 258 | } 259 | }; -------------------------------------------------------------------------------- /data_structure/other/cartesian_tree_min.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief デカルト木 4 | */ 5 | vector cartesian_tree_min(vector &A){ 6 | int N = A.size(); 7 | vector pr(N, -1); 8 | stack st; 9 | st.push(0); 10 | for (int i = 1; i < N; i++){ 11 | int prev = -1; 12 | while (!st.empty()){ 13 | int j = st.top(); 14 | if (A[i] < A[j]){ 15 | st.pop(); 16 | if (prev != -1){ 17 | pr[prev] = j; 18 | } 19 | prev = j; 20 | } else { 21 | break; 22 | } 23 | } 24 | if (prev != -1){ 25 | pr[prev] = i; 26 | } 27 | st.push(i); 28 | } 29 | while (st.size() >= 2){ 30 | int x = st.top(); 31 | st.pop(); 32 | pr[x] = st.top(); 33 | } 34 | return pr; 35 | } -------------------------------------------------------------------------------- /data_structure/other/li_chao_tree.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | template 3 | struct li_chao_tree{ 4 | struct line{ 5 | T a, b; 6 | line(): a(0), b(INF){ 7 | } 8 | line(T a, T b): a(a), b(b){ 9 | } 10 | T get(T x){ 11 | return a * x + b; 12 | } 13 | }; 14 | int N; 15 | vector x; 16 | vector ST; 17 | li_chao_tree(){ 18 | } 19 | li_chao_tree(const vector &x2){ 20 | x = x2; 21 | sort(x.begin(), x.end()); 22 | int N2 = x.size(); 23 | N = 1; 24 | while (N < N2){ 25 | N *= 2; 26 | } 27 | x.resize(N); 28 | for (int i = N2; i < N; i++){ 29 | x[i] = x[N2 - 1]; 30 | } 31 | ST = vector(N * 2 - 1); 32 | } 33 | void line_add(line L, int i, int l, int r){ 34 | T la = L.get(x[l]); 35 | T lb = ST[i].get(x[l]); 36 | T ra = L.get(x[r - 1]); 37 | T rb = ST[i].get(x[r - 1]); 38 | if (la >= lb && ra >= rb){ 39 | return; 40 | } else if (la <= lb && ra <= rb){ 41 | ST[i] = L; 42 | } else { 43 | int m = (l + r) / 2; 44 | T ma = L.get(x[m]); 45 | T mb = ST[i].get(x[m]); 46 | if (ma < mb){ 47 | swap(L, ST[i]); 48 | swap(la, lb); 49 | swap(ra, rb); 50 | } 51 | if (la < lb){ 52 | line_add(L, i * 2 + 1, l, m); 53 | } 54 | if (ra < rb){ 55 | line_add(L, i * 2 + 2, m, r); 56 | } 57 | } 58 | } 59 | void line_add(T a, T b){ 60 | line_add(line(a, b), 0, 0, N); 61 | } 62 | void segment_add(int L, int R, line S, int i, int l, int r){ 63 | if (r <= L || R <= l){ 64 | return; 65 | } else if (L <= l && r <= R){ 66 | line_add(S, i, l, r); 67 | } else { 68 | int m = (l + r) / 2; 69 | segment_add(L, R, S, i * 2 + 1, l, m); 70 | segment_add(L, R, S, i * 2 + 2, m, r); 71 | } 72 | } 73 | void segment_add(T l, T r, T a, T b){ 74 | int pl = lower_bound(x.begin(), x.end(), l) - x.begin(); 75 | int pr = lower_bound(x.begin(), x.end(), r) - x.begin(); 76 | segment_add(pl, pr, line(a, b), 0, 0, N); 77 | } 78 | T get(T x2){ 79 | int p = lower_bound(x.begin(), x.end(), x2) - x.begin(); 80 | p += N - 1; 81 | T ans = INF; 82 | ans = min(ans, ST[p].get(x2)); 83 | while (p > 0){ 84 | p = (p - 1) / 2; 85 | ans = min(ans, ST[p].get(x2)); 86 | } 87 | return ans; 88 | } 89 | }; -------------------------------------------------------------------------------- /data_structure/other/sliding_window_aggregation.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief Sliding Window Aggregation 4 | */ 5 | template 6 | struct sliding_window_aggregation{ 7 | function f; 8 | T E; 9 | stack> fr, bk; 10 | sliding_window_aggregation(function f, T E): f(f), E(E){ 11 | } 12 | void push(T x){ 13 | if (fr.empty()){ 14 | fr.push(make_pair(x, x)); 15 | } else { 16 | fr.push(make_pair(x, f(fr.top().second, x))); 17 | } 18 | } 19 | void pop(){ 20 | if (bk.empty()){ 21 | while (!fr.empty()){ 22 | T x = fr.top().first; 23 | fr.pop(); 24 | if (bk.empty()){ 25 | bk.push(make_pair(x, x)); 26 | } else { 27 | bk.push(make_pair(x, f(x, bk.top().second))); 28 | } 29 | } 30 | } 31 | bk.pop(); 32 | } 33 | T get(){ 34 | T ans1 = E; 35 | if (!fr.empty()){ 36 | ans1 = fr.top().second; 37 | } 38 | T ans2 = E; 39 | if (!bk.empty()){ 40 | ans2 = bk.top().second; 41 | } 42 | return f(ans2, ans1); 43 | } 44 | }; -------------------------------------------------------------------------------- /data_structure/sequence/binary_indexed_tree.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief Binary Indexed Tree 4 | */ 5 | template 6 | struct binary_indexed_tree{ 7 | int N; 8 | vector BIT; 9 | function f; 10 | T E; 11 | binary_indexed_tree(){ 12 | } 13 | binary_indexed_tree(int N, function f, T E): N(N), BIT(N + 1, E), f(f), E(E){ 14 | } 15 | binary_indexed_tree(vector &A, function f, T E): N(A.size()), BIT(N + 1), f(f), E(E){ 16 | for (int i = 0; i < N; i++){ 17 | BIT[i + 1] = A[i]; 18 | } 19 | for (int i = 1; i < N; i++){ 20 | if (i + (i & -i) <= N){ 21 | BIT[i + (i & -i)] = f(BIT[i + (i & -i)], BIT[i]); 22 | } 23 | } 24 | } 25 | void add(int i, T x){ 26 | i++; 27 | while (i <= N){ 28 | BIT[i] = f(BIT[i], x); 29 | i += i & -i; 30 | } 31 | } 32 | T sum(int i){ 33 | T ans = E; 34 | while (i > 0){ 35 | ans = f(ans, BIT[i]); 36 | i -= i & -i; 37 | } 38 | return ans; 39 | } 40 | }; -------------------------------------------------------------------------------- /data_structure/sequence/commutative_dual_segment_tree.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief 可換双対セグメント木 (らて木) 4 | */ 5 | template 6 | struct commutative_dual_segment_tree{ 7 | int N; 8 | vector ST; 9 | function f; 10 | T E; 11 | commutative_dual_segment_tree(int n, function f, T E): f(f), E(E){ 12 | N = 1; 13 | while (N < n){ 14 | N *= 2; 15 | } 16 | ST = vector(N * 2 - 1, E); 17 | } 18 | commutative_dual_segment_tree(vector A, function f, T E): f(f), E(E){ 19 | int n = A.size(); 20 | N = 1; 21 | while (N < n){ 22 | N *= 2; 23 | } 24 | ST = vector(N * 2 - 1, E); 25 | for (int i = 0; i < n; i++){ 26 | ST[N - 1 + i] = A[i]; 27 | } 28 | } 29 | T operator [](int k){ 30 | k += N - 1; 31 | T ans = ST[k]; 32 | while (k > 0){ 33 | k = (k - 1) / 2; 34 | ans = f(ans, ST[k]); 35 | } 36 | return ans; 37 | } 38 | void range_apply(int L, int R, T x, int i, int l, int r){ 39 | if (r <= L || R <= l){ 40 | } else if (L <= l && r <= R){ 41 | ST[i] = f(ST[i], x); 42 | } else { 43 | int m = (l + r) / 2; 44 | range_apply(L, R, x, i * 2 + 1, l, m); 45 | range_apply(L, R, x, i * 2 + 2, m, r); 46 | } 47 | } 48 | void range_apply(int L, int R, T x){ 49 | range_apply(L, R, x, 0, 0, N); 50 | } 51 | }; -------------------------------------------------------------------------------- /data_structure/sequence/compact_bit_vector.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief コンパクト Bit Vector 4 | */ 5 | struct bit_vector{ 6 | vector A; 7 | vector S; 8 | bit_vector(){ 9 | } 10 | bit_vector(vector &a){ 11 | int N = a.size(); 12 | int M = (N + 64 - 1) >> 6; 13 | A = vector(M, 0); 14 | for (int i = 0; i < M; i++){ 15 | for (int j = i << 6; j < min((i + 1) << 6, N); j++){ 16 | if (a[j]){ 17 | A[i] |= (unsigned long long) 1 << (j - (i << 6)); 18 | } 19 | } 20 | } 21 | S = vector(M + 1, 0); 22 | for (int i = 0; i < M; i++){ 23 | S[i + 1] = S[i] + __builtin_popcountll(A[i]); 24 | } 25 | } 26 | int operator [](int k){ 27 | return A[k >> 6] >> (k & 63) & 1; 28 | } 29 | int rank0(int k){ 30 | return k - rank1(k); 31 | } 32 | int rank1(int k){ 33 | if ((k & 63) == 0){ 34 | return S[k >> 6]; 35 | } else { 36 | return S[k >> 6] + __builtin_popcountll(A[k >> 6] << (64 - k + (k >> 6 << 6))); 37 | } 38 | } 39 | }; -------------------------------------------------------------------------------- /data_structure/sequence/cumulative_sum.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief 累積和 4 | */ 5 | template 6 | struct cumulative_sum{ 7 | vector S; 8 | function f; 9 | T E; 10 | cumulative_sum(){ 11 | } 12 | cumulative_sum(vector A, function f, T E): f(f), E(E){ 13 | int N = A.size(); 14 | S = vector(N + 1); 15 | S[0] = E; 16 | for (int i = 0; i < N; i++){ 17 | S[i + 1] = f(S[i], A[i]); 18 | } 19 | } 20 | T get(int i){ 21 | return S[i]; 22 | } 23 | }; -------------------------------------------------------------------------------- /data_structure/sequence/disjoint_sparse_table.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief Disjoint Sparse Table 4 | */ 5 | template 6 | struct disjoint_sparse_table{ 7 | vector A; 8 | vector> D; 9 | function f; 10 | T E; 11 | disjoint_sparse_table(){ 12 | } 13 | disjoint_sparse_table(int N, function f, T E): A(N, E), f(f), E(E){ 14 | if (N > 1){ 15 | int LOG = 32 - __builtin_clz(N - 1); 16 | D = vector>(LOG, vector(N)); 17 | } 18 | } 19 | disjoint_sparse_table(vector &A, function f, T E): A(A), f(f), E(E){ 20 | int N = A.size(); 21 | if (N > 1){ 22 | int LOG = 32 - __builtin_clz(N - 1); 23 | D = vector>(LOG, vector(N)); 24 | for (int i = 0; i < LOG; i++){ 25 | int d = 1 << i; 26 | for (int j = 0; j + d < N; j += d * 2){ 27 | D[i][j + d - 1] = A[j + d - 1]; 28 | for (int k = j + d - 2; k >= j; k--){ 29 | D[i][k] = f(A[k], D[i][k + 1]); 30 | } 31 | D[i][j + d] = A[j + d]; 32 | for (int k = j + d + 1; k < min(j + d * 2, N); k++){ 33 | D[i][k] = f(D[i][k - 1], A[k]); 34 | } 35 | } 36 | } 37 | } 38 | } 39 | T query(int L, int R){ 40 | if (R == L){ 41 | return E; 42 | } else if (R - L == 1){ 43 | return A[L]; 44 | } else { 45 | R--; 46 | int b = 31 - __builtin_clz(R ^ L); 47 | return f(D[b][L], D[b][R]); 48 | } 49 | } 50 | }; -------------------------------------------------------------------------------- /data_structure/sequence/dual_binary_indexed_tree.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief 双対 Binary Indexed Tree 4 | */ 5 | template 6 | struct dual_binary_indexed_tree{ 7 | int N; 8 | vector BIT; 9 | function f; 10 | T E; 11 | dual_binary_indexed_tree(){ 12 | } 13 | dual_binary_indexed_tree(int N, function f, T E): N(N), BIT(N + 1, E), f(f), E(E){ 14 | } 15 | dual_binary_indexed_tree(vector &A, function f, T E): N(A.size()), BIT(N + 1), f(f), E(E){ 16 | for (int i = 0; i < N; i++){ 17 | BIT[i + 1] = A[i]; 18 | } 19 | } 20 | void add(int i, T x){ 21 | while (i > 0){ 22 | BIT[i] = f(BIT[i], x); 23 | i -= i & -i; 24 | } 25 | } 26 | T operator [](int i){ 27 | i++; 28 | T ans = E; 29 | while (i <= N){ 30 | ans = f(ans, BIT[i]); 31 | i += i & -i; 32 | } 33 | return ans; 34 | } 35 | vector get(){ 36 | vector ans = BIT; 37 | for (int i = N - 1; i >= 1; i--){ 38 | if (i + (i & -i) <= N){ 39 | ans[i] = f(ans[i + (i & -i)], ans[i]); 40 | } 41 | } 42 | ans.erase(ans.begin()); 43 | return ans; 44 | } 45 | }; -------------------------------------------------------------------------------- /data_structure/sequence/dual_disjoint_sparse_table.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief 双対 Disjoint Sparse Table 4 | */ 5 | template 6 | struct dual_disjoint_sparse_table{ 7 | vector A; 8 | vector> D; 9 | function f; 10 | T E; 11 | dual_disjoint_sparse_table(){ 12 | } 13 | dual_disjoint_sparse_table(int N, function f, T E): A(N, E), f(f), E(E){ 14 | if (N > 1){ 15 | int LOG = 32 - __builtin_clz(N - 1); 16 | D = vector>(LOG, vector(N, E)); 17 | } 18 | } 19 | dual_disjoint_sparse_table(vector &A, function f, T E): A(A), f(f), E(E){ 20 | int N = A.size(); 21 | if (N > 1){ 22 | int LOG = 32 - __builtin_clz(N - 1); 23 | D = vector>(LOG, vector(N, E)); 24 | } 25 | } 26 | void apply(int L, int R, T x){ 27 | if (L == R){ 28 | return; 29 | } else if (R - L == 1){ 30 | A[L] = f(A[L], x); 31 | } else { 32 | R--; 33 | int b = 31 - __builtin_clz(R ^ L); 34 | D[b][L] = f(D[b][L], x); 35 | D[b][R] = f(D[b][R], x); 36 | } 37 | } 38 | vector get(){ 39 | int LOG = D.size(); 40 | int N = A.size(); 41 | for (int i = 0; i < LOG; i++){ 42 | int d = 1 << i; 43 | for (int j = 0; j + d < N; j += d * 2){ 44 | T L = E; 45 | for (int k = j; k < j + d; k++){ 46 | L = f(L, D[i][k]); 47 | A[k] = f(A[k], L); 48 | } 49 | T R = E; 50 | for (int k = min(j + d * 2, N) - 1; k >= j + d; k--){ 51 | R = f(R, D[i][k]); 52 | A[k] = f(A[k], R); 53 | } 54 | } 55 | } 56 | return A; 57 | } 58 | }; -------------------------------------------------------------------------------- /data_structure/sequence/dual_invertible_binary_indexed_tree.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief 双対可逆 Binary Indexed Tree 4 | */ 5 | template 6 | struct dual_invertible_binary_indexed_tree{ 7 | int N; 8 | vector BIT; 9 | function f; 10 | function inv; 11 | T E; 12 | dual_invertible_binary_indexed_tree(){ 13 | } 14 | dual_invertible_binary_indexed_tree(int N, function f, function inv, T E): N(N), BIT(N + 1, E), f(f), inv(inv), E(E){ 15 | } 16 | dual_invertible_binary_indexed_tree(vector &A, function f, function inv, T E): N(A.size()), BIT(N + 1), f(f), inv(inv), E(E){ 17 | for (int i = 0; i < N; i++){ 18 | BIT[i + 1] = A[i]; 19 | } 20 | } 21 | void add(int i, T x){ 22 | while (i > 0){ 23 | BIT[i] = f(BIT[i], x); 24 | i -= i & -i; 25 | } 26 | } 27 | void add(int l, int r, T x){ 28 | add(l, inv(x)); 29 | add(r, x); 30 | } 31 | T operator [](int i){ 32 | i++; 33 | T ans = E; 34 | while (i <= N){ 35 | ans = f(ans, BIT[i]); 36 | i += i & -i; 37 | } 38 | return ans; 39 | } 40 | vector get(){ 41 | vector ans = BIT; 42 | for (int i = N - 1; i >= 1; i--){ 43 | if (i + (i & -i) <= N){ 44 | ans[i] = f(ans[i + (i & -i)], ans[i]); 45 | } 46 | } 47 | ans.erase(ans.begin()); 48 | return ans; 49 | } 50 | }; -------------------------------------------------------------------------------- /data_structure/sequence/dual_segment_tree.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief 双対セグメント木 (びーと木) 4 | */ 5 | template 6 | struct dual_segment_tree{ 7 | int N; 8 | vector ST; 9 | function f; 10 | T E; 11 | dual_segment_tree(int n, function f, T E): f(f), E(E){ 12 | N = 1; 13 | while (N < n){ 14 | N *= 2; 15 | } 16 | ST = vector(N * 2 - 1, E); 17 | } 18 | dual_segment_tree(vector A, function f, T E): f(f), E(E){ 19 | int n = A.size(); 20 | N = 1; 21 | while (N < n){ 22 | N *= 2; 23 | } 24 | ST = vector(N * 2 - 1, E); 25 | for (int i = 0; i < n; i++){ 26 | ST[N - 1 + i] = A[i]; 27 | } 28 | } 29 | void push(int i){ 30 | if (i < N - 1){ 31 | ST[i * 2 + 1] = f(ST[i * 2 + 1], ST[i]); 32 | ST[i * 2 + 2] = f(ST[i * 2 + 2], ST[i]); 33 | ST[i] = E; 34 | } 35 | } 36 | T operator [](int k){ 37 | int v = 0; 38 | for (int i = N / 2; i >= 1; i >>= 1){ 39 | push(v); 40 | if ((k & i) == 0){ 41 | v = v * 2 + 1; 42 | } else { 43 | v = v * 2 + 2; 44 | } 45 | } 46 | return ST[v]; 47 | } 48 | void range_apply(int L, int R, T x, int i, int l, int r){ 49 | if (r <= L || R <= l){ 50 | } else if (L <= l && r <= R){ 51 | ST[i] = f(ST[i], x); 52 | } else { 53 | push(i); 54 | int m = (l + r) / 2; 55 | range_apply(L, R, x, i * 2 + 1, l, m); 56 | range_apply(L, R, x, i * 2 + 2, m, r); 57 | } 58 | } 59 | void range_apply(int L, int R, T x){ 60 | range_apply(L, R, x, 0, 0, N); 61 | } 62 | }; -------------------------------------------------------------------------------- /data_structure/sequence/dual_sparse_table.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief 双対スパーステーブル 4 | */ 5 | template 6 | struct dual_sparse_table{ 7 | vector> ST; 8 | function f; 9 | T E; 10 | dual_sparse_table(){ 11 | } 12 | dual_sparse_table(int N, function f, T E): f(f), E(E){ 13 | int LOG = 32 - __builtin_clz(N); 14 | ST = vector>(LOG, vector(N, E)); 15 | } 16 | dual_sparse_table(vector &A, function f, T E): f(f), E(E){ 17 | int N = A.size(); 18 | int LOG = 32 - __builtin_clz(N); 19 | ST = vector>(LOG, vector(N, E)); 20 | ST[0] = A; 21 | } 22 | void apply(int L, int R, T x){ 23 | if (L == R){ 24 | return; 25 | } 26 | int d = 31 - __builtin_clz(R - L); 27 | ST[d][L] = f(ST[d][L], x); 28 | ST[d][R - (1 << d)] = f(ST[d][R - (1 << d)], x); 29 | } 30 | vector get(){ 31 | int LOG = ST.size(); 32 | int N = ST[0].size(); 33 | for (int i = LOG - 2; i >= 0; i--){ 34 | for (int j = 0; j < N - (1 << i); j++){ 35 | ST[i][j] = f(ST[i][j], ST[i + 1][j]); 36 | ST[i][j + (1 << i)] = f(ST[i][j + (1 << i)], ST[i + 1][j]); 37 | } 38 | } 39 | return ST[0]; 40 | } 41 | }; -------------------------------------------------------------------------------- /data_structure/sequence/invertible_binary_indexed_tree.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief 可逆 Binary Indexed Tree 4 | */ 5 | template 6 | struct invertible_binary_indexed_tree{ 7 | int N; 8 | vector BIT; 9 | function f; 10 | function inv; 11 | T E; 12 | invertible_binary_indexed_tree(){ 13 | } 14 | invertible_binary_indexed_tree(int N, function f, function inv, T E): N(N), BIT(N + 1, E), f(f), inv(inv), E(E){ 15 | } 16 | invertible_binary_indexed_tree(vector &A, function f, function inv, T E): N(A.size()), BIT(N + 1), f(f), inv(inv), E(E){ 17 | for (int i = 0; i < N; i++){ 18 | BIT[i + 1] = A[i]; 19 | } 20 | for (int i = 1; i < N; i++){ 21 | if (i + (i & -i) <= N){ 22 | BIT[i + (i & -i)] = f(BIT[i + (i & -i)], BIT[i]); 23 | } 24 | } 25 | } 26 | void add(int i, T x){ 27 | i++; 28 | while (i <= N){ 29 | BIT[i] = f(BIT[i], x); 30 | i += i & -i; 31 | } 32 | } 33 | T sum(int i){ 34 | T ans = E; 35 | while (i > 0){ 36 | ans = f(ans, BIT[i]); 37 | i -= i & -i; 38 | } 39 | return ans; 40 | } 41 | T sum(int l, int r){ 42 | return f(sum(r), inv(sum(l))); 43 | } 44 | }; -------------------------------------------------------------------------------- /data_structure/sequence/invertible_cumulative_sum.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief 可逆累積和 4 | */ 5 | template 6 | struct invertible_cumulative_sum{ 7 | vector S; 8 | function f; 9 | function inv; 10 | T E; 11 | invertible_cumulative_sum(){ 12 | } 13 | invertible_cumulative_sum(vector A, function f, function inv, T E): f(f), inv(inv), E(E){ 14 | int N = A.size(); 15 | S = vector(N + 1); 16 | S[0] = E; 17 | for (int i = 0; i < N; i++){ 18 | S[i + 1] = f(S[i], A[i]); 19 | } 20 | } 21 | T get(int i){ 22 | return S[i]; 23 | } 24 | T get(int l, int r){ 25 | return f(S[r], inv(S[l])); 26 | } 27 | }; -------------------------------------------------------------------------------- /data_structure/sequence/lazy_segment_tree.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief 遅延セグメント木 4 | */ 5 | template 6 | struct lazy_segment_tree{ 7 | int N; 8 | vector ST; 9 | vector lazy; 10 | function op; 11 | function mp; 12 | function comp; 13 | T E; 14 | F id; 15 | lazy_segment_tree(int n, function op, function mp, function comp, T E, F id): op(op), mp(mp), comp(comp), E(E), id(id){ 16 | N = 1; 17 | while (N < n){ 18 | N *= 2; 19 | } 20 | ST = vector(N * 2 - 1, E); 21 | for (int i = N - 2; i >= 0; i--){ 22 | ST[i] = op(ST[i * 2 + 1], ST[i * 2 + 2]); 23 | } 24 | lazy = vector(N * 2 - 1, id); 25 | } 26 | lazy_segment_tree(vector &A, function op, function mp, function comp, T E, F id): op(op), mp(mp), comp(comp), E(E), id(id){ 27 | int n = A.size(); 28 | N = 1; 29 | while (N < n){ 30 | N *= 2; 31 | } 32 | ST = vector(N * 2 - 1, E); 33 | for (int i = 0; i < n; i++){ 34 | ST[N - 1 + i] = A[i]; 35 | } 36 | for (int i = N - 2; i >= 0; i--){ 37 | ST[i] = op(ST[i * 2 + 1], ST[i * 2 + 2]); 38 | } 39 | lazy = vector(N * 2 - 1, id); 40 | } 41 | void push(int i){ 42 | if (i < N - 1){ 43 | lazy[i * 2 + 1] = comp(lazy[i * 2 + 1], lazy[i]); 44 | lazy[i * 2 + 2] = comp(lazy[i * 2 + 2], lazy[i]); 45 | } 46 | ST[i] = mp(lazy[i], ST[i]); 47 | lazy[i] = id; 48 | } 49 | void range_apply(int L, int R, F f, int i, int l, int r){ 50 | push(i); 51 | if (r <= L || R <= l){ 52 | return; 53 | } else if (L <= l && r <= R){ 54 | lazy[i] = f; 55 | push(i); 56 | } else { 57 | int m = (l + r) / 2; 58 | range_apply(L, R, f, i * 2 + 1, l, m); 59 | range_apply(L, R, f, i * 2 + 2, m, r); 60 | ST[i] = op(ST[i * 2 + 1], ST[i * 2 + 2]); 61 | } 62 | } 63 | void range_apply(int L, int R, F f){ 64 | range_apply(L, R, f, 0, 0, N); 65 | } 66 | T range_fold(int L, int R, int i, int l, int r){ 67 | push(i); 68 | if (r <= L || R <= l){ 69 | return E; 70 | } else if (L <= l && r <= R){ 71 | return ST[i]; 72 | } else { 73 | int m = (l + r) / 2; 74 | return op(range_fold(L, R, i * 2 + 1, l, m), range_fold(L, R, i * 2 + 2, m, r)); 75 | } 76 | } 77 | T range_fold(int L, int R){ 78 | return range_fold(L, R, 0, 0, N); 79 | } 80 | T all(){ 81 | push(0); 82 | return ST[0]; 83 | } 84 | }; -------------------------------------------------------------------------------- /data_structure/sequence/segment_tree.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief セグメント木 (うし木) 4 | */ 5 | template 6 | struct segment_tree{ 7 | int N; 8 | vector ST; 9 | function f; 10 | T E; 11 | segment_tree(){ 12 | } 13 | segment_tree(int n, function f, T E): f(f), E(E){ 14 | N = 1; 15 | while (N < n){ 16 | N *= 2; 17 | } 18 | ST = vector(N * 2 - 1, E); 19 | } 20 | segment_tree(vector A, function f, T E): f(f), E(E){ 21 | int n = A.size(); 22 | N = 1; 23 | while (N < n){ 24 | N *= 2; 25 | } 26 | ST = vector(N * 2 - 1, E); 27 | for (int i = 0; i < n; i++){ 28 | ST[N - 1 + i] = A[i]; 29 | } 30 | for (int i = N - 2; i >= 0; i--){ 31 | ST[i] = f(ST[i * 2 + 1], ST[i * 2 + 2]); 32 | } 33 | } 34 | T operator [](int k){ 35 | return ST[N - 1 + k]; 36 | } 37 | void update(int k, T x){ 38 | k += N - 1; 39 | ST[k] = x; 40 | while (k > 0){ 41 | k = (k - 1) / 2; 42 | ST[k] = f(ST[k * 2 + 1], ST[k * 2 + 2]); 43 | } 44 | } 45 | T query(int L, int R, int i, int l, int r){ 46 | if (r <= L || R <= l){ 47 | return E; 48 | } else if (L <= l && r <= R){ 49 | return ST[i]; 50 | } else { 51 | int m = (l + r) / 2; 52 | return f(query(L, R, i * 2 + 1, l, m), query(L, R, i * 2 + 2, m, r)); 53 | } 54 | } 55 | T query(int L, int R){ 56 | return query(L, R, 0, 0, N); 57 | } 58 | T all(){ 59 | return ST[0]; 60 | } 61 | }; -------------------------------------------------------------------------------- /data_structure/sequence/segment_tree_beats.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief Segment Tree Beats 4 | */ 5 | template 6 | struct segment_tree_beats{ 7 | int N; 8 | vector ST; 9 | vector lazy; 10 | function op; 11 | function mp; 12 | function comp; 13 | T E; 14 | F id; 15 | segment_tree_beats(vector &A, function op, function mp, function comp, T E, F id): op(op), mp(mp), comp(comp), E(E), id(id){ 16 | int n = A.size(); 17 | N = 1; 18 | while (N < n){ 19 | N *= 2; 20 | } 21 | ST = vector(N * 2 - 1, E); 22 | for (int i = 0; i < n; i++){ 23 | ST[N - 1 + i] = A[i]; 24 | } 25 | for (int i = N - 2; i >= 0; i--){ 26 | update(i); 27 | } 28 | lazy = vector(N * 2 - 1, id); 29 | } 30 | void update(int i){ 31 | ST[i] = op(ST[i * 2 + 1], ST[i * 2 + 2]); 32 | } 33 | void push(int i){ 34 | ST[i] = mp(lazy[i], ST[i]); 35 | if (i < N - 1){ 36 | lazy[i * 2 + 1] = comp(lazy[i], lazy[i * 2 + 1]); 37 | lazy[i * 2 + 2] = comp(lazy[i], lazy[i * 2 + 2]); 38 | if (ST[i].fail){ 39 | push(i * 2 + 1); 40 | push(i * 2 + 2); 41 | update(i); 42 | } 43 | } 44 | lazy[i] = id; 45 | } 46 | void range_apply(int L, int R, F f, int i, int l, int r){ 47 | push(i); 48 | if (r <= L || R <= l){ 49 | return; 50 | } else if (L <= l && r <= R){ 51 | lazy[i] = f; 52 | push(i); 53 | } else { 54 | int m = (l + r) / 2; 55 | range_apply(L, R, f, i * 2 + 1, l, m); 56 | range_apply(L, R, f, i * 2 + 2, m, r); 57 | update(i); 58 | } 59 | } 60 | void range_apply(int L, int R, F f){ 61 | range_apply(L, R, f, 0, 0, N); 62 | } 63 | T range_fold(int L, int R, int i, int l, int r){ 64 | push(i); 65 | if (r <= L || R <= l){ 66 | return E; 67 | } else if (L <= l && r <= R){ 68 | return ST[i]; 69 | } else { 70 | int m = (l + r) / 2; 71 | return op(range_fold(L, R, i * 2 + 1, l, m), range_fold(L, R, i * 2 + 2, m, r)); 72 | } 73 | } 74 | T range_fold(int L, int R){ 75 | return range_fold(L, R, 0, 0, N); 76 | } 77 | }; -------------------------------------------------------------------------------- /data_structure/sequence/sparse_table.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief スパーステーブル 4 | */ 5 | template 6 | struct sparse_table{ 7 | vector> ST; 8 | function f; 9 | T E; 10 | sparse_table(){ 11 | } 12 | sparse_table(int N, function f, T E): f(f), E(E){ 13 | int LOG = 32 - __builtin_clz(N); 14 | ST = vector>(LOG, vector(N, E)); 15 | } 16 | sparse_table(vector &A, function f, T E): f(f), E(E){ 17 | int N = A.size(); 18 | int LOG = 32 - __builtin_clz(N); 19 | ST = vector>(LOG, vector(N)); 20 | for (int i = 0; i < N; i++){ 21 | ST[0][i] = A[i]; 22 | } 23 | for (int i = 0; i < LOG - 1; i++){ 24 | for (int j = 0; j < N - (1 << i); j++){ 25 | ST[i + 1][j] = f(ST[i][j], ST[i][j + (1 << i)]); 26 | } 27 | } 28 | } 29 | int query(int L, int R){ 30 | if (L == R){ 31 | return E; 32 | } 33 | int d = 31 - __builtin_clz(R - L); 34 | return f(ST[d][L], ST[d][R - (1 << d)]); 35 | } 36 | }; -------------------------------------------------------------------------------- /data_structure/sequence/wavelet_matrix.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief ウェーブレット行列 4 | */ 5 | #include "compact_bit_vector.hpp" 6 | struct wavelet_matrix{ 7 | int N, LOG; 8 | vector D; 9 | vector cnt, T; 10 | wavelet_matrix(){ 11 | } 12 | wavelet_matrix(vector &A): N(A.size()){ 13 | LOG = 1; 14 | for (int i = 0; i < N; i++){ 15 | if (A[i] > 0){ 16 | LOG = max(LOG, 32 - __builtin_clz(A[i])); 17 | } 18 | } 19 | D.resize(LOG); 20 | cnt.resize(LOG, 0); 21 | for (int i = LOG - 1; i >= 0; i--){ 22 | vector B(N, false); 23 | for (int j = 0; j < N; j++){ 24 | if ((A[j] >> i & 1) == 1){ 25 | B[j] = true; 26 | } 27 | } 28 | D[LOG - 1 - i] = bit_vector(B); 29 | vector A2; 30 | for (int j = 0; j < N; j++){ 31 | if ((A[j] >> i & 1) == 0){ 32 | A2.push_back(A[j]); 33 | cnt[LOG - 1 - i]++; 34 | } 35 | } 36 | for (int j = 0; j < N; j++){ 37 | if ((A[j] >> i & 1) == 1){ 38 | A2.push_back(A[j]); 39 | } 40 | } 41 | swap(A, A2); 42 | } 43 | T = A; 44 | } 45 | int operator [](int k){ 46 | int ans = 0; 47 | for (int i = 0; i < LOG; i++){ 48 | if (D[i][k] == 0){ 49 | k = D[i].rank0(k); 50 | } else { 51 | ans += 1 << (LOG - 1 - i); 52 | k = cnt[i] + D[i].rank1(k); 53 | } 54 | } 55 | return ans; 56 | } 57 | int rank(int l, int r, int c){ 58 | for (int i = 0; i < LOG; i++){ 59 | if ((c >> (LOG - 1 - i) & 1) == 0){ 60 | l = D[i].rank0(l); 61 | r = D[i].rank0(r); 62 | } else { 63 | l = cnt[i] + D[i].rank1(l); 64 | r = cnt[i] + D[i].rank1(r); 65 | } 66 | } 67 | return r - l; 68 | } 69 | int quantile(int l, int r, int k){ 70 | int ans = 0; 71 | for (int i = 0; i < LOG; i++){ 72 | int cnt0 = D[i].rank0(r) - D[i].rank0(l); 73 | if (k < cnt0){ 74 | l = D[i].rank0(l); 75 | r = D[i].rank0(r); 76 | } else { 77 | ans += 1 << (LOG - 1 - i); 78 | k -= cnt0; 79 | l = cnt[i] + D[i].rank1(l); 80 | r = cnt[i] + D[i].rank1(r); 81 | } 82 | } 83 | return ans; 84 | } 85 | }; -------------------------------------------------------------------------------- /data_structure/sequence/xor_segment_tree.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief XOR セグメント木 4 | */ 5 | template 6 | struct xor_segment_tree{ 7 | int N; 8 | vector> ST; 9 | function f; 10 | T E; 11 | xor_segment_tree(vector &A, function f, T E): f(f), E(E){ 12 | N = A.size(); 13 | ST = vector>(N * 2 - 1); 14 | for (int i = 0; i < N; i++){ 15 | ST[N - 1 + i].push_back(A[i]); 16 | } 17 | for (int i = N - 2; i >= 0; i--){ 18 | int cnt = ST[i * 2 + 1].size(); 19 | for (int j = 0; j < cnt; j++){ 20 | ST[i].push_back(f(ST[i * 2 + 1][j], ST[i * 2 + 2][j])); 21 | } 22 | for (int j = 0; j < cnt; j++){ 23 | ST[i].push_back(f(ST[i * 2 + 2][j], ST[i * 2 + 1][j])); 24 | } 25 | } 26 | } 27 | T range_fold(int L, int R, int x, int i, int l, int r){ 28 | if (r <= L || R <= l){ 29 | return E; 30 | } else if (L <= l && r <= R){ 31 | return ST[i][x]; 32 | } else { 33 | int p = (r - l) / 2; 34 | int m = (l + r) / 2; 35 | if ((x & p) == 0){ 36 | T resL = range_fold(L, R, x, i * 2 + 1, l, m); 37 | T resR = range_fold(L, R, x, i * 2 + 2, m, r); 38 | return f(resL, resR); 39 | } else { 40 | T resL = E; 41 | if (R >= m){ 42 | resL = range_fold(max(L, m) - p, R - p, x ^ p, i * 2 + 1, l, m); 43 | } 44 | T resR = E; 45 | if (L < m){ 46 | resR = range_fold(L + p, min(R, m) + p, x ^ p, i * 2 + 2, m, r); 47 | } 48 | return f(resR, resL); 49 | } 50 | } 51 | } 52 | T range_fold(int L, int R, int x){ 53 | return range_fold(L, R, x, 0, 0, N); 54 | } 55 | }; -------------------------------------------------------------------------------- /data_structure/tree/heavy_light_decomposition.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief 重軽分解 4 | */ 5 | struct heavy_light_decomposition{ 6 | vector p, sz, in, next; 7 | void dfs1(vector> &c, int v){ 8 | sz[v] = 1; 9 | for (int &w : c[v]){ 10 | dfs1(c, w); 11 | sz[v] += sz[w]; 12 | if (sz[w] > sz[c[v][0]]){ 13 | swap(w, c[v][0]); 14 | } 15 | } 16 | } 17 | void dfs2(vector> &c, int &t, int v){ 18 | in[v] = t; 19 | t++; 20 | for (int w : c[v]){ 21 | if (w == c[v][0]){ 22 | next[w] = next[v]; 23 | } else { 24 | next[w] = w; 25 | } 26 | dfs2(c, t, w); 27 | } 28 | } 29 | heavy_light_decomposition(vector &p, vector> &c, int r = 0): p(p){ 30 | int N = p.size(); 31 | sz = vector(N); 32 | dfs1(c, r); 33 | in = vector(N); 34 | next = vector(N, r); 35 | int t = 0; 36 | dfs2(c, t, r); 37 | } 38 | int lca(int u, int v){ 39 | while (true){ 40 | if (in[u] > in[v]){ 41 | swap(u, v); 42 | } 43 | if (next[u] == next[v]){ 44 | return u; 45 | } 46 | v = p[next[v]]; 47 | } 48 | } 49 | int dist(int u, int v){ 50 | int ans = 0; 51 | while (true){ 52 | if (in[u] > in[v]){ 53 | swap(u, v); 54 | } 55 | if (next[u] == next[v]){ 56 | ans += in[v] - in[u]; 57 | return ans; 58 | } 59 | ans += in[v] - in[next[v]] + 1; 60 | v = p[next[v]]; 61 | } 62 | } 63 | }; -------------------------------------------------------------------------------- /data_structure/unionfind/unionfind.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | struct unionfind{ 3 | vector p; 4 | unionfind(int N){ 5 | p = vector(N, -1); 6 | } 7 | int root(int x){ 8 | if (p[x] < 0){ 9 | return x; 10 | } else { 11 | p[x] = root(p[x]); 12 | return p[x]; 13 | } 14 | } 15 | bool same(int x, int y){ 16 | return root(x) == root(y); 17 | } 18 | void unite(int x, int y){ 19 | x = root(x); 20 | y = root(y); 21 | if (x != y){ 22 | if (p[x] < p[y]){ 23 | swap(x, y); 24 | } 25 | p[y] += p[x]; 26 | p[x] = y; 27 | } 28 | } 29 | }; -------------------------------------------------------------------------------- /docs/data_structure/other/li_chao_tree.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Li Chao Tree 3 | documentation_of: data_structure/other/li_chao_tree.hpp 4 | --- 5 | 6 | # Li Chao Tree 7 | 8 | ## ``li_chao_tree(const vector &x2)`` 9 | 座標の列が $x2$ であるような Li Chao Tree を構築する。 10 | 11 | ## ``void line_add(T a, T b)`` 12 | 直線 $y=ax+b$ を追加する。 13 | 14 | ## ``void segment_add(T l, T r, T a, T b)`` 15 | 線分 $y=ax+b \ (l \leq x < r)$ を追加する。 16 | 17 | ## ``vector manacher(const T &A)`` 18 | 長さ $N$ の列 $A$ を引数に取り、長さ $N$ の配列を返す。 19 | 20 | ## ``T get(T x2)`` 21 | $x=x2$ における最小値を求める。$x2$ は構築時に与えられた座標に含まれる必要がある。 -------------------------------------------------------------------------------- /docs/data_structure/unionfind/unionfind.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: UnionFind 3 | documentation_of: data_structure/unionfind/unionfind.hpp 4 | --- 5 | 6 | # UnionFind 7 | 集合を扱うデータ構造。 8 | 9 | ## 操作 10 | * `unionfind(N)`: $0, 1, \dots, N-1$ がそれぞれ異なる集合に属している状態で初期化する。 11 | * `root(x)`: $x$ が属する集合を代表する要素を $1$ つ答える。同じ集合の要素について `root` を行ったとき、同じ要素が返ることが保証される。 12 | * `same(x, y)`: $x, y$ が同じ集合に属するか判定する。 13 | * `unite(x, y)`: $x$ の属する集合と $y$ の属する集合を併合する。既に同じ集合に属する場合は何も発生しない。 14 | 15 | ## 資料 16 | [data-structures](https://scrapbox.io/data-structures/Union_Find) -------------------------------------------------------------------------------- /docs/other/poker_hands.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: ポーカー役判定 3 | documentation_of: other/poker_hands.hpp 4 | --- 5 | 6 | # ポーカー役判定 7 | ポーカーの役を判定する。 8 | 9 | ## ``struct card`` 10 | 各カードを扱う構造体である。 11 | 12 | ``char suit`` はカードのスートを表す文字である。各スートにどの文字を割り当てるかは自由に決められる。 13 | 14 | ``int rank`` はカードのランクを表す数である。2~10 のカードの ``rank`` はその数と同じである。J (ジャック)、Q (クイーン)、K (キング)、A (エース) の ``rank`` はそれぞれ ``11, 12, 13, 14`` である。 15 | 16 | カードを ``std::istream`` から ``operator>>`` を用いて入力できる。入力は以下の形式で行われる。 17 | 18 | * 2 文字の文字列を入力する。 19 | * 文字列の 1 文字目はカードのスートを表す。 20 | * 文字列の 2 文字目はカードのランクを表す。 21 | * 2~9 の文字はそれぞれランクが 2~9 のカードとして扱われる。 22 | * ``T, J, Q, K, A`` はそれぞれ 10、J (ジャック)、Q (クイーン)、K (キング)、A (エース) のカードとして扱われる。 23 | 24 | ## `` enum poker_hand`` 25 | ポーカーの役の種類を表す。 26 | 27 | ``poker_hand`` の要素と役の対応は以下のようである。 28 | 29 | |``poker_hand`` の要素|役| 30 | |-|-| 31 | |``HIGH_CARD``|ハイカード| 32 | |``ONE_PAIR``|ワンペア| 33 | |``TWO_PAIR``|ツーペア| 34 | |``THREE_OF_A_KIND``|スリー・オブ・ア・カインド| 35 | |``STRAIGHT``|ストレート| 36 | |``FLUSH``|フラッシュ| 37 | |``FULL_HOUSE``|フルハウス| 38 | |``FOUR_OF_A_KIND``|フォー・オブ・ア・カインド| 39 | |``STRAIGHT_FLUSH``|ストレートフラッシュ| 40 | |``ROYAL_STRAIGHT_FLUSH``|ロイヤルストレートフラッシュ| 41 | 42 | ``poker_hand`` の各要素には、上の表で示した順に 0~9 の整数が割り当てられている。 43 | 44 | ## ``vector hand(array C)`` 45 | 手札を表す 5 枚のカードの配列 ``C`` が与えられたとき、そのカードの役と役のうちの相対的な強さを表す配列を返す。ただし、スートもランクも同じカードが 2 枚含まれることはないことを仮定する。 46 | 47 | 返り値の最初の整数は ``poker_hand`` の要素であり、役の種類を表す。残りの要素は、その役のうちの相対的な強さを表す。 48 | 49 | それぞれの役に対し、返り値は以下のようになる。 50 | 51 | ### ロイヤルストレートフラッシュ 52 | 53 | ``{ROYAL_STRAIGHT_FLUSH}`` を返す。 54 | 55 | ### ストレートフラッシュ 56 | 手札のうち最も大きい ``rank`` を a としたとき、``{STRAIGHT_FLUSH, a}`` を返す。ただし、手札のランクが A,2,3,4,5 のとき、``{STRAIGHT_FLUSH, 5}`` を返す。 57 | 58 | ### フォー・オブ・ア・カインド 59 | 4 枚ある ``rank`` を a、残りのカードの ``rank`` を b としたとき、``{FOUR_OF_A_KIND, a, b}`` を返す。 60 | 61 | ### フルハウス 62 | 3 枚ある ``rank`` を a、残りの 2 枚のカードの ``rank`` を b としたとき、``{FULL_HOUSE, a, b}`` を返す。 63 | 64 | ### フラッシュ 65 | 5 枚のカードの ``rank`` を大きい順に a, b, c, d, e としたとき、``{FLUSH, a, b, c, d, e}`` を返す。 66 | 67 | ### ストレート 68 | 手札のうち最も大きい ``rank`` を a としたとき、``{STRAIGHT, a}`` を返す。ただし、手札のランクが A,2,3,4,5 のとき、``{STRAIGHT, 5}`` を返す。 69 | 70 | ### スリー・オブ・ア・カインド 71 | 3 枚ある ``rank`` を a、残りの 2 枚のカードの ``rank`` を大きい順に b, c としたとき、``{THREE_OF_A_KIND, a, b, c}`` を返す。 72 | 73 | ### ツーペア 74 | 2 枚ある ``rank`` を大きい順に a, b、残りのカードの ``rank`` を c としたとき、``{TWO_PAIR, a, b, c}`` を返す。 75 | 76 | ### ワンペア 77 | 2 枚ある ``rank`` を a、残りの 3 枚のカードの ``rank`` を大きい順に b, c, d としたとき、``{ONE_PAIR, a, b, c, d}`` を返す。 78 | 79 | ### ハイカード 80 | 5 枚のカードの ``rank`` を大きい順に a, b, c, d, e としたとき、``{HIGH_CARD, a, b, c, d, e}`` を返す。 81 | 82 | ``hand`` の返り値は、2 つの手札に対する ``hand`` の返り値を辞書順に比較した結果が役の強さの比較と一致するようになっている。 -------------------------------------------------------------------------------- /docs/string/lcp_array.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 高さ配列 (LCP Array) 3 | documentation_of: string/lcp_array.hpp 4 | --- 5 | 6 | # LCP Array 7 | 列の高さ配列を求める。 8 | 9 | ## ``vector lcp_array(const T &A, vector &SA)`` 10 | 列 $A$ とその接尾辞配列 $SA$ が与えられたとき、$A$ の高さ配列を求める。 11 | 12 | 列 $A$ の長さを $N$ とすると、高さ配列の長さは $N-1$ であり、各 $i \ (0 \leq i < N-1)$ に対して高さ配列の $i$ 番目の要素は $A[SA_i, N)$ と $A[SA_{i + 1}, N)$ の最長共通接頭辞の長さである。 13 | 14 | 時間計算量は $O(N)$ である。 -------------------------------------------------------------------------------- /docs/string/manacher.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 最長回文 (Manacher's Algorithm) 3 | documentation_of: string/manacher.hpp 4 | --- 5 | 6 | # Manacher's Algorithm 7 | 列が与えられたとき、各文字を中心とする回文の半径の最大値を求める。 8 | 9 | ## ``vector manacher(const T &A)`` 10 | 長さ $N$ の列 $A$ を引数に取り、長さ $N$ の配列を返す。 11 | 12 | 返り値の $i$ 番目の要素は、$A[i-k+1,i+k-1]$ が回文であるような $k$ の最大値である。 13 | 14 | 時間計算量は $O(N)$ である。 15 | 16 | ## 資料 17 | [あなたは嘘つきですかと聞かれたら「YES」と答えるブログ](https://snuke.hatenablog.com/entry/2014/12/02/235837) -------------------------------------------------------------------------------- /docs/string/suffix_array.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 接尾辞配列 (SA-IS) 3 | documentation_of: string/suffix_array.hpp 4 | --- 5 | 6 | # Suffix Array 7 | 8 | バグが発見されています。使用しないでください。 9 | 10 | 文字列 `cabcab` の接尾辞配列を求めようとすると配列外参照をします。原因を調査中です。 11 | 12 | 13 | 数列の接尾辞配列を求める。 14 | 15 | ## ``vector suffix_array(const vector &A, int mx)`` 16 | 各要素が $0$ 以上 $\text{mx}$ 未満の数列 $A$ が与えられたとき、$A$ の接尾辞配列を返す。 17 | 18 | 長さ $N$ の数列 $A$ の接尾辞配列とは、$\{0, 1, \dots, N-1\}$ の順列 $P$ であって、任意の $i \ (0 \leq i < N-1)$ に対し $A[P_i,N) < A[P_{i+1},N)$ が成り立つようなものである。 19 | 20 | 時間計算量は $O(N + \text{mx})$ である。 21 | 22 | ## ``vector suffix_array(const string &S)`` 23 | 文字列 $S$ が与えられたとき、$S$ の接尾辞配列を返す。 24 | 25 | 文字列の接尾辞配列は数列と同様に定義される。 26 | 27 | 文字列の長さを $N$ とすると、時間計算量は $O(N)$ である。 28 | 29 | ## 資料 30 | [nekolib](https://rsk0315.github.io/library-rs/nekolib/seq/struct.SuffixArray.html) -------------------------------------------------------------------------------- /docs/string/z_algorithm.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Z Algorithm 3 | documentation_of: string/z_algorithm.hpp 4 | --- 5 | 6 | # Z Algorithm 7 | 列のそれぞれの接尾辞について、列全体との最長共通接頭辞の長さを求める。 8 | 9 | ## ``vector z_algorithm(const T &A)`` 10 | $A$ を長さ $N$ の列とするとき、長さ $N$ の列 $Z$ を返す。ただし、$0 \leq i < N$ について $Z_i$ は $A$ と $A[i,N)$ の最長共通接頭辞の長さである。 11 | 12 | 時間計算量は $O(N)$ である。 -------------------------------------------------------------------------------- /graph/biconnected_components.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief 二重頂点連結成分分解 4 | */ 5 | struct biconnected_components{ 6 | vector bcc; 7 | int cnt = 0; 8 | biconnected_components(vector>> &E){ 9 | int N = E.size(); 10 | vector next(N, -1); 11 | vector d(N, -1); 12 | vector imos(N, 0); 13 | for (int i = 0; i < N; i++){ 14 | if (d[i] == -1){ 15 | d[i] = 0; 16 | dfs1(E, next, d, imos, i); 17 | } 18 | } 19 | int M = 0; 20 | for (int i = 0; i < N; i++){ 21 | M += E[i].size(); 22 | } 23 | M /= 2; 24 | bcc = vector(M, -1); 25 | for (int i = 0; i < N; i++){ 26 | if (d[i] == 0){ 27 | dfs2(E, d, imos, cnt, i); 28 | } 29 | } 30 | } 31 | void dfs1(vector>> &E, vector &next, vector &d, vector &imos, int v){ 32 | for (auto P : E[v]){ 33 | int w = P.second; 34 | if (d[w] == -1){ 35 | d[w] = d[v] + 1; 36 | next[v] = w; 37 | dfs1(E, next, d, imos, w); 38 | imos[v] += imos[w]; 39 | } else if (d[w] < d[v] - 1){ 40 | imos[v]++; 41 | imos[next[w]]--; 42 | } 43 | } 44 | } 45 | void dfs2(vector>> &E, vector &d, vector &imos, int b, int v){ 46 | for (auto P : E[v]){ 47 | int x = P.first; 48 | int w = P.second; 49 | if (d[w] < d[v]){ 50 | bcc[x] = b; 51 | } else if (d[w] == d[v] + 1 && bcc[x] == -1){ 52 | if (imos[w] > 0){ 53 | bcc[x] = b; 54 | } else { 55 | bcc[x] = cnt; 56 | cnt++; 57 | } 58 | dfs2(E, d, imos, bcc[x], w); 59 | } 60 | } 61 | } 62 | int operator [](int k){ 63 | return bcc[k]; 64 | } 65 | }; -------------------------------------------------------------------------------- /graph/block_cut_tree.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief Block Cut Tree 4 | */ 5 | #include "biconnected_components.hpp" 6 | struct block_cut_tree{ 7 | int V; 8 | vector art; 9 | vector cut; 10 | vector> G; 11 | vector> node; 12 | block_cut_tree(vector> &E){ 13 | int N = E.size(); 14 | int M = 0; 15 | vector>> E2(N); 16 | for (int i = 0; i < N; i++){ 17 | for (int j : E[i]){ 18 | if (j > i){ 19 | E2[i].push_back(make_pair(M, j)); 20 | E2[j].push_back(make_pair(M, i)); 21 | M++; 22 | } 23 | } 24 | } 25 | biconnected_components B(E2); 26 | art = vector(N, false); 27 | int cnt = 0; 28 | for (int i = 0; i < N; i++){ 29 | for (auto P : E2[i]){ 30 | if (B[P.first] != B[E2[i][0].first]){ 31 | art[i] = true; 32 | } 33 | } 34 | if (art[i]){ 35 | cnt++; 36 | } 37 | if (E[i].empty()){ 38 | cnt++; 39 | } 40 | } 41 | V = cnt + B.cnt; 42 | cut = vector(V, false); 43 | G.resize(V); 44 | node.resize(V); 45 | int cnt2 = 0; 46 | vector used(B.cnt, false); 47 | for (int i = 0; i < N; i++){ 48 | if (art[i]){ 49 | cut[cnt2] = true; 50 | node[cnt2].push_back(i); 51 | for (auto P : E2[i]){ 52 | int b = B[P.first]; 53 | if (!used[b]){ 54 | used[b] = true; 55 | G[cnt + b].push_back(cnt2); 56 | G[cnt2].push_back(cnt + b); 57 | node[cnt + b].push_back(i); 58 | } 59 | } 60 | for (auto P : E2[i]){ 61 | int b = B[P.first]; 62 | used[b] = false; 63 | } 64 | cnt2++; 65 | } else if (!E2[i].empty()){ 66 | int b = B[E2[i][0].first]; 67 | node[cnt + b].push_back(i); 68 | } else { 69 | node[cnt2].push_back(i); 70 | cnt2++; 71 | } 72 | } 73 | } 74 | }; -------------------------------------------------------------------------------- /graph/enumerate_triangles.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief 三角形列挙 4 | */ 5 | vector> enumerate_triangles(vector> &E){ 6 | int N = E.size(); 7 | vector d(N); 8 | for (int i = 0; i < N; i++){ 9 | d[i] = E[i].size(); 10 | } 11 | vector> E2(N); 12 | for (int i = 0; i < N; i++){ 13 | for (int j : E[i]){ 14 | if (d[i] < d[j] || d[i] == d[j] && i < j){ 15 | E2[i].push_back(j); 16 | } 17 | } 18 | } 19 | vector flg(N, false); 20 | vector> ans; 21 | for (int i = 0; i < N; i++){ 22 | for (int j : E2[i]){ 23 | for (int k : E2[i]){ 24 | flg[k] = true; 25 | } 26 | for (int k : E2[j]){ 27 | if (flg[k]){ 28 | ans.push_back(make_tuple(i, j, k)); 29 | } 30 | } 31 | for (int k : E2[i]){ 32 | flg[k] = false; 33 | } 34 | } 35 | } 36 | return ans; 37 | } 38 | -------------------------------------------------------------------------------- /graph/extended_block_cut_tree.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief 拡張 Block Cut Tree 4 | */ 5 | struct extended_block_cut_tree{ 6 | int N, cnt; 7 | vector> G; 8 | extended_block_cut_tree(vector> &E){ 9 | N = E.size(); 10 | vector next(N, -1); 11 | vector d(N, -1); 12 | vector imos(N, 0); 13 | for (int i = 0; i < N; i++){ 14 | if (d[i] == -1){ 15 | d[i] = 0; 16 | dfs1(E, next, d, imos, i); 17 | } 18 | } 19 | cnt = 0; 20 | G.resize(N + 1); 21 | vector used(N, false); 22 | for (int i = 0; i < N; i++){ 23 | if (d[i] == 0){ 24 | dfs2(E, d, imos, used, cnt, i); 25 | } 26 | if (E[i].empty()){ 27 | G[i].push_back(N + cnt); 28 | G[N + cnt].push_back(i); 29 | cnt++; 30 | G.push_back({}); 31 | } 32 | } 33 | G.pop_back(); 34 | } 35 | void dfs1(vector> &E, vector &next, vector &d, vector &imos, int v){ 36 | for (int w : E[v]){ 37 | if (d[w] == -1){ 38 | d[w] = d[v] + 1; 39 | next[v] = w; 40 | dfs1(E, next, d, imos, w); 41 | imos[v] += imos[w]; 42 | } else if (d[w] < d[v] - 1){ 43 | imos[v]++; 44 | imos[next[w]]--; 45 | } 46 | } 47 | } 48 | void dfs2(vector> &E, vector &d, vector &imos, vector &used, int b, int v){ 49 | used[v] = true; 50 | bool ok = false; 51 | for (int w : E[v]){ 52 | if (d[w] == d[v] + 1 && !used[w]){ 53 | if (imos[w] > 0){ 54 | if (!ok){ 55 | ok = true; 56 | G[v].push_back(N + b); 57 | G[N + b].push_back(v); 58 | } 59 | dfs2(E, d, imos, used, b, w); 60 | } else { 61 | G[v].push_back(N + cnt); 62 | G[N + cnt].push_back(v); 63 | cnt++; 64 | G.push_back({}); 65 | dfs2(E, d, imos, used, cnt - 1, w); 66 | } 67 | } 68 | } 69 | if (!ok && d[v] > 0){ 70 | G[v].push_back(N + b); 71 | G[N + b].push_back(v); 72 | } 73 | } 74 | int size(){ 75 | return G.size(); 76 | } 77 | vector &operator [](int v){ 78 | return G[v]; 79 | } 80 | }; -------------------------------------------------------------------------------- /graph/strongly_connected_components.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief 強連結成分分解 4 | */ 5 | struct strongly_connected_components{ 6 | vector scc; 7 | int cnt = 0; 8 | void dfs1(vector> &E, vector &t, vector &used, int v){ 9 | for (int w : E[v]){ 10 | if (!used[w]){ 11 | used[w] = true; 12 | dfs1(E, t, used, w); 13 | } 14 | } 15 | t.push_back(v); 16 | } 17 | void dfs2(vector> &E2, vector &used2, int v){ 18 | scc[v] = cnt; 19 | for (int w : E2[v]){ 20 | if (!used2[w]){ 21 | used2[w] = true; 22 | dfs2(E2, used2, w); 23 | } 24 | } 25 | } 26 | strongly_connected_components(vector> &E){ 27 | int N = E.size(); 28 | vector> E2(N); 29 | for (int i = 0; i < N; i++){ 30 | for (int j : E[i]){ 31 | E2[j].push_back(i); 32 | } 33 | } 34 | vector t; 35 | vector used(N, false); 36 | for (int i = 0; i < N; i++){ 37 | if (!used[i]){ 38 | used[i] = true; 39 | dfs1(E, t, used, i); 40 | } 41 | } 42 | reverse(t.begin(), t.end()); 43 | vector used2(N, false); 44 | scc = vector(N); 45 | for (int i = 0; i < N; i++){ 46 | if (!used2[t[i]]){ 47 | used2[t[i]] = true; 48 | dfs2(E2, used2, t[i]); 49 | cnt++; 50 | } 51 | } 52 | } 53 | int operator [](int k){ 54 | return scc[k]; 55 | } 56 | }; 57 | -------------------------------------------------------------------------------- /graph/two_edge_connected_components.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * @brief 二重辺連結成分分解 4 | */ 5 | struct two_edge_connected_components{ 6 | vector tcc; 7 | int cnt = 0; 8 | two_edge_connected_components(vector> &E){ 9 | int N = E.size(); 10 | vector p(N, -1); 11 | vector d(N, -1); 12 | vector imos(N, 0); 13 | for (int i = 0; i < N; i++){ 14 | if (p[i] == -1){ 15 | d[i] = 0; 16 | dfs1(E, p, d, imos, i); 17 | } 18 | } 19 | tcc = vector(N, -1); 20 | for (int i = 0; i < N; i++){ 21 | if (tcc[i] == -1){ 22 | tcc[i] = cnt; 23 | cnt++; 24 | dfs2(E, p, imos, i); 25 | } 26 | } 27 | } 28 | void dfs1(vector> &E, vector &p, vector &d, vector &imos, int v = 0){ 29 | bool pe = false; 30 | for (int w : E[v]){ 31 | if (w != p[v] || pe){ 32 | if (d[w] == -1){ 33 | p[w] = v; 34 | d[w] = d[v] + 1; 35 | dfs1(E, p, d, imos, w); 36 | imos[v] += imos[w]; 37 | } else if (d[w] < d[v]){ 38 | imos[v]++; 39 | imos[w]--; 40 | } 41 | } else { 42 | pe = true; 43 | } 44 | } 45 | } 46 | void dfs2(vector> &E, vector &p, vector &imos, int v = 0){ 47 | for (int w : E[v]){ 48 | if (tcc[w] == -1){ 49 | if (imos[w] > 0){ 50 | tcc[w] = tcc[v]; 51 | } else { 52 | tcc[w] = cnt; 53 | cnt++; 54 | } 55 | dfs2(E, p, imos, w); 56 | } 57 | } 58 | } 59 | int operator [](int v){ 60 | return tcc[v]; 61 | } 62 | }; -------------------------------------------------------------------------------- /old_Data_Structures/Bidirectional_Segment_Tree.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct bidirectional_segment_tree{ 3 | int N; 4 | vector> ST; 5 | function f; 6 | T E; 7 | bidirectional_segment_tree(vector A, function f, T E): f(f), E(E){ 8 | int n = A.size(); 9 | N = 1; 10 | while (N < n){ 11 | N *= 2; 12 | } 13 | ST = vector>(N * 2 - 1, array{E, E}); 14 | for (int i = 0; i < n; i++){ 15 | ST[N - 1 + i][0] = A[i]; 16 | ST[N - 1 + i][1] = A[i]; 17 | } 18 | for (int i = N - 2; i >= 0; i--){ 19 | ST[i][0] = f(ST[i * 2 + 1][0], ST[i * 2 + 2][0]); 20 | ST[i][1] = f(ST[i * 2 + 2][1], ST[i * 2 + 1][1]); 21 | } 22 | } 23 | T operator [](int k){ 24 | return ST[N - 1 + k][0]; 25 | } 26 | void update(int k, T x){ 27 | k += N - 1; 28 | ST[k][0] = x; 29 | ST[k][1] = x; 30 | while (k > 0){ 31 | k = (k - 1) / 2; 32 | ST[k][0] = f(ST[k * 2 + 1][0], ST[k * 2 + 2][0]); 33 | ST[k][1] = f(ST[k * 2 + 2][1], ST[k * 2 + 1][1]); 34 | } 35 | } 36 | T query(int L, int R, int i, int l, int r, int d){ 37 | if (R <= l || r <= L){ 38 | return E; 39 | } else if (L <= l && r <= R){ 40 | return ST[i][d]; 41 | } else { 42 | int m = (l + r) / 2; 43 | if (d == 0){ 44 | return f(query(L, R, i * 2 + 1, l, m, d), query(L, R, i * 2 + 2, m, r, d)); 45 | } else { 46 | return f(query(L, R, i * 2 + 2, m, r, d), query(L, R, i * 2 + 1, l, m, d)); 47 | } 48 | } 49 | } 50 | T query(int L, int R, int d){ 51 | return query(L, R, 0, 0, N, d); 52 | } 53 | }; 54 | -------------------------------------------------------------------------------- /old_Data_Structures/Euler_Tour_Path_Query.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct euler_tour_path_query{ 3 | lowest_common_ancestor G; 4 | vector A; 5 | vector left; 6 | vector right; 7 | T E; 8 | function f; 9 | function inv; 10 | bidirectional_segment_tree ST; 11 | void dfs(int v, vector> &c, vector &a){ 12 | left[v] = A.size(); 13 | A.push_back(a[v]); 14 | for (int w : c[v]){ 15 | dfs(w, c, a); 16 | } 17 | right[v] = A.size(); 18 | A.push_back(inv(a[v])); 19 | } 20 | euler_tour_path_query(vector &p, vector> &c, vector &a, function f, T E, function inv): f(f), E(E), inv(inv){ 21 | int N = p.size(); 22 | G = lowest_common_ancestor(p, c); 23 | left = vector(N); 24 | right = vector(N); 25 | dfs(0, c, a); 26 | ST = bidirectional_segment_tree(A, f, E); 27 | } 28 | operator [](int v){ 29 | return A[left[v]]; 30 | } 31 | void update(int v, T x){ 32 | ST.update(left[v], x); 33 | ST.update(right[v], inv(x)); 34 | } 35 | T query(int v, int w){ 36 | int u = G.lca(v, w); 37 | return f(ST.query(left[u] + 1, left[v] + 1, 1), ST.query(left[u], left[w] + 1, 0)); 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /old_Data_Structures/Euler_Tour_Path_Query_Commutative.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct euler_tour_path_query_commutative{ 3 | lowest_common_ancestor G; 4 | vector A; 5 | vector left; 6 | vector right; 7 | T E; 8 | function f; 9 | function inv; 10 | segment_tree ST; 11 | void dfs(int v, vector> &c, vector &a){ 12 | left[v] = A.size(); 13 | A.push_back(a[v]); 14 | for (int w : c[v]){ 15 | dfs(w, c, a); 16 | } 17 | right[v] = A.size(); 18 | A.push_back(inv(a[v])); 19 | } 20 | euler_tour_path_query_commutative(vector &p, vector> &c, vector &a, function f, T E, function inv): f(f), E(E), inv(inv){ 21 | int N = p.size(); 22 | G = lowest_common_ancestor(p, c); 23 | left = vector(N); 24 | right = vector(N); 25 | dfs(0, c, a); 26 | ST = segment_tree(A, f, E); 27 | } 28 | operator [](int v){ 29 | return A[left[v]]; 30 | } 31 | void update(int v, T x){ 32 | A[left[v]] = x; 33 | A[right[v]] = inv(x); 34 | ST.update(left[v], x); 35 | ST.update(right[v], inv(x)); 36 | } 37 | T query(int v, int w){ 38 | int u = G.lca(v, w); 39 | return f(f(ST.query(left[u], left[v] + 1), ST.query(left[u], left[w] + 1)), inv(A[left[u]])); 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /old_Data_Structures/Euler_Tour_Subtree_Query.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct euler_tour_subtree_query{ 3 | vector left; 4 | vector right; 5 | vector A; 6 | T E; 7 | function f; 8 | segment_tree ST; 9 | void dfs(int v, vector> &c, vector &a){ 10 | left[v] = A.size(); 11 | A.push_back(a[v]); 12 | for (int w : c[v]){ 13 | dfs(w, c, a); 14 | } 15 | right[v] = A.size(); 16 | } 17 | euler_tour_subtree_query(vector> &c, vector &a, function f, T E): f(f), E(E){ 18 | int N = c.size(); 19 | left = vector(N); 20 | right = vector(N); 21 | dfs(0, c, a); 22 | ST = segment_tree(A, f, E); 23 | } 24 | T operator [](int v){ 25 | return A[left[v]]; 26 | } 27 | void update(int v, T x){ 28 | A[left[v]] = x; 29 | ST.update(left[v], x); 30 | } 31 | T query(int v){ 32 | return ST.query(left[v], right[v]); 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /old_Data_Structures/Heavy_Light_Decomposition.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct heavy_light_decomposition{ 3 | lowest_common_ancestor LCA; 4 | vector p; 5 | vector sz, in, out, next; 6 | int t; 7 | bidirectional_segment_tree ST; 8 | function f; 9 | T E; 10 | void dfs1(vector> &c, int v = 0){ 11 | sz[v] = 1; 12 | for (int &w : c[v]){ 13 | dfs1(c, w); 14 | sz[v] += sz[w]; 15 | if (sz[w] > sz[c[v][0]]){ 16 | swap(w, c[v][0]); 17 | } 18 | } 19 | } 20 | void dfs2(vector> &c, int v = 0){ 21 | in[v] = t; 22 | t++; 23 | for (int w : c[v]){ 24 | if (w == c[v][0]){ 25 | next[w] = next[v]; 26 | } else { 27 | next[w] = w; 28 | } 29 | dfs2(c, w); 30 | } 31 | out[v] = t; 32 | } 33 | heavy_light_decomposition(vector &p, vector> &c, vector &A, function f, T E): p(p), f(f), E(E){ 34 | LCA = lowest_common_ancestor(p, c); 35 | int N = p.size(); 36 | in = vector(N, -1); 37 | out = vector(N, -1); 38 | sz = vector(N, -1); 39 | next = vector(N, 0); 40 | t = 0; 41 | dfs1(c); 42 | dfs2(c); 43 | vector tmp(N); 44 | for (int i = 0; i < N; i++){ 45 | tmp[in[i]] = A[i]; 46 | } 47 | ST = bidirectional_segment_tree(tmp, f, E); 48 | } 49 | void update(int v, T x){ 50 | ST.update(in[v], x); 51 | } 52 | T query(int u, int v){ 53 | int w = LCA.lca(u, v); 54 | T tmp1 = E; 55 | while (next[u] != next[w]){ 56 | tmp1 = f(tmp1, ST.query(in[next[u]], in[u] + 1, 1)); 57 | u = p[next[u]]; 58 | } 59 | tmp1 = f(tmp1, ST.query(in[w], in[u] + 1, 1)); 60 | T tmp2 = E; 61 | while (next[v] != next[w]){ 62 | tmp2 = f(ST.query(in[next[v]], in[v] + 1, 0), tmp2); 63 | v = p[next[v]]; 64 | } 65 | tmp2 = f(ST.query(in[w] + 1, in[v] + 1, 0), tmp2); 66 | return f(tmp1, tmp2); 67 | } 68 | }; 69 | -------------------------------------------------------------------------------- /old_Data_Structures/Heavy_Light_Decomposition_Commutative.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct heavy_light_decomposition{ 3 | lowest_common_ancestor LCA; 4 | vector p; 5 | vector sz, in, out, next; 6 | int t; 7 | segment_tree ST; 8 | function f; 9 | T E; 10 | void dfs1(vector> &c, int v = 0){ 11 | sz[v] = 1; 12 | for (int &w : c[v]){ 13 | dfs1(c, w); 14 | sz[v] += sz[w]; 15 | if (sz[w] > sz[c[v][0]]){ 16 | swap(w, c[v][0]); 17 | } 18 | } 19 | } 20 | void dfs2(vector> &c, int v = 0){ 21 | in[v] = t; 22 | t++; 23 | for (int w : c[v]){ 24 | if (w == c[v][0]){ 25 | next[w] = next[v]; 26 | } else { 27 | next[w] = w; 28 | } 29 | dfs2(c, w); 30 | } 31 | out[v] = t; 32 | } 33 | heavy_light_decomposition(vector &p, vector> &c, vector &A, function f, T E): p(p), f(f), E(E){ 34 | LCA = lowest_common_ancestor(p, c); 35 | int N = p.size(); 36 | in = vector(N, -1); 37 | out = vector(N, -1); 38 | sz = vector(N, -1); 39 | next = vector(N, 0); 40 | t = 0; 41 | dfs1(c); 42 | dfs2(c); 43 | vector tmp(N); 44 | for (int i = 0; i < N; i++){ 45 | tmp[in[i]] = A[i]; 46 | } 47 | ST = segment_tree(tmp, f, E); 48 | } 49 | void update(int v, T x){ 50 | ST.update(in[v], x); 51 | } 52 | T path_query(int u, int v){ 53 | int w = LCA.lca(u, v); 54 | T ans = E; 55 | while (next[u] != next[w]){ 56 | ans = f(ans, ST.query(in[next[u]], in[u] + 1)); 57 | u = p[next[u]]; 58 | } 59 | ans = f(ans, ST.query(in[w], in[u] + 1)); 60 | while (next[v] != next[w]){ 61 | ans = f(ans, ST.query(in[next[v]], in[v] + 1)); 62 | v = p[next[v]]; 63 | } 64 | ans = f(ans, ST.query(in[w] + 1, in[v] + 1)); 65 | return ans; 66 | } 67 | T subtree_query(int v){ 68 | return ST.query(in[v], out[v]); 69 | } 70 | }; 71 | -------------------------------------------------------------------------------- /old_Data_Structures/Inversion_Number.cpp: -------------------------------------------------------------------------------- 1 | long long inversion_number(vector &p){ 2 | int N = p.size(); 3 | long long ans = 0; 4 | vector bit(N + 1, 0); 5 | for (int i = 0; i < N; i++){ 6 | ans += i; 7 | int j = p[i]; 8 | while (j > 0){ 9 | ans -= bit[j]; 10 | j -= j & -j; 11 | } 12 | j = p[i]; 13 | while (j <= N){ 14 | bit[j]++; 15 | j += j & -j; 16 | } 17 | } 18 | return ans; 19 | } 20 | long long inversion_number(vector &A){ 21 | int N = A.size(); 22 | vector B = A; 23 | sort(B.begin(), B.end()); 24 | map mp; 25 | for (int i = 0; i < N; i++){ 26 | mp[B[i]] = i + 1; 27 | } 28 | for (int i = 0; i < N; i++){ 29 | A[i] = mp[A[i]]; 30 | } 31 | long long ans = 0; 32 | vector BIT(N + 1, 0); 33 | for (int i = 0; i < N; i++){ 34 | ans += i; 35 | int j = A[i]; 36 | while (j > 0){ 37 | ans -= BIT[j]; 38 | j -= j & -j; 39 | } 40 | j = A[i]; 41 | while (j <= N){ 42 | BIT[j]++; 43 | j += j & -j; 44 | } 45 | } 46 | return ans; 47 | } 48 | -------------------------------------------------------------------------------- /old_Data_Structures/Segment_Tree_Beats.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct segment_tree_beats{ 3 | int N; 4 | vector max1, max2, min1, min2; 5 | vector add, sum; 6 | vector maxc, minc, len; 7 | void update_max(int i, T x){ 8 | sum[i] += (x - max1[i]) * maxc[i]; 9 | if (max1[i] == min1[i]){ 10 | min1[i] = x; 11 | } else if (max1[i] == min2[i]){ 12 | min2[i] = x; 13 | } 14 | max1[i] = x; 15 | } 16 | void update_min(int i, T x){ 17 | sum[i] += (x - min1[i]) * minc[i]; 18 | if (min1[i] == max1[i]){ 19 | max1[i] = x; 20 | } else if (min1[i] == max2[i]){ 21 | max2[i] = x; 22 | } 23 | min1[i] = x; 24 | } 25 | void update_add(int i, T x){ 26 | max1[i] += x; 27 | if (max2[i] != -INF){ 28 | max2[i] += x; 29 | } 30 | min1[i] += x; 31 | if (min2[i] != INF){ 32 | min2[i] += x; 33 | } 34 | sum[i] += x * len[i]; 35 | add[i] += x; 36 | } 37 | void push(int i){ 38 | if (i >= N - 1){ 39 | return; 40 | } 41 | int l = i * 2 + 1; 42 | int r = i * 2 + 2; 43 | if (add[i] != 0){ 44 | update_add(l, add[i]); 45 | update_add(r, add[i]); 46 | add[i] = 0; 47 | } 48 | if (max1[i] < max1[l]){ 49 | update_max(l, max1[i]); 50 | } 51 | if (min1[i] > min1[l]){ 52 | update_min(l, min1[i]); 53 | } 54 | if (max1[i] < max1[r]){ 55 | update_max(r, max1[i]); 56 | } 57 | if (min1[i] > min1[r]){ 58 | update_min(r, min1[i]); 59 | } 60 | } 61 | void update(int i){ 62 | int l = i * 2 + 1; 63 | int r = i * 2 + 2; 64 | sum[i] = sum[l] + sum[r]; 65 | if (max1[l] > max1[r]){ 66 | max1[i] = max1[l]; 67 | max2[i] = max(max2[l], max1[r]); 68 | maxc[i] = maxc[l]; 69 | } else if (max1[l] < max1[r]){ 70 | max1[i] = max1[r]; 71 | max2[i] = max(max1[l], max2[r]); 72 | maxc[i] = maxc[r]; 73 | } else { 74 | max1[i] = max1[l]; 75 | max2[i] = max(max2[l], max2[r]); 76 | maxc[i] = maxc[l] + maxc[r]; 77 | } 78 | if (min1[l] < min1[r]){ 79 | min1[i] = min1[l]; 80 | min2[i] = min(min2[l], min1[r]); 81 | minc[i] = minc[l]; 82 | } else if (min1[l] > min1[r]){ 83 | min1[i] = min1[r]; 84 | min2[i] = min(min1[l], min2[r]); 85 | minc[i] = minc[r]; 86 | } else { 87 | min1[i] = min1[l]; 88 | min2[i] = min(min2[l], min2[r]); 89 | minc[i] = minc[l] + minc[r]; 90 | } 91 | } 92 | segment_tree_beats(vector A){ 93 | int n = A.size(); 94 | N = 1; 95 | while (N < n){ 96 | N *= 2; 97 | } 98 | max1 = vector(N * 2 - 1, -INF); 99 | max2 = vector(N * 2 - 1, -INF); 100 | min1 = vector(N * 2 - 1, INF); 101 | min2 = vector(N * 2 - 1, INF); 102 | add = vector(N * 2 - 1, 0); 103 | sum = vector(N * 2 - 1, 0); 104 | maxc = vector(N * 2 - 1, 0); 105 | minc = vector(N * 2 - 1, 0); 106 | len = vector(N * 2 - 1, 1); 107 | for (int i = 0; i < n; i++){ 108 | max1[N - 1 + i] = A[i]; 109 | min1[N - 1 + i] = A[i]; 110 | sum[N - 1 + i] = A[i]; 111 | maxc[N - 1 + i] = 1; 112 | minc[N - 1 + i] = 1; 113 | } 114 | for (int i = N - 2; i >= 0; i--){ 115 | len[i] = len[i * 2 + 1] + len[i * 2 + 2]; 116 | update(i); 117 | } 118 | } 119 | void range_chmin(int L, int R, T x, int i, int l, int r){ 120 | if (r <= L || R <= l || x >= max1[i]){ 121 | return; 122 | } else if (L <= l && r <= R && x > max2[i]){ 123 | update_max(i, x); 124 | return; 125 | } 126 | push(i); 127 | int m = (l + r) / 2; 128 | range_chmin(L, R, x, i * 2 + 1, l, m); 129 | range_chmin(L, R, x, i * 2 + 2, m, r); 130 | update(i); 131 | } 132 | void range_chmin(int L, int R, T x){ 133 | range_chmin(L, R, x, 0, 0, N); 134 | } 135 | void range_chmax(int L, int R, T x, int i, int l, int r){ 136 | if (r <= L || R <= l || x <= min1[i]){ 137 | return; 138 | } else if (L <= l && r <= R && x < min2[i]){ 139 | update_min(i, x); 140 | return; 141 | } 142 | push(i); 143 | int m = (l + r) / 2; 144 | range_chmax(L, R, x, i * 2 + 1, l, m); 145 | range_chmax(L, R, x, i * 2 + 2, m, r); 146 | update(i); 147 | } 148 | void range_chmax(int L, int R, T x){ 149 | range_chmax(L, R, x, 0, 0, N); 150 | } 151 | void range_add(int L, int R, T x, int i, int l, int r){ 152 | if (r <= L || R <= l){ 153 | return; 154 | } else if (L <= l && r <= R){ 155 | update_add(i, x); 156 | return; 157 | } 158 | push(i); 159 | int m = (l + r) / 2; 160 | range_add(L, R, x, i * 2 + 1, l, m); 161 | range_add(L, R, x, i * 2 + 2, m, r); 162 | update(i); 163 | } 164 | void range_add(int L, int R, T x){ 165 | range_add(L, R, x, 0, 0, N); 166 | } 167 | T range_sum(int L, int R, int i, int l, int r){ 168 | if (r <= L || R <= l){ 169 | return 0; 170 | } else if (L <= l && r <= R){ 171 | return sum[i]; 172 | } 173 | push(i); 174 | int m = (l + r) / 2; 175 | return range_sum(L, R, i * 2 + 1, l, m) + range_sum(L, R, i * 2 + 2, m, r); 176 | } 177 | T range_sum(int L, int R){ 178 | return range_sum(L, R, 0, 0, N); 179 | } 180 | }; 181 | -------------------------------------------------------------------------------- /old_Data_Structures/Treap.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct treap{ 3 | int N; 4 | T E; 5 | function f; 6 | vector node; 7 | vector prod; 8 | vector priority; 9 | vector parent; 10 | vector left, right; 11 | vector size; 12 | int root; 13 | treap(T E, function f): E(E), f(f){ 14 | N = 0; 15 | root = 0; 16 | } 17 | void eval(int v){ 18 | size[v] = 1; 19 | if (left[v] != -1){ 20 | size[v] += size[left[v]]; 21 | } 22 | if (right[v] != -1){ 23 | size[v] += size[right[v]]; 24 | } 25 | prod[v] = node[v]; 26 | if (left[v] != -1){ 27 | prod[v] = f(prod[left[v]], prod[v]); 28 | } 29 | if (right[v] != -1){ 30 | prod[v] = f(prod[v], prod[right[v]]); 31 | } 32 | } 33 | int right_rotate(int v){ 34 | int w = left[v]; 35 | left[v] = right[w]; 36 | parent[w] = parent[v]; 37 | if (right[w] != -1){ 38 | parent[right[w]] = v; 39 | } 40 | right[w] = v; 41 | if (parent[w] != -1){ 42 | if (left[parent[w]] == v){ 43 | left[parent[w]] = w; 44 | } else { 45 | right[parent[w]] = w; 46 | } 47 | } 48 | parent[v] = w; 49 | if (root == v){ 50 | root = w; 51 | } 52 | eval(v); 53 | return w; 54 | } 55 | int left_rotate(int v){ 56 | int w = right[v]; 57 | right[v] = left[w]; 58 | parent[w] = parent[v]; 59 | if (left[w] != -1){ 60 | parent[left[w]] = v; 61 | } 62 | left[w] = v; 63 | if (parent[w] != -1){ 64 | if (left[parent[w]] == v){ 65 | left[parent[w]] = w; 66 | } else { 67 | right[parent[w]] = w; 68 | } 69 | } 70 | parent[v] = w; 71 | if (root == v){ 72 | root = w; 73 | } 74 | eval(v); 75 | return w; 76 | } 77 | int get_id(int k){ 78 | int v = root; 79 | while (true){ 80 | int lsz = 0; 81 | if (left[v] != -1){ 82 | lsz = size[left[v]]; 83 | } 84 | if (k < lsz){ 85 | v = left[v]; 86 | } else if (k == lsz){ 87 | return v; 88 | } else { 89 | k -= lsz + 1; 90 | v = right[v]; 91 | } 92 | } 93 | } 94 | T operator [](int k){ 95 | return node[get_id(k)]; 96 | } 97 | void insert(int pos, T x, int pri){ 98 | int v = -1; 99 | if (N > 0){ 100 | v = root; 101 | while (true){ 102 | int lsz = 0; 103 | if (left[v] != -1){ 104 | lsz = size[left[v]]; 105 | } 106 | if (pos <= lsz){ 107 | if (left[v] == -1){ 108 | left[v] = N; 109 | break; 110 | } else { 111 | v = left[v]; 112 | } 113 | } else { 114 | pos -= lsz + 1; 115 | if (right[v] == -1){ 116 | right[v] = N; 117 | break; 118 | } else { 119 | v = right[v]; 120 | } 121 | } 122 | } 123 | } 124 | node.push_back(x); 125 | prod.push_back(x); 126 | priority.push_back(pri); 127 | parent.push_back(v); 128 | left.push_back(-1); 129 | right.push_back(-1); 130 | size.push_back(1); 131 | N++; 132 | if (N == 1){ 133 | root = 0; 134 | } 135 | v = N - 1; 136 | while (parent[v] != -1){ 137 | if (priority[parent[v]] < priority[v]){ 138 | if (left[parent[v]] == v){ 139 | v = right_rotate(parent[v]); 140 | } else { 141 | v = left_rotate(parent[v]); 142 | } 143 | } else { 144 | break; 145 | } 146 | } 147 | while (parent[v] != -1){ 148 | eval(v); 149 | v = parent[v]; 150 | } 151 | eval(v); 152 | } 153 | void erase(int k){ 154 | int v = get_id(k); 155 | while (left[v] != -1 || right[v] != -1){ 156 | if (left[v] != -1 && right[v] != -1){ 157 | if (priority[left[v]] > priority[right[v]]){ 158 | v = right[right_rotate(v)]; 159 | } else { 160 | v = left[left_rotate(v)]; 161 | } 162 | } else if (left[v] != -1){ 163 | v = right[right_rotate(v)]; 164 | } else { 165 | v = left[left_rotate(v)]; 166 | } 167 | } 168 | int w = v; 169 | size[w] = 0; 170 | prod[w] = E; 171 | while (parent[w] != -1){ 172 | w = parent[w]; 173 | eval(w); 174 | } 175 | if (parent[v] != -1){ 176 | if (left[parent[v]] == v){ 177 | left[parent[v]] = -1; 178 | } else { 179 | right[parent[v]] = -1; 180 | } 181 | } 182 | if (v != N - 1){ 183 | if (parent[N - 1] != -1){ 184 | if (left[parent[N - 1]] == N - 1){ 185 | left[parent[N - 1]] = v; 186 | } else { 187 | right[parent[N - 1]] = v; 188 | } 189 | } 190 | if (left[N - 1] != -1){ 191 | parent[left[N - 1]] = v; 192 | } 193 | if (right[N - 1] != -1){ 194 | parent[right[N - 1]] = v; 195 | } 196 | node[v] = node[N - 1]; 197 | prod[v] = prod[N - 1]; 198 | priority[v] = priority[N - 1]; 199 | parent[v] = parent[N - 1]; 200 | left[v] = left[N - 1]; 201 | right[v] = right[N - 1]; 202 | size[v] = size[N - 1]; 203 | if (root == N - 1){ 204 | root = v; 205 | } 206 | } 207 | node.pop_back(); 208 | prod.pop_back(); 209 | priority.pop_back(); 210 | parent.pop_back(); 211 | left.pop_back(); 212 | right.pop_back(); 213 | size.pop_back(); 214 | N--; 215 | } 216 | void update(int k, T x){ 217 | int v = get_id(k); 218 | node[v] = x; 219 | while (parent[v] != -1){ 220 | eval(v); 221 | v = parent[v]; 222 | } 223 | eval(v); 224 | } 225 | T range_fold(int L, int R, int i, int l, int r){ 226 | if (r <= L || R <= l){ 227 | return E; 228 | } else if (L <= l && r <= R){ 229 | return prod[i]; 230 | } else { 231 | int lsz = 0; 232 | if (left[i] != -1){ 233 | lsz = size[left[i]]; 234 | } 235 | T ans = E; 236 | if (L <= l + lsz && l + lsz < R){ 237 | ans = node[i]; 238 | } 239 | if (left[i] != -1){ 240 | ans = f(range_fold(L, R, left[i], l, l + lsz), ans); 241 | } 242 | if (right[i] != -1){ 243 | ans = f(ans, range_fold(L, R, right[i], l + lsz + 1, r)); 244 | } 245 | return ans; 246 | } 247 | } 248 | T range_fold(int L, int R){ 249 | return range_fold(L, R, root, 0, N); 250 | } 251 | }; 252 | -------------------------------------------------------------------------------- /old_Data_Structures/Trie.cpp: -------------------------------------------------------------------------------- 1 | struct trie{ 2 | int N; 3 | vector, char, bool>> T; 4 | trie(){ 5 | T = vector, char, bool>>(1); 6 | T[0] = make_tuple(vector(), ' ', false); 7 | } 8 | void insert(string s){ 9 | int v = 0; 10 | for (char c : s){ 11 | bool flg = false; 12 | for (int i : get<0>(T[v])){ 13 | if (get<1>(T[i]) == c){ 14 | v = i; 15 | flg = true; 16 | break; 17 | } 18 | } 19 | if (!flg){ 20 | get<0>(T[v]).push_back(T.size()); 21 | v = T.size(); 22 | T.push_back(make_tuple(vector(), c, false)); 23 | } 24 | } 25 | get<2>(T[v]) = true; 26 | } 27 | vector query(string s){ 28 | int M = s.size(); 29 | int v = 0; 30 | vector ans(M, false); 31 | for (int i = 0; i < M; i++){ 32 | bool flg = falsr; 33 | for (int j : get<0>(T[v])){ 34 | if (get<1>(T[j]) == s[i]){ 35 | v = j; 36 | flg = true; 37 | break; 38 | } 39 | } 40 | if (flg){ 41 | ans[i] = get<2>(T[v]); 42 | } else { 43 | break; 44 | } 45 | } 46 | return ans; 47 | } 48 | }; 49 | -------------------------------------------------------------------------------- /old_Dynamic_Programming/Count_Subsequences.cpp: -------------------------------------------------------------------------------- 1 | long long count_subsequences(string &S){ 2 | int N = S.size(); 3 | vector> next(N + 1, vector(26, N)); 4 | for (int i = N - 1; i >= 0; i--){ 5 | for (int j = 0; j < 26; j++){ 6 | next[i][j] = next[i + 1][j]; 7 | } 8 | next[i][S[i] - 'a'] = i; 9 | } 10 | vector dp(N + 1, 0); 11 | dp[0] = 1; 12 | for (int i = 0; i < N; i++){ 13 | for (int j = 0; j < 26; j++){ 14 | if (next[i][j] < N){ 15 | dp[next[i][j] + 1] = (dp[next[i][j] + 1] + dp[i]) % MOD; 16 | } 17 | } 18 | } 19 | long long ans = 0; 20 | for (int i = 0; i <= N; i++){ 21 | ans = (ans + dp[i]) % MOD; 22 | } 23 | return ans; 24 | } 25 | -------------------------------------------------------------------------------- /old_Dynamic_Programming/Longest_Common_Subsequence.cpp: -------------------------------------------------------------------------------- 1 | int longest_common_subsequence_length(string &S, string &T){ 2 | vector> dp(S.size() + 1, vector(T.size() + 1, 0)); 3 | for (int i = 0; i < S.size(); i++){ 4 | for (int j = 0; j < T.size(); j++){ 5 | if (S[i] == T[j]){ 6 | dp[i + 1][j + 1] = dp[i][j] + 1; 7 | } else { 8 | dp[i + 1][j + 1] = max(dp[i + 1][j], dp[i][j + 1]); 9 | } 10 | } 11 | } 12 | return dp[S.size()][T.size()]; 13 | } 14 | string longest_common_subsequence(string &S, string &T){ 15 | vector> dp(S.size() + 1, vector(T.size() + 1, 0)); 16 | for (int i = 0; i < S.size(); i++){ 17 | for (int j = 0; j < T.size(); j++){ 18 | if (S[i] == T[j]){ 19 | dp[i + 1][j + 1] = dp[i][j] + 1; 20 | } else { 21 | dp[i + 1][j + 1] = max(dp[i + 1][j], dp[i][j + 1]); 22 | } 23 | } 24 | } 25 | string ans; 26 | int i = S.size(); 27 | int j = T.size(); 28 | while (dp[i][j] > 0){ 29 | if (dp[i - 1][j] == dp[i][j]){ 30 | i--; 31 | } else if (dp[i][j - 1] == dp[i][j]){ 32 | j--; 33 | } else { 34 | i--; 35 | j--; 36 | ans.push_back(S[i]); 37 | } 38 | } 39 | reverse(ans.begin(), ans.end()); 40 | return ans; 41 | } 42 | int longest_common_subsequence_length(vector &A, vector &B){ 43 | vector> dp(A.size() + 1, vector(B.size() + 1, 0)); 44 | for (int i = 0; i < A.size(); i++){ 45 | for (int j = 0; j < B.size(); j++){ 46 | if (A[i] == B[j]){ 47 | dp[i + 1][j + 1] = dp[i][j] + 1; 48 | } else { 49 | dp[i + 1][j + 1] = max(dp[i + 1][j], dp[i][j + 1]); 50 | } 51 | } 52 | } 53 | return dp[A.size()][B.size()]; 54 | } 55 | vector longest_common_subsequence(vector &A, vector &B){ 56 | vector> dp(A.size() + 1, vector(B.size() + 1, 0)); 57 | for (int i = 0; i < A.size(); i++){ 58 | for (int j = 0; j < B.size(); j++){ 59 | if (A[i] == B[j]){ 60 | dp[i + 1][j + 1] = dp[i][j] + 1; 61 | } else { 62 | dp[i + 1][j + 1] = max(dp[i + 1][j], dp[i][j + 1]); 63 | } 64 | } 65 | } 66 | vector ans; 67 | int i = A.size(); 68 | int j = B.size(); 69 | while (dp[i][j] > 0){ 70 | if (dp[i - 1][j] == dp[i][j]){ 71 | i--; 72 | } else if (dp[i][j - 1] == dp[i][j]){ 73 | j--; 74 | } else { 75 | i--; 76 | j--; 77 | ans.push_back(A[i]); 78 | } 79 | } 80 | reverse(ans.begin(), ans.end()); 81 | return ans; 82 | } 83 | -------------------------------------------------------------------------------- /old_Dynamic_Programming/Longest_Increasing_Subsequence.cpp: -------------------------------------------------------------------------------- 1 | int longest_increasing_subsequence_length(vector &A){ 2 | int N = A.size(); 3 | vector dp(N, INF); 4 | for (int i = 0; i < N; i++){ 5 | *lower_bound(dp.begin(), dp.end(), A[i]) = A[i]; 6 | } 7 | return lower_bound(dp.begin(), dp.end(), INF) - dp.begin(); 8 | } 9 | -------------------------------------------------------------------------------- /old_Dynamic_Programming/Matrix_Chain_Multiplication.cpp: -------------------------------------------------------------------------------- 1 | long long matrix_chain_multiplication(vector &A){ 2 | int n = A.size() - 1; 3 | vector> dp(n, vector(n, INF)); 4 | for (int i = 0; i < n; i++){ 5 | dp[i][i] = 0; 6 | } 7 | for (int i = 1; i < n; i++){ 8 | for (int j = 0; j < n - i; j++){ 9 | for (int k = j; k < j + i; k++){ 10 | dp[j][j + i] = min(dp[j][j + i], dp[j][k] + dp[k + 1][j + i] + A[j] * A[k + 1] * A[j + i + 1]); 11 | } 12 | } 13 | } 14 | return dp[0][n - 1]; 15 | } 16 | -------------------------------------------------------------------------------- /old_Geometry/Circle.cpp: -------------------------------------------------------------------------------- 1 | struct circle{ 2 | point C; 3 | double r; 4 | circle(){ 5 | } 6 | circle(point C, double r): C(C), r(r){ 7 | } 8 | }; 9 | pair line_circle_intersection(line L, circle C){ 10 | point P = projection(C.C, L); 11 | double d = point_line_distance(C.C, L); 12 | double h = sqrt(C.r * C.r - d * d); 13 | point A = P + vec(L) / abs(vec(L)) * h; 14 | point B = P - vec(L) / abs(vec(L)) * h; 15 | return make_pair(A, B); 16 | } 17 | pair circle_intersection(circle C1, circle C2){ 18 | double d = dist(C1.C, C2.C); 19 | double m = (C1.r * C1.r - C2.r * C2.r + d * d) / (d * 2); 20 | point M = C1.C + (C2.C - C1.C) / d * m; 21 | double h = sqrt(C1.r * C1.r - m * m); 22 | point H = rotate90(C2.C - C1.C) / d * h; 23 | return make_pair(M - H, M + H); 24 | } 25 | pair circle_tangent(point P, circle C){ 26 | double d = dist(P, C.C); 27 | double r = sqrt(d * d - C.r * C.r); 28 | return circle_intersection(C, circle(P, r)); 29 | } 30 | vector common_tangent(circle C1, circle C2){ 31 | if (C1.r < C2.r){ 32 | swap(C1, C2); 33 | } 34 | double d = dist(C1.C, C2.C); 35 | vector L; 36 | if (C1.r - C2.r <= d + eps){ 37 | if (C1.r - C2.r <= eps){ 38 | point D = rotate90(C2.C - C1.C) / d * C1.r; 39 | L.push_back(line(C1.C + D, C2.C + D)); 40 | L.push_back(line(C1.C - D, C2.C - D)); 41 | } else { 42 | double m = (C1.r - C2.r) * (C1.r - C2.r) / d; 43 | point M = C1.C + (C2.C - C1.C) / d * m; 44 | double h = sqrt((C1.r - C2.r) * (C1.r - C2.r) - m * m); 45 | point H1 = M + rotate90(C2.C - C1.C) / d * h; 46 | point D1 = (H1 - C1.C) / dist(H1, C1.C) * C2.r; 47 | L.push_back(line(H1 + D1, C2.C + D1)); 48 | point H2 = M - rotate90(C2.C - C1.C) / d * h; 49 | point D2 = (H2 - C1.C) / dist(H2, C1.C) * C2.r; 50 | L.push_back(line(H2 + D2, C2.C + D2)); 51 | } 52 | } 53 | if (C1.r + C2.r <= d + eps){ 54 | double m = (C1.r + C2.r) * (C1.r + C2.r) / d; 55 | point M = C1.C + (C2.C - C1.C) / d * m; 56 | double h = sqrt((C1.r + C2.r) * (C1.r + C2.r) - m * m); 57 | point H1 = M + rotate90(C2.C - C1.C) / d * h; 58 | point D1 = (H1 - C1.C) / dist(H1, C1.C) * C2.r; 59 | L.push_back(line(H1 - D1, C2.C - D1)); 60 | point H2 = M - rotate90(C2.C - C1.C) / d * h; 61 | point D2 = (H2 - C1.C) / dist(H2, C1.C) * C2.r; 62 | L.push_back(line(H2 - D2, C2.C - D2)); 63 | } 64 | return L; 65 | } 66 | -------------------------------------------------------------------------------- /old_Geometry/Line.cpp: -------------------------------------------------------------------------------- 1 | struct line{ 2 | point A, B; 3 | line(){ 4 | } 5 | line(point A, point B): A(A), B(B){ 6 | } 7 | }; 8 | point vec(line L){ 9 | return L.B - L.A; 10 | } 11 | bool point_on_segment(point P, line L){ 12 | return dot(P - L.A, vec(L)) > -eps && dot(P - L.B, vec(L)) < eps; 13 | } 14 | point projection(point P, line L){ 15 | return L.A + vec(L) / abs(vec(L)) * dot(P - L.A, vec(L)) / abs(vec(L)); 16 | } 17 | point reflection(point P, line L){ 18 | return projection(P, L) * 2 - P; 19 | } 20 | double point_line_distance(point P, line L){ 21 | return abs(cross(P - L.A, vec(L))) / abs(vec(L)); 22 | } 23 | double point_segment_distance(point P, line L){ 24 | if (dot(P - L.A, vec(L)) < 0){ 25 | return dist(P, L.A); 26 | } else if (dot(P - L.B, vec(L)) > 0){ 27 | return dist(P, L.B); 28 | } else { 29 | return point_line_distance(P, L); 30 | } 31 | } 32 | bool is_parallel(line L1, line L2){ 33 | return abs(cross(vec(L1), vec(L2))) < eps; 34 | } 35 | point line_intersection(line L1, line L2){ 36 | return L1.A + vec(L1) * cross(L2.A - L1.A, vec(L2)) / cross(vec(L1), vec(L2)); 37 | } 38 | bool segment_intersect(line L1, line L2){ 39 | return cross(L1.A - L2.A, vec(L2)) * cross(L1.B - L2.A, vec(L2)) < eps && cross(L2.A - L1.A, vec(L1)) * cross(L2.B - L1.A, vec(L1)) < eps; 40 | } 41 | double segment_distance(line L1, line L2){ 42 | if (segment_intersect(L1, L2)){ 43 | return 0; 44 | } else { 45 | double ans = INF; 46 | ans = min(ans, point_segment_distance(L1.A, L2)); 47 | ans = min(ans, point_segment_distance(L1.B, L2)); 48 | ans = min(ans, point_segment_distance(L2.A, L1)); 49 | ans = min(ans, point_segment_distance(L2.B, L1)); 50 | return ans; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /old_Geometry/Point.cpp: -------------------------------------------------------------------------------- 1 | struct point{ 2 | double x, y; 3 | point(){ 4 | } 5 | point(double x, double y): x(x), y(y){ 6 | } 7 | point operator +(point P){ 8 | return point(x + P.x, y + P.y); 9 | } 10 | point operator -(point P){ 11 | return point(x - P.x, y - P.y); 12 | } 13 | point operator *(double k){ 14 | return point(x * k, y * k); 15 | } 16 | point operator /(double k){ 17 | return point(x / k, y / k); 18 | } 19 | }; 20 | point rotate90(point P){ 21 | return point(-P.y, P.x); 22 | } 23 | point rotate(point P, double t){ 24 | return point(P.x * cos(t) - P.y * sin(t), P.x * sin(t) + P.y * cos(t)); 25 | } 26 | double abs(point P){ 27 | return sqrt(P.x * P.x + P.y * P.y); 28 | } 29 | double dist(point P, point Q){ 30 | return abs(Q - P); 31 | } 32 | double dot(point P, point Q){ 33 | return P.x * Q.x + P.y * Q.y; 34 | } 35 | double cross(point P, point Q){ 36 | return P.x * Q.y - P.y * Q.x; 37 | } 38 | -------------------------------------------------------------------------------- /old_Graph/All_Pairs_Shortest_Path_(Warshall_Floyd).cpp: -------------------------------------------------------------------------------- 1 | vector> warshall_floyd(vector>> &E){ 2 | int V = E.size(); 3 | vector> d(V, vector(V, INF)); 4 | for (int i = 0; i < V; i++){ 5 | d[i][i] = 0; 6 | } 7 | for (int i = 0; i < V; i++){ 8 | for (int j = 0; j < E[i].size(); j++){ 9 | d[i][E[i][j].second] = E[i][j].first; 10 | } 11 | } 12 | for (int k = 0; k < V; k++){ 13 | for (int i = 0; i < V; i++){ 14 | for (int j = 0; j < V; j++){ 15 | if (d[i][k] != INF && d[k][j] != INF){ 16 | d[i][j] = min(d[i][j], d[i][k] + d[k][j]); 17 | } 18 | } 19 | } 20 | } 21 | return d; 22 | } 23 | -------------------------------------------------------------------------------- /old_Graph/Bipartite_Matching.cpp: -------------------------------------------------------------------------------- 1 | int bipartite_matching(vector> &E, int X, int Y){ 2 | int V = X + Y + 2; 3 | vector> E2(V); 4 | for (int i = 0; i < X; i++){ 5 | E2[0].insert(i + 1); 6 | } 7 | for (int i = 0; i < E.size(); i++){ 8 | int v = E[i].first; 9 | int w = E[i].second; 10 | E2[v + 1].insert(X + 1 + w); 11 | } 12 | for (int i = X + 1; i < V - 1; i++){ 13 | E2[i].insert(V - 1); 14 | } 15 | int F = 0; 16 | while (1){ 17 | vector used(V, false); 18 | vector prev(V, -1); 19 | used[0] = true; 20 | queue Q; 21 | Q.push(0); 22 | while (!Q.empty()){ 23 | int v = Q.front(); 24 | Q.pop(); 25 | for (int w : E2[v]){ 26 | if (!used[w]){ 27 | used[w] = true; 28 | prev[w] = v; 29 | Q.push(w); 30 | } 31 | } 32 | } 33 | if (!used[V - 1]){ 34 | break; 35 | } 36 | int c = V - 1; 37 | while (c != 0){ 38 | E2[prev[c]].erase(c); 39 | E2[c].insert(prev[c]); 40 | c = prev[c]; 41 | } 42 | F++; 43 | } 44 | return F; 45 | } 46 | -------------------------------------------------------------------------------- /old_Graph/Convert_to_Rooted_Tree.cpp: -------------------------------------------------------------------------------- 1 | vector parent(vector> &E, int r){ 2 | int N = E.size(); 3 | vector p(N, -1); 4 | queue Q; 5 | Q.push(r); 6 | while (!Q.empty()){ 7 | int v = Q.front(); 8 | Q.pop(); 9 | for (int w : E[v]){ 10 | if (p[w] == -1){ 11 | p[w] = v; 12 | Q.push(w); 13 | } 14 | } 15 | } 16 | return p; 17 | } 18 | vector> child(vector> E, int r){ 19 | int N = E.size(); 20 | vector> c(N); 21 | queue Q; 22 | Q.push(r); 23 | while (!Q.empty()){ 24 | int v = Q.front(); 25 | Q.pop(); 26 | for (int w : E[v]){ 27 | if (c[w].empty()){ 28 | c[v].push_back(w); 29 | Q.push(w); 30 | } 31 | } 32 | } 33 | return c; 34 | } 35 | vector> child_2(vector &p, int r){ 36 | int N = p.size(); 37 | vector> c(N); 38 | for (int i = 0; i < N; i++){ 39 | if (i != r){ 40 | c[p[i]].push_back(i); 41 | } 42 | } 43 | return c; 44 | } 45 | -------------------------------------------------------------------------------- /old_Graph/Detect_Cycle.cpp: -------------------------------------------------------------------------------- 1 | bool detect_cycle(vector> &E){ 2 | int V = E.size(); 3 | vector deg(V, 0); 4 | for (int i = 0; i < V; i++){ 5 | for (int j : E[i]){ 6 | deg[j]++; 7 | } 8 | } 9 | queue Q; 10 | for (int i = 0; i < V; i++){ 11 | if (deg[i] == 0){ 12 | Q.push(i); 13 | } 14 | } 15 | while (!Q.empty()){ 16 | int v = Q.front(); 17 | Q.pop(); 18 | for (int w : E[v]){ 19 | deg[w]--; 20 | if (deg[w] == 0){ 21 | Q.push(w); 22 | } 23 | } 24 | } 25 | for (int i = 0; i < V; i++){ 26 | if (deg[i] != 0){ 27 | return true; 28 | } 29 | } 30 | return false; 31 | } 32 | -------------------------------------------------------------------------------- /old_Graph/Lowest_Common_Ancestor.cpp: -------------------------------------------------------------------------------- 1 | struct lowest_common_ancestor{ 2 | vector p, sz, in, next; 3 | void dfs1(vector> &c, int v = 0){ 4 | sz[v] = 1; 5 | for (int &w : c[v]){ 6 | dfs1(c, w); 7 | sz[v] += sz[w]; 8 | if (sz[w] > sz[c[v][0]]){ 9 | swap(w, c[v][0]); 10 | } 11 | } 12 | } 13 | void dfs2(vector> &c, int &t, int v = 0){ 14 | in[v] = t; 15 | t++; 16 | for (int w : c[v]){ 17 | if (w == c[v][0]){ 18 | next[w] = next[v]; 19 | } else { 20 | next[w] = w; 21 | } 22 | dfs2(c, t, w); 23 | } 24 | } 25 | lowest_common_ancestor(vector &p, vector> &c): p(p){ 26 | int N = p.size(); 27 | sz = vector(N); 28 | dfs1(c); 29 | in = vector(N); 30 | next = vector(N, 0); 31 | int t = 0; 32 | dfs2(c, t); 33 | } 34 | int lca(int u, int v){ 35 | while (1){ 36 | if (in[u] > in[v]){ 37 | swap(u, v); 38 | } 39 | if (next[u] == next[v]){ 40 | return u; 41 | } 42 | v = p[next[v]]; 43 | } 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /old_Graph/Max_Flow_(Dinic).cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct dinic{ 3 | struct edge{ 4 | int to, rev; 5 | Cap cap; 6 | edge(int to, int rev, Cap cap): to(to), rev(rev), cap(cap){ 7 | } 8 | }; 9 | int N; 10 | vector> G; 11 | dinic(){ 12 | } 13 | dinic(int N): N(N), G(N){ 14 | } 15 | void add_edge(int from, int to, Cap cap){ 16 | G[from].push_back(edge(to, G[to].size(), cap)); 17 | G[to].push_back(edge(from, G[from].size() - 1, 0)); 18 | } 19 | Cap dfs(vector &d, vector &iter, int v, int t, Cap f){ 20 | if (v == t){ 21 | return f; 22 | } 23 | while (iter[v] < G[v].size()){ 24 | int w = G[v][iter[v]].to; 25 | if (G[v][iter[v]].cap > 0 && d[v] < d[w]){ 26 | Cap f2 = dfs(d, iter, w, t, min(f, G[v][iter[v]].cap)); 27 | if (f2 > 0){ 28 | G[v][iter[v]].cap -= f2; 29 | G[w][G[v][iter[v]].rev].cap += f2; 30 | return f2; 31 | } 32 | } 33 | iter[v]++; 34 | } 35 | return 0; 36 | } 37 | Cap max_flow(int s, int t){ 38 | Cap flow = 0; 39 | while (true){ 40 | vector d(N, -1); 41 | d[s] = 0; 42 | queue Q; 43 | Q.push(s); 44 | while (!Q.empty()){ 45 | if (d[t] != -1){ 46 | break; 47 | } 48 | int v = Q.front(); 49 | Q.pop(); 50 | for (auto &e : G[v]){ 51 | int w = e.to; 52 | if (e.cap > 0 && d[w] == -1){ 53 | d[w] = d[v] + 1; 54 | Q.push(w); 55 | } 56 | } 57 | } 58 | if (d[t] == -1){ 59 | break; 60 | } 61 | vector iter(N, 0); 62 | while (true){ 63 | Cap f = dfs(d, iter, s, t, INF); 64 | if (f == 0){ 65 | break; 66 | } 67 | flow += f; 68 | } 69 | } 70 | return flow; 71 | } 72 | }; 73 | -------------------------------------------------------------------------------- /old_Graph/Max_Flow_(Ford_Fulkerson).cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct ford_fulkerson{ 3 | struct edge{ 4 | int to, rev; 5 | Cap cap; 6 | edge(int to, int rev, Cap cap): to(to), rev(rev), cap(cap){ 7 | } 8 | }; 9 | int N; 10 | vector> G; 11 | ford_fulkerson(){ 12 | } 13 | ford_fulkerson(int N): N(N), G(N){ 14 | } 15 | void add_edge(int from, int to, Cap cap){ 16 | int id1 = G[from].size(); 17 | int id2 = G[to].size(); 18 | G[from].push_back(edge(to, id2, cap)); 19 | G[to].push_back(edge(from, id1, 0)); 20 | } 21 | Cap max_flow(int s, int t){ 22 | Cap flow = 0; 23 | while (1){ 24 | vector m(N, INF); 25 | vector pv(N, -1); 26 | vector pe(N, -1); 27 | vector used(N, false); 28 | queue Q; 29 | Q.push(s); 30 | used[s] = true; 31 | while (!Q.empty()){ 32 | int v = Q.front(); 33 | Q.pop(); 34 | int cnt = G[v].size(); 35 | for (int i = 0; i < cnt; i++){ 36 | int w = G[v][i].to; 37 | if (!used[w] && G[v][i].cap > 0){ 38 | used[w] = true; 39 | m[w] = min(m[v], G[v][i].cap); 40 | pv[w] = v; 41 | pe[w] = i; 42 | Q.push(w); 43 | } 44 | } 45 | } 46 | if (!used[t]){ 47 | break; 48 | } 49 | Cap f = m[t]; 50 | for (int i = t; i != s; i = pv[i]){ 51 | G[pv[i]][pe[i]].cap -= f; 52 | G[i][G[pv[i]][pe[i]].rev].cap += f; 53 | } 54 | flow += f; 55 | } 56 | return flow; 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /old_Graph/Min_Cost_Flow_(Primal_Dual).cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct primal_dual{ 3 | struct edge{ 4 | int to, rev; 5 | Cap cap; 6 | Cost cost; 7 | edge(int to, int rev, Cap cap, Cost cost): to(to), rev(rev), cap(cap), cost(cost){ 8 | } 9 | }; 10 | int N; 11 | vector> G; 12 | primal_dual(){ 13 | } 14 | primal_dual(int N): N(N), G(N){ 15 | } 16 | void add_edge(int from, int to, Cap cap, Cost cost){ 17 | int id1 = G[from].size(); 18 | int id2 = G[to].size(); 19 | G[from].push_back(edge(to, id2, cap, cost)); 20 | G[to].push_back(edge(from, id1, 0, - cost)); 21 | } 22 | pair min_cost_flow(int s, int t, Cap F){ 23 | Cap flow = 0; 24 | Cost cost = 0; 25 | vector h(N, 0); 26 | while (flow < F){ 27 | vector m(N, INF); 28 | vector d(N, INF); 29 | vector pv(N, -1); 30 | vector pe(N, -1); 31 | vector used(N, false); 32 | priority_queue, vector>, greater>> pq; 33 | pq.push(make_pair(0, s)); 34 | d[s] = 0; 35 | while (!pq.empty()){ 36 | int v = pq.top().second; 37 | pq.pop(); 38 | if (!used[v]){ 39 | used[v] = true; 40 | if (v == t){ 41 | break; 42 | } 43 | int cnt = G[v].size(); 44 | for (int i = 0; i < cnt; i++){ 45 | int w = G[v][i].to; 46 | if (!used[w] && G[v][i].cap > 0){ 47 | Cost tmp = G[v][i].cost - h[w] + h[v]; 48 | if (d[w] > d[v] + tmp){ 49 | d[w] = d[v] + tmp; 50 | m[w] = min(m[v], G[v][i].cap); 51 | pv[w] = v; 52 | pe[w] = i; 53 | pq.push(make_pair(d[w], w)); 54 | } 55 | } 56 | } 57 | } 58 | } 59 | if (!used[t]){ 60 | break; 61 | } 62 | for (int i = 0; i < N; i++){ 63 | if (used[i]){ 64 | h[i] -= d[t] - d[i]; 65 | } 66 | } 67 | Cap c = min(m[t], F - flow); 68 | for (int i = t; i != s; i = pv[i]){ 69 | G[pv[i]][pe[i]].cap -= c; 70 | G[i][G[pv[i]][pe[i]].rev].cap += c; 71 | } 72 | flow += c; 73 | cost += c * (- h[s]); 74 | } 75 | return make_pair(flow, cost); 76 | } 77 | }; 78 | -------------------------------------------------------------------------------- /old_Graph/Minimium_Cost_Arborescence.cpp: -------------------------------------------------------------------------------- 1 | int minimum_cost_arborescence(vector>> E, int r){ 2 | int ans = 0; 3 | while (true){ 4 | int N = E.size(); 5 | vector mn(N, INF), p(N, -1); 6 | for (int i = 0; i < N; i++){ 7 | for (auto P : E[i]){ 8 | int c = P.first; 9 | int w = P.second; 10 | if (w != r && mn[w] > c){ 11 | mn[w] = c; 12 | p[w] = i; 13 | } 14 | } 15 | } 16 | vector d(N, 0); 17 | for (int i = 0; i < N; i++){ 18 | if (i != r){ 19 | d[p[i]]++; 20 | } 21 | } 22 | queue Q; 23 | for (int i = 0; i < N; i++){ 24 | if (i != r && d[i] == 0){ 25 | Q.push(i); 26 | } 27 | } 28 | while (!Q.empty()){ 29 | int v = Q.front(); 30 | Q.pop(); 31 | if (v != r){ 32 | d[p[v]]--; 33 | if (d[p[v]] == 0){ 34 | Q.push(p[v]); 35 | } 36 | } 37 | } 38 | vector cycle; 39 | vector id(N, -1); 40 | for (int i = 0; i < N; i++){ 41 | if (d[i] == 1){ 42 | cycle.push_back(i); 43 | while (true){ 44 | int v = cycle.back(); 45 | id[v] = 0; 46 | ans += mn[v]; 47 | if (p[v] == i){ 48 | break; 49 | } 50 | cycle.push_back(p[v]); 51 | } 52 | break; 53 | } 54 | } 55 | if (cycle.empty()){ 56 | for (int i = 0; i < N; i++){ 57 | if (i != r){ 58 | ans += mn[i]; 59 | } 60 | } 61 | break; 62 | } 63 | int cnt = 1; 64 | for (int i = 0; i < N; i++){ 65 | if (id[i] == -1){ 66 | id[i] = cnt; 67 | cnt++; 68 | } 69 | } 70 | vector>> E2(cnt); 71 | for (int i = 0; i < N; i++){ 72 | for (auto P : E[i]){ 73 | int c = P.first; 74 | int w = P.second; 75 | if (id[w] == 0){ 76 | c -= mn[w]; 77 | } 78 | if (id[i] != id[w]){ 79 | E2[id[i]].push_back(make_pair(c, id[w])); 80 | } 81 | } 82 | } 83 | swap(E, E2); 84 | swap(r, id[r]); 85 | } 86 | return ans; 87 | } 88 | -------------------------------------------------------------------------------- /old_Graph/Minimum_Spanning_Tree_(Kruskal).cpp: -------------------------------------------------------------------------------- 1 | long long kruskal(vector>> &E){ 2 | int V = E.size(); 3 | vector> edges; 4 | for (int i = 0; i < V; i++){ 5 | for (auto P : E[i]){ 6 | edges.push_back(make_tuple(P.first, i, P.second)); 7 | } 8 | } 9 | sort(edges.begin(), edges.end()); 10 | unionfind UF(V); 11 | long long ans = 0; 12 | for (auto e : edges){ 13 | int c = get<0>(e); 14 | int v = get<1>(e); 15 | int w = get<2>(e); 16 | if (!UF.same(v, w)){ 17 | UF.unite(v, w); 18 | ans += c; 19 | } 20 | } 21 | return ans; 22 | } 23 | -------------------------------------------------------------------------------- /old_Graph/Range_Edges.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct range_edges{ 3 | int N; 4 | int V; 5 | vector>> E; 6 | range_edges(int n){ 7 | N = 1; 8 | while (N < n){ 9 | N *= 2; 10 | } 11 | V = N * 5 - 2; 12 | E = vector>>(V); 13 | for (int i = 0; i < N - 1; i++){ 14 | E[i].emplace_back(0, i * 2 + 1); 15 | E[i].emplace_back(0, i * 2 + 2); 16 | E[i * 2 + N * 2].emplace_back(0, i + N * 2 - 1); 17 | E[i * 2 + N * 2 + 1].emplace_back(0, i + N * 2 - 1); 18 | } 19 | for (int i = 0; i < N; i++){ 20 | E[N - 1 + i].emplace_back(0, N * 4 - 2 + i); 21 | E[N * 4 - 2 + i].emplace_back(0, N * 3 - 2 + i); 22 | } 23 | } 24 | void add_edge_from(int L, int R, int v, int i, int l, int r){ 25 | if (R <= l || r <= L){ 26 | return; 27 | } else if (L <= l && r <= R){ 28 | E[i + N * 2 - 1].emplace_back(0, v); 29 | } else { 30 | int m = (l + r) / 2; 31 | add_edge_from(L, R, v, i * 2 + 1, l, m); 32 | add_edge_from(L, R, v, i * 2 + 2, m, r); 33 | } 34 | } 35 | void add_edge_from(int L, int R, int v){ 36 | add_edge_from(L, R, v, 0, 0, N); 37 | } 38 | void add_edge_to(int L, int R, int v, int i, int l, int r){ 39 | if (R <= l || r <= L){ 40 | return; 41 | } else if (L <= l && r <= R){ 42 | E[v].emplace_back(0, i); 43 | } else { 44 | int m = (l + r) / 2; 45 | add_edge_to(L, R, v, i * 2 + 1, l, m); 46 | add_edge_to(L, R, v, i * 2 + 2, m, r); 47 | } 48 | } 49 | void add_edge_to(int L, int R, int v){ 50 | add_edge_to(L, R, v, 0, 0, N); 51 | } 52 | void add_edge(int L1, int R1, int L2, int R2, T cost){ 53 | E.emplace_back(); 54 | E.emplace_back(); 55 | V += 2; 56 | add_edge_from(L1, R1, V - 2); 57 | add_edge_to(L2, R2, V - 1); 58 | E[V - 2].emplace_back(cost, V - 1); 59 | } 60 | void debug(){ 61 | for (int i = 0; i < V; i++){ 62 | cout << i << ":"; 63 | for (auto P : E[i]){ 64 | cout << " (" << P.first << "," << P.second << ")"; 65 | } 66 | cout << endl; 67 | } 68 | } 69 | }; 70 | -------------------------------------------------------------------------------- /old_Graph/Rerooting.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct rerooting{ 3 | vector dp1; 4 | vector dp2; 5 | T E; 6 | function add; 7 | function root; 8 | void dfs1(vector> &c, int v){ 9 | dp1[v] = E; 10 | for (auto w : c[v]){ 11 | dfs1(c, w); 12 | dp1[v] = add(dp1[v], root(dp1[w])); 13 | } 14 | } 15 | void dfs2(vector> &c, int v){ 16 | int deg = c[v].size(); 17 | vector L(deg + 1, E); 18 | for (int i = 0; i < deg; i++){ 19 | L[i + 1] = add(L[i], root(dp1[c[v][i]])); 20 | } 21 | vector R(deg + 1, E); 22 | for (int i = deg - 1; i >= 0; i--){ 23 | R[i] = add(R[i + 1], root(dp1[c[v][i]])); 24 | } 25 | for (int i = 0; i < deg; i++){ 26 | dp2[c[v][i]] = root(add(dp2[v], add(L[i], R[i + 1]))); 27 | dfs2(c, c[v][i]); 28 | } 29 | } 30 | rerooting(vector> &c, function add, function root, T E): add(add), root(root), E(E){ 31 | int N = c.size(); 32 | dp1 = vector(N, E); 33 | dfs1(c, 0); 34 | dp2 = vector(N, E); 35 | dfs2(c, 0); 36 | } 37 | T operator [](int k){ 38 | return add(dp1[k], dp2[k]); 39 | } 40 | }; 41 | struct rerooting{ 42 | vector dp1; 43 | vector dp2; 44 | T E; 45 | function add; 46 | function root; 47 | void dfs1(vector>> &c, int v){ 48 | dp1[v] = E; 49 | for (auto P : c[v]){ 50 | int w = P.second; 51 | dfs1(c, w); 52 | dp1[v] = add(dp1[v], root(dp1[w], P.first)); 53 | } 54 | } 55 | void dfs2(vector>> &c, int v){ 56 | int deg = c[v].size(); 57 | vector L(deg + 1, E); 58 | for (int i = 0; i < deg; i++){ 59 | L[i + 1] = add(L[i], root(dp1[c[v][i].second], c[v][i].first)); 60 | } 61 | vector R(deg + 1, E); 62 | for (int i = deg - 1; i >= 0; i--){ 63 | R[i] = add(R[i + 1], root(dp1[c[v][i].second], c[v][i].first)); 64 | } 65 | for (int i = 0; i < deg; i++){ 66 | dp2[c[v][i].second] = root(add(dp2[v], add(L[i], R[i + 1])), c[v][i].first); 67 | dfs2(c, c[v][i].second); 68 | } 69 | } 70 | rerooting(vector>> &c, function add, function root, T E): add(add), root(root), E(E){ 71 | int N = c.size(); 72 | dp1 = vector(N); 73 | dfs1(c, 0); 74 | dp2 = vector(N); 75 | dfs2(c, 0); 76 | } 77 | T operator [](int k){ 78 | return add(dp1[k], dp2[k]); 79 | } 80 | }; 81 | -------------------------------------------------------------------------------- /old_Graph/Rerooting_1.cpp: -------------------------------------------------------------------------------- 1 | int dfs1(vector &dp, vector> &c, int v){ 2 | for (int w : c[v]) { 3 | vp[v] = add(dp[v], root(dfs1(dp, c, w))); 4 | } 5 | return dp[v]; 6 | } 7 | void dfs2(vector &dp, vector> &c, int v){ 8 | for (int w : c[v]){ 9 | dp[w] = add(dp[w], root(sub(dp[v], root(dp[w])))); 10 | dfs2(dp, c, w); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /old_Graph/Rerooting_2.cpp: -------------------------------------------------------------------------------- 1 | int dfs1(vector &dp, vector> &c, int v){ 2 | dp[v] = 1; 3 | for (int w : c[v]) dp[v] = add(dp[v], root(dfs1(dp, c, w))); 4 | return dp[v]; 5 | } 6 | void dfs2(vector &dp1, vector &dp2, vector> &c, int v){ 7 | int deg = c[v].size(); 8 | vector L(deg + 1, 1), R(deg + 1, 1); 9 | for (int i = 0; i < deg; i++) L[i + 1] = add(L[i], root(dp1[c[v][i]])); 10 | for (int i = deg - 1; i >= 0; i--) R[i] = add(R[i + 1], root(dp1[c[v][i]])); 11 | for (int i = 0; i < deg; i++){ 12 | dp2[c[v][i]] = root(add(dp2[v], add(L[i], R[i + 1]))); 13 | dfs2(dp1, dp2, c, c[v][i]); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /old_Graph/Single_Source_Shortest_Path_(Bellman_Ford).cpp: -------------------------------------------------------------------------------- 1 | vector bellman_ford(vector>> &E, int s){ 2 | int V = E.size(); 3 | vector d(V, INF); 4 | d[s] = 0; 5 | while (1){ 6 | bool update = false; 7 | for (int i = 0; i < V; i++){ 8 | for (int j = 0; j < E[i].size(); j++){ 9 | int c = E[i][j].first; 10 | int v = E[i][j].second; 11 | if (d[v] > d[i] + c && d[i] != INF){ 12 | d[v] = d[i] + c; 13 | update = true; 14 | } 15 | } 16 | } 17 | if (!update){ 18 | break; 19 | } 20 | } 21 | return d; 22 | } 23 | bool detect_negative_cycles(vector>> &E, int s){ 24 | int V = E.size(); 25 | vector d(V, INF); 26 | d[s] = 0; 27 | for (int i = 0; i < V; i++){ 28 | bool update = false; 29 | for (int j = 0; j < V; j++){ 30 | for (int k = 0; k < E[j].size(); k++){ 31 | int c = E[j][k].first; 32 | int v = E[j][k].second; 33 | if (d[v] > d[j] + c && d[j] != INF){ 34 | d[v] = d[j] + c; 35 | update = true; 36 | if (i == V - 1){ 37 | return true; 38 | } 39 | } 40 | } 41 | } 42 | if (!update){ 43 | break; 44 | } 45 | } 46 | return false; 47 | } 48 | bool detect_negative_cycles_2(vector>> &E){ 49 | int V = E.size(); 50 | vector d(V, 0); 51 | for (int i = 0; i < V; i++){ 52 | bool update = false; 53 | for (int j = 0; j < V; j++){ 54 | for (int k = 0; k < E[j].size(); k++){ 55 | int c = E[j][k].first; 56 | int v = E[j][k].second; 57 | if (d[v] > d[j] + c && d[j] != INF){ 58 | d[v] = d[j] + c; 59 | update = true; 60 | if (i == V - 1){ 61 | return true; 62 | } 63 | } 64 | } 65 | } 66 | if (!update){ 67 | break; 68 | } 69 | } 70 | return false; 71 | } 72 | vector find_negative_cycles(vector>> &E){ 73 | int V = E.size(); 74 | vector d(V, 0); 75 | for (int i = 0; i < V; i++){ 76 | bool update = false; 77 | for (int j = 0; j < V; j++){ 78 | for (int k = 0; k < E[j].size(); k++){ 79 | int c = E[j][k].first; 80 | int v = E[j][k].second; 81 | if (d[v] > d[j] + c){ 82 | d[v] = d[j] + c; 83 | update = true; 84 | } 85 | } 86 | } 87 | if (!update){ 88 | break; 89 | } 90 | } 91 | vector res(V, false); 92 | for (int i = 0; i < V; i++){ 93 | if (d[i] < 0){ 94 | res[i] = true; 95 | } 96 | } 97 | return res; 98 | } 99 | -------------------------------------------------------------------------------- /old_Graph/Single_Source_Shortest_Path_(Dijkstra).cpp: -------------------------------------------------------------------------------- 1 | vector dijkstra(vector>> &E, int s){ 2 | int V = E.size(); 3 | vector d(V, INF); 4 | d[s] = 0; 5 | priority_queue, vector>, greater>> Q; 6 | Q.push(make_pair(0, s)); 7 | while (!Q.empty()){ 8 | long long c = Q.top().first; 9 | int v = Q.top().second; 10 | Q.pop(); 11 | if (d[v] >= c){ 12 | for (auto P : E[v]){ 13 | int w = P.second; 14 | if (d[w] > d[v] + P.first){ 15 | d[w] = d[v] + P.first; 16 | Q.push(make_pair(d[w], w)); 17 | } 18 | } 19 | } 20 | } 21 | return d; 22 | } 23 | pair> dijkstra_path(vector>> &E, int s, int t){ 24 | int V = E.size(); 25 | vector d(V, INF); 26 | d[s] = 0; 27 | vector prev(V); 28 | priority_queue, vector>, greater>> Q; 29 | Q.push(make_pair(0, s)); 30 | while (!Q.empty()){ 31 | long long c = Q.top().first; 32 | int v = Q.top().second; 33 | Q.pop(); 34 | if (d[v] >= c){ 35 | for (auto P : E[v]){ 36 | int w = P.second; 37 | if (d[w] > d[v] + P.first){ 38 | d[w] = d[v] + P.first; 39 | Q.push(make_pair(d[w], w)); 40 | prev[w] = v; 41 | } 42 | } 43 | } 44 | } 45 | if (d[t] == INF){ 46 | return make_pair(-1, vector()); 47 | } else { 48 | vector path; 49 | path.push_back(t); 50 | while (path.back() != s){ 51 | path.push_back(prev[path.back()]); 52 | } 53 | reverse(path.begin(), path.end()); 54 | return make_pair(d[t], path); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /old_Graph/Topological_Sort.cpp: -------------------------------------------------------------------------------- 1 | vector topological_sort(vector> &E){ 2 | int V = E.size(); 3 | vector deg(V, 0); 4 | for (int i = 0; i < V; i++){ 5 | for (int j : E[i]){ 6 | deg[j]++; 7 | } 8 | } 9 | queue Q; 10 | for (int i = 0; i < V; i++){ 11 | if (deg[i] == 0){ 12 | Q.push(i); 13 | } 14 | } 15 | vector ans; 16 | while (!Q.empty()){ 17 | int v = Q.front(); 18 | Q.pop(); 19 | ans.push_back(v); 20 | for (int w : E[v]){ 21 | deg[w]--; 22 | if (deg[w] == 0){ 23 | Q.push(w); 24 | } 25 | } 26 | } 27 | return ans; 28 | } 29 | -------------------------------------------------------------------------------- /old_Graph/Tree_Diameter.cpp: -------------------------------------------------------------------------------- 1 | long long tree_diameter(vector>> &E){ 2 | int N = E.size(); 3 | vector d1(N, INF); 4 | d1[0] = 0; 5 | queue Q1; 6 | Q1.push(0); 7 | while (!Q1.empty()){ 8 | int v = Q1.front(); 9 | Q1.pop(); 10 | for (auto P : E[v]){ 11 | int c = P.first; 12 | int w = P.second; 13 | if (d1[w] == INF){ 14 | d1[w] = d1[v] + c; 15 | Q1.push(w); 16 | } 17 | } 18 | } 19 | int s = max_element(d1.begin(), d1.end()) - d1.begin(); 20 | vector d2(N, INF); 21 | d2[s] = 0; 22 | queue Q2; 23 | Q2.push(s); 24 | while (!Q2.empty()){ 25 | int v = Q2.front(); 26 | Q2.pop(); 27 | for (auto P : E[v]){ 28 | int c = P.first; 29 | int w = P.second; 30 | if (d2[w] == INF){ 31 | d2[w] = d2[v] + c; 32 | Q2.push(w); 33 | } 34 | } 35 | } 36 | return *max_element(d2.begin(), d2.end()); 37 | } 38 | -------------------------------------------------------------------------------- /old_Graph/Tree_Height.cpp: -------------------------------------------------------------------------------- 1 | vector tree_height(vector> &E){ 2 | int N = E.size(); 3 | vector d(N, -1); 4 | d[0] = 0; 5 | queue Q; 6 | Q.push(0); 7 | while (!Q.empty()){ 8 | int v = Q.front(); 9 | Q.pop(); 10 | for (int w : E[v]){ 11 | if (d[w] == -1){ 12 | d[w] = d[v] + 1; 13 | Q.push(w); 14 | } 15 | } 16 | } 17 | int s = max_element(d.begin(), d.end()) - d.begin(); 18 | vector d2(N, -1); 19 | d2[s] = 0; 20 | queue Q2; 21 | Q2.push(s); 22 | while (!Q2.empty()){ 23 | int v = Q2.front(); 24 | Q2.pop(); 25 | for (int w : E[v]){ 26 | if (d2[w] == -1){ 27 | d2[w] = d2[v] + 1; 28 | Q2.push(w); 29 | } 30 | } 31 | } 32 | int t = max_element(d2.begin(), d2.end()) - d2.begin(); 33 | vector d3(N, -1); 34 | d3[t] = 0; 35 | queue Q3; 36 | Q3.push(t); 37 | while (!Q3.empty()){ 38 | int v = Q3.front(); 39 | Q3.pop(); 40 | for (int w : E[v]){ 41 | if (d3[w] == -1){ 42 | d3[w] = d3[v] + 1; 43 | Q3.push(w); 44 | } 45 | } 46 | } 47 | vector ans(N); 48 | for (int i = 0; i < N; i++){ 49 | ans[i] = max(d2[i], d3[i]); 50 | } 51 | return ans; 52 | } 53 | -------------------------------------------------------------------------------- /old_Math/Bitwise_And_Convolution.cpp: -------------------------------------------------------------------------------- 1 | vector and_fwt(vector A, bool inv){ 2 | int N = A.size(); 3 | for (int i = 1; i < N; i <<= 1){ 4 | for (int j = 0; j < N; j++){ 5 | if ((j & i) == 0){ 6 | if (!inv){ 7 | A[j] += A[j | i]; 8 | A[j] %= MOD; 9 | } else { 10 | A[j] -= A[j | i]; 11 | A[j] += MOD; 12 | A[j] %= MOD; 13 | } 14 | } 15 | } 16 | } 17 | return A; 18 | } 19 | vector and_convolution(vector A, vector B){ 20 | int N = A.size(); 21 | A = and_fwt(A, false); 22 | B = and_fwt(B, false); 23 | vector C(N); 24 | for (int i = 0; i < N; i++){ 25 | C[i] = A[i] * B[i] % MOD; 26 | } 27 | C = and_fwt(C, true); 28 | return C; 29 | } 30 | -------------------------------------------------------------------------------- /old_Math/Catalan_Number.cpp: -------------------------------------------------------------------------------- 1 | //Input: n, MOD 2 | //Output: C_n mod MOD 3 | //Time: O(1) 4 | long long modpow(long long a, long long b){ 5 | long long res = 1; 6 | while (b > 0){ 7 | if (b % 2 == 1) res = res * a % MOD; 8 | a = a * a % MOD; 9 | b = b / 2; 10 | } 11 | return res; 12 | } 13 | long long modinv(long long a){ 14 | return modpow(a, MOD - 2); 15 | } 16 | vector mf; 17 | long long modfact(long long n){ 18 | if (n < mf.size()){ 19 | return mf[n]; 20 | } else { 21 | if (mf.empty()) mf.push_back(1); 22 | long long res = mf.back(); 23 | for (int i = mf.size(); i <= n; i++){ 24 | res = res * i % MOD; 25 | mf.push_back(res); 26 | } 27 | return res; 28 | } 29 | } 30 | long long catalan_number(long long n){ 31 | long long res; 32 | res = modfact(n * 2); 33 | res = res * modinv(modfact(n + 1)) % MOD; 34 | res = res * modinv(modfact(n)) % MOD; 35 | return res; 36 | } 37 | -------------------------------------------------------------------------------- /old_Math/Convolution_(FFT).cpp: -------------------------------------------------------------------------------- 1 | double PI = acos(-1); 2 | vector> fft(vector> A, bool inv){ 3 | int N = A.size(); 4 | complex r = polar((double) 1, (2 * PI) / (N)); 5 | if (inv){ 6 | r = pow(r, -1); 7 | } 8 | vector> B(N); 9 | for (int i = N / 2; i > 0; i /= 2){ 10 | complex z = pow(r, i); 11 | complex z2 = 1; 12 | for (int j = 0; j < N; j += i * 2){ 13 | for (int k = 0; k < i; k++){ 14 | A[i + j + k] *= z2; 15 | B[j / 2 + k] = A[j + k] + A[i + j + k]; 16 | B[N / 2 + j / 2 + k] = A[j + k] - A[i + j + k]; 17 | } 18 | z2 *= z; 19 | } 20 | swap(A, B); 21 | } 22 | if (inv){ 23 | for (int i = 0; i < N; i++){ 24 | A[i] /= N; 25 | } 26 | } 27 | return A; 28 | } 29 | vector convolution(vector A, vector B){ 30 | int deg = A.size() + B.size() - 1; 31 | int N = 1; 32 | while (N < deg){ 33 | N *= 2; 34 | } 35 | vector> A2(N, 0); 36 | for (int i = 0; i < A.size(); i++){ 37 | A2[i] = A[i]; 38 | } 39 | vector> B2(N, 0); 40 | for (int i = 0; i < B.size(); i++){ 41 | B2[i] = B[i]; 42 | } 43 | A2 = fft(A2, false); 44 | B2 = fft(B2, false); 45 | vector> C2(N); 46 | for (int i = 0; i < N; i++){ 47 | C2[i] = A2[i] * B2[i]; 48 | } 49 | C2 = fft(C2, true); 50 | vector C(deg); 51 | for (int i = 0; i < deg; i++){ 52 | C[i] = C2[i].real(); 53 | } 54 | return C; 55 | } 56 | -------------------------------------------------------------------------------- /old_Math/Convolution_(NTT).cpp: -------------------------------------------------------------------------------- 1 | long long modpow(long long a, long long b){ 2 | long long ans = 1; 3 | while (b > 0){ 4 | if (b % 2 == 1){ 5 | ans *= a; 6 | ans %= MOD; 7 | } 8 | a *= a; 9 | a %= MOD; 10 | b /= 2; 11 | } 12 | return ans; 13 | } 14 | long long modinv(long long a){ 15 | return modpow(a, MOD - 2); 16 | } 17 | vector ntt(vector A, bool inv){ 18 | int N = A.size(); 19 | long long r = 3; 20 | if (inv){ 21 | r = modinv(r); 22 | } 23 | vector B(N); 24 | for (int i = N / 2; i > 0; i /= 2){ 25 | long long z = modpow(r, (MOD - 1) / (N / i)); 26 | long long z2 = 1; 27 | for (int j = 0; j < N; j += i * 2){ 28 | for (int k = 0; k < i; k++){ 29 | A[i + j + k] *= z2; 30 | A[i + j + k] %= MOD; 31 | B[j / 2 + k] = (A[j + k] + A[i + j + k]) % MOD; 32 | B[N / 2 + j / 2 + k] = (A[j + k] - A[i + j + k] + MOD) % MOD; 33 | } 34 | z2 = z2 * z % MOD; 35 | } 36 | swap(A, B); 37 | } 38 | if (inv){ 39 | int Ninv = modinv(N); 40 | for (int i = 0; i < N; i++){ 41 | A[i] = A[i] * Ninv % MOD; 42 | } 43 | } 44 | return A; 45 | } 46 | vector convolution(vector A, vector B, int d = -1){ 47 | int deg = A.size() + B.size() - 1; 48 | int N = 1; 49 | while (N < deg){ 50 | N *= 2; 51 | } 52 | A.resize(N); 53 | B.resize(N); 54 | A = ntt(A, false); 55 | B = ntt(B, false); 56 | vector ans(N); 57 | for (int i = 0; i < N; i++){ 58 | ans[i] = A[i] * B[i] % MOD; 59 | } 60 | ans = ntt(ans, true); 61 | if (d != -1){ 62 | deg = d; 63 | } 64 | ans.resize(deg); 65 | return ans; 66 | } 67 | -------------------------------------------------------------------------------- /old_Math/Cycle_Decomposition.cpp: -------------------------------------------------------------------------------- 1 | vector> cycle_decomposition(vector &P){ 2 | int N = P.size(); 3 | vector used(N, false); 4 | vector> ans; 5 | for (int i = N - 1; i >= 0; i--){ 6 | if (used[i]) continue; 7 | vector C; 8 | C.push_back(i); 9 | while (C.front() != P[C.back()]){ 10 | C.push_back(P[C.back()]); 11 | used[C.back()] = true; 12 | } 13 | ans.push_back(C); 14 | } 15 | return ans; 16 | } 17 | -------------------------------------------------------------------------------- /old_Math/Euler_phi.cpp: -------------------------------------------------------------------------------- 1 | long long euler_phi(long long x){ 2 | long long ans = x; 3 | for (long long i = 2; i * i <= x; i++){ 4 | if (x % i == 0){ 5 | ans /= i; 6 | ans *= i - 1; 7 | while (x % i == 0){ 8 | x /= i; 9 | } 10 | } 11 | } 12 | if (x > 1){ 13 | ans /= x; 14 | ans *= x - 1; 15 | } 16 | return ans; 17 | } 18 | -------------------------------------------------------------------------------- /old_Math/Matrix_Multiplication.cpp: -------------------------------------------------------------------------------- 1 | vector> matmul(vector> A, vector> B){ 2 | int N = A.size(); 3 | vector> ans(N, vector(N, 0)); 4 | for (int i = 0; i < N; i++){ 5 | for (int j = 0; j < N; j++){ 6 | for (int k = 0; k < N; k++){ 7 | ans[i][k] += A[i][j] * B[j][k]; 8 | ans[i][k] %= MOD; 9 | } 10 | } 11 | } 12 | return ans; 13 | } 14 | vector> matexp(vector> A, long long b){ 15 | int N = A.size(); 16 | vector> ans(N, vector(N, 0)); 17 | for (int i = 0; i < N; i++){ 18 | ans[i][i] = 1; 19 | } 20 | while (b > 0){ 21 | if (b % 2 == 1){ 22 | ans = matmul(ans, A); 23 | } 24 | A = matmul(A, A); 25 | b /= 2; 26 | } 27 | return ans; 28 | } 29 | -------------------------------------------------------------------------------- /old_Math/Modulo.cpp: -------------------------------------------------------------------------------- 1 | const long long MOD = 1000000007; 2 | long long modsub(long long a, long long b){ 3 | return (a % MOD - b % MOD + MOD) % MOD; 4 | } 5 | long long modpow(long long a, long long b){ 6 | long long ans = 1; 7 | while (b > 0){ 8 | if (b % 2 == 1){ 9 | ans *= a; 10 | ans %= MOD; 11 | } 12 | a *= a; 13 | a %= MOD; 14 | b /= 2; 15 | } 16 | return ans; 17 | } 18 | long long modinv(long long a){ 19 | return modpow(a, MOD - 2); 20 | } 21 | vector mf = {1}; 22 | vector mfi = {1}; 23 | long long modfact(int n){ 24 | if (mf.size() > n){ 25 | return mf[n]; 26 | } else { 27 | for (int i = mf.size(); i <= n; i++){ 28 | long long next = mf.back() * i % MOD; 29 | mf.push_back(next); 30 | mfi.push_back(modinv(next)); 31 | } 32 | return mf[n]; 33 | } 34 | } 35 | long long modfactinv(int n){ 36 | if (mfi.size() > n){ 37 | return mfi[n]; 38 | } else { 39 | return modinv(modfact(n)); 40 | } 41 | } 42 | long long modbinom(int n, int k){ 43 | if (n < 0 || k < 0 || k > n){ 44 | return 0; 45 | } else { 46 | return modfact(n) * modfactinv(k) % MOD * modfactinv(n - k) % MOD; 47 | } 48 | } 49 | long long modbinom2(long long n, int r){ 50 | long long ans = 1; 51 | for (int i = 0; i < r; i++){ 52 | ans = ans * ((n - i) % MOD) % MOD; 53 | ans = ans * modinv(i + 1) % MOD; 54 | } 55 | return ans; 56 | } 57 | -------------------------------------------------------------------------------- /old_Math/Multipoint_Evaluation.cpp: -------------------------------------------------------------------------------- 1 | vector multipoint_evaluation(vector &f, vector x){ 2 | int M = x.size(); 3 | int M2 = 1; 4 | while (M2 < M){ 5 | M2 *= 2; 6 | } 7 | vector> g(M2 * 2 - 1, {1}); 8 | for (int i = 0; i < M; i++){ 9 | g[M2 - 1 + i] = vector{MOD - x[i], 1}; 10 | } 11 | for (int i = M2 - 2; i >= 0; i--){ 12 | g[i] = convolution(g[i * 2 + 1], g[i * 2 + 2]); 13 | } 14 | g[0] = polynomial_remainder(f, g[0]); 15 | for (int i = 1; i < M2 * 2 - 1; i++){ 16 | g[i] = polynomial_remainder(g[(i - 1) / 2], g[i]); 17 | } 18 | vector ans(M); 19 | for (int i = 0; i < M; i++){ 20 | ans[i] = g[M2 - 1 + i][0]; 21 | } 22 | return ans; 23 | } 24 | -------------------------------------------------------------------------------- /old_Math/Polynomial_Division.cpp: -------------------------------------------------------------------------------- 1 | vector polynomial_quotient(vector f, vector g){ 2 | int N = f.size(), M = g.size(); 3 | if (N < M){ 4 | return {0}; 5 | } 6 | reverse(g.begin(), g.end()); 7 | g.resize(N - M + 1); 8 | vector t = polynomial_inverse(g); 9 | reverse(f.begin(), f.end()); 10 | vector q = convolution(f, t, N - M + 1); 11 | reverse(q.begin(), q.end()); 12 | return q; 13 | } 14 | vector polynomial_remainder(vector f, vector g){ 15 | int N = f.size(); 16 | int M = g.size(); 17 | if (M <= 1200){ 18 | for (int i = N - M; i >= 0; i--){ 19 | long long q = f[i + M - 1] * modinv(g[M - 1]) % MOD; 20 | for (int j = 0; j < M; j++){ 21 | f[i + j] += MOD - q * g[j] % MOD; 22 | f[i + j] %= MOD; 23 | } 24 | f.pop_back(); 25 | } 26 | return f; 27 | } else { 28 | vector q = polynomial_quotient(f, g); 29 | vector b = convolution(g, q); 30 | for (int i = 0; i < N; i++){ 31 | f[i] += MOD - b[i]; 32 | f[i] %= MOD; 33 | } 34 | f.resize(M - 1); 35 | return f; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /old_Math/Polynomial_Inverse.cpp: -------------------------------------------------------------------------------- 1 | vector polynomial_inverse(vector f){ 2 | int N = f.size(); 3 | vector ans(1); 4 | ans[0] = modinv(f[0]); 5 | for (int i = 1; i < N * 2; i *= 2){ 6 | vector ans2 = ans; 7 | ans2.resize(i * 4); 8 | int N2 = min(N, i * 2); 9 | vector f2(i * 4, 0); 10 | for (int j = 0; j < N2; j++){ 11 | f2[j] = f[j]; 12 | } 13 | ans2 = convolution(ans2, ans2, i * 2); 14 | ans2 = convolution(ans2, f2, i * 2); 15 | for (int j = 0; j < i; j++){ 16 | ans2[j] = MOD - ans2[j] + ans[j] * 2; 17 | ans2[j] %= MOD; 18 | } 19 | swap(ans, ans2); 20 | } 21 | ans.resize(N); 22 | return ans; 23 | } 24 | -------------------------------------------------------------------------------- /old_Math/Prime.cpp: -------------------------------------------------------------------------------- 1 | bool is_prime(long long N){ 2 | for (long long i = 2; i * i <= N; i++){ 3 | if (N % i == 0){ 4 | return false; 5 | } 6 | } 7 | return true; 8 | } 9 | vector prime_factorization(long long N){ 10 | vector ans; 11 | for (long long i = 2; i * i <= N; i++){ 12 | if (N % i == 0){ 13 | while (N % i == 0){ 14 | N /= i; 15 | ans.push_back(i); 16 | } 17 | } 18 | } 19 | if (N != 1){ 20 | ans.push_back(N); 21 | } 22 | return ans; 23 | } 24 | int factor_count(long long N){ 25 | int ans = 1; 26 | for (long long i = 2; i * i <= N; i++){ 27 | if (N % i == 0){ 28 | int e = 0; 29 | while (N % i == 0){ 30 | N /= i; 31 | e++; 32 | } 33 | ans *= e + 1; 34 | } 35 | } 36 | if (N != 1){ 37 | ans *= 2; 38 | } 39 | return ans; 40 | } 41 | -------------------------------------------------------------------------------- /old_Math/Quotient_Ranges.cpp: -------------------------------------------------------------------------------- 1 | vector>> quotient_ranges(long long N){ 2 | vector>> ans; 3 | for (long long i = 1; i * i <= N; i++){ 4 | ans.push_back(make_pair(N / i, make_pair(i, i))); 5 | } 6 | for (long long i = N / ((long long) sqrt(N) + 1); i >= 1; i--){ 7 | ans.push_back(make_pair(i, make_pair(N / (i + 1) + 1, N / i))); 8 | } 9 | return ans; 10 | } 11 | -------------------------------------------------------------------------------- /old_Math/XOR_Convolution.cpp: -------------------------------------------------------------------------------- 1 | vector xor_fwt(vector A, bool inv){ 2 | int N = A.size(); 3 | for (int i = 1; i < N; i <<= 1){ 4 | for (int j = 0; j < N; j++){ 5 | if ((j & i) == 0){ 6 | long long x = A[j]; 7 | long long y = A[j | i]; 8 | A[j] = (x + y) % MOD; 9 | A[j | i] = (x + MOD - y) % MOD; 10 | if (inv){ 11 | A[j] *= (MOD + 1) / 2; 12 | A[j] %= MOD; 13 | A[j | i] *= (MOD + 1) / 2; 14 | A[j | i] %= MOD; 15 | } 16 | } 17 | } 18 | } 19 | return A; 20 | } 21 | vector xor_convolution(vector A, vector B){ 22 | int N = A.size(); 23 | A = xor_fwt(A, false); 24 | B = xor_fwt(B, false); 25 | vector C(N); 26 | for (int i = 0; i < N; i++){ 27 | C[i] = A[i] * B[i] % MOD; 28 | } 29 | C = xor_fwt(C, true); 30 | return C; 31 | } 32 | -------------------------------------------------------------------------------- /old_Range_Queries/Naive.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct naive{ 3 | int N; 4 | vector A; 5 | naive(int N): N(N){ 6 | A = vector(N); 7 | } 8 | naive(int N, T x): N(N){ 9 | A = vector(N, x); 10 | } 11 | naive(vector A): A(A){ 12 | N = A.size(); 13 | } 14 | void update(int i, T x){ 15 | A[i] = x; 16 | } 17 | void add(int i, T x){ 18 | A[i] += x; 19 | } 20 | void chmin(int i, T x){ 21 | A[i] = min(A[i], x); 22 | } 23 | void chmax(int i, T x){ 24 | A[i] = max(A[i], x); 25 | } 26 | void range_update(int L, int R, T x){ 27 | for (int i = L; i < R; i++){ 28 | A[i] = x; 29 | } 30 | } 31 | void range_add(int L, int R, T x){ 32 | for (int i = L; i < R; i++){ 33 | A[i] += x; 34 | } 35 | } 36 | void range_chmin(int L, int R, T x){ 37 | for (int i = L; i < R; i++){ 38 | A[i] = min(A[i], x); 39 | } 40 | } 41 | void range_chmax(int L, int R, T x){ 42 | for (int i = L; i < R; i++){ 43 | A[i] = max(A[i], x); 44 | } 45 | } 46 | T operator [](int i){ 47 | return A[i]; 48 | } 49 | T range_sum(int L, int R){ 50 | T ans = 0; 51 | for (int i = L; i < R; i++){ 52 | ans += A[i]; 53 | } 54 | return ans; 55 | } 56 | T range_min(int L, int R){ 57 | T ans = INF; 58 | for (int i = L; i < R; i++){ 59 | ans = min(ans, A[i]); 60 | } 61 | return ans; 62 | } 63 | T range_max(int L, int R){ 64 | T ans = -INF; 65 | for (int i = L; i < R; i++){ 66 | ans = max(ans, A[i]); 67 | } 68 | return ans; 69 | } 70 | void debug(){ 71 | cout << "["; 72 | for (int i = 0; i < N; i++){ 73 | cout << A[i]; 74 | if (i < N - 1){ 75 | cout << ","; 76 | } 77 | } 78 | cout << "]" << endl; 79 | } 80 | }; 81 | -------------------------------------------------------------------------------- /old_Range_Queries/Point_Add_Range_Sum.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct binary_indexed_tree{ 3 | int N; 4 | vector BIT; 5 | binary_indexed_tree(){ 6 | } 7 | binary_indexed_tree(int N): N(N), BIT(N + 1, 0){ 8 | } 9 | binary_indexed_tree(vector &A){ 10 | N = A.size(); 11 | BIT = vector(N + 1, 0); 12 | for (int i = 0; i < N; i++){ 13 | BIT[i + 1] = A[i]; 14 | } 15 | for (int i = 1; i < N; i++){ 16 | if (i + (i & -i) <= N){ 17 | BIT[i + (i & -i)] += BIT[i]; 18 | } 19 | } 20 | } 21 | void add(int i, T x){ 22 | i++; 23 | while (i <= N){ 24 | BIT[i] += x; 25 | i += i & -i; 26 | } 27 | } 28 | T sum(int i){ 29 | T ans = 0; 30 | while (i > 0){ 31 | ans += BIT[i]; 32 | i -= i & -i; 33 | } 34 | return ans; 35 | } 36 | T sum(int L, int R){ 37 | return sum(R) - sum(L); 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /old_Range_Queries/Point_Update_Range_Max.cpp: -------------------------------------------------------------------------------- 1 | //point update range max 2 | template 3 | struct segment_tree{ 4 | int N; 5 | vector ST; 6 | segment_tree(int n){ 7 | N = 1; 8 | while (N < n){ 9 | N *= 2; 10 | } 11 | ST = vector(N * 2 - 1, -INF); 12 | } 13 | segment_tree(vector A){ 14 | int n = A.size(); 15 | N = 1; 16 | while (N < n){ 17 | N *= 2; 18 | } 19 | ST = vector(N * 2 - 1, -INF); 20 | for (int i = 0; i < n; i++){ 21 | ST[N - 1 + i] = A[i]; 22 | } 23 | for (int i = N - 2; i >= 0; i--){ 24 | ST[i] = max(ST[i * 2 + 1], ST[i * 2 + 2]); 25 | } 26 | } 27 | T operator [](int k){ 28 | return ST[N - 1 + k]; 29 | } 30 | void update(int k, T x){ 31 | k += N - 1; 32 | ST[k] = x; 33 | while (k > 0){ 34 | k = (k - 1) / 2; 35 | ST[k] = max(ST[k * 2 + 1], ST[k * 2 + 2]); 36 | } 37 | } 38 | T range_max(int L, int R, int i, int l, int r){ 39 | if (R <= l || r <= L){ 40 | return -INF; 41 | } else if (L <= l && r <= R){ 42 | return ST[i]; 43 | } else { 44 | int m = (l + r) / 2; 45 | return max(range_max(L, R, i * 2 + 1, l, m), range_max(L, R, i * 2 + 2, m, r)); 46 | } 47 | } 48 | T range_max(int L, int R){ 49 | return range_max(L, R, 0, 0, N); 50 | } 51 | T all(){ 52 | return ST[0]; 53 | } 54 | }; 55 | -------------------------------------------------------------------------------- /old_Range_Queries/Point_Update_Range_Min.cpp: -------------------------------------------------------------------------------- 1 | //point update range min 2 | template 3 | struct segment_tree{ 4 | int N; 5 | vector ST; 6 | segment_tree(int n){ 7 | N = 1; 8 | while (N < n){ 9 | N *= 2; 10 | } 11 | ST = vector(N * 2 - 1, INF); 12 | } 13 | segment_tree(vector A){ 14 | int n = A.size(); 15 | N = 1; 16 | while (N < n){ 17 | N *= 2; 18 | } 19 | ST = vector(N * 2 - 1, INF); 20 | for (int i = 0; i < n; i++){ 21 | ST[N - 1 + i] = A[i]; 22 | } 23 | for (int i = N - 2; i >= 0; i--){ 24 | ST[i] = min(ST[i * 2 + 1], ST[i * 2 + 2]); 25 | } 26 | } 27 | T operator [](int k){ 28 | return ST[N - 1 + k]; 29 | } 30 | void update(int k, T x){ 31 | k += N - 1; 32 | ST[k] = x; 33 | while (k > 0){ 34 | k = (k - 1) / 2; 35 | ST[k] = min(ST[k * 2 + 1], ST[k * 2 + 2]); 36 | } 37 | } 38 | T range_min(int L, int R, int i, int l, int r){ 39 | if (R <= l || r <= L){ 40 | return INF; 41 | } else if (L <= l && r <= R){ 42 | return ST[i]; 43 | } else { 44 | int m = (l + r) / 2; 45 | return min(range_min(L, R, i * 2 + 1, l, m), range_min(L, R, i * 2 + 2, m, r)); 46 | } 47 | } 48 | T range_min(int L, int R){ 49 | return range_min(L, R, 0, 0, N); 50 | } 51 | T all(){ 52 | return ST[0]; 53 | } 54 | }; 55 | -------------------------------------------------------------------------------- /old_Range_Queries/Range_Add_Point_Value.cpp: -------------------------------------------------------------------------------- 1 | //range add point value 2 | template 3 | struct dual_segment_tree{ 4 | int N; 5 | vector ST; 6 | dual_segment_tree(int n){ 7 | N = 1; 8 | while (N < n){ 9 | N *= 2; 10 | } 11 | ST = vector(N * 2 - 1, 0); 12 | } 13 | dual_segment_tree(vector A){ 14 | int n = A.size(); 15 | N = 1; 16 | while (N < n){ 17 | N *= 2; 18 | } 19 | ST = vector(N * 2 - 1, 0); 20 | for (int i = 0; i < n; i++){ 21 | ST[N - 1 + i] = A[i]; 22 | } 23 | } 24 | T operator [](int k){ 25 | k += N - 1; 26 | T ans = ST[k]; 27 | while (k > 0){ 28 | k = (k - 1) / 2; 29 | ans += ST[k]; 30 | } 31 | return ans; 32 | } 33 | void range_add(int L, int R, T x, int i, int l, int r){ 34 | if (R <= l || r <= L){ 35 | return; 36 | } else if (L <= l && r <= R){ 37 | ST[i] += x; 38 | return; 39 | } else { 40 | int m = (l + r) / 2; 41 | range_add(L, R, x, i * 2 + 1, l, m); 42 | range_add(L, R, x, i * 2 + 2, m, r); 43 | return; 44 | } 45 | } 46 | void range_add(int L, int R, T x){ 47 | range_add(L, R, x, 0, 0, N); 48 | } 49 | void all_add(T x){ 50 | ST[0] += x; 51 | } 52 | }; 53 | -------------------------------------------------------------------------------- /old_Range_Queries/Range_Add_Range_Min.cpp: -------------------------------------------------------------------------------- 1 | //range add range min 2 | template 3 | struct lazy_segment_tree{ 4 | int N; 5 | vector ST; 6 | vector lazy; 7 | lazy_segment_tree(int n){ 8 | N = 1; 9 | while (N < n){ 10 | N *= 2; 11 | } 12 | ST = vector(N * 2 - 1, 0); 13 | lazy = vector(N * 2 - 1, 0); 14 | } 15 | lazy_segment_tree(vector &A){ 16 | int n = A.size(); 17 | N = 1; 18 | while (N < n){ 19 | N *= 2; 20 | } 21 | ST = vector(N * 2 - 1, 0); 22 | lazy = vector(N * 2 - 1, 0); 23 | for (int i = 0; i < n; i++){ 24 | ST[N - 1 + i] = A[i]; 25 | } 26 | for (int i = N - 2; i >= 0; i--){ 27 | ST[i] = min(ST[i * 2 + 1], ST[i * 2 + 2]); 28 | } 29 | } 30 | void eval(int i){ 31 | if (i < N - 1){ 32 | lazy[i * 2 + 1] += lazy[i]; 33 | lazy[i * 2 + 2] += lazy[i]; 34 | } 35 | ST[i] += lazy[i]; 36 | lazy[i] = 0; 37 | } 38 | void range_add(int L, int R, T x, int i, int l, int r){ 39 | eval(i); 40 | if (R <= l || r <= L){ 41 | return; 42 | } else if (L <= l && r <= R){ 43 | lazy[i] += x; 44 | eval(i); 45 | } else { 46 | int m = (l + r) / 2; 47 | range_add(L, R, x, i * 2 + 1, l, m); 48 | range_add(L, R, x, i * 2 + 2, m, r); 49 | ST[i] = min(ST[i * 2 + 1], ST[i * 2 + 2]); 50 | } 51 | } 52 | void range_add(int L, int R, T x){ 53 | range_add(L, R, x, 0, 0, N); 54 | } 55 | T range_min(int L, int R, int i, int l, int r){ 56 | eval(i); 57 | if (R <= l || r <= L){ 58 | return INF; 59 | } else if (L <= l && r <= R){ 60 | return ST[i]; 61 | } else { 62 | int m = (l + r) / 2; 63 | return min(range_min(L, R, i * 2 + 1, l, m), range_min(L, R, i * 2 + 2, m, r)); 64 | } 65 | } 66 | T range_min(int L, int R){ 67 | return range_min(L, R, 0, 0, N); 68 | } 69 | T all(){ 70 | eval(0); 71 | return ST[0]; 72 | } 73 | }; 74 | -------------------------------------------------------------------------------- /old_Range_Queries/Range_Add_Range_Sum.cpp: -------------------------------------------------------------------------------- 1 | //range add range sum 2 | template 3 | struct lazy_segment_tree{ 4 | int N; 5 | vector ST; 6 | vector lazy; 7 | lazy_segment_tree(int n){ 8 | N = 1; 9 | while (N < n){ 10 | N *= 2; 11 | } 12 | ST = vector(N * 2 - 1, 0); 13 | lazy = vector(N * 2 - 1, 0); 14 | } 15 | lazy_segment_tree(vector &a){ 16 | int n = a.size(); 17 | N = 1; 18 | while (N < n){ 19 | N *= 2; 20 | } 21 | ST = vector(N * 2 - 1, 0); 22 | lazy = vector(N * 2 - 1, 0); 23 | for (int i = 0; i < n; i++){ 24 | ST[N - 1 + i] = a[i]; 25 | } 26 | for (int i = N - 2; i >= 0; i--){ 27 | ST[i] = ST[i * 2 + 1] + ST[i * 2 + 2]; 28 | } 29 | } 30 | void eval(int i){ 31 | if (i < N - 1){ 32 | lazy[i * 2 + 1] += lazy[i] / 2; 33 | lazy[i * 2 + 2] += lazy[i] / 2; 34 | } 35 | ST[i] += lazy[i]; 36 | lazy[i] = 0; 37 | } 38 | void range_add(int L, int R, T x, int i, int l, int r){ 39 | eval(i); 40 | if (R <= l || r <= L){ 41 | return; 42 | } else if (L <= l && r <= R){ 43 | lazy[i] += (r - l) * x; 44 | eval(i); 45 | } else { 46 | int m = (l + r) / 2; 47 | range_add(L, R, x, i * 2 + 1, l, m); 48 | range_add(L, R, x, i * 2 + 2, m, r); 49 | ST[i] = ST[i * 2 + 1] + ST[i * 2 + 2]; 50 | } 51 | } 52 | void range_add(int L, int R, T x){ 53 | range_add(L, R, x, 0, 0, N); 54 | } 55 | T range_sum(int L, int R, int i, int l, int r){ 56 | eval(i); 57 | if (R <= l || r <= L){ 58 | return 0; 59 | } else if (L <= l && r <= R){ 60 | return ST[i]; 61 | } else { 62 | int m = (l + r) / 2; 63 | return range_sum(L, R, i * 2 + 1, l, m) + range_sum(L, R, i * 2 + 2, m, r); 64 | } 65 | } 66 | T range_sum(int L, int R){ 67 | return range_sum(L, R, 0, 0, N); 68 | } 69 | T all(){ 70 | eval(0); 71 | return ST[0]; 72 | } 73 | }; 74 | -------------------------------------------------------------------------------- /old_Range_Queries/Range_Chmin_Range_Min.cpp: -------------------------------------------------------------------------------- 1 | //Range Chmin Range Min 2 | template 3 | struct lazy_segment_tree{ 4 | int N; 5 | vector ST; 6 | vector lazy; 7 | lazy_segment_tree(int n){ 8 | N = 1; 9 | while (N < n){ 10 | N *= 2; 11 | } 12 | ST = vector(N * 2 - 1, INF); 13 | lazy = vector(N * 2 - 1, INF); 14 | } 15 | void eval(int i){ 16 | if (i < N - 1){ 17 | lazy[i * 2 + 1] = min(lazy[i * 2 + 1], lazy[i]); 18 | lazy[i * 2 + 2] = min(lazy[i * 2 + 2], lazy[i]); 19 | } 20 | ST[i] = min(ST[i], lazy[i]); 21 | lazy[i] = INF; 22 | } 23 | void range_chmin(int L, int R, T x, int i, int l, int r){ 24 | eval(i); 25 | if (R <= l || r <= L){ 26 | return; 27 | } else if (L <= l && r <= R){ 28 | lazy[i] = x; 29 | eval(i); 30 | } else { 31 | int m = (l + r) / 2; 32 | range_chmin(L, R, x, i * 2 + 1, l, m); 33 | range_chmin(L, R, x, i * 2 + 2, m, r); 34 | ST[i] = min(ST[i * 2 + 1], ST[i * 2 + 2]); 35 | } 36 | } 37 | void range_chmin(int L, int R, T x){ 38 | return range_chmin(L, R, x, 0, 0, N); 39 | } 40 | void chmin(int k, T x){ 41 | return range_chmin(k, k + 1, x); 42 | } 43 | T range_min(int L, int R, int i, int l, int r){ 44 | eval(i); 45 | if (R <= l || r <= L){ 46 | return INF; 47 | } else if (L <= l && r <= R){ 48 | return ST[i]; 49 | } else { 50 | int m = (l + r) / 2; 51 | return min(range_min(L, R, i * 2 + 1, l, m), range_min(L, R, i * 2 + 2, m, r)); 52 | } 53 | } 54 | T range_min(int L, int R){ 55 | return range_min(L, R, 0, 0, N); 56 | } 57 | T operator [](int k){ 58 | return range_min(k, k + 1); 59 | } 60 | }; 61 | -------------------------------------------------------------------------------- /old_Range_Queries/Range_Min.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct sparse_table{ 3 | vector> ST; 4 | sparse_table(vector &A){ 5 | int N = A.size(); 6 | int LOG = 32 - __builtin_clz(N); 7 | ST = vector>(LOG, vector(N)); 8 | for (int i = 0; i < N; i++){ 9 | ST[0][i] = A[i]; 10 | } 11 | for (int i = 0; i < LOG - 1; i++){ 12 | for (int j = 0; j < N - (1 << i); j++){ 13 | ST[i + 1][j] = min(ST[i][j], ST[i][j + (1 << i)]); 14 | } 15 | } 16 | } 17 | T range_min(int L, int R){ 18 | if (L == R){ 19 | retun INF; 20 | } 21 | int d = 31 - __builtin_clz(R - L); 22 | return min(ST[d][L], ST[d][R - (1 << d)]); 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /old_Range_Queries/Range_Sum.cpp: -------------------------------------------------------------------------------- 1 | //Range Sum 2 | template 3 | struct prefix_sum{ 4 | int N; 5 | vector S; 6 | prefix_sum(vector A){ 7 | N = A.size(); 8 | S = vector(N + 1, 0); 9 | for (int i = 0; i < N; i++){ 10 | S[i + 1] = S[i] + A[i]; 11 | } 12 | } 13 | T range_sum(int p, int q){ 14 | return S[q] - S[p]; 15 | } 16 | T all(){ 17 | return S[N]; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /old_Range_Queries/Range_Update_Add_Range_Sum.cpp: -------------------------------------------------------------------------------- 1 | //Range Update Add Range Sum 2 | template 3 | struct lazy_segment_tree{ 4 | int N; 5 | vector ST; 6 | vector> lazy; 7 | lazy_segment_tree(){ 8 | } 9 | lazy_segment_tree(int n){ 10 | N = 1; 11 | while (N < n){ 12 | N *= 2; 13 | } 14 | ST = vector(N * 2 - 1, 0); 15 | lazy = vector>(N * 2 - 1, make_pair(1, 0)); 16 | } 17 | void eval(int i, int l, int r){ 18 | if (i < N - 1){ 19 | if (lazy[i].first == 0){ 20 | lazy[i * 2 + 1] = lazy[i]; 21 | lazy[i * 2 + 2] = lazy[i]; 22 | } else { 23 | lazy[i * 2 + 1].second += lazy[i].second; 24 | lazy[i * 2 + 2].second += lazy[i].second; 25 | } 26 | } 27 | ST[i] = ST[i] * lazy[i].first + lazy[i].second * (r - l); 28 | lazy[i] = make_pair(1, 0); 29 | } 30 | void update(int L, int R, T x, int t, int i, int l, int r){ 31 | eval(i, l, r); 32 | if (r <= L || R <= l){ 33 | return; 34 | } else if (L <= l && r <= R){ 35 | lazy[i] = make_pair(t, x); 36 | eval(i, l, r); 37 | } else { 38 | int m = (l + r) / 2; 39 | update(L, R, x, t, i * 2 + 1, l, m); 40 | update(L, R, x, t, i * 2 + 2, m, r); 41 | ST[i] = ST[i * 2 + 1] + ST[i * 2 + 2]; 42 | } 43 | } 44 | void range_update(int L, int R, T x){ 45 | update(L, R, x, 0, 0, 0, N); 46 | } 47 | void range_add(int L, int R, T x){ 48 | update(L, R, x, 1, 0, 0, N); 49 | } 50 | T range_sum(int L, int R, int i, int l, int r){ 51 | eval(i, l, r); 52 | if (r <= L || R <= l){ 53 | return 0; 54 | } else if (L <= l && r <= R){ 55 | return ST[i]; 56 | } else { 57 | int m = (l + r) / 2; 58 | return range_sum(L, R, i * 2 + 1, l, m) + range_sum(L, R, i * 2 + 2, m, r); 59 | } 60 | } 61 | T range_sum(int L, int R){ 62 | return range_sum(L, R, 0, 0, N); 63 | } 64 | }; 65 | -------------------------------------------------------------------------------- /old_Range_Queries/Range_Update_Point_Value.cpp: -------------------------------------------------------------------------------- 1 | //Range Update Point Value 2 | template 3 | struct dual_segment_tree{ 4 | int N; 5 | vector> ST; 6 | int t; 7 | dual_segment_tree(int n){ 8 | N = 1; 9 | while (N < n){ 10 | N *= 2; 11 | } 12 | ST = vector>(N * 2 - 1, make_pair(0, 0)); 13 | t = 1; 14 | } 15 | dual_segment_tree(vector A){ 16 | int n = A.size(); 17 | N = 1; 18 | while (N < n){ 19 | N *= 2; 20 | } 21 | ST = vector>(N * 2 - 1, make_pair(0, 0)); 22 | for (int i = 0; i < n; i++){ 23 | ST[N - 1 + i] = make_pair(A[i], 1); 24 | } 25 | t = 2; 26 | } 27 | T operator [](int k){ 28 | k += N - 1; 29 | T ans = ST[k].first; 30 | T time = ST[k].second; 31 | while (k > 0){ 32 | k = (k - 1) / 2; 33 | if (ST[k].second > time){ 34 | ans = ST[k].first; 35 | time = ST[k].second; 36 | } 37 | } 38 | return ans; 39 | } 40 | void range_update(int L, int R, T x, int i, int l, int r){ 41 | if (R <= l || r <= L){ 42 | return; 43 | } else if (L <= l && r <= R){ 44 | ST[i] = make_pair(x, t); 45 | } else { 46 | int m = (l + r) / 2; 47 | range_update(L, R, x, i * 2 + 1, l, m); 48 | range_update(L, R, x, i * 2 + 2, m, r); 49 | } 50 | } 51 | void range_update(int L, int R, T x){ 52 | range_update(L, R, x, 0, 0, N); 53 | t++; 54 | } 55 | }; 56 | -------------------------------------------------------------------------------- /old_Range_Queries/Range_Update_Range_Min.cpp: -------------------------------------------------------------------------------- 1 | //Range Update Range Min 2 | template 3 | struct lazy_segment_tree{ 4 | int N; 5 | vector ST; 6 | vector lazy; 7 | lazy_segment_tree(int n){ 8 | N = 1; 9 | while (N < n){ 10 | N *= 2; 11 | } 12 | ST = vector(N * 2 - 1, INF); 13 | lazy = vector(N * 2 - 1, -1); 14 | } 15 | lazy_segment_tree(vector A){ 16 | int n = A.size(); 17 | N = 1; 18 | while (N < n){ 19 | N *= 2; 20 | } 21 | ST = vector(N * 2 - 1, INF); 22 | lazy = vector(N * 2 - 1, -1); 23 | for (int i = 0; i < n; i++){ 24 | ST[N - 1 + i] = A[i]; 25 | } 26 | for (int i = N - 2; i >= 0; i--){ 27 | ST[i] = min(ST[i * 2 + 1], ST[i * 2 + 2]); 28 | } 29 | } 30 | void eval(int i){ 31 | if (lazy[i] != -1){ 32 | if (i < N - 1){ 33 | lazy[i * 2 + 1] = lazy[i]; 34 | lazy[i * 2 + 2] = lazy[i]; 35 | } 36 | ST[i] = lazy[i]; 37 | lazy[i] = -1; 38 | } 39 | } 40 | void range_update(int L, int R, T x, int i, int l, int r){ 41 | eval(i); 42 | if (R <= l || r <= L){ 43 | return; 44 | } else if (L <= l && r <= R){ 45 | lazy[i] = x; 46 | eval(i); 47 | } else { 48 | int m = (l + r) / 2; 49 | range_update(L, R, x, i * 2 + 1, l, m); 50 | range_update(L, R, x, i * 2 + 2, m, r); 51 | ST[i] = min(ST[i * 2 + 1], ST[i * 2 + 2]); 52 | } 53 | } 54 | void range_update(int L, int R, T x){ 55 | return range_update(L, R, x, 0, 0, N); 56 | } 57 | T range_min(int L, int R, int i, int l, int r){ 58 | eval(i); 59 | if (R <= l || r <= L){ 60 | return INF; 61 | } else if (L <= l && r <= R){ 62 | return ST[i]; 63 | } else { 64 | int m = (l + r) / 2; 65 | return min(range_min(L, R, i * 2 + 1, l, m), range_min(L, R, i * 2 + 2, m, r)); 66 | } 67 | } 68 | T range_min(int L, int R){ 69 | return range_min(L, R, 0, 0, N); 70 | } 71 | }; 72 | -------------------------------------------------------------------------------- /old_Range_Queries/Range_Update_Range_Sum.cpp: -------------------------------------------------------------------------------- 1 | //Range Update Range Sum 2 | template 3 | struct lazy_segment_tree{ 4 | int N; 5 | vector ST; 6 | vector lazy; 7 | lazy_segment_tree(int n){ 8 | N = 1; 9 | while (N < n){ 10 | N *= 2; 11 | } 12 | ST = vector(N * 2 - 1, 0); 13 | lazy = vector(N * 2 - 1, e); 14 | } 15 | lazy_segment_tree(vector &A){ 16 | int n = A.size(); 17 | N = 1; 18 | while (N < n){ 19 | N *= 2; 20 | } 21 | ST = vector(N * 2 - 1, 0); 22 | lazy = vector(N * 2 - 1, e); 23 | for (int i = 0; i < n; i++){ 24 | ST[N - 1 + i] = A[i]; 25 | } 26 | for (int i = N - 2; i >= 0; i--){ 27 | ST[i] = ST[i * 2 + 1] + ST[i * 2 + 2]; 28 | } 29 | } 30 | void eval(int i, int l, int r){ 31 | if (lazy[i] != e){ 32 | if (i < N - 1){ 33 | lazy[i * 2 + 1] = lazy[i]; 34 | lazy[i * 2 + 2] = lazy[i]; 35 | } 36 | ST[i] = lazy[i] * (r - l); 37 | lazy[i] = e; 38 | } 39 | } 40 | void range_update(int L, int R, T x, int i, int l, int r){ 41 | eval(i, l, r); 42 | if (R <= l || r <= L){ 43 | return; 44 | } else if (L <= l && r <= R){ 45 | lazy[i] = x; 46 | eval(i, l, r); 47 | } else { 48 | int m = (l + r) / 2; 49 | range_update(L, R, x, i * 2 + 1, l, m); 50 | range_update(L, R, x, i * 2 + 2, m, r); 51 | ST[i] = ST[i * 2 + 1] + ST[i * 2 + 2]; 52 | } 53 | } 54 | void range_update(int L, int R, T x){ 55 | range_update(L, R, x, 0, 0, N); 56 | } 57 | T range_sum(int L, int R, int i, int l, int r){ 58 | eval(i, l, r); 59 | if (R <= l || r <= L){ 60 | return 0; 61 | } else if (L <= l && r <= R){ 62 | return ST[i]; 63 | } else { 64 | int m = (l + r) / 2; 65 | return range_sum(L, R, i * 2 + 1, l, m) + range_sum(L, R, i * 2 + 2, m, r); 66 | } 67 | } 68 | T range_sum(int L, int R){ 69 | return range_sum(L, R, 0, 0, N); 70 | } 71 | }; 72 | -------------------------------------------------------------------------------- /old_String/LCP_Array.cpp: -------------------------------------------------------------------------------- 1 | vector lcp_array(string &S, vector &SA){ 2 | int N = S.size(); 3 | vector rank(N); 4 | for (int i = 0; i < N; i++){ 5 | rank[SA[i]] = i; 6 | } 7 | vector lcp(N - 1, 0); 8 | int h = 0; 9 | for (int i = 0; i < N; i++){ 10 | if (rank[i] > 0){ 11 | int prev = SA[rank[i] - 1]; 12 | if (h > 0){ 13 | h--; 14 | } 15 | while (i + h < N && prev + h < N){ 16 | if (S[i + h] != S[prev + h]){ 17 | break; 18 | } 19 | h++; 20 | } 21 | lcp[rank[i] - 1] = h; 22 | } 23 | } 24 | return lcp; 25 | } 26 | -------------------------------------------------------------------------------- /old_String/Rolling_Hash.cpp: -------------------------------------------------------------------------------- 1 | struct rolling_hash{ 2 | vector S; 3 | rolling_hash(string s){ 4 | int N = s.size(); 5 | S = vector(N + 1, 0); 6 | for (int i = N - 1; i >= 0; i--){ 7 | S[i] = (S[i + 1] * BASE + s[i]) % MOD; 8 | } 9 | } 10 | long long get(int L, int R){ 11 | return (S[L] - S[R] * POW[R - L] % MOD + MOD) % MOD; 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /other/monoids/affine_sum.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | struct affine_sum{ 3 | int cnt; 4 | long long sum; 5 | affine_sum(): cnt(0), sum(0){ 6 | } 7 | }; 8 | affine_sum op(affine_sum A, affine_sum B){ 9 | A.cnt += B.cnt; 10 | A.sum += B.sum; 11 | A.sum %= MOD; 12 | return A; 13 | } 14 | affine_sum mp(linear f, affine_sum A){ 15 | A.sum = (A.sum * f.a + A.cnt * f.b) % MOD; 16 | return A; 17 | } -------------------------------------------------------------------------------- /other/monoids/linear.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | struct linear{ 3 | long long a, b; 4 | linear(){ 5 | a = 1; 6 | b = 0; 7 | } 8 | linear(int a, int b): a(a), b(b){ 9 | } 10 | }; 11 | linear composite(linear A, linear B){ 12 | return linear(A.a * B.a % MOD, (A.b * B.a + B.b) % MOD); 13 | } 14 | int value(linear A, int x){ 15 | return (A.a * x + A.b) % MOD; 16 | } -------------------------------------------------------------------------------- /other/poker_hands.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | struct card{ 3 | char suit; 4 | int rank; 5 | card(){ 6 | } 7 | bool operator <(card C){ 8 | return rank < C.rank || rank == C.rank && suit < C.suit; 9 | } 10 | }; 11 | istream& operator >>(istream& is, card& C){ 12 | string S; 13 | is >> S; 14 | C.suit = S[0]; 15 | if (S[1] == 'A'){ 16 | C.rank = 14; 17 | } else if (S[1] == 'K'){ 18 | C.rank = 13; 19 | } else if (S[1] == 'Q'){ 20 | C.rank = 12; 21 | } else if (S[1] == 'J'){ 22 | C.rank = 11; 23 | } else if (S[1] == 'T'){ 24 | C.rank = 10; 25 | } else { 26 | C.rank = S[1] - '0'; 27 | } 28 | return is; 29 | } 30 | enum poker_hand{HIGH_CARD, ONE_PAIR, TWO_PAIR, THREE_OF_A_KIND, STRAIGHT, FLUSH, FULL_HOUSE, FOUR_OF_A_KIND, STRAIGHT_FLUSH, ROYAL_STRAIGHT_FLUSH}; 31 | vector hand(array C){ 32 | sort(C.begin(), C.end()); 33 | bool is_flush = true; 34 | for (int i = 1; i < 5; i++){ 35 | if (C[i].suit != C[0].suit){ 36 | is_flush = false; 37 | } 38 | } 39 | if (is_flush && C[4].rank == 14 && C[0].rank == 10){ 40 | return {ROYAL_STRAIGHT_FLUSH}; 41 | } else if (is_flush && C[4].rank - C[0].rank == 4){ 42 | return {STRAIGHT_FLUSH, C[4].rank}; 43 | } else if (is_flush && C[3].rank == 5 && C[4].rank == 14){ 44 | return {STRAIGHT_FLUSH, 5}; 45 | } else if (C[0].rank == C[3].rank){ 46 | return {FOUR_OF_A_KIND, C[0].rank, C[4].rank}; 47 | } else if (C[1].rank == C[4].rank){ 48 | return {FOUR_OF_A_KIND, C[1].rank, C[0].rank}; 49 | } else if (C[0].rank == C[2].rank && C[3].rank == C[4].rank){ 50 | return {FULL_HOUSE, C[0].rank, C[3].rank}; 51 | } else if (C[2].rank == C[4].rank && C[0].rank == C[1].rank){ 52 | return {FULL_HOUSE, C[2].rank, C[0].rank}; 53 | } else if (is_flush){ 54 | return {FLUSH, C[4].rank, C[3].rank, C[2].rank, C[1].rank, C[0].rank}; 55 | } else if (C[1].rank - C[0].rank == 1 && C[2].rank - C[1].rank == 1 && C[3].rank - C[2].rank == 1 && C[4].rank - C[3].rank == 1){ 56 | return {STRAIGHT, C[4].rank}; 57 | } else if (C[0].rank == 2 && C[1].rank == 3 && C[2].rank == 4 && C[3].rank == 5 && C[4].rank == 14){ 58 | return {STRAIGHT, 5}; 59 | } else if (C[0].rank == C[2].rank){ 60 | return {THREE_OF_A_KIND, C[0].rank, C[4].rank, C[3].rank}; 61 | } else if (C[1].rank == C[3].rank){ 62 | return {THREE_OF_A_KIND, C[1].rank, C[4].rank, C[0].rank}; 63 | } else if (C[2].rank == C[4].rank){ 64 | return {THREE_OF_A_KIND, C[2].rank, C[1].rank, C[0].rank}; 65 | } else if (C[0].rank == C[1].rank && C[2].rank == C[3].rank){ 66 | return {TWO_PAIR, C[2].rank, C[0].rank, C[4].rank}; 67 | } else if (C[0].rank == C[1].rank && C[3].rank == C[4].rank){ 68 | return {TWO_PAIR, C[3].rank, C[0].rank, C[2].rank}; 69 | } else if (C[1].rank == C[2].rank && C[3].rank == C[4].rank){ 70 | return {TWO_PAIR, C[3].rank, C[1].rank, C[0].rank}; 71 | } else if (C[0].rank == C[1].rank){ 72 | return {ONE_PAIR, C[0].rank, C[4].rank, C[3].rank, C[2].rank}; 73 | } else if (C[1].rank == C[2].rank){ 74 | return {ONE_PAIR, C[1].rank, C[4].rank, C[3].rank, C[0].rank}; 75 | } else if (C[2].rank == C[3].rank){ 76 | return {ONE_PAIR, C[2].rank, C[4].rank, C[1].rank, C[0].rank}; 77 | } else if (C[3].rank == C[4].rank){ 78 | return {ONE_PAIR, C[3].rank, C[2].rank, C[1].rank, C[0].rank}; 79 | } else { 80 | return {HIGH_CARD, C[4].rank, C[3].rank, C[2].rank, C[1].rank, C[0].rank}; 81 | } 82 | } -------------------------------------------------------------------------------- /string/lcp_array.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "suffix_array.hpp" 3 | template 4 | vector lcp_array(const T &A, vector &SA){ 5 | int N = A.size(); 6 | vector rank(N); 7 | for (int i = 0; i < N; i++){ 8 | rank[SA[i]] = i; 9 | } 10 | vector lcp(N - 1, 0); 11 | int h = 0; 12 | for (int i = 0; i < N; i++){ 13 | if (rank[i] > 0){ 14 | int prev = SA[rank[i] - 1]; 15 | if (h > 0){ 16 | h--; 17 | } 18 | while (i + h < N && prev + h < N){ 19 | if (A[i + h] != A[prev + h]){ 20 | break; 21 | } 22 | h++; 23 | } 24 | lcp[rank[i] - 1] = h; 25 | } 26 | } 27 | return lcp; 28 | } -------------------------------------------------------------------------------- /string/manacher.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | template 3 | vector manacher(const T &A){ 4 | int N = A.size(); 5 | vector ans(N, 0); 6 | int i = 0, j = 0; 7 | while (i < N){ 8 | while (i >= j && i + j < N && A[i - j] == A[i + j]){ 9 | j++; 10 | } 11 | ans[i] = j; 12 | int k = 1; 13 | while (i >= k && i + k < N && k + ans[i - k] < j){ 14 | ans[i + k] = ans[i - k]; 15 | k++; 16 | } 17 | i += k; 18 | j -= k; 19 | } 20 | return ans; 21 | } -------------------------------------------------------------------------------- /string/suffix_array.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | vector suffix_array(const vector &A, int mx){ 3 | int N = A.size(); 4 | vector sum(mx + 1, 0); 5 | for (int i = 0; i < N; i++){ 6 | sum[A[i] + 1]++; 7 | } 8 | for (int i = 0; i < mx; i++){ 9 | sum[i + 1] += sum[i]; 10 | } 11 | vector is_s(N); 12 | is_s[N - 1] = false; 13 | for (int i = N - 2; i >= 0; i--){ 14 | is_s[i] = A[i] < A[i + 1] || A[i] == A[i + 1] && is_s[i + 1]; 15 | } 16 | vector id(N, -1); 17 | vector pos; 18 | int M = 0; 19 | for (int i = 1; i < N; i++){ 20 | if (is_s[i] && !is_s[i - 1]){ 21 | id[i] = M; 22 | pos.push_back(i); 23 | M++; 24 | } 25 | } 26 | vector sa(N); 27 | auto induce = [&](vector& lms){ 28 | sa = vector(N, -1); 29 | vector used(N, false); 30 | vector p(mx); 31 | vector p2(mx); 32 | for (int i = 0; i < mx; i++){ 33 | p[i] = sum[i + 1] - 1; 34 | p2[i] = sum[i]; 35 | } 36 | for (int i = M - 1; i >= 0; i--){ 37 | sa[p[A[lms[i]]]] = lms[i]; 38 | p[A[lms[i]]]--; 39 | used[lms[i]] = true; 40 | } 41 | sa[p2[A[N - 1]]] = N - 1; 42 | p2[A[N - 1]]++; 43 | used[N - 1] = true; 44 | for (int i = 0; i < N; i++){ 45 | if (sa[i] > 0){ 46 | if (!is_s[sa[i] - 1] && !used[sa[i] - 1]){ 47 | sa[p2[A[sa[i] - 1]]] = sa[i] - 1; 48 | p2[A[sa[i] - 1]]++; 49 | used[sa[i] - 1] = true; 50 | } 51 | } 52 | } 53 | for (int i = 0; i < N; i++){ 54 | if (sa[i] != -1){ 55 | if (id[sa[i]] != -1){ 56 | used[sa[i]] = false; 57 | sa[i] = -1; 58 | } 59 | } 60 | } 61 | for (int i = 0; i < mx; i++){ 62 | p[i] = sum[i + 1] - 1; 63 | } 64 | for (int i = N - 1; i >= 0; i--){ 65 | if (sa[i] > 0){ 66 | if (is_s[sa[i] - 1] && !used[sa[i] - 1]){ 67 | sa[p[A[sa[i] - 1]]] = sa[i] - 1; 68 | p[A[sa[i] - 1]]--; 69 | used[sa[i] - 1] = true; 70 | } 71 | } 72 | } 73 | }; 74 | induce(pos); 75 | if (M == 0){ 76 | return sa; 77 | } 78 | vector lms; 79 | for (int i = 0; i < N; i++){ 80 | if (id[sa[i]] != -1){ 81 | lms.push_back(sa[i]); 82 | } 83 | } 84 | vector c(M); 85 | c[0] = 0; 86 | for (int i = 0; i < M - 1; i++){ 87 | c[i + 1] = c[i]; 88 | int x = lms[i]; 89 | int y = lms[i + 1]; 90 | bool ok = true; 91 | while (x < N && y < N){ 92 | if (A[x] != A[y]){ 93 | ok = false; 94 | break; 95 | } 96 | x++; 97 | y++; 98 | if (id[x] != -1){ 99 | if (id[y] == -1){ 100 | ok = false; 101 | } 102 | break; 103 | } 104 | } 105 | if (x == N || y == N){ 106 | ok = false; 107 | } 108 | if (!ok){ 109 | c[i + 1]++; 110 | } 111 | } 112 | vector rec(M); 113 | for (int i = 0; i < M; i++){ 114 | rec[id[lms[i]]] = c[i]; 115 | } 116 | vector sa2 = suffix_array(rec, c[M - 1] + 1); 117 | vector pos2(M); 118 | for (int i = 0; i < M; i++){ 119 | pos2[i] = pos[sa2[i]]; 120 | } 121 | induce(pos2); 122 | return sa; 123 | } 124 | vector suffix_array(const string &S){ 125 | int N = S.size(); 126 | vector A(N); 127 | for (int i = 0; i < N; i++){ 128 | A[i] = S[i]; 129 | } 130 | return suffix_array(A, 256); 131 | } -------------------------------------------------------------------------------- /string/z_algorithm.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | template 3 | vector z_algorithm(const T &A){ 4 | int N = A.size(); 5 | vector Z(N, 0); 6 | for (int i = 1, j = 0; i < N; i++){ 7 | if (i + Z[i - j] < j + Z[j]){ 8 | Z[i] = Z[i - j]; 9 | } else { 10 | int k = max(0, j + Z[j] - i); 11 | while (i + k < N && A[k] == A[i + k]){ 12 | k++; 13 | } 14 | Z[i] = k; 15 | j = i; 16 | } 17 | } 18 | Z[0] = N; 19 | return Z; 20 | } -------------------------------------------------------------------------------- /test/aoj/dsl/dsl_1_a.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_1_A" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/unionfind/unionfind.hpp" 5 | int main(){ 6 | int n, q; 7 | cin >> n >> q; 8 | unionfind UF(n); 9 | for (int i = 0; i < q; i++){ 10 | int com, x, y; 11 | cin >> com >> x >> y; 12 | if (com == 0){ 13 | UF.unite(x, y); 14 | } 15 | if (com == 1){ 16 | if (UF.same(x, y)){ 17 | cout << 1 << endl; 18 | } else { 19 | cout << 0 << endl; 20 | } 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /test/aoj/dsl/dsl_2_a.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_A" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/sequence/segment_tree.hpp" 5 | int main(){ 6 | int n, q; 7 | cin >> n >> q; 8 | segment_tree ST(n, [](int a, int b){return min(a, b);}, 2147483647); 9 | for (int i = 0; i < q; i++){ 10 | int com, x, y; 11 | cin >> com >> x >> y; 12 | if (com == 0){ 13 | ST.update(x, y); 14 | } 15 | if (com == 1){ 16 | y++; 17 | cout << ST.query(x, y) << endl; 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /test/aoj/dsl/dsl_2_b.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_B" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/sequence/binary_indexed_tree.hpp" 5 | int main(){ 6 | int n, q; 7 | cin >> n >> q; 8 | binary_indexed_tree BIT(n, plus(), 0); 9 | for (int i = 0; i < q; i++){ 10 | int com, x, y; 11 | cin >> com >> x >> y; 12 | if (com == 0){ 13 | x--; 14 | BIT.add(x, y); 15 | } 16 | if (com == 1){ 17 | x--; 18 | cout << BIT.sum(y) - BIT.sum(x) << endl; 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /test/aoj/dsl/dsl_2_b_2.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_B" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/sequence/invertible_binary_indexed_tree.hpp" 5 | int main(){ 6 | int n, q; 7 | cin >> n >> q; 8 | invertible_binary_indexed_tree BIT(n, plus(), negate(), 0); 9 | for (int i = 0; i < q; i++){ 10 | int com, x, y; 11 | cin >> com >> x >> y; 12 | if (com == 0){ 13 | x--; 14 | BIT.add(x, y); 15 | } 16 | if (com == 1){ 17 | x--; 18 | cout << BIT.sum(x, y) << endl; 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /test/aoj/dsl/dsl_2_b_3.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_B" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/sequence/segment_tree.hpp" 5 | int main(){ 6 | int n, q; 7 | cin >> n >> q; 8 | vector a(n); 9 | segment_tree ST(n, plus(), 0); 10 | for (int i = 0; i < q; i++){ 11 | int com, x, y; 12 | cin >> com >> x >> y; 13 | if (com == 0){ 14 | x--; 15 | a[x] += y; 16 | ST.update(x, a[x]); 17 | } 18 | if (com == 1){ 19 | x--; 20 | cout << ST.query(x, y) << endl; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /test/aoj/dsl/dsl_2_d.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_D" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/sequence/commutative_dual_segment_tree.hpp" 5 | int main(){ 6 | int n, q; 7 | cin >> n >> q; 8 | commutative_dual_segment_tree> ST(n, [](pair a, pair b){return max(a, b);}, make_pair(-1, 2147483647)); 9 | for (int i = 0; i < q; i++){ 10 | int c; 11 | cin >> c; 12 | if (c == 0){ 13 | int s, t, x; 14 | cin >> s >> t >> x; 15 | t++; 16 | ST.range_apply(s, t, make_pair(i, x)); 17 | } 18 | if (c == 1){ 19 | int t; 20 | cin >> t; 21 | cout << ST[t].second << endl; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /test/aoj/dsl/dsl_2_e.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_E" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/sequence/dual_binary_indexed_tree.hpp" 5 | int main(){ 6 | int n, q; 7 | cin >> n >> q; 8 | dual_binary_indexed_tree BIT(n, plus(), 0); 9 | for (int i = 0; i < q; i++){ 10 | int c; 11 | cin >> c; 12 | if (c == 0){ 13 | int s, t, x; 14 | cin >> s >> t >> x; 15 | s--; 16 | BIT.add(s, -x); 17 | BIT.add(t, x); 18 | } 19 | if (c == 1){ 20 | int t; 21 | cin >> t; 22 | t--; 23 | cout << BIT[t] << endl; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /test/aoj/dsl/dsl_2_e_2.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_E" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/sequence/dual_invertible_binary_indexed_tree.hpp" 5 | int main(){ 6 | int n, q; 7 | cin >> n >> q; 8 | dual_invertible_binary_indexed_tree BIT(n, plus(), negate(), 0); 9 | for (int i = 0; i < q; i++){ 10 | int c; 11 | cin >> c; 12 | if (c == 0){ 13 | int s, t, x; 14 | cin >> s >> t >> x; 15 | s--; 16 | BIT.add(s, t, x); 17 | } 18 | if (c == 1){ 19 | int t; 20 | cin >> t; 21 | t--; 22 | cout << BIT[t] << endl; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /test/aoj/dsl/dsl_2_e_3.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_E" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/sequence/commutative_dual_segment_tree.hpp" 5 | int main(){ 6 | int n, q; 7 | cin >> n >> q; 8 | commutative_dual_segment_tree ST(n, plus(), 0); 9 | for (int i = 0; i < q; i++){ 10 | int c; 11 | cin >> c; 12 | if (c == 0){ 13 | int s, t, x; 14 | cin >> s >> t >> x; 15 | s--; 16 | ST.range_apply(s, t, x); 17 | } 18 | if (c == 1){ 19 | int t; 20 | cin >> t; 21 | t--; 22 | cout << ST[t] << endl; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /test/aoj/dsl/dsl_2_f.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_F" 2 | #include 3 | using namespace std; 4 | const int INF = 2147483647; 5 | #include "../../../data_structure/sequence/lazy_segment_tree.hpp" 6 | int main(){ 7 | int n, q; 8 | cin >> n >> q; 9 | function op = [](int a, int b){ 10 | return min(a, b); 11 | }; 12 | function mp = [](int a, int b){ 13 | if (a == -1){ 14 | return b; 15 | } else { 16 | return a; 17 | } 18 | }; 19 | function comp = [](int a, int b){ 20 | if (b == -1){ 21 | return a; 22 | } else { 23 | return b; 24 | } 25 | }; 26 | lazy_segment_tree ST(n, op, mp, comp, INF, -1); 27 | for (int i = 0; i < q; i++){ 28 | int c; 29 | cin >> c; 30 | if (c == 0){ 31 | int s, t, x; 32 | cin >> s >> t >> x; 33 | t++; 34 | ST.range_apply(s, t, x); 35 | } 36 | if (c == 1){ 37 | int s, t; 38 | cin >> s >> t; 39 | t++; 40 | cout << ST.range_fold(s, t) << endl; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /test/aoj/dsl/dsl_2_g.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_G" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/sequence/lazy_segment_tree.hpp" 5 | struct monoid{ 6 | int cnt; 7 | long long sum; 8 | monoid(): cnt(0), sum(0){ 9 | } 10 | }; 11 | int main(){ 12 | int n, q; 13 | cin >> n >> q; 14 | vector A(n); 15 | for (int i = 0; i < n; i++){ 16 | A[i].cnt = 1; 17 | } 18 | function op = [](monoid a, monoid b){ 19 | a.cnt += b.cnt; 20 | a.sum += b.sum; 21 | return a; 22 | }; 23 | function mp = [](int a, monoid b){ 24 | b.sum += (long long) a * b.cnt; 25 | return b; 26 | }; 27 | lazy_segment_tree ST(A, op, mp, plus(), monoid(), 0); 28 | for (int i = 0; i < q; i++){ 29 | int c; 30 | cin >> c; 31 | if (c == 0){ 32 | int s, t, x; 33 | cin >> s >> t >> x; 34 | s--; 35 | ST.range_apply(s, t, x); 36 | } 37 | if (c == 1){ 38 | int s, t; 39 | cin >> s >> t; 40 | s--; 41 | cout << ST.range_fold(s, t).sum << endl; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /test/aoj/dsl/dsl_2_h.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_H" 2 | #include 3 | using namespace std; 4 | const int INF = 1000000000; 5 | #include "../../../data_structure/sequence/lazy_segment_tree.hpp" 6 | int main(){ 7 | int n, q; 8 | cin >> n >> q; 9 | vector a(n, 0); 10 | function op = [](int a, int b){return min(a, b);}; 11 | lazy_segment_tree ST(a, op, plus(), plus(), INF, 0); 12 | for (int i = 0; i < q; i++){ 13 | int c; 14 | cin >> c; 15 | if (c == 0){ 16 | int s, t, x; 17 | cin >> s >> t >> x; 18 | t++; 19 | ST.range_apply(s, t, x); 20 | } 21 | if (c == 1){ 22 | int s, t; 23 | cin >> s >> t; 24 | t++; 25 | cout << ST.range_fold(s, t) << endl; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /test/aoj/dsl/dsl_2_i.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_I" 2 | #include 3 | using namespace std; 4 | const int e = 100000; 5 | #include "../../../data_structure/sequence/lazy_segment_tree.hpp" 6 | struct monoid{ 7 | int cnt, sum; 8 | monoid(): cnt(0), sum(0){ 9 | } 10 | }; 11 | int main(){ 12 | int n, q; 13 | cin >> n >> q; 14 | vector A(n); 15 | for (int i = 0; i < n; i++){ 16 | A[i].cnt = 1; 17 | } 18 | function op = [](monoid a, monoid b){ 19 | a.cnt += b.cnt; 20 | a.sum += b.sum; 21 | return a; 22 | }; 23 | function mp = [](int a, monoid b){ 24 | if (a != e){ 25 | b.sum = a * b.cnt; 26 | } 27 | return b; 28 | }; 29 | function comp = [](int a, int b){ 30 | if (b == e){ 31 | return a; 32 | } else { 33 | return b; 34 | } 35 | }; 36 | lazy_segment_tree ST(A, op, mp, comp, monoid(), e); 37 | for (int i = 0; i < q; i++){ 38 | int c; 39 | cin >> c; 40 | if (c == 0){ 41 | int s, t, x; 42 | cin >> s >> t >> x; 43 | t++; 44 | ST.range_apply(s, t, x); 45 | } 46 | if (c == 1){ 47 | int s, t; 48 | cin >> s >> t; 49 | t++; 50 | cout << ST.range_fold(s, t).sum << endl; 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /test/aoj/dsl/dsl_5_a.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_5_A" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/sequence/dual_binary_indexed_tree.hpp" 5 | int main(){ 6 | int N, T; 7 | cin >> N >> T; 8 | dual_binary_indexed_tree BIT(T, plus(), 0); 9 | for (int i = 0; i < N; i++){ 10 | int l, r; 11 | cin >> l >> r; 12 | BIT.add(l, -1); 13 | BIT.add(r, 1); 14 | } 15 | vector S = BIT.get(); 16 | int ans = 0; 17 | for (int i = 0; i < T; i++){ 18 | ans = max(ans, S[i]); 19 | } 20 | cout << ans << endl; 21 | } -------------------------------------------------------------------------------- /test/aoj/dsl/dsl_5_a_2.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_5_A" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/sequence/dual_invertible_binary_indexed_tree.hpp" 5 | int main(){ 6 | int N, T; 7 | cin >> N >> T; 8 | dual_invertible_binary_indexed_tree BIT(T, plus(), negate(), 0); 9 | for (int i = 0; i < N; i++){ 10 | int l, r; 11 | cin >> l >> r; 12 | BIT.add(l, r, 1); 13 | } 14 | vector S = BIT.get(); 15 | int ans = 0; 16 | for (int i = 0; i < T; i++){ 17 | ans = max(ans, S[i]); 18 | } 19 | cout << ans << endl; 20 | } -------------------------------------------------------------------------------- /test/aoj/dsl/dsl_5_a_3.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_5_A" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/sequence/dual_disjoint_sparse_table.hpp" 5 | int main(){ 6 | int N, T; 7 | cin >> N >> T; 8 | dual_disjoint_sparse_table DST(T, plus(), 0); 9 | for (int i = 0; i < N; i++){ 10 | int l, r; 11 | cin >> l >> r; 12 | DST.apply(l, r, 1); 13 | } 14 | vector S = DST.get(); 15 | int ans = 0; 16 | for (int i = 0; i < T; i++){ 17 | ans = max(ans, S[i]); 18 | } 19 | cout << ans << endl; 20 | } -------------------------------------------------------------------------------- /test/aoj/grl/grl_3_a.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_3_A" 2 | #include 3 | using namespace std; 4 | #include "../../../graph/block_cut_tree.hpp" 5 | int main(){ 6 | int N, M; 7 | cin >> N >> M; 8 | vector> E(N); 9 | for (int i = 0; i < M; i++){ 10 | int s, t; 11 | cin >> s >> t; 12 | E[s].push_back(t); 13 | E[t].push_back(s); 14 | } 15 | block_cut_tree G(E); 16 | for (int i = 0; i < N; i++){ 17 | if (G.art[i]){ 18 | cout << i << endl; 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /test/aoj/grl/grl_3_a_2.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_3_A" 2 | #include 3 | using namespace std; 4 | #include "../../../graph/extended_block_cut_tree.hpp" 5 | int main(){ 6 | int N, M; 7 | cin >> N >> M; 8 | vector> E(N); 9 | for (int i = 0; i < M; i++){ 10 | int s, t; 11 | cin >> s >> t; 12 | E[s].push_back(t); 13 | E[t].push_back(s); 14 | } 15 | extended_block_cut_tree T(E); 16 | for (int i = 0; i < N; i++){ 17 | if (T[i].size() >= 2){ 18 | cout << i << endl; 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /test/aoj/grl/grl_3_b.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_3_B" 2 | #include 3 | using namespace std; 4 | #include "../../../graph/two_edge_connected_components.hpp" 5 | int main(){ 6 | int N, M; 7 | cin >> N >> M; 8 | vector> E(N); 9 | for (int i = 0; i < M; i++){ 10 | int s, t; 11 | cin >> s >> t; 12 | E[s].push_back(t); 13 | E[t].push_back(s); 14 | } 15 | two_edge_connected_components G(E); 16 | vector> ans; 17 | for (int i = 0; i < N; i++){ 18 | for (int j : E[i]){ 19 | if (j > i && G[i] != G[j]){ 20 | ans.push_back(make_pair(i, j)); 21 | } 22 | } 23 | } 24 | sort(ans.begin(), ans.end()); 25 | int cnt = ans.size(); 26 | for (int i = 0; i < cnt; i++){ 27 | cout << ans[i].first << ' ' << ans[i].second << endl; 28 | } 29 | } -------------------------------------------------------------------------------- /test/aoj/grl/grl_3_c.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_3_C" 2 | #include 3 | using namespace std; 4 | #include "../../../graph/strongly_connected_components.hpp" 5 | int main(){ 6 | int N, M; 7 | cin >> N >> M; 8 | vector> E(N); 9 | for (int i = 0; i < M; i++){ 10 | int s, t; 11 | cin >> s >> t; 12 | E[s].push_back(t); 13 | } 14 | strongly_connected_components G(E); 15 | int Q; 16 | cin >> Q; 17 | for (int i = 0; i < Q; i++){ 18 | int u, v; 19 | cin >> u >> v; 20 | if (G[u] == G[v]){ 21 | cout << 1 << endl; 22 | } else { 23 | cout << 0 << endl; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /test/aoj/itp/itp1_6_a.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_6_A" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/sequence/wavelet_matrix.hpp" 5 | int main(){ 6 | int n; 7 | cin >> n; 8 | vector a(n); 9 | for (int i = 0; i < n; i++){ 10 | cin >> a[i]; 11 | } 12 | wavelet_matrix WM(a); 13 | for (int i = n - 1; i >= 0; i--){ 14 | cout << WM[i]; 15 | if (i > 0){ 16 | cout << ' '; 17 | } 18 | } 19 | cout << endl; 20 | } -------------------------------------------------------------------------------- /test/aoj/other/1508.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1508" 2 | #include 3 | using namespace std; 4 | const int INF = 10000000; 5 | #include "../../../data_structure/bbst/splay_tree.hpp" 6 | int main(){ 7 | int n, q; 8 | cin >> n >> q; 9 | vector a(n); 10 | for (int i = 0; i < n; i++){ 11 | cin >> a[i]; 12 | } 13 | function op = [](int x, int y){ 14 | return min(x, y); 15 | }; 16 | splay_tree ST(a, op, INF); 17 | for (int i = 0; i < q; i++){ 18 | int x, y, z; 19 | cin >> x >> y >> z; 20 | if (x == 0){ 21 | splay_tree::node* v = ST.get(z); 22 | int s = v->val; 23 | ST.erase(v); 24 | ST.insert(y, s); 25 | } 26 | if (x == 1){ 27 | z++; 28 | cout << ST.query(y, z) << endl; 29 | } 30 | if (x == 2){ 31 | ST.set(y, z); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /test/aoj/other/1508_2.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1508" 2 | #include 3 | using namespace std; 4 | const int INF = 10000000; 5 | #include "../../../data_structure/bbst/splay_tree.hpp" 6 | int main(){ 7 | int n, q; 8 | cin >> n >> q; 9 | vector a(n); 10 | for (int i = 0; i < n; i++){ 11 | cin >> a[i]; 12 | } 13 | function op = [](int x, int y){ 14 | return min(x, y); 15 | }; 16 | splay_tree ST(a, op, INF); 17 | for (int i = 0; i < q; i++){ 18 | int x, y, z; 19 | cin >> x >> y >> z; 20 | if (x == 0){ 21 | z++; 22 | pair::node*, splay_tree::node*> A = ST.split(z - 1); 23 | pair::node*, splay_tree::node*> B = ST.split(A.first, y); 24 | pair::node*, splay_tree::node*> C = ST.split(A.second, 1); 25 | splay_tree::node* l = ST.merge(B.first, C.first); 26 | splay_tree::node* r = ST.merge(B.second, C.second); 27 | ST.merge(l, r); 28 | } 29 | if (x == 1){ 30 | z++; 31 | pair::node*, splay_tree::node*> A = ST.split(z); 32 | pair::node*, splay_tree::node*> B = ST.split(A.first, y); 33 | cout << B.second->sum << endl; 34 | splay_tree::node* l = ST.merge(B.first, B.second); 35 | ST.merge(l, A.second); 36 | } 37 | if (x == 2){ 38 | ST.set(y, z); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /test/aoj/other/2535.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2535" 2 | #define ERROR 0.0000001 3 | #include 4 | using namespace std; 5 | #include "other/poker_hands.hpp" 6 | vector hand2(vector C){ 7 | vector ans; 8 | vector p = {0, 0, 1, 1, 1, 1, 1}; 9 | while (true){ 10 | array C2; 11 | int cnt = 0; 12 | for (int i = 0; i < 7; i++){ 13 | if (p[i] == 1){ 14 | C2[cnt] = C[i]; 15 | cnt++; 16 | } 17 | } 18 | ans = max(ans, hand(C2)); 19 | if (!next_permutation(p.begin(), p.end())){ 20 | break; 21 | } 22 | } 23 | return ans; 24 | } 25 | int main(){ 26 | cout << fixed << setprecision(20); 27 | while (true){ 28 | vector C(9); 29 | for (int i = 0; i < 7; i++){ 30 | cin >> C[i]; 31 | } 32 | if (!cin){ 33 | break; 34 | } 35 | string suits = "SHDC"; 36 | int cnt1 = 0, cnt2 = 0; 37 | for (int s1 = 0; s1 < 4; s1++){ 38 | for (int r1 = 2; r1 <= 14; r1++){ 39 | for (int s2 = 0; s2 < 4; s2++){ 40 | for (int r2 = 2; r2 <= 14; r2++){ 41 | C[7].suit = suits[s1]; 42 | C[7].rank = r1; 43 | C[8].suit = suits[s2]; 44 | C[8].rank = r2; 45 | bool ok = true; 46 | for (int i = 0; i < 9; i++){ 47 | for (int j = i + 1; j < 9; j++){ 48 | if (C[i].suit == C[j].suit && C[i].rank == C[j].rank){ 49 | ok = false; 50 | } 51 | } 52 | } 53 | if (ok){ 54 | vector A = {C[0], C[1], C[4], C[5], C[6], C[7], C[8]}; 55 | vector B = {C[2], C[3], C[4], C[5], C[6], C[7], C[8]}; 56 | if (hand2(A) > hand2(B)){ 57 | cnt1++; 58 | } 59 | cnt2++; 60 | } 61 | } 62 | } 63 | } 64 | } 65 | cout << (double) cnt1 / cnt2 << endl; 66 | } 67 | } -------------------------------------------------------------------------------- /test/aoj/other/2677.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2677" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/tree/heavy_light_decomposition.hpp" 5 | int main(){ 6 | int n; 7 | cin >> n; 8 | vector p(n); 9 | for (int i = 1; i < n; i++){ 10 | cin >> p[i]; 11 | p[i]--; 12 | } 13 | vector> c(n); 14 | for (int i = 1; i < n; i++){ 15 | c[p[i]].push_back(i); 16 | } 17 | vector bfs; 18 | queue Q; 19 | Q.push(0); 20 | while (!Q.empty()){ 21 | int v = Q.front(); 22 | Q.pop(); 23 | bfs.push_back(v); 24 | for (int w : c[v]){ 25 | Q.push(w); 26 | } 27 | } 28 | heavy_light_decomposition T(p, c); 29 | long long ans = 0; 30 | for (int i = 0; i < n - 1; i++){ 31 | ans += T.dist(bfs[i], bfs[i + 1]); 32 | } 33 | cout << ans << endl; 34 | } -------------------------------------------------------------------------------- /test/library_checker/data_structure/line_add_get_min.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/line_add_get_min" 2 | #include 3 | using namespace std; 4 | const long long INF = 3000000000000000000; 5 | #include "../../../data_structure/other/li_chao_tree.hpp" 6 | int main(){ 7 | int N, Q; 8 | cin >> N >> Q; 9 | vector a(N), b(N); 10 | for (int i = 0; i < N; i++){ 11 | cin >> a[i] >> b[i]; 12 | } 13 | vector t(Q); 14 | vector a2(Q), b2(Q); 15 | vector p(Q); 16 | for (int i = 0; i < Q; i++){ 17 | cin >> t[i]; 18 | if (t[i] == 0){ 19 | cin >> a2[i] >> b2[i]; 20 | } 21 | if (t[i] == 1){ 22 | cin >> p[i]; 23 | } 24 | } 25 | vector x; 26 | for (int i = 0; i < Q; i++){ 27 | if (t[i] == 1){ 28 | x.push_back(p[i]); 29 | } 30 | } 31 | li_chao_tree T(x); 32 | for (int i = 0; i < N; i++){ 33 | T.line_add(a[i], b[i]); 34 | } 35 | for (int i = 0; i < Q; i++){ 36 | if (t[i] == 0){ 37 | T.line_add(a2[i], b2[i]); 38 | } 39 | if (t[i] == 1){ 40 | cout << T.get(p[i]) << endl; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /test/library_checker/data_structure/point_add_range_sum.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/point_add_range_sum" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/sequence/binary_indexed_tree.hpp" 5 | int main(){ 6 | int N, Q; 7 | cin >> N >> Q; 8 | vector a(N); 9 | for (int i = 0; i < N; i++){ 10 | cin >> a[i]; 11 | } 12 | binary_indexed_tree BIT(a, plus(), 0); 13 | for (int i = 0; i < Q; i++){ 14 | int t; 15 | cin >> t; 16 | if (t == 0){ 17 | int p, x; 18 | cin >> p >> x; 19 | BIT.add(p, x); 20 | } 21 | if (t == 1){ 22 | int l, r; 23 | cin >> l >> r; 24 | cout << BIT.sum(r) - BIT.sum(l) << endl; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /test/library_checker/data_structure/point_add_range_sum_2.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/point_add_range_sum" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/sequence/invertible_binary_indexed_tree.hpp" 5 | int main(){ 6 | int N, Q; 7 | cin >> N >> Q; 8 | vector a(N); 9 | for (int i = 0; i < N; i++){ 10 | cin >> a[i]; 11 | } 12 | invertible_binary_indexed_tree BIT(a, plus(), negate(), 0); 13 | for (int i = 0; i < Q; i++){ 14 | int t; 15 | cin >> t; 16 | if (t == 0){ 17 | int p, x; 18 | cin >> p >> x; 19 | BIT.add(p, x); 20 | } 21 | if (t == 1){ 22 | int l, r; 23 | cin >> l >> r; 24 | cout << BIT.sum(l, r) << endl; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /test/library_checker/data_structure/point_add_range_sum_3.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/point_add_range_sum" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/sequence/segment_tree.hpp" 5 | int main(){ 6 | int N, Q; 7 | cin >> N >> Q; 8 | vector a(N); 9 | for (int i = 0; i < N; i++){ 10 | cin >> a[i]; 11 | } 12 | segment_tree ST(a, plus(), 0); 13 | for (int i = 0; i < Q; i++){ 14 | int t; 15 | cin >> t; 16 | if (t == 0){ 17 | int p, x; 18 | cin >> p >> x; 19 | a[p] += x; 20 | ST.update(p, a[p]); 21 | } 22 | if (t == 1){ 23 | int l, r; 24 | cin >> l >> r; 25 | cout << ST.query(l, r) << endl; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /test/library_checker/data_structure/point_set_range_composite.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/point_set_range_composite" 2 | #include 3 | using namespace std; 4 | const long long MOD = 998244353; 5 | #include "../../../data_structure/sequence/segment_tree.hpp" 6 | #include "../../../other/monoids/linear.hpp" 7 | int main(){ 8 | int N, Q; 9 | cin >> N >> Q; 10 | vector f(N); 11 | for (int i = 0; i < N; i++){ 12 | cin >> f[i].a >> f[i].b; 13 | } 14 | segment_tree ST(f, composite, linear()); 15 | for (int i = 0; i < Q; i++){ 16 | int t; 17 | cin >> t; 18 | if (t == 0){ 19 | int p, c, d; 20 | cin >> p >> c >> d; 21 | ST.update(p, linear(c, d)); 22 | } 23 | if (t == 1){ 24 | int l, r, x; 25 | cin >> l >> r >> x; 26 | cout << value(ST.query(l, r), x) << endl; 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /test/library_checker/data_structure/queue_operate_all_composite.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/queue_operate_all_composite" 2 | #include 3 | using namespace std; 4 | const long long MOD = 998244353; 5 | #include "../../../data_structure/other/sliding_window_aggregation.hpp" 6 | #include "../../../other/monoids/linear.hpp" 7 | int main(){ 8 | int Q; 9 | cin >> Q; 10 | sliding_window_aggregation S(composite, linear()); 11 | for (int i = 0; i < Q; i++){ 12 | int t; 13 | cin >> t; 14 | if (t == 0){ 15 | int a, b; 16 | cin >> a >> b; 17 | S.push(linear(a, b)); 18 | } 19 | if (t == 1){ 20 | S.pop(); 21 | } 22 | if (t == 2){ 23 | int x; 24 | cin >> x; 25 | cout << value(S.get(),x) << endl; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /test/library_checker/data_structure/range_affine_point_get.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/range_affine_point_get" 2 | #include 3 | using namespace std; 4 | const long long MOD = 998244353; 5 | #include "../../../data_structure/sequence/dual_segment_tree.hpp" 6 | #include "../../../other/monoids/linear.hpp" 7 | int main(){ 8 | int N, Q; 9 | cin >> N >> Q; 10 | vector a(N); 11 | for (int i = 0; i < N; i++){ 12 | a[i].a = 0; 13 | cin >> a[i].b; 14 | } 15 | dual_segment_tree ST(a, composite, linear()); 16 | for (int i = 0; i < Q; i++){ 17 | int t; 18 | cin >> t; 19 | if (t == 0){ 20 | int l, r, b, c; 21 | cin >> l >> r >> b >> c; 22 | ST.range_apply(l, r, linear(b, c)); 23 | } 24 | if (t == 1){ 25 | int p; 26 | cin >> p; 27 | cout << ST[p].b << endl; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /test/library_checker/data_structure/range_affine_range_sum.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/range_affine_range_sum" 2 | #include 3 | using namespace std; 4 | const long long MOD = 998244353; 5 | #include "../../../data_structure/sequence/lazy_segment_tree.hpp" 6 | #include "../../../other/monoids/linear.hpp" 7 | #include "../../../other/monoids/affine_sum.hpp" 8 | int main(){ 9 | int N, Q; 10 | cin >> N >> Q; 11 | vector a(N); 12 | for (int i = 0; i < N; i++){ 13 | a[i].cnt = 1; 14 | cin >> a[i].sum; 15 | } 16 | lazy_segment_tree ST(a, op, mp, composite, affine_sum(), linear()); 17 | for (int i = 0; i < Q; i++){ 18 | int t; 19 | cin >> t; 20 | if (t == 0){ 21 | int l, r, b, c; 22 | cin >> l >> r >> b >> c; 23 | ST.range_apply(l, r, linear(b, c)); 24 | } 25 | if (t == 1){ 26 | int l, r; 27 | cin >> l >> r; 28 | cout << ST.range_fold(l, r).sum << endl; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /test/library_checker/data_structure/range_chmin_chmax_add_range_sum.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/range_chmin_chmax_add_range_sum" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/sequence/segment_tree_beats.hpp" 5 | const long long INF = 1000000000000000000; 6 | struct monoid{ 7 | int sz, minc, maxc; 8 | long long min1, min2, max1, max2, sum; 9 | bool fail; 10 | monoid(): sz(0), minc(0), maxc(0), min1(INF), min2(INF), max1(-INF), max2(-INF), sum(0), fail(false){ 11 | } 12 | monoid(long long x, int sz = 1): sz(sz), minc(sz), maxc(sz), min1(x), min2(INF), max1(x), max2(-INF), sum(x * sz), fail(false){ 13 | } 14 | }; 15 | monoid op(monoid L, monoid R){ 16 | monoid ans; 17 | ans.sz = L.sz + R.sz; 18 | ans.sum = L.sum + R.sum; 19 | ans.min1 = min(L.min1, R.min1); 20 | if (L.min1 < R.min1){ 21 | ans.min2 = min(L.min2, R.min1); 22 | ans.minc = L.minc; 23 | } else if (L.min1 > R.min1){ 24 | ans.min2 = min(L.min1, R.min2); 25 | ans.minc = R.minc; 26 | } else { 27 | ans.min2 = min(L.min2, R.min2); 28 | ans.minc = L.minc + R.minc; 29 | } 30 | ans.max1 = max(L.max1, R.max1); 31 | if (L.max1 > R.max1){ 32 | ans.max2 = max(L.max2, R.max1); 33 | ans.maxc = L.maxc; 34 | } else if (L.max1 < R.max1){ 35 | ans.max2 = max(L.max1, R.max2); 36 | ans.maxc = R.maxc; 37 | } else { 38 | ans.max2 = max(L.max2, R.max2); 39 | ans.maxc = L.maxc + R.maxc; 40 | } 41 | return ans; 42 | } 43 | struct func{ 44 | long long mn, mx, add; 45 | func(): mn(-INF), mx(INF), add(0){ 46 | } 47 | func(long long mn, long long mx, long long add): mn(mn), mx(mx), add(add){ 48 | } 49 | }; 50 | func comp(func g, func f){ 51 | func ans; 52 | ans.mn = max(min(f.mn + g.add, g.mx), g.mn); 53 | ans.mx = min(max(f.mx + g.add, g.mn), g.mx); 54 | ans.add = f.add + g.add; 55 | return ans; 56 | } 57 | monoid mp(func f, monoid x){ 58 | if (x.sz == 0){ 59 | return x; 60 | } 61 | x.min1 += f.add; 62 | if (x.min2 != INF){ 63 | x.min2 += f.add; 64 | } 65 | x.max1 += f.add; 66 | if (x.max2 != -INF){ 67 | x.max2 += f.add; 68 | } 69 | x.sum += x.sz * f.add; 70 | if (x.max1 <= f.mn){ 71 | return monoid(f.mn, x.sz); 72 | } 73 | if (x.min1 >= f.mx){ 74 | return monoid(f.mx, x.sz); 75 | } 76 | if (f.mn < x.min2){ 77 | if (x.min1 < f.mn){ 78 | x.sum += (f.mn - x.min1) * x.minc; 79 | if (x.min1 == x.max1){ 80 | x.max1 = f.mn; 81 | } else if (x.min1 == x.max2){ 82 | x.max2 = f.mn; 83 | } 84 | x.min1 = f.mn; 85 | } 86 | } else { 87 | x.fail = true; 88 | return x; 89 | } 90 | if (f.mx > x.max2){ 91 | if (x.max1 > f.mx){ 92 | x.sum -= (x.max1 - f.mx) * x.maxc; 93 | if (x.max1 == x.min1){ 94 | x.min1 = f.mx; 95 | } else if (x.max1 == x.min2){ 96 | x.min2 = f.mx; 97 | } 98 | x.max1 = f.mx; 99 | } 100 | } else { 101 | x.fail = true; 102 | return x; 103 | } 104 | return x; 105 | } 106 | int main(){ 107 | int N, Q; 108 | cin >> N >> Q; 109 | vector A(N); 110 | for (int i = 0; i < N; i++){ 111 | long long a; 112 | cin >> a; 113 | A[i] = monoid(a); 114 | } 115 | segment_tree_beats ST(A, op, mp, comp, monoid(), func()); 116 | for (int i = 0; i < Q; i++){ 117 | int t; 118 | cin >> t; 119 | if (t == 0){ 120 | int l, r; 121 | long long b; 122 | cin >> l >> r >> b; 123 | ST.range_apply(l, r, func(-INF, b, 0)); 124 | } 125 | if (t == 1){ 126 | int l, r; 127 | long long b; 128 | cin >> l >> r >> b; 129 | ST.range_apply(l, r, func(b, INF, 0)); 130 | } 131 | if (t == 2){ 132 | int l, r; 133 | long long b; 134 | cin >> l >> r >> b; 135 | ST.range_apply(l, r, func(-INF, INF, b)); 136 | } 137 | if (t == 3){ 138 | int l, r; 139 | cin >> l >> r; 140 | cout << ST.range_fold(l, r).sum << endl; 141 | } 142 | } 143 | } -------------------------------------------------------------------------------- /test/library_checker/data_structure/range_kth_smallest.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/range_kth_smallest" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/sequence/wavelet_matrix.hpp" 5 | int main(){ 6 | int N, Q; 7 | cin >> N >> Q; 8 | vector a(N); 9 | for (int i = 0; i < N; i++){ 10 | cin >> a[i]; 11 | } 12 | wavelet_matrix WM(a); 13 | for (int i = 0; i < Q; i++){ 14 | int l, r, k; 15 | cin >> l >> r >> k; 16 | cout << WM.quantile(l, r, k) << endl; 17 | } 18 | } -------------------------------------------------------------------------------- /test/library_checker/data_structure/segment_add_get_min.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/segment_add_get_min" 2 | #include 3 | using namespace std; 4 | const long long INF = 3000000000000000000; 5 | #include "../../../data_structure/other/li_chao_tree.hpp" 6 | int main(){ 7 | int N, Q; 8 | cin >> N >> Q; 9 | vector l(N), r(N), a(N), b(N); 10 | for (int i = 0; i < N; i++){ 11 | cin >> l[i] >> r[i] >> a[i] >> b[i]; 12 | } 13 | vector t(Q); 14 | vector l2(Q), r2(Q), a2(Q), b2(Q); 15 | vector p(Q); 16 | for (int i = 0; i < Q; i++){ 17 | cin >> t[i]; 18 | if (t[i] == 0){ 19 | cin >> l2[i] >> r2[i] >> a2[i] >> b2[i]; 20 | } 21 | if (t[i] == 1){ 22 | cin >> p[i]; 23 | } 24 | } 25 | vector x; 26 | for (int i = 0; i < Q; i++){ 27 | if (t[i] == 1){ 28 | x.push_back(p[i]); 29 | } 30 | } 31 | li_chao_tree T(x); 32 | for (int i = 0; i < N; i++){ 33 | T.segment_add(l[i], r[i], a[i], b[i]); 34 | } 35 | for (int i = 0; i < Q; i++){ 36 | if (t[i] == 0){ 37 | T.segment_add(l2[i], r2[i], a2[i], b2[i]); 38 | } 39 | if (t[i] == 1){ 40 | long long ans = T.get(p[i]); 41 | if (ans == INF){ 42 | cout << "INFINITY" << endl; 43 | } else { 44 | cout << ans << endl; 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /test/library_checker/data_structure/static_range_frequency.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/static_range_frequency" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/sequence/wavelet_matrix.hpp" 5 | int main(){ 6 | int N, Q; 7 | cin >> N >> Q; 8 | vector a(N); 9 | for (int i = 0; i < N; i++){ 10 | cin >> a[i]; 11 | } 12 | wavelet_matrix WM(a); 13 | for (int i = 0; i < Q; i++){ 14 | int l, r, x; 15 | cin >> l >> r >> x; 16 | cout << WM.rank(l, r, x) << endl; 17 | } 18 | } -------------------------------------------------------------------------------- /test/library_checker/data_structure/static_range_sum.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/static_range_sum" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/sequence/cumulative_sum.hpp" 5 | int main(){ 6 | int N, Q; 7 | cin >> N >> Q; 8 | vector a(N); 9 | for (int i = 0; i < N; i++){ 10 | cin >> a[i]; 11 | } 12 | cumulative_sum S(a, plus(), 0); 13 | for (int i = 0; i < Q; i++){ 14 | int l, r; 15 | cin >> l >> r; 16 | cout << S.get(r) - S.get(l) << endl; 17 | } 18 | } -------------------------------------------------------------------------------- /test/library_checker/data_structure/static_range_sum_2.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/static_range_sum" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/sequence/invertible_cumulative_sum.hpp" 5 | int main(){ 6 | int N, Q; 7 | cin >> N >> Q; 8 | vector a(N); 9 | for (int i = 0; i < N; i++){ 10 | cin >> a[i]; 11 | } 12 | invertible_cumulative_sum S(a, plus(), negate(), 0); 13 | for (int i = 0; i < Q; i++){ 14 | int l, r; 15 | cin >> l >> r; 16 | cout << S.get(l, r) << endl; 17 | } 18 | } -------------------------------------------------------------------------------- /test/library_checker/data_structure/static_range_sum_3.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/static_range_sum" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/sequence/disjoint_sparse_table.hpp" 5 | int main(){ 6 | int N, Q; 7 | cin >> N >> Q; 8 | vector a(N); 9 | for (int i = 0; i < N; i++){ 10 | cin >> a[i]; 11 | } 12 | disjoint_sparse_table DST(a, plus(), 0); 13 | for (int i = 0; i < Q; i++){ 14 | int l, r; 15 | cin >> l >> r; 16 | cout << DST.query(l, r) << endl; 17 | } 18 | } -------------------------------------------------------------------------------- /test/library_checker/data_structure/staticrmq.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/staticrmq" 2 | #include 3 | using namespace std; 4 | const int INF = 1000000000; 5 | #include "../../../data_structure/sequence/disjoint_sparse_table.hpp" 6 | int main(){ 7 | int N, Q; 8 | cin >> N >> Q; 9 | vector a(N); 10 | for (int i = 0; i < N; i++){ 11 | cin >> a[i]; 12 | } 13 | disjoint_sparse_table DST(a, [](int a, int b){return min(a, b);}, INF); 14 | for (int i = 0; i < Q; i++){ 15 | int l, r; 16 | cin >> l >> r; 17 | cout << DST.query(l, r) << endl; 18 | } 19 | } -------------------------------------------------------------------------------- /test/library_checker/data_structure/staticrmq_2.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/staticrmq" 2 | #include 3 | using namespace std; 4 | const int INF = 1000000000; 5 | #include "../../../data_structure/sequence/sparse_table.hpp" 6 | int main(){ 7 | int N, Q; 8 | cin >> N >> Q; 9 | vector a(N); 10 | for (int i = 0; i < N; i++){ 11 | cin >> a[i]; 12 | } 13 | sparse_table ST(a, [](int a, int b){return min(a, b);}, INF); 14 | for (int i = 0; i < Q; i++){ 15 | int l, r; 16 | cin >> l >> r; 17 | cout << ST.query(l, r) << endl; 18 | } 19 | } -------------------------------------------------------------------------------- /test/library_checker/data_structure/staticrmq_3.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/staticrmq" 2 | #include 3 | using namespace std; 4 | const int INF = 1000000000; 5 | #include "../../../data_structure/sequence/segment_tree.hpp" 6 | int main(){ 7 | int N, Q; 8 | cin >> N >> Q; 9 | vector a(N); 10 | for (int i = 0; i < N; i++){ 11 | cin >> a[i]; 12 | } 13 | segment_tree ST(a, [](int x, int y){return min(x, y);}, INF); 14 | for (int i = 0; i < Q; i++){ 15 | int L, R; 16 | cin >> L >> R; 17 | cout << ST.query(L, R) << endl; 18 | } 19 | } -------------------------------------------------------------------------------- /test/library_checker/data_structure/unionfind.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/unionfind" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/unionfind/unionfind.hpp" 5 | int main(){ 6 | int N, Q; 7 | cin >> N >> Q; 8 | unionfind UF(N); 9 | for (int i = 0; i < Q; i++){ 10 | int t, u, v; 11 | cin >> t >> u >> v; 12 | if (t == 0){ 13 | UF.unite(u, v); 14 | } 15 | if (t == 1){ 16 | if (UF.same(u, v)){ 17 | cout << 1 << endl; 18 | } else { 19 | cout << 0 << endl; 20 | } 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /test/library_checker/graph/biconnected_components.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/biconnected_components" 2 | #include 3 | using namespace std; 4 | #include "../../../graph/block_cut_tree.hpp" 5 | int main(){ 6 | int N, M; 7 | cin >> N >> M; 8 | vector> E(N); 9 | for (int i = 0; i < M; i++){ 10 | int s, t; 11 | cin >> s >> t; 12 | E[s].push_back(t); 13 | E[t].push_back(s); 14 | } 15 | block_cut_tree G(E); 16 | int V = G.V; 17 | vector> v; 18 | for (int i = 0; i < V; i++){ 19 | if (!G.cut[i]){ 20 | v.push_back(G.node[i]); 21 | } 22 | } 23 | int K = v.size(); 24 | cout << K << endl; 25 | for (int i = 0; i < K; i++){ 26 | int l = v[i].size(); 27 | cout << l; 28 | for (int j = 0; j < l; j++){ 29 | cout << ' ' << v[i][j]; 30 | } 31 | cout << endl; 32 | } 33 | } -------------------------------------------------------------------------------- /test/library_checker/graph/biconnected_components_2.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/biconnected_components" 2 | #include 3 | using namespace std; 4 | #include "../../../graph/extended_block_cut_tree.hpp" 5 | int main(){ 6 | int N, M; 7 | cin >> N >> M; 8 | vector> E(N); 9 | for (int i = 0; i < M; i++){ 10 | int a, b; 11 | cin >> a >> b; 12 | E[a].push_back(b); 13 | E[b].push_back(a); 14 | } 15 | extended_block_cut_tree T(E); 16 | int V = T.size(); 17 | int K = V - N; 18 | cout << K << endl; 19 | for (int i = 0; i < K; i++){ 20 | cout << T[N + i].size(); 21 | for (int j : T[N + i]){ 22 | cout << ' ' << j; 23 | } 24 | cout << endl; 25 | } 26 | } -------------------------------------------------------------------------------- /test/library_checker/graph/enumerate_triangles.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/enumerate_triangles" 2 | #include 3 | using namespace std; 4 | const long long MOD = 998244353; 5 | #include "../../../graph/enumerate_triangles.hpp" 6 | int main(){ 7 | int N, M; 8 | cin >> N >> M; 9 | vector x(N); 10 | for (int i = 0; i < N; i++){ 11 | cin >> x[i]; 12 | } 13 | vector> E(N); 14 | for (int i = 0; i < M; i++){ 15 | int u, v; 16 | cin >> u >> v; 17 | E[u].push_back(v); 18 | E[v].push_back(u); 19 | } 20 | vector> T = enumerate_triangles(E); 21 | int cnt = T.size(); 22 | long long ans = 0; 23 | for (int i = 0; i < cnt; i++){ 24 | int a = get<0>(T[i]); 25 | int b = get<1>(T[i]); 26 | int c = get<2>(T[i]); 27 | ans += x[a] * x[b] % MOD * x[c] % MOD; 28 | ans %= MOD; 29 | } 30 | cout << ans << endl; 31 | } -------------------------------------------------------------------------------- /test/library_checker/graph/scc.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/scc" 2 | #include 3 | using namespace std; 4 | #include "../../../graph/strongly_connected_components.hpp" 5 | int main(){ 6 | int N, M; 7 | cin >> N >> M; 8 | vector> E(N); 9 | for (int i = 0; i < M; i++){ 10 | int a, b; 11 | cin >> a >> b; 12 | E[a].push_back(b); 13 | } 14 | strongly_connected_components G(E); 15 | int K = G.cnt; 16 | vector> v(K); 17 | for (int i = 0; i < N; i++){ 18 | v[G[i]].push_back(i); 19 | } 20 | cout << K << endl; 21 | for (int i = 0; i < K; i++){ 22 | int l = v[i].size(); 23 | cout << l; 24 | for (int j = 0; j < l; j++){ 25 | cout << ' ' << v[i][j]; 26 | } 27 | cout << endl; 28 | } 29 | } -------------------------------------------------------------------------------- /test/library_checker/graph/two_edge_connected_components.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/two_edge_connected_components" 2 | #include 3 | using namespace std; 4 | #include "../../../graph/two_edge_connected_components.hpp" 5 | int main(){ 6 | int N, M; 7 | cin >> N >> M; 8 | vector> E(N); 9 | for (int i = 0; i < M; i++){ 10 | int a, b; 11 | cin >> a >> b; 12 | E[a].push_back(b); 13 | E[b].push_back(a); 14 | } 15 | two_edge_connected_components G(E); 16 | int K = G.cnt; 17 | vector> v(K); 18 | for (int i = 0; i < N; i++){ 19 | v[G[i]].push_back(i); 20 | } 21 | cout << K << endl; 22 | for (int i = 0; i < K; i++){ 23 | int l = v[i].size(); 24 | cout << l; 25 | for (int j = 0; j < l; j++){ 26 | cout << ' ' << v[i][j]; 27 | } 28 | cout << endl; 29 | } 30 | } -------------------------------------------------------------------------------- /test/library_checker/string/enumerate_palindromes.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/enumerate_palindromes" 2 | #include 3 | using namespace std; 4 | #include "../../../string/manacher.hpp" 5 | int main(){ 6 | string S; 7 | cin >> S; 8 | int N = S.size(); 9 | string T = "$"; 10 | for (int i = 0; i < N; i++){ 11 | T += S[i]; 12 | T += '$'; 13 | } 14 | vector ans = manacher(T); 15 | for (int i = 1; i < N * 2; i++){ 16 | cout << ans[i] - 1; 17 | if (i < N * 2 - 1){ 18 | cout << ' '; 19 | } 20 | } 21 | cout << endl; 22 | } -------------------------------------------------------------------------------- /test/library_checker/string/number_of_substrings.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/number_of_substrings" 2 | #include 3 | using namespace std; 4 | #include "../../../string/lcp_array.hpp" 5 | int main(){ 6 | string S; 7 | cin >> S; 8 | int N = S.size(); 9 | vector SA = suffix_array(S); 10 | vector LCP = lcp_array(S, SA); 11 | long long ans = 1; 12 | for (int i = 0; i < N - 1; i++){ 13 | ans += i + 2 - LCP[i]; 14 | } 15 | cout << ans << endl; 16 | } -------------------------------------------------------------------------------- /test/library_checker/string/suffixarray.test.cpp: -------------------------------------------------------------------------------- 1 | #define _GLIBCXX_DEBUG 2 | #define PROBLEM "https://judge.yosupo.jp/problem/suffixarray" 3 | #include 4 | using namespace std; 5 | #include "../../../string/suffix_array.hpp" 6 | int main(){ 7 | string S; 8 | cin >> S; 9 | int N = S.size(); 10 | vector A = suffix_array(S); 11 | for (int i = 0; i < N; i++){ 12 | cout << A[i]; 13 | if (i < N - 1){ 14 | cout << ' '; 15 | } 16 | } 17 | cout << endl; 18 | } -------------------------------------------------------------------------------- /test/library_checker/string/zalgorithm.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/zalgorithm" 2 | #include 3 | using namespace std; 4 | #include "../../../string/z_algorithm.hpp" 5 | int main(){ 6 | string S; 7 | cin >> S; 8 | int N = S.size(); 9 | vector ans = z_algorithm(S); 10 | for (int i = 0; i < N; i++){ 11 | cout << ans[i]; 12 | if (i < N - 1){ 13 | cout << ' '; 14 | } 15 | } 16 | cout << endl; 17 | } -------------------------------------------------------------------------------- /test/library_checker/tree/cartesian_tree.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/cartesian_tree" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/other/cartesian_tree_min.hpp" 5 | int main(){ 6 | int N; 7 | cin >> N; 8 | vector a(N); 9 | for (int i = 0; i < N; i++){ 10 | cin >> a[i]; 11 | } 12 | vector p = cartesian_tree_min(a); 13 | for (int i = 0; i < N; i++){ 14 | if (p[i] == -1){ 15 | cout << i; 16 | } else { 17 | cout << p[i]; 18 | } 19 | if (i < N - 1){ 20 | cout << ' '; 21 | } 22 | } 23 | cout << endl; 24 | } -------------------------------------------------------------------------------- /test/library_checker/tree/lca.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/lca" 2 | #include 3 | using namespace std; 4 | #include "../../../data_structure/tree/heavy_light_decomposition.hpp" 5 | int main(){ 6 | int N, Q; 7 | cin >> N >> Q; 8 | vector p(N); 9 | for (int i = 1; i < N; i++){ 10 | cin >> p[i]; 11 | } 12 | vector> c(N); 13 | for (int i = 1; i < N; i++){ 14 | c[p[i]].push_back(i); 15 | } 16 | heavy_light_decomposition T(p, c); 17 | for (int i = 0; i < Q; i++){ 18 | int u, v; 19 | cin >> u >> v; 20 | cout << T.lca(u, v) << endl; 21 | } 22 | } -------------------------------------------------------------------------------- /test/yukicoder/yuki_1326.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/1326" 2 | #include 3 | using namespace std; 4 | #include "../../graph/block_cut_tree.hpp" 5 | #include "../../data_structure/tree/heavy_light_decomposition.hpp" 6 | int main(){ 7 | int N, M; 8 | cin >> N >> M; 9 | vector> E(N); 10 | for (int i = 0; i < M; i++){ 11 | int a, b; 12 | cin >> a >> b; 13 | a--; 14 | b--; 15 | E[a].push_back(b); 16 | E[b].push_back(a); 17 | } 18 | block_cut_tree G(E); 19 | vector id(N, -1); 20 | for (int i = 0; i < G.V; i++){ 21 | for (int j : G.node[i]){ 22 | if (id[j] == -1){ 23 | id[j] = i; 24 | } 25 | } 26 | } 27 | vector p(G.V, -1); 28 | vector> c(G.V); 29 | vector d(G.V, 0); 30 | if (G.cut[0]){ 31 | d[0]++; 32 | } 33 | queue q; 34 | q.push(0); 35 | while (!q.empty()){ 36 | int v = q.front(); 37 | q.pop(); 38 | for (int w : G.G[v]){ 39 | if (w != p[v]){ 40 | p[w] = v; 41 | c[v].push_back(w); 42 | d[w] = d[v]; 43 | if (G.cut[w]){ 44 | d[w]++; 45 | } 46 | q.push(w); 47 | } 48 | } 49 | } 50 | heavy_light_decomposition T(p, c); 51 | int Q; 52 | cin >> Q; 53 | for (int i = 0; i < Q; i++){ 54 | int x, y; 55 | cin >> x >> y; 56 | x--; 57 | y--; 58 | x = id[x]; 59 | y = id[y]; 60 | if (x == y){ 61 | cout << 0 << endl; 62 | } else { 63 | int z = T.lca(x, y); 64 | int ans = d[x] + d[y] - d[z] * 2; 65 | if (G.cut[z]){ 66 | ans++; 67 | } 68 | if (G.cut[x]){ 69 | ans--; 70 | } 71 | if (G.cut[y]){ 72 | ans--; 73 | } 74 | cout << ans << endl; 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /test/yukicoder/yuki_1326_2.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/1326" 2 | #include 3 | using namespace std; 4 | #include "../../graph/extended_block_cut_tree.hpp" 5 | #include "../../data_structure/tree/heavy_light_decomposition.hpp" 6 | int main(){ 7 | int N, M; 8 | cin >> N >> M; 9 | vector> E(N); 10 | for (int i = 0; i < M; i++){ 11 | int a, b; 12 | cin >> a >> b; 13 | a--; 14 | b--; 15 | E[a].push_back(b); 16 | E[b].push_back(a); 17 | } 18 | extended_block_cut_tree T(E); 19 | int V = T.size(); 20 | vector p(V, -1); 21 | vector> c(V); 22 | vector d(V, 0); 23 | queue q; 24 | q.push(0); 25 | while (!q.empty()){ 26 | int v = q.front(); 27 | q.pop(); 28 | for (int w : T[v]){ 29 | if (w != p[v]){ 30 | p[w] = v; 31 | c[v].push_back(w); 32 | d[w] = d[v] + 1; 33 | q.push(w); 34 | } 35 | } 36 | } 37 | heavy_light_decomposition HLD(p, c); 38 | int Q; 39 | cin >> Q; 40 | for (int i = 0; i < Q; i++){ 41 | int x, y; 42 | cin >> x >> y; 43 | x--; 44 | y--; 45 | cout << max(HLD.dist(x, y) / 2 - 1, 0) << endl; 46 | } 47 | } -------------------------------------------------------------------------------- /test/yukicoder/yuki_1891.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/1891" 2 | #include 3 | using namespace std; 4 | const long long MOD = 998244353; 5 | #include "../../data_structure/sequence/xor_segment_tree.hpp" 6 | #include "../../other/monoids/linear.hpp" 7 | int main(){ 8 | int N, Q; 9 | cin >> N >> Q; 10 | vector f(N); 11 | for (int i = 0; i < N; i++){ 12 | int a, b; 13 | cin >> a >> b; 14 | f[i] = linear(a, b); 15 | } 16 | xor_segment_tree F(f, composite, linear()); 17 | for (int i = 0; i < Q; i++){ 18 | int l, r, p, x; 19 | cin >> l >> r >> p >> x; 20 | cout << value(F.range_fold(l, r, p), x) << endl; 21 | } 22 | } -------------------------------------------------------------------------------- /test/yukicoder/yuki_945.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/945" 2 | #include 3 | using namespace std; 4 | const int INF = 1000000; 5 | #include "../../data_structure/sequence/dual_sparse_table.hpp" 6 | int main(){ 7 | int N, M; 8 | cin >> N >> M; 9 | dual_sparse_table> ST(N, [](pair a, pair b){return min(a, b);}, make_pair(INF, 0)); 10 | for (int i = 0; i < M; i++){ 11 | int L, R; 12 | char T; 13 | cin >> L >> R >> T; 14 | L--; 15 | if (T == 'Y'){ 16 | ST.apply(L, R, make_pair(i, 0)); 17 | } 18 | if (T == 'K'){ 19 | ST.apply(L, R, make_pair(i, 1)); 20 | } 21 | if (T == 'C'){ 22 | ST.apply(L, R, make_pair(i, 2)); 23 | } 24 | } 25 | vector> A = ST.get(); 26 | vector ans(3, 0); 27 | for (int i = 0; i < N; i++){ 28 | if (A[i].first != INF){ 29 | ans[A[i].second]++; 30 | } 31 | } 32 | cout << ans[0] << ' ' << ans[1] << ' ' << ans[2] << endl; 33 | } --------------------------------------------------------------------------------