├── .github └── workflows │ └── verify.yml ├── .gitignore ├── .verify-helper ├── .gitignore ├── config.toml ├── docs │ ├── _config.yml │ └── static │ │ ├── assets │ │ ├── css │ │ │ └── copy-button.css │ │ └── js │ │ │ └── copy-button.js │ │ └── favicon.png ├── timestamps.local.json └── timestamps.remote.json ├── DataStructure ├── basic_segment_tree.cpp ├── bit_vector.cpp ├── disjoint_set.cpp ├── disjoint_sparse_table.cpp ├── docs │ └── basic_segment_tree.md ├── dynamic_bitvector.cpp ├── foldable_deque.cpp ├── foldable_queue.cpp ├── integral_intervals.cpp ├── li_chao_tree.cpp ├── potential_function.cpp ├── rectangle_query.cpp ├── rollbackable_array.cpp ├── rollbackable_disjoint_set.cpp ├── segment_tree.cpp ├── sparse_table.cpp ├── splay_tree.cpp ├── starry_sky_tree.cpp └── wavelet_matrix.cpp ├── Graph ├── adjacency_list.cpp ├── capacitated_adjacency_list.cpp ├── dinitz.cpp ├── hl_decomposition.cpp ├── lowest_common_ancestor_segment_tree.cpp ├── lowest_common_ancestor_sparse_table.cpp ├── lowest_common_ancestor_squaring.cpp ├── pre17 │ └── shortest_path.cpp ├── scc.cpp ├── shortest_path.cpp ├── topological_sort.cpp └── two_sat.cpp ├── LICENSE ├── Math ├── factor.cpp ├── lp_solver.cpp └── remainder_sum.cpp ├── ModularArithmetic ├── chinese_remaindering.cpp ├── factorial.cpp ├── garner.cpp ├── interpolation.cpp ├── modint.cpp ├── modtable.cpp ├── operations.cpp └── polynomial.cpp ├── README.md ├── String ├── knuth_morris_pratt_searcher.cpp ├── rolling_hash_l61m1.cpp ├── sa_is.cpp ├── suffix_array.cpp ├── tree_attack.cpp └── z_algorithm.cpp ├── algorithm ├── dp_on_tree.cpp ├── mo.cpp ├── moebius_transform.cpp ├── monotone_minima.cpp ├── online_to_offline_optimization.cpp ├── parallel_binary_search.cpp ├── ternary_search.cpp └── tortoise_and_hare.cpp ├── debug └── sa_is.cpp ├── integer ├── bit.cpp ├── fused_operations.cpp ├── gcd.cpp ├── mod_misc.cpp ├── mul_upper.cpp ├── overflow.cpp └── sqrt.cpp ├── misc └── interface │ ├── action.cpp │ └── monoid.cpp ├── preface ├── license.cpp ├── license.md ├── todo.cpp └── todo.md ├── script └── check.sh ├── test ├── .gitignore ├── .verify-helper │ └── .gitignore ├── aoj_0355.test.cpp ├── aoj_0425.test.cpp ├── aoj_0575.test.cpp ├── aoj_0613.test.cpp ├── aoj_1180.test.cpp ├── aoj_1322.test.cpp ├── aoj_1595.test.cpp ├── aoj_2178.test.cpp ├── aoj_2313.test.cpp ├── aoj_2444.test.cpp ├── aoj_2446.test.cpp ├── aoj_2450.test.cpp ├── aoj_2580.test.cpp ├── aoj_2748.test.cpp ├── aoj_2880.test.cpp ├── aoj_2911.test.cpp ├── aoj_2970.test.cpp ├── aoj_2976.test.cpp ├── aoj_2991.test.cpp ├── aoj_3110.test.cpp ├── aoj_3111.test.cpp ├── aoj_3112.test.cpp ├── aoj_3112_sa_is.test.cpp ├── aoj_ALDS1_10_A.test.cpp ├── aoj_ALDS1_14_B_kmp.test.cpp ├── aoj_ALDS1_14_B_l61m1.test.cpp ├── aoj_ALDS1_14_B_z.test.cpp ├── aoj_ALDS1_5_D.test.cpp ├── aoj_DPL_1_D.test.cpp ├── aoj_DPL_1_E.test.cpp ├── aoj_DPL_5_A.test.cpp ├── aoj_DPL_5_B.test.cpp ├── aoj_DPL_5_C.test.cpp ├── aoj_DPL_5_D.test.cpp ├── aoj_DPL_5_E.test.cpp ├── aoj_DPL_5_F.test.cpp ├── aoj_DPL_5_G.test.cpp ├── aoj_DPL_5_I.test.cpp ├── aoj_DPL_5_J.test.cpp ├── aoj_DPL_5_L.test.cpp ├── aoj_DSL_1_A.test.cpp ├── aoj_DSL_1_B.test.cpp ├── aoj_DSL_2_A.test.cpp ├── aoj_DSL_2_B.test.cpp ├── aoj_DSL_2_G.test.cpp ├── aoj_DSL_2_H.test.cpp ├── aoj_DSL_2_I.test.cpp ├── aoj_DSL_3_D.test.cpp ├── aoj_GRL_4_B.test.cpp ├── aoj_GRL_5_C_segment_tree.test.cpp ├── aoj_GRL_5_C_sparse_table.test.cpp ├── aoj_GRL_5_C_squaring.test.cpp ├── aoj_GRL_5_D.test.cpp ├── aoj_GRL_5_E.test.cpp ├── aoj_list.txt ├── mini │ ├── .gitignore │ ├── bit.cpp │ ├── fast_io.cpp │ ├── fft.cpp │ ├── foldable_deque.cpp │ ├── fused_operations.test.cpp │ ├── modint.cpp │ ├── mul_upper.cpp │ ├── qq.cpp │ ├── rectangle_sum.cpp │ └── twoword.cpp ├── yc_1036.test.cpp ├── yc_1036_disjoint_sparse_table.test.cpp ├── yc_1036_sparse_table.test.cpp ├── yc_3014.test.cpp ├── yc_306.test.cpp ├── yc_306_maximize.test.cpp ├── yc_502.test.cpp ├── yc_551.test.cpp ├── yc_703_lichao.test.cpp ├── yc_703_onoff.test.cpp ├── yc_704_onoff.test.cpp ├── yc_705_onoff.test.cpp ├── yc_752.test.cpp ├── yc_878.test.cpp ├── yc_878_reversed.test.cpp ├── yj_bipartitematching.test.cpp ├── yj_convolution_mod.test.cpp ├── yj_convolution_mod_1000000007.test.cpp ├── yj_convolution_mod_raw.test.cpp ├── yj_inv_of_formal_power_series.test.cpp ├── yj_lca_squaring.test.cpp ├── yj_line_add_get_min_li_chao_tree.test.cpp ├── yj_log_of_formal_power_series.test.cpp ├── yj_many_aplusb.test.cpp ├── yj_multipoint_evaluation.test.cpp ├── yj_persistent_unionfind_rollback.test.cpp ├── yj_point_add_range_sum.test.cpp ├── yj_point_set_range_composite.test.cpp ├── yj_polynomial_interpolation.test.cpp ├── yj_queue_operate_all_composite.test.cpp ├── yj_range_affine_range_sum.test.cpp ├── yj_range_kth_smallest.test.cpp ├── yj_rectangle_sum.test.cpp ├── yj_scc.test.cpp ├── yj_segment_add_get_min.test.cpp ├── yj_static_range_sum.test.cpp ├── yj_staticrmq.test.cpp ├── yj_suffixarray.test.cpp ├── yj_two_sat.test.cpp ├── yj_unionfind.test.cpp ├── yj_vertex_add_path_sum.test.cpp ├── yj_vertex_set_path_composite.test.cpp └── yj_zalgorithm.test.cpp └── utility ├── action ├── add_max.cpp ├── add_min.cpp ├── add_sum.cpp ├── affine_sum.cpp ├── min_min.cpp └── set_sum.cpp ├── fast_io.cpp ├── four_neighbor.cpp ├── io.cpp ├── limits.cpp ├── literals.cpp ├── macro ├── assert_eq.cpp └── stack_extend.cpp ├── make ├── fix_point.cpp ├── pre17 │ └── vector.cpp └── vector.cpp ├── monoid ├── composite.cpp ├── gcd.cpp ├── length.cpp ├── max.cpp ├── max_subsum.cpp ├── min.cpp ├── rolling_hash.cpp └── set.cpp └── set_if.cpp /.github/workflows/verify.yml: -------------------------------------------------------------------------------- 1 | name: verify 2 | 3 | on: push 4 | 5 | jobs: 6 | build: 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: Check environments 19 | run: script/check.sh 20 | 21 | - name: Run tests 22 | env: 23 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 24 | GH_PAT: ${{ secrets.GH_PAT }} 25 | YUKICODER_TOKEN: ${{ secrets.YUKICODER_TOKEN }} 26 | CXXFLAGS: -I ./ --std=c++17 27 | run: oj-verify all --timeout 1200 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # Backups 35 | *~ 36 | *.swp 37 | 38 | # Jekylls 39 | .jekyll-cache/ 40 | _site/ -------------------------------------------------------------------------------- /.verify-helper/.gitignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | cache/ 3 | include/ 4 | markdown/ 5 | timestamps.local.json 6 | -------------------------------------------------------------------------------- /.verify-helper/config.toml: -------------------------------------------------------------------------------- 1 | [[languages.cpp.environments]] 2 | CXX = "g++" 3 | CXXFLAGS = ["--std=c++17", "-Wall", "-Wno-unused-result", "-Werror", "-O3"] 4 | -------------------------------------------------------------------------------- /.verify-helper/docs/_config.yml: -------------------------------------------------------------------------------- 1 | docs: 2 | categorize_library: true 3 | categorize_verify: false 4 | html: false 5 | toc: false 6 | plugins: 7 | - jemoji 8 | - jekyll-remote-theme 9 | remote_theme: rsk0315/minima 10 | theme: jekyll-theme-minimal 11 | 12 | title: えびちゃんライブラリ 13 | author: えびちゃん 14 | # description: "[えびちゃん](https://twitter.com/rsk0315_h4x) のライブラリです。[online-judge-verify-helper](https://github.com/kmyk/online-judge-verify-helper) で管理されています。" 15 | # footer_description: "えびちゃんかわいいね。にゃんにゃん。" 16 | description: "えびちゃんかわいいね。にゃんにゃん。" 17 | -------------------------------------------------------------------------------- /.verify-helper/docs/static/assets/css/copy-button.css: -------------------------------------------------------------------------------- 1 | .div-btn-copy { 2 | position: relative; 3 | display: block; 4 | } 5 | .btn-pre { 6 | position: absolute; 7 | /* top: 0; */ 8 | /* right: 0; */ 9 | display: block; 10 | padding: 0 6px; 11 | font-size: 12px; 12 | font-family: Lato; 13 | color: #767676; 14 | cursor: pointer; 15 | background-color: #fff; 16 | border: 1px solid #ccc; 17 | border-radius: 0 4px 0 4px; 18 | line-height: 23px; 19 | } 20 | .btn-pre:hover { 21 | color: #fff; 22 | background-color: #563d7c; 23 | border-color: #563d7c 24 | } 25 | .btn-copy { 26 | vertical-align: top; 27 | top: 0; 28 | right: 0; 29 | border-bottom-left-radius: 0; 30 | } 31 | .btn-bundle { 32 | vertical-align: top; 33 | top: 0; 34 | right: 3.4em; 35 | border-top-right-radius: 0; 36 | } 37 | /* .code-copy-btn { */ 38 | /* top: 0px; */ 39 | /* right: 0px; */ 40 | /* } */ 41 | /* .code-bundle-btn { */ 42 | /* display: none; */ 43 | /* top: 0px; */ 44 | /* right: 6em; */ 45 | /* } */ 46 | -------------------------------------------------------------------------------- /.verify-helper/docs/static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsk0315/library/a6f5988dce73bfc2d95cc641da897d93df573cb5/.verify-helper/docs/static/favicon.png -------------------------------------------------------------------------------- /.verify-helper/timestamps.local.json: -------------------------------------------------------------------------------- 1 | { 2 | "test/aoj_ALDS1_14_B_kmp.test.cpp": "1970-01-01 00:00:00 +0000" 3 | } -------------------------------------------------------------------------------- /DataStructure/disjoint_set.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_disjoint_set 2 | #define H_disjoint_set 3 | 4 | /** 5 | * @brief 素集合データ構造 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | class disjoint_set { 15 | public: 16 | using size_type = size_t; 17 | 18 | private: 19 | mutable std::vector M_c; 20 | 21 | public: 22 | disjoint_set() = default; 23 | 24 | explicit disjoint_set(size_type n): M_c(n, -1) {} 25 | 26 | void reset() { M_c.assign(M_c.size(), -1); } 27 | 28 | size_type representative(size_type v) const { 29 | if (M_c[v] < 0) return v; 30 | return (M_c[v] = representative(M_c[v])); 31 | } 32 | 33 | bool unite(size_type u, size_type v) { 34 | u = representative(u); 35 | v = representative(v); 36 | if (u == v) return false; 37 | if (-M_c[u] > -M_c[v]) std::swap(u, v); 38 | M_c[v] += M_c[u]; 39 | M_c[u] = v; 40 | return true; 41 | } 42 | 43 | bool equivalent(size_type u, size_type v) const { 44 | return (representative(u) == representative(v)); 45 | } 46 | 47 | size_type size() const noexcept { return M_c.size(); } 48 | size_type count(size_type v) const { 49 | return -M_c[representative(v)]; 50 | } 51 | }; 52 | 53 | #endif /* !defined(H_disjoint_set) */ 54 | -------------------------------------------------------------------------------- /DataStructure/disjoint_sparse_table.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_disjoint_sparse_table 2 | #define H_disjoint_sparse_table 3 | 4 | /** 5 | * @brief disjoint sparse table 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include "integer/bit.cpp" 13 | 14 | template 15 | class disjoint_sparse_table { 16 | public: 17 | using size_type = size_t; 18 | using value_type = Monoid; 19 | 20 | private: 21 | std::vector> M_c; 22 | 23 | public: 24 | disjoint_sparse_table() = default; 25 | 26 | template 27 | disjoint_sparse_table(InputIt first, InputIt last) { assign(first, last); } 28 | disjoint_sparse_table(std::initializer_list il) { 29 | assign(il.begin(), il.end()); 30 | } 31 | 32 | template 33 | void assign(InputIt first, InputIt last) { 34 | M_c.resize(1); 35 | M_c[0].assign(first, last); 36 | size_type n = M_c[0].size(); 37 | 38 | for (size_type i = n-1, s = 2; i > 1; i >>= 1, s <<= 1) { 39 | std::vector tmp = M_c[0]; 40 | for (size_type j = 0; j+s < n; j += s+s) { 41 | for (size_type k = 1; k < s; ++k) 42 | tmp[j+s-k-1] += tmp[j+s-k]; 43 | for (size_type k = 1; k < s && j+s+k < n; ++k) 44 | tmp[j+s+k] += tmp[j+s+k-1]; 45 | } 46 | M_c.push_back(std::move(tmp)); 47 | } 48 | } 49 | 50 | void assign(std::initializer_list il) { 51 | assign(il.begin(), il.end()); 52 | } 53 | 54 | value_type fold(size_type l, size_type r) const { 55 | if (l == r) return value_type{}; 56 | size_type i = (l ^ --r); 57 | if (i == 0) return M_c[0][l]; 58 | size_type j = ilog2(i); 59 | return M_c[j][l] + M_c[j][r]; 60 | } 61 | }; 62 | 63 | #endif /* !defined(H_disjoint_sparse_table) */ 64 | -------------------------------------------------------------------------------- /DataStructure/docs/basic_segment_tree.md: -------------------------------------------------------------------------------- 1 | 要素更新・区間和取得のセグメント木です。 2 | 3 | どう書くのがいいんだろうね。 4 | あと名前が気に入っていません。 5 | 6 | ## テンプレート引数 7 | - `Monoid` 8 | - default constructor が単位元のモノイドです。 9 | - `operator +=` と `operator +` が定義されている必要があります。 10 | 11 | ## public 関数 12 | 13 | ### コンストラクタ 14 | ``` 15 | basic_segment_tree(); 16 | ``` 17 | 18 | 空列で初期化します。 19 | 20 | ``` 21 | explicit basic_segment_tree(size_type n); 22 | ``` 23 | 24 | $a\_0, a\_1, \\dots, a\_{n-1}$ を単位元で初期化します。 25 | 26 | ``` 27 | basic_segment_tree(size_type n, value_type const& x); 28 | ``` 29 | 30 | $a\_0, a\_1, \\dots, a\_{n-1}$ を $x$ で初期化します。 31 | 32 | ``` 33 | template 34 | basic_segment_tree(InputIt first, InputIt last); 35 | ``` 36 | 37 | $a\_0, a\_1, \\dots, a\_{n-1}$ を範囲 $[\\mathit{first}, \\mathit{last})$ の値で初期化します。 38 | $n$ は範囲の長さです。 39 | 40 | ### メンバ関数 41 | 42 | ``` 43 | void assign(size_type n, value_type const& x); 44 | template 45 | void assign(first, last); 46 | ``` 47 | 48 | 値 $x$ や範囲 $[\\mathit{first}, \\mathit{last})$ の値を代入します。 49 | 計算量は $O(n)$ です。 50 | 51 | ``` 52 | void set(size_type i, value_type const& x); 53 | void set(size_type i, value_type&& x); 54 | ``` 55 | 56 | $a\_i$ を $x$ で置き換えます。 57 | 計算量は $O(\\log(n))$ です。 58 | 59 | ``` 60 | value_type const& operator [](size_type i) const; 61 | ``` 62 | 63 | $a\_i$ を返します。 64 | 計算量は $O(1)$ です。 65 | 66 | ``` 67 | value_type fold(size_type l, size_type r) const; 68 | ``` 69 | 70 | $a\_l + a\_{l+1} + \\dots + a\_{r-1}$ を返します。 71 | 計算量は $O(\\log(n))$ です。 72 | 73 | ``` 74 | template 75 | size_type foldl_bisect(size_type l, Predicate pred) const; 76 | ``` 77 | 78 | $\\mathit{fold}(l, n)$ が真の場合は `size_type` の `-1` を返します。 79 | そうでない場合、$\\mathit{pred}(\\mathit{fold}(l, r))$ が真になるような最大の $r$ を返します。 80 | 計算量は $O(\\log(n))$ です。 81 | 82 | ``` 83 | template 84 | size_type foldr_bisect(size_type r, Predicate pred) const; 85 | ``` 86 | 87 | $\\mathit{pred}(\\mathit{fold}(0, r))$ が真の場合は `size_type` の `-1` を返します。 88 | そうでない場合、$\\mathit{pred}(\\mathit{fold}(l, r))$ が偽になるような最大の $l$ を返します。 89 | 計算量は $O(\\log(n))$ です。 90 | 91 | `fold*_bisect` で返される境界値について補足します。 92 | 返ってきた添字の値を含めて足した場合は述語が偽になり、含めなかった場合は真になります。 93 | 94 | `foldl_bisect(l, pred)` の返り値を $r$ とすると、$[l, r)$ の和では真で、$[l, r]$ の和では偽です。 95 | `foldr_bisect(r, pred)` の返り値を $l$ とすると、$(l, r)$ の和では真で、$[l, r)$ の和では偽です。 96 | `foldl_bisect(n, pred)` と呼び出して、単位元で真になる場合は注意がいるかもしれません。 97 | 98 | ## 備考 99 | `utility/monoid/` にあるクラスを使うことで、区間最小値取得などに対応させます。 100 | 101 | `std::reverse_iterator` が `operator ++` で元のイテレータの `operator --` を呼び出すのと似ている気がします。 102 | adaptor とか呼ばれていそうです。 103 | -------------------------------------------------------------------------------- /DataStructure/foldable_queue.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_foldable_queue 2 | #define H_foldable_queue 3 | 4 | /** 5 | * @brief fold 可能キュー 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | template 14 | class foldable_queue { 15 | public: 16 | using size_type = size_t; 17 | using value_type = Monoid; 18 | 19 | private: 20 | std::stack M_front, M_back; 21 | value_type M_back_folded{}; 22 | 23 | void M_rotate_to_front() { 24 | if (!M_back.empty()) { 25 | M_front.push(std::move(M_back.top())); 26 | M_back.pop(); 27 | } 28 | while (!M_back.empty()) { 29 | M_back.top() += M_front.top(); 30 | M_front.push(std::move(M_back.top())); 31 | M_back.pop(); 32 | } 33 | M_back_folded = value_type{}; 34 | } 35 | 36 | public: 37 | size_type size() const { return M_front.size() + M_back.size(); } 38 | bool empty() const noexcept { return M_front.empty() && M_back.empty(); } 39 | 40 | void push(value_type const& x) { 41 | M_back.push(x); 42 | M_back_folded += M_back.top(); 43 | } 44 | 45 | template 46 | void emplace(Args&&... args) { 47 | M_back.emplace(std::forward(args)...); 48 | M_back_folded += M_back.top(); 49 | } 50 | 51 | void pop() { 52 | if (M_front.empty()) M_rotate_to_front(); 53 | M_front.pop(); 54 | } 55 | 56 | value_type fold() const { 57 | if (M_front.empty()) return M_back_folded; 58 | return M_front.top() + M_back_folded; 59 | } 60 | }; 61 | 62 | #endif /* !defined(H_foldable_queue) */ 63 | -------------------------------------------------------------------------------- /DataStructure/li_chao_tree.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_li_chao_tree 2 | #define H_li_chao_tree 3 | 4 | /** 5 | * @brief Li-Chao tree 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "utility/limits.cpp" 15 | 16 | template 17 | class lower_linear_envelope; 18 | 19 | struct li_chao_tree_tag {}; 20 | 21 | template 22 | class lower_linear_envelope { 23 | public: 24 | using value_type = Tp; 25 | using size_type = size_t; 26 | 27 | private: 28 | std::vector M_x; 29 | std::vector M_a, M_b; 30 | 31 | // FIXME: use fused_mul_add_min(a, x, b, y) 32 | 33 | void M_descend(size_type i, value_type a, value_type b) { 34 | size_type n = M_x.size(); 35 | size_type l = i, r = l+1; 36 | while (l < n) l <<= 1, r <<= 1; 37 | 38 | while (l < r) { 39 | size_type m = (l+r) >> 1; 40 | value_type xl = M_x[l-n], xm = M_x[m-n], xr = M_x[r-1-n]; 41 | value_type a0 = M_a[i], b0 = M_b[i]; 42 | value_type yl0 = a0*xl+b0, ym0 = a0*xm+b0, yr0 = a0*xr+b0; 43 | value_type yl = a*xl+b, ym = a*xm+b, yr = a*xr+b; 44 | if (yl0 < yl && yr0 < yr) return; 45 | if (yl < yl0 && yr < yr0) { 46 | M_a[i] = a, M_b[i] = b; 47 | return; 48 | } 49 | 50 | if (ym < ym0) { 51 | std::swap(M_a[i], a); 52 | std::swap(M_b[i], b); 53 | } 54 | if ((yl0 < yl && yr < yr0) ^ (ym < ym0)) { 55 | l = m; 56 | (i <<= 1) |= 1; 57 | } else { 58 | r = m; 59 | i <<= 1; 60 | } 61 | } 62 | } 63 | 64 | public: 65 | lower_linear_envelope() = default; 66 | 67 | template 68 | lower_linear_envelope(InputIt first, InputIt last): 69 | M_x(first, last), 70 | M_a(2*M_x.size(), 0), M_b(2*M_x.size(), limits::max()) 71 | {} 72 | 73 | void push(value_type a, value_type b) { push(a, b, 0, M_x.size()); } 74 | void push(value_type a, value_type b, size_type l, size_type r) { 75 | size_type n = M_x.size(); 76 | for (l += n, r += n; l < r; l >>= 1, r >>= 1) { 77 | if (l & 1) M_descend(l++, a, b); 78 | if (r & 1) M_descend(--r, a, b); 79 | } 80 | } 81 | 82 | value_type get_nth(size_type i) const { 83 | size_type n = M_x.size(); 84 | value_type x = M_x[i]; 85 | value_type y = limits::max(); 86 | i += n; 87 | while (i > 0) { 88 | value_type a = M_a[i], b = M_b[i]; 89 | y = std::min(y, a*x+b); 90 | i >>= 1; 91 | } 92 | return y; 93 | } 94 | }; 95 | 96 | #endif /* !defined(H_li_chao_tree) */ 97 | -------------------------------------------------------------------------------- /DataStructure/potential_function.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_potential_function 2 | #define H_potential_function 3 | 4 | /** 5 | * @brief ポテンシャル関数 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | template 14 | class potential_function { 15 | public: 16 | using value_type = AbelianGroup; 17 | using size_type = size_t; 18 | 19 | private: 20 | mutable std::vector M_c; 21 | mutable std::vector M_v; 22 | 23 | public: 24 | potential_function(size_type n): M_c(n, -1), M_v(n) {} 25 | 26 | size_type representative(size_type v) const { 27 | if (M_c[v] < 0) return v; 28 | size_type r = representative(M_c[v]); 29 | M_v[v] += M_v[M_c[v]]; 30 | return (M_c[v] = r); 31 | } 32 | 33 | bool define(size_type x, size_type y, value_type z) { 34 | size_type rx = representative(x); 35 | size_type ry = representative(y); 36 | z -= M_v[x] - M_v[y]; 37 | if (rx == ry) { 38 | if (z == value_type{}) return false; 39 | throw std::logic_error("inconsistent definitions"); 40 | } 41 | 42 | if (-M_c[rx] >= -M_c[ry]) { 43 | std::swap(rx, ry); 44 | std::swap(x, y); 45 | z = -z; 46 | } 47 | M_c[ry] += M_c[rx]; 48 | M_c[rx] = ry; 49 | M_v[rx] = z; 50 | return true; 51 | } 52 | 53 | bool defined(size_type u, size_type v) const { 54 | return representative(u) == representative(v); 55 | } 56 | 57 | value_type operator ()(size_type x, size_type y) const { 58 | if (!defined(x, y)) throw std::logic_error("undefined value"); 59 | return M_v[x] - M_v[y]; 60 | } 61 | 62 | size_type count(size_type x) const { return -M_c[representative(x)]; } 63 | }; 64 | 65 | #endif /* !defined(H_potential_function) */ 66 | -------------------------------------------------------------------------------- /DataStructure/rollbackable_array.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_rollbackable_array 2 | #define H_rollbackable_array 3 | 4 | /** 5 | * @brief rollback 可能配列 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | template 14 | class rollbackable_array { 15 | public: 16 | using size_type = size_t; 17 | using value_type = Tp; 18 | 19 | private: 20 | std::vector M_c; 21 | std::vector> M_h; 22 | 23 | public: 24 | rollbackable_array() = default; 25 | 26 | template 27 | rollbackable_array(InputIt first, InputIt last): M_c(first, last) {} 28 | rollbackable_array(size_type n, value_type const& x): M_c(n, x) {} 29 | 30 | void set(size_type i, value_type const& x) { 31 | M_h.emplace_back(i, M_c[i]); 32 | M_c[i] = x; 33 | } 34 | 35 | value_type const& operator [](size_type i) const { return M_c[i]; } 36 | 37 | bool empty() const noexcept { return M_c.empty(); } 38 | size_type size() const noexcept { return M_c.size(); } 39 | 40 | void rollback() { 41 | auto [i, x] = M_h.back(); 42 | M_h.pop_back(); 43 | M_c[i] = x; 44 | } 45 | 46 | auto begin() const { return M_c.begin(); } 47 | auto end() const { return M_c.end(); } 48 | }; 49 | 50 | #endif /* !defined(H_rollbackable_array) */ 51 | -------------------------------------------------------------------------------- /DataStructure/rollbackable_disjoint_set.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_rollbackable_disjoint_set 2 | #define H_rollbackable_disjoint_set 3 | 4 | /** 5 | * @brief rollback 可能な素集合データ構造 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "DataStructure/rollbackable_array.cpp" 15 | 16 | class rollbackable_disjoint_set { 17 | public: 18 | using size_type = size_t; 19 | 20 | private: 21 | rollbackable_array M_c; 22 | std::vector M_h; 23 | 24 | public: 25 | rollbackable_disjoint_set() = default; 26 | 27 | explicit rollbackable_disjoint_set(size_type n): M_c(n, -1) {} 28 | 29 | size_type representative(size_type v) const { 30 | while (!(M_c[v] < 0)) v = M_c[v]; 31 | return v; 32 | } 33 | 34 | bool unite(size_type u, size_type v) { 35 | u = representative(u); 36 | v = representative(v); 37 | if (u == v) { 38 | M_h.push_back(false); 39 | return false; 40 | } 41 | if (!(-M_c[u] <= -M_c[v])) std::swap(u, v); 42 | M_c.set(v, M_c[v] + M_c[u]); 43 | M_c.set(u, v); 44 | M_h.push_back(true); 45 | return true; 46 | } 47 | 48 | bool equivalent(size_type u, size_type v) const { 49 | return (representative(u) == representative(v)); 50 | } 51 | 52 | size_type size() const noexcept { return M_c.size(); } 53 | size_type count(size_type v) const { return -M_c[representative(v)]; } 54 | 55 | void rollback() { 56 | if (M_h.back()) M_c.rollback(), M_c.rollback(); 57 | M_h.pop_back(); 58 | } 59 | }; 60 | 61 | #endif /* !defined(H_rollbackable_disjoint_set) */ 62 | -------------------------------------------------------------------------------- /DataStructure/sparse_table.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_sparse_table 2 | #define H_sparse_table 3 | 4 | /** 5 | * @brief sparse table 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include "utility/literals.cpp" 13 | #include "integer/bit.cpp" 14 | 15 | template 16 | class sparse_table { 17 | public: 18 | using size_type = size_t; 19 | using value_type = Band; 20 | 21 | private: 22 | std::vector> M_c; 23 | 24 | public: 25 | sparse_table() = default; 26 | 27 | template 28 | sparse_table(InputIt first, InputIt last) { 29 | assign(first, last); 30 | } 31 | template 32 | sparse_table(std::initializer_list il) { 33 | assign(il.begin(), il.end()); 34 | } 35 | 36 | template 37 | void assign(InputIt first, InputIt last) { 38 | M_c.assign(1, std::vector(first, last)); 39 | size_type n = M_c[0].size(); 40 | for (size_type i = 1, ii = 1; M_c.back().size() > ii; (++i, ii <<= 1)) { 41 | M_c.emplace_back(); 42 | M_c.back().reserve(n - ii); 43 | for (size_type j = ii; j < M_c[i-1].size(); ++j) 44 | M_c[i].push_back(M_c[i-1][j] + M_c[i-1][j-ii]); 45 | } 46 | } 47 | 48 | void assign(std::initializer_list il) { 49 | assign(il.begin(), il.end()); 50 | } 51 | 52 | value_type fold(size_type l, size_type r) const { 53 | if (l >= r) return {}; 54 | size_type e = ilog2(r-l); 55 | r -= (1_zu << e) - 1; 56 | return M_c[e][l] + M_c[e][r-1]; 57 | } 58 | }; 59 | 60 | #endif /* !defined(H_sparse_table) */ 61 | -------------------------------------------------------------------------------- /DataStructure/starry_sky_tree.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_starry_sky_tree 2 | #define H_starry_sky_tree 3 | 4 | /** 5 | * @brief starry-sky tree 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include "integer/bit.cpp" 13 | 14 | template 15 | class starry_sky_tree { 16 | public: 17 | using size_type = size_t; 18 | using value_type = Tp; 19 | 20 | private: 21 | size_type M_n = 0; 22 | std::vector M_c; 23 | 24 | void M_fix_up(size_type i) { 25 | for (; i > 1; i >>= 1) { 26 | value_type d = std::max(M_c[i], M_c[i^1]); 27 | M_c[i] -= d; 28 | M_c[i^1] -= d; 29 | M_c[i >> 1] += d; 30 | } 31 | } 32 | 33 | public: 34 | starry_sky_tree() = default; 35 | starry_sky_tree(size_type n): M_n(ceil2(n)), M_c(2*M_n, value_type{0}) {} 36 | 37 | void add(size_type l, size_type r, value_type const& x) { 38 | if (l >= r) return; 39 | l += M_n, r += M_n; 40 | for (size_type il = l, ir = r; il < ir; il >>= 1, ir >>= 1) { 41 | if (il & 1) M_c[il++] += x; 42 | if (ir & 1) M_c[--ir] += x; 43 | } 44 | M_fix_up(l), M_fix_up(r-1); 45 | } 46 | 47 | value_type max() const { return M_c[1]; } 48 | }; 49 | 50 | #endif /* !defined(H_starry_sky_tree) */ 51 | -------------------------------------------------------------------------------- /Graph/adjacency_list.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_adjacency_list 2 | #define H_adjacency_list 3 | 4 | /** 5 | * @brief 重みつきグラフの隣接リスト 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | template 15 | class weighted_edge { 16 | public: 17 | using size_type = size_t; 18 | using weight_type = WeightType; 19 | 20 | protected: 21 | size_type M_src, M_dst; 22 | weight_type M_weight; 23 | 24 | public: 25 | weighted_edge() = default; 26 | weighted_edge(weighted_edge const&) = default; 27 | weighted_edge(weighted_edge&&) = default; 28 | 29 | weighted_edge(size_type s, size_type d, weight_type w): 30 | M_src(s), M_dst(d), M_weight(w) 31 | {} 32 | 33 | weighted_edge& operator =(weighted_edge const&) = default; 34 | weighted_edge& operator =(weighted_edge&&) = default; 35 | 36 | bool operator <(weighted_edge const& other) const { 37 | if (M_weight < other.M_weight) return true; 38 | if (other.M_weight < M_weight) return false; 39 | if (M_src != other.M_src) return M_src < other.M_src; 40 | return M_dst < other.M_dst; 41 | } 42 | 43 | size_type source() const { return M_src; } 44 | size_type target() const { return M_dst; } 45 | weight_type weight() const { return M_weight; } 46 | }; 47 | 48 | struct directed_tag {}; 49 | struct undirected_tag {}; 50 | 51 | template 52 | class adjacency_list { 53 | public: 54 | using size_type = size_t; 55 | using edge_type = Edge; 56 | using weight_type = typename Edge::weight_type; 57 | 58 | private: 59 | std::vector> M_g; 60 | 61 | public: 62 | adjacency_list() = default; 63 | adjacency_list(adjacency_list const&) = default; 64 | adjacency_list(adjacency_list&&) = default; 65 | explicit adjacency_list(size_type n): M_g(n) {} 66 | 67 | template 68 | void emplace(size_type src, size_type dst, Args... args) { 69 | M_g[src].emplace_back(src, dst, args...); 70 | if (std::is_same::value) 71 | M_g[dst].emplace_back(dst, src, args...); 72 | } 73 | 74 | void sort_by_index() { 75 | auto cmp = [](auto const& e1, auto const& e2) { 76 | return e1.target() < e2.target(); 77 | }; 78 | for (auto v: M_g) std::sort(v.begin(), v.end(), cmp); 79 | } 80 | 81 | size_type size() const { return M_g.size(); } 82 | auto const& operator [](size_type i) const { return M_g[i]; } 83 | }; 84 | 85 | #endif /* !defined(H_adjacency_list) */ 86 | -------------------------------------------------------------------------------- /Graph/capacitated_adjacency_list.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_capacitated_adjacency_list 2 | #define H_capacitated_adjacency_list 3 | 4 | /** 5 | * @brief 容量つきグラフの隣接リスト 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | 11 | #include "Graph/adjacency_list.cpp" 12 | 13 | template 14 | class capacitated_edge { 15 | public: 16 | using size_type = size_t; 17 | using weight_type = WeightType; 18 | 19 | protected: 20 | size_type M_src, M_dst; 21 | weight_type M_capacity; 22 | size_type M_rev; 23 | 24 | public: 25 | capacitated_edge() = default; 26 | capacitated_edge(capacitated_edge const&) = default; 27 | capacitated_edge(capacitated_edge&&) = default; 28 | 29 | capacitated_edge(size_type s, size_type d, weight_type c, size_type r): 30 | M_src(s), M_dst(d), M_capacity(c), M_rev(r) 31 | {} 32 | 33 | capacitated_edge& operator =(capacitated_edge const&) = default; 34 | capacitated_edge& operator =(capacitated_edge&&) = default; 35 | 36 | bool operator <(capacitated_edge const& other) const { 37 | if (M_capacity < other.M_capacity) return true; 38 | if (other.M_capacity < M_capacity) return false; 39 | if (M_src != other.M_src) return M_src < other.M_src; 40 | return M_dst < other.M_dst; 41 | } 42 | 43 | size_type source() const { return M_src; } 44 | size_type target() const { return M_dst; } 45 | weight_type capacity() const { return M_capacity; } 46 | weight_type& capacity() { return M_capacity; } 47 | size_type reversed() const { return M_rev; } 48 | }; 49 | 50 | template 51 | class adjacency_list, Directedness> { 52 | public: 53 | using size_type = size_t; 54 | using edge_type = capacitated_edge; 55 | using weight_type = WeightType; 56 | 57 | private: 58 | std::vector> M_g; 59 | 60 | public: 61 | adjacency_list() = default; 62 | adjacency_list(adjacency_list const&) = default; 63 | adjacency_list(adjacency_list&&) = default; 64 | explicit adjacency_list(size_type n): M_g(n) {} 65 | 66 | template 67 | void emplace(size_type src, size_type dst, weight_type cap) { 68 | M_g[src].emplace_back(src, dst, cap, M_g[dst].size()); 69 | if (std::is_same::value) { 70 | M_g[dst].emplace_back(dst, src, weight_type{0}, M_g[src].size()-1); 71 | } else if (std::is_same::value) { 72 | M_g[dst].emplace_back(dst, src, cap, M_g[src].size()-1); 73 | } 74 | } 75 | 76 | size_type size() const { return M_g.size(); } 77 | auto const& operator [](size_type i) const { return M_g[i]; } 78 | auto& operator [](size_type i) { return M_g[i]; } 79 | }; 80 | 81 | #endif /* !defined(H_capacitated_adjacency_list) */ 82 | -------------------------------------------------------------------------------- /Graph/dinitz.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_max_flow_dinitz 2 | #define H_max_flow_dinitz 3 | 4 | /** 5 | * @brief 最大流 (Dinitz 法) 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include "utility/literals.cpp" 13 | #include "utility/limits.cpp" 14 | #include "utility/make/fix_point.cpp" 15 | 16 | struct dinitz_tag {} dinitz; 17 | 18 | template 19 | auto max_flow(AdjacencyList& g, size_t s, size_t t, 20 | typename AdjacencyList::weight_type fl, dinitz_tag) { 21 | 22 | using size_type = typename AdjacencyList::size_type; 23 | using weight_type = typename AdjacencyList::weight_type; 24 | size_type n = g.size(); 25 | std::vector level(n), iter(n); 26 | 27 | auto bfs = [&](size_type s) -> void { 28 | level.assign(n, -1_zu); 29 | std::queue q; 30 | level[s] = 0; 31 | q.push(s); 32 | while (!q.empty()) { 33 | size_type v = q.front(); 34 | q.pop(); 35 | for (auto const& e: g[v]) { 36 | if (e.capacity() > weight_type(0) && level[e.target()] == -1_zu) { 37 | level[e.target()] = level[e.source()] + 1; 38 | q.push(e.target()); 39 | } 40 | } 41 | } 42 | }; 43 | 44 | auto dfs = make_fix_point([&](auto dfs_, size_type v, weight_type f) -> weight_type { 45 | if (v == t) return f; 46 | for (size_type& i = iter[v]; i < g[v].size(); ++i) { 47 | auto& e = g[v][i]; 48 | if (e.capacity() > weight_type(0) && level[v] < level[e.target()]) { 49 | weight_type f0 = dfs_(e.target(), std::min(f, e.capacity())); 50 | if (f0 > weight_type(0)) { 51 | e.capacity() -= f0; 52 | g[e.target()][e.reversed()].capacity() += f0; 53 | return f0; 54 | } 55 | } 56 | } 57 | return weight_type(0); 58 | }); 59 | 60 | weight_type res{0}; 61 | while (true) { 62 | bfs(s); 63 | if (level[t] == -1_zu) return res; 64 | iter.assign(n, 0); 65 | weight_type f; 66 | while ((f = dfs(s, fl)) > weight_type(0)) { 67 | res += f; 68 | fl -= f; 69 | if (fl == weight_type(0)) return res; 70 | } 71 | } 72 | } 73 | 74 | template 75 | auto max_flow(AdjacencyList& g, size_t s, size_t t, dinitz_tag) { 76 | auto fl = limits::max(); 77 | return max_flow(g, s, t, fl, dinitz); 78 | } 79 | 80 | #endif /* !defined(H_max_flow_dinitz) */ 81 | -------------------------------------------------------------------------------- /Graph/lowest_common_ancestor_segment_tree.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_lowest_common_ancestor_segment_tree 2 | #define H_lowest_common_ancestor_segment_tree 3 | 4 | /** 5 | * @brief 最深共通祖先 (segment tree) 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "integer/bit.cpp" 16 | #include "utility/literals.cpp" 17 | 18 | class lowest_common_ancestor { 19 | public: 20 | using size_type = size_t; 21 | 22 | private: 23 | std::vector M_e; 24 | std::vector> M_st; 25 | 26 | template 27 | void M_euler_tour(Tree const& g, size_type v, size_type p, size_type d = 0) { 28 | M_e[v] = M_st.size(); 29 | M_st.emplace_back(d, v); 30 | for (auto const& e: g[v]) { 31 | size_type u = e.target(); 32 | if (u == p) continue; 33 | M_euler_tour(g, u, v, d+1); 34 | M_st.emplace_back(d, v); 35 | } 36 | } 37 | 38 | void M_build_rmq() { 39 | // segment tree 40 | size_type n = M_st.size(); 41 | std::vector> tmp(n); 42 | M_st.insert(M_st.begin(), tmp.begin(), tmp.end()); 43 | for (size_type i = n; i--;) 44 | M_st[i] = std::min(M_st[i<<1|0], M_st[i<<1|1]); 45 | } 46 | 47 | public: 48 | lowest_common_ancestor() = default; 49 | lowest_common_ancestor(lowest_common_ancestor const&) = default; 50 | lowest_common_ancestor(lowest_common_ancestor&&) = default; 51 | 52 | template 53 | lowest_common_ancestor(Tree const& g, size_type r) { 54 | size_type n = g.size(); 55 | M_e.resize(n); 56 | M_st.reserve(n+n-2); 57 | M_euler_tour(g, r, -1); 58 | M_build_rmq(); 59 | } 60 | 61 | lowest_common_ancestor& operator =(lowest_common_ancestor const&) = default; 62 | lowest_common_ancestor& operator =(lowest_common_ancestor&&) = default; 63 | 64 | size_type operator ()(size_type u, size_type v) const { 65 | if (u == v) return u; 66 | size_type l, r; 67 | std::tie(l, r) = std::minmax(M_e[u], M_e[v]); 68 | size_type n = M_st.size() >> 1; 69 | l += n; 70 | r += n+1; 71 | std::pair res{n, n}; 72 | while (l < r) { 73 | if (l & 1) res = std::min(res, M_st[l++]); 74 | if (r & 1) res = std::min(M_st[--r], res); 75 | l >>= 1; 76 | r >>= 1; 77 | } 78 | return res.second; 79 | } 80 | }; 81 | 82 | #endif /* !defined(H_lowest_common_ancestor_segment_tree) */ 83 | -------------------------------------------------------------------------------- /Graph/lowest_common_ancestor_sparse_table.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_lowest_common_ancestor_sparse_table 2 | #define H_lowest_common_ancestor_sparse_table 3 | 4 | /** 5 | * @brief 最深共通祖先 (sparse table) 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "integer/bit.cpp" 16 | #include "utility/literals.cpp" 17 | 18 | class lowest_common_ancestor { 19 | public: 20 | using size_type = size_t; 21 | 22 | private: 23 | std::vector M_e; 24 | std::vector>> M_st; 25 | 26 | template 27 | void M_euler_tour(Tree const& g, size_type v, size_type p, size_type d = 0) { 28 | M_e[v] = M_st[0].size(); 29 | M_st[0].emplace_back(d, v); 30 | for (auto const& e: g[v]) { 31 | size_type u = e.target(); 32 | if (u == p) continue; 33 | M_euler_tour(g, u, v, d+1); 34 | M_st[0].emplace_back(d, v); 35 | } 36 | } 37 | 38 | void M_build_rmq() { 39 | // non-disjoint sparse table 40 | for (size_type i = 1, ii = 1; M_st[i-1].size() > ii; (++i, ii <<= 1)) { 41 | M_st.emplace_back(); 42 | M_st[i].reserve(M_st[i-1].size()-ii); 43 | for (size_type j = ii; j < M_st[i-1].size(); ++j) 44 | M_st[i].push_back(std::min(M_st[i-1][j], M_st[i-1][j-ii])); 45 | } 46 | } 47 | 48 | public: 49 | lowest_common_ancestor() = default; 50 | lowest_common_ancestor(lowest_common_ancestor const&) = default; 51 | lowest_common_ancestor(lowest_common_ancestor&&) = default; 52 | 53 | template 54 | lowest_common_ancestor(Tree const& g, size_type r) { 55 | size_type n = g.size(); 56 | M_e.resize(n); 57 | M_st.emplace_back(); 58 | M_st[0].reserve(2*n); 59 | M_euler_tour(g, r, -1); 60 | M_build_rmq(); 61 | } 62 | 63 | lowest_common_ancestor& operator =(lowest_common_ancestor const&) = default; 64 | lowest_common_ancestor& operator =(lowest_common_ancestor&&) = default; 65 | 66 | size_type operator ()(size_type u, size_type v) const { 67 | if (u == v) return u; 68 | size_type l, r; 69 | std::tie(l, r) = std::minmax(M_e[u], M_e[v]); 70 | size_type e = ilog2(++r-l); 71 | r -= 1_zu << e; 72 | return std::min(M_st[e][l], M_st[e][r]).second; 73 | } 74 | }; 75 | 76 | #endif /* !defined(H_lowest_common_ancestor_sparse_table) */ 77 | -------------------------------------------------------------------------------- /Graph/lowest_common_ancestor_squaring.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_lowest_common_ancestor_squaring 2 | #define H_lowest_common_ancestor_squaring 3 | 4 | /** 5 | * @brief 最深共通祖先 (squaring) 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "utility/literals.cpp" 16 | 17 | class lowest_common_ancestor { 18 | public: 19 | using size_type = size_t; 20 | 21 | private: 22 | std::vector M_d; 23 | std::vector> M_p; 24 | 25 | template 26 | void M_dfs(Tree const& g, size_type v, size_type p) { 27 | for (auto const& e: g[v]) { 28 | size_type u = e.target(); 29 | if (u == p) continue; 30 | M_p[0][u] = v; 31 | M_d[u] = M_d[v] + 1; 32 | M_dfs(g, u, v); 33 | } 34 | } 35 | 36 | void M_double() { 37 | size_type n = M_p[0].size(); 38 | while (true) { 39 | bool valid = false; 40 | auto const& back = M_p.back(); 41 | std::vector tmp(n, -1); 42 | for (size_type i = 0; i < n; ++i) { 43 | if (back[i] == -1_zu) continue; 44 | tmp[i] = back[back[i]]; 45 | if (tmp[i] != -1_zu) valid = true; 46 | } 47 | if (!valid) break; 48 | M_p.push_back(std::move(tmp)); 49 | } 50 | } 51 | 52 | public: 53 | lowest_common_ancestor() = default; 54 | lowest_common_ancestor(lowest_common_ancestor const&) = default; 55 | lowest_common_ancestor(lowest_common_ancestor&&) = default; 56 | 57 | template 58 | lowest_common_ancestor(Tree const& g, size_type r) { 59 | size_type n = g.size(); 60 | M_d.assign(n, 0); 61 | M_p.emplace_back(n, -1); 62 | M_dfs(g, r, -1); 63 | M_double(); 64 | } 65 | 66 | lowest_common_ancestor& operator =(lowest_common_ancestor const&) = default; 67 | lowest_common_ancestor& operator =(lowest_common_ancestor&&) = default; 68 | 69 | size_type operator ()(size_type u, size_type v) const { 70 | if (M_d[u] > M_d[v]) std::swap(u, v); 71 | if (M_d[u] < M_d[v]) { 72 | size_type d = M_d[v] - M_d[u]; 73 | for (size_type i = 0; i < M_p.size(); ++i) 74 | if (d >> i & 1) v = M_p[i][v]; 75 | } 76 | if (u == v) return u; 77 | for (size_type i = M_p.size(); i--;) { 78 | if (M_p[i][u] == M_p[i][v]) continue; 79 | u = M_p[i][u]; 80 | v = M_p[i][v]; 81 | } 82 | return M_p[0][u]; 83 | } 84 | }; 85 | 86 | #endif /* !defined(H_lowest_common_ancestor_squaring) */ 87 | -------------------------------------------------------------------------------- /Graph/pre17/shortest_path.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_shortest_path 2 | #define H_shortest_path 3 | 4 | /** 5 | * @brief グラフ上の最短距離 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "utility/limits.cpp" 16 | 17 | struct dijkstra_tag {} dijkstra; 18 | struct bfs01_tag {} bfs01; 19 | 20 | template 21 | auto shortest_path(AdjacencyList const& g, size_t s, dijkstra_tag) { 22 | size_t n = g.size(); 23 | using weight_type = typename AdjacencyList::weight_type; 24 | using pair = std::pair; 25 | std::vector d(n, limits::max()); 26 | d[s] = 0; 27 | std::priority_queue, std::greater<>> pq; 28 | pq.emplace(0, s); 29 | while (!pq.empty()) { 30 | weight_type w; 31 | size_t v; 32 | std::tie(w, v) = pq.top(); 33 | pq.pop(); 34 | if (d[v] < w) continue; 35 | for (auto const& e: g[v]) { 36 | size_t nv = e.target(); 37 | auto nw = w + e.weight(); 38 | if (nw < d[nv]) { 39 | d[nv] = nw; 40 | pq.emplace(nw, nv); 41 | } 42 | } 43 | } 44 | return d; 45 | } 46 | 47 | template 48 | auto shortest_path(AdjacencyList const& g, size_t s, bfs01_tag) { 49 | size_t n = g.size(); 50 | std::vector d(n, n); 51 | d[s] = 0; 52 | std::deque dq; 53 | dq.push_back(s); 54 | while (!dq.empty()) { 55 | size_t v = dq.front(); 56 | dq.pop_front(); 57 | for (auto const& e: g[v]) { 58 | size_t nv = e.target(); 59 | size_t nw = d[v] + ((e.weight() == 0)? 0: 1); 60 | if (!(nw < d[nv])) continue; 61 | d[nv] = nw; 62 | if (e.weight() == 0) { 63 | dq.push_front(nv); 64 | } else { 65 | dq.push_back(nv); 66 | } 67 | } 68 | } 69 | return d; 70 | } 71 | 72 | #endif /* !defined(H_shortest_path) */ 73 | -------------------------------------------------------------------------------- /Graph/scc.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_strongly_connected_components 2 | #define H_strongly_connected_components 3 | 4 | /** 5 | * @brief 強連結成分分解 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include "utility/make/fix_point.cpp" 13 | #include "Graph/adjacency_list.cpp" 14 | 15 | template 16 | auto strongly_connected_components(AdjacencyList const& g) { 17 | size_t n = g.size(); 18 | adjacency_list, directed_tag> h(n); 19 | for (size_t v = 0; v < n; ++v) 20 | for (auto const& e: g[v]) h.emplace(e.target(), e.source(), 1); 21 | 22 | std::vector used(n); 23 | std::vector vs; 24 | auto dfs = make_fix_point([&](auto f, size_t v) -> void { 25 | used[v] = true; 26 | for (auto const& e: g[v]) 27 | if (!used[e.target()]) f(e.target()); 28 | vs.push_back(v); 29 | }); 30 | for (size_t v = 0; v < n; ++v) 31 | if (!used[v]) dfs(v); 32 | 33 | used.assign(n, false); 34 | std::vector cmp(n); 35 | size_t num = 0; 36 | auto rdfs = make_fix_point([&](auto f, size_t v) -> void { 37 | used[v] = true; 38 | cmp[v] = num; 39 | for (auto const& e: h[v]) 40 | if (!used[e.target()]) f(e.target()); 41 | }); 42 | for (size_t v = vs.size(); v--;) 43 | if (!used[vs[v]]) 44 | rdfs(vs[v]), ++num; 45 | 46 | return cmp; 47 | } 48 | 49 | #endif /* !defined(H_strongly_connected_components) */ 50 | -------------------------------------------------------------------------------- /Graph/shortest_path.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_shortest_path 2 | #define H_shortest_path 3 | 4 | /** 5 | * @brief グラフ上の最短距離 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "utility/limits.cpp" 16 | 17 | struct dijkstra_tag {} dijkstra; 18 | struct bfs01_tag {} bfs01; 19 | 20 | template 21 | auto shortest_path(AdjacencyList const& g, size_t s, dijkstra_tag) { 22 | size_t n = g.size(); 23 | using weight_type = typename AdjacencyList::weight_type; 24 | using pair = std::pair; 25 | std::vector d(n, limits::max()); 26 | d[s] = 0; 27 | std::priority_queue, std::greater<>> pq; 28 | pq.emplace(0, s); 29 | while (!pq.empty()) { 30 | auto [w, v] = pq.top(); 31 | pq.pop(); 32 | if (d[v] < w) continue; 33 | for (auto const& e: g[v]) { 34 | size_t nv = e.target(); 35 | if (auto nw = w + e.weight(); nw < d[nv]) { 36 | d[nv] = nw; 37 | pq.emplace(nw, nv); 38 | } 39 | } 40 | } 41 | return d; 42 | } 43 | 44 | template 45 | auto shortest_path(AdjacencyList const& g, size_t s, bfs01_tag) { 46 | size_t n = g.size(); 47 | std::vector d(n, n); 48 | d[s] = 0; 49 | std::deque dq; 50 | dq.push_back(s); 51 | while (!dq.empty()) { 52 | size_t v = dq.front(); 53 | dq.pop_front(); 54 | for (auto const& e: g[v]) { 55 | size_t nv = e.target(); 56 | size_t nw = d[v] + ((e.weight() == 0)? 0: 1); 57 | if (!(nw < d[nv])) continue; 58 | d[nv] = nw; 59 | if (e.weight() == 0) { 60 | dq.push_front(nv); 61 | } else { 62 | dq.push_back(nv); 63 | } 64 | } 65 | } 66 | return d; 67 | } 68 | 69 | #endif /* !defined(H_shortest_path) */ 70 | -------------------------------------------------------------------------------- /Graph/topological_sort.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_topological_sort 2 | #define H_topological_sort 3 | 4 | /** 5 | * @brief トポロジカルソート 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | template 13 | std::vector topological_sort(AdjacencyList const& g) { 14 | size_t n = g.size(); 15 | std::vector ord, indeg(n, 0); 16 | std::queue q; 17 | ord.reserve(n); 18 | for (size_t v = 0; v < n; ++v) 19 | for (auto const& e: g[v]) ++indeg[e.target()]; 20 | for (size_t v = 0; v < n; ++v) 21 | if (indeg[v] == 0) q.push(v); 22 | while (!q.empty()) { 23 | size_t v = q.front(); 24 | q.pop(); 25 | ord.push_back(v); 26 | for (auto const& e: g[v]) { 27 | size_t u = e.target(); 28 | if (--indeg[u] == 0) q.push(u); 29 | } 30 | } 31 | if (ord.size() < n) ord.clear(); 32 | return ord; 33 | } 34 | 35 | #endif /* !defined(H_topological_sort) */ 36 | -------------------------------------------------------------------------------- /Graph/two_sat.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_two_sat 2 | #define H_two_sat 3 | 4 | /** 5 | * @brief 2-SAT 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include "Graph/adjacency_list.cpp" 13 | #include "Graph/scc.cpp" 14 | 15 | class two_sat { 16 | public: 17 | using size_type = size_t; 18 | 19 | private: 20 | size_type M_n; 21 | adjacency_list, directed_tag> M_g; 22 | std::vector M_scc; 23 | bool M_sat; 24 | 25 | void M_solve() { 26 | if (!M_scc.empty()) return; 27 | M_scc = strongly_connected_components(M_g); 28 | for (size_type i = 0; i < M_n; ++i) 29 | if (M_scc[i] == M_scc[i+M_n]) { 30 | M_sat = false; 31 | return; 32 | } 33 | M_sat = true; 34 | } 35 | 36 | public: 37 | two_sat() = default; 38 | explicit two_sat(size_type n): M_n(n), M_g(n+n) {} 39 | 40 | void push(size_type i, bool bi, size_type j, bool bj) { 41 | M_scc.clear(); 42 | 43 | size_type not_i = i + M_n; 44 | size_type not_j = j + M_n; 45 | if (!bi) std::swap(i, not_i); 46 | if (!bj) std::swap(j, not_j); 47 | 48 | // i or j, (not i => j, not j => i) 49 | M_g.emplace(not_i, j, 1); 50 | M_g.emplace(not_j, i, 1); 51 | } 52 | 53 | bool satisfiable() { 54 | M_solve(); 55 | return M_sat; 56 | } 57 | 58 | bool operator [](size_type i) { 59 | M_solve(); 60 | return M_scc[i+M_n] < M_scc[i]; 61 | } 62 | }; 63 | 64 | #endif /* !defined(H_two_sat) */ 65 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 rsk0315 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Math/factor.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_factor 2 | #define H_factor 3 | 4 | /** 5 | * @brief 素因数分解 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | std::map factor(intmax_t n) { 13 | std::map res; 14 | for (intmax_t i = 2; i*i <= n; ++i) { 15 | if (n % i != 0) continue; 16 | do { 17 | ++res[i]; 18 | n /= i; 19 | } while (n % i == 0); 20 | } 21 | if (n > 1) ++res[n]; 22 | return res; 23 | } 24 | 25 | #endif /* !defined(H_factor) */ 26 | -------------------------------------------------------------------------------- /Math/remainder_sum.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_remainder_sum 2 | #define H_remainder_sum 3 | 4 | /** 5 | * @brief $i \\bmod{n}$ の和 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | template 14 | class remainder_sum_table { 15 | public: 16 | using value_type = Tp; 17 | 18 | private: 19 | intmax_t M_n; 20 | std::vector M_d; 21 | std::vector M_s; 22 | 23 | public: 24 | remainder_sum_table() = default; 25 | 26 | explicit remainder_sum_table(intmax_t n): M_n(n) { 27 | M_d = {0}; 28 | std::vector tmp; 29 | for (intmax_t i = 1; i*i <= n; ++i) { 30 | M_d.push_back(i); 31 | if (i*i < n) tmp.push_back(n/i); 32 | } 33 | M_d.insert(M_d.end(), tmp.rbegin(), tmp.rend()); 34 | 35 | M_s = {0}; 36 | for (size_t i = 1; i < M_d.size(); ++i) { 37 | intmax_t dl = M_d[i-1] + 1; 38 | intmax_t dr = M_d[i]; 39 | value_type sum = value_type(n % dl + n % dr) * value_type(dr-dl+1) / 2; 40 | M_s.push_back(sum); 41 | } 42 | 43 | M_s.insert(M_s.begin(), 0); 44 | for (size_t i = 1; i < M_s.size(); ++i) M_s[i] += M_s[i-1]; 45 | } 46 | 47 | value_type operator ()(intmax_t r) const { 48 | if (r == 0) return 0; 49 | auto it = std::upper_bound(M_d.begin(), M_d.end(), r); 50 | size_t j = it - M_d.begin(); 51 | intmax_t dl = it[-1] + 1; 52 | intmax_t dr = r; 53 | return M_s[j] + value_type(M_n % dl + M_n % dr) * value_type(dr-dl+1) / 2; 54 | } 55 | }; 56 | 57 | #endif /* !defined(H_remainder_sum) */ 58 | -------------------------------------------------------------------------------- /ModularArithmetic/chinese_remaindering.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_chinese_remaindering 2 | #define H_chinese_remaindering 3 | 4 | /** 5 | * @brief 連立合同式の解の構成 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include "integer/fused_operations.cpp" 13 | 14 | class simultaneous_congruences { 15 | public: 16 | using value_type = intmax_t; 17 | 18 | private: 19 | value_type M_mod = 1; 20 | value_type M_sol = 0; 21 | 22 | static auto S_gcd_bezout(value_type a, value_type b) { 23 | value_type x{1}, y{0}; 24 | for (value_type u{y}, v{x}; b != 0;) { 25 | value_type q{a/b}; 26 | std::swap(x -= q*u, u); 27 | std::swap(y -= q*v, v); 28 | std::swap(a -= q*b, b); 29 | } 30 | return std::make_tuple(a, x, y); 31 | } 32 | 33 | public: 34 | simultaneous_congruences() = default; 35 | 36 | bool push(value_type a, value_type m) { 37 | if (M_mod == 0) return false; 38 | if ((a %= m) < 0) a += m; 39 | 40 | auto [g, x, y] = S_gcd_bezout(M_mod, m); 41 | value_type mod = M_mod / g * m; 42 | value_type sol0 = fused_mul_mod(fused_mul_mod(M_mod / g, a, mod), x, mod); 43 | value_type sol1 = fused_mul_mod(fused_mul_mod(m / g, M_sol, mod), y, mod); 44 | value_type sol = fused_add_mod(sol0, sol1, mod); 45 | 46 | if (g > 1 && (sol % M_mod != M_sol || sol % m != a)) { 47 | M_mod = M_sol = 0; 48 | return false; 49 | } 50 | M_sol = sol; 51 | M_mod = mod; 52 | return true; 53 | } 54 | 55 | auto get() const { return std::make_pair(M_sol, M_mod); } 56 | }; 57 | 58 | #endif /* !defined(H_chinese_remaindering) */ 59 | -------------------------------------------------------------------------------- /ModularArithmetic/factorial.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_factorial 2 | #define H_factorial 3 | 4 | /** 5 | * @brief 階乗の高速計算 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include "ModularArithmetic/modint.cpp" 13 | #include "ModularArithmetic/modtable.cpp" 14 | #include "ModularArithmetic/polynomial.cpp" 15 | #include "integer/sqrt.cpp" 16 | #include "integer/bit.cpp" 17 | 18 | template 19 | modint factorial(intmax_t n) { 20 | if (n == 0) return 1; 21 | if (n >= Mod) return 0; 22 | using value_type = modint; 23 | using int_type = typename value_type::value_type; 24 | int_type v = ceil2(isqrt(n)); 25 | modtable mt(v); 26 | 27 | std::vector g{1, v+1}; 28 | for (int_type d = 1; d < v; d <<= 1) { 29 | std::vector a(d+1); 30 | for (int_type i = 0; i <= d; ++i) { 31 | a[i] = g[i] * mt.factorial_inverse(i) * mt.factorial_inverse(d-i); 32 | if ((d-i) % 2 != 0) a[i] = -a[i]; 33 | } 34 | 35 | auto shift = [&](int_type m0) { 36 | m0 = (value_type(m0) / v).get(); 37 | int_type m = std::max(m0, d+1); 38 | 39 | std::vector b(d+1), c(d+1); 40 | for (int_type i = 0; i <= d; ++i) { 41 | b[i] = value_type{1} / (m+i); 42 | c[d-i] = value_type{1} / (m-i-1); 43 | } 44 | 45 | polynomial fa(a.begin(), a.end()), fb(b.begin(), b.end()), fc(c.begin(), c.end()); 46 | fb *= fa, fc *= fa; 47 | 48 | std::vector res(d+1); 49 | value_type mul = 1; 50 | for (int j = 0; j <= d; ++j) mul *= m-j; 51 | for (int k = 0; k <= d; ++k) { 52 | res[k] = (fb[k] + fc[k+d+1]) * mul; 53 | if (k < d) mul *= value_type(m+k+1) / value_type(m+k-d); 54 | } 55 | if (m0 <= d) { 56 | for (int_type i = m0; i--;) res[d-(m0-i-1)] = res[i]; 57 | for (int_type i = m0; i <= d; ++i) res[i-m0] = g[i]; 58 | } 59 | return res; 60 | }; 61 | std::vector gd = shift(d); 62 | std::vector gdv = shift(d*v); 63 | std::vector gdvd = shift(d*v+d); 64 | 65 | g.resize(2*d+1); 66 | for (int_type i = 0; i < d; ++i) g[i] *= gd[i]; 67 | for (int_type i = 0; i <= d; ++i) g[d+i] = gdv[i] * gdvd[i]; 68 | } 69 | 70 | value_type res = 1; 71 | int_type i = 0; 72 | for (size_t j = 0; i+v <= n && j < g.size(); i += v, ++j) res *= g[j]; 73 | for (++i; i <= n; ++i) res *= i; 74 | return res; 75 | } 76 | 77 | #endif /* !defined(H_factorial) */ 78 | -------------------------------------------------------------------------------- /ModularArithmetic/garner.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_garner 2 | #define H_garner 3 | 4 | /** 5 | * @brief Garner's algorithm 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | class simultaneous_congruences_garner { 14 | public: 15 | using value_type = intmax_t; 16 | using size_type = size_t; 17 | 18 | private: 19 | value_type M_mod = 1; 20 | value_type M_sol = 0; 21 | std::vector M_c, M_m; 22 | 23 | static auto S_gcd_bezout(value_type a, value_type b) { 24 | value_type x{1}, y{0}; 25 | for (value_type u{y}, v{x}; b != 0;) { 26 | value_type q{a/b}; 27 | std::swap(x -= q*u, u); 28 | std::swap(y -= q*v, v); 29 | std::swap(a -= q*b, b); 30 | } 31 | return std::make_tuple(a, x, y); 32 | } 33 | 34 | public: 35 | simultaneous_congruences_garner() = default; 36 | 37 | void push(value_type a, value_type m) { 38 | if (M_c.empty()) { 39 | M_c.push_back(a); 40 | M_m.push_back(m); 41 | return; 42 | } 43 | 44 | value_type c = M_c.back(); 45 | value_type mi = M_m.back(); 46 | for (size_type i = M_c.size()-1; i--;) { 47 | c = (c * M_m[i] + M_c[i]) % m; 48 | (mi *= M_m[i]) %= m; 49 | } 50 | c = (a-c) * std::get<1>(S_gcd_bezout(mi, m)) % m; 51 | if (c < 0) c += m; 52 | M_c.push_back(c); 53 | M_m.push_back(m); 54 | } 55 | 56 | auto get(value_type m) const { 57 | value_type x = M_c.back() % m; 58 | for (size_type i = M_c.size()-1; i--;) { 59 | x = (x * M_m[i] + M_c[i]) % m; 60 | } 61 | return x; 62 | } 63 | }; 64 | 65 | #endif /* !defined(H_garner) */ 66 | -------------------------------------------------------------------------------- /ModularArithmetic/interpolation.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_interpolation 2 | #define H_interpolation 3 | 4 | /** 5 | * @brief 補間多項式 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include "ModularArithmetic/polynomial.cpp" 13 | #include "integer/bit.cpp" 14 | 15 | template 16 | polynomial interpolate(std::vector const& xs, std::vector const& ys) { 17 | size_t n = xs.size(); 18 | size_t n2 = ceil2(n); 19 | std::vector> mul(n2+n2, {1}), g(n2+n2); 20 | for (size_t i = 0; i < n; ++i) mul[n2+i] = {-xs[i], 1}; 21 | for (size_t i = n2; i-- > 1;) mul[i] = mul[i<<1|0] * mul[i<<1|1]; 22 | 23 | auto f = mul[1]; 24 | f.differentiate(); 25 | 26 | g[1] = f % mul[1]; 27 | for (size_t i = 2; i < n2+n; ++i) g[i] = g[i>>1] % mul[i]; 28 | for (size_t i = 0; i < n; ++i) g[n2+i] = {ys[i] / g[n2+i][0]}; 29 | for (size_t i = n2; i--;) g[i] = g[i<<1|0] * mul[i<<1|1] + g[i<<1|1] * mul[i<<1|0]; 30 | return g[1]; 31 | } 32 | 33 | #endif /* !defined(H_interpolation) */ 34 | -------------------------------------------------------------------------------- /ModularArithmetic/modtable.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_modtable 2 | #define H_modtable 3 | 4 | /** 5 | * @brief 合同演算の前計算テーブル 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | template 13 | class modtable { 14 | public: 15 | using value_type = ModInt; 16 | using size_type = size_t; 17 | using underlying_type = typename ModInt::value_type; 18 | 19 | private: 20 | std::vector M_f, M_i, M_fi; 21 | 22 | public: 23 | modtable() = default; 24 | 25 | explicit modtable(underlying_type n): M_f(n+1), M_i(n+1), M_fi(n+1) { 26 | M_f[0] = 1; 27 | for (underlying_type i = 1; i <= n; ++i) 28 | M_f[i] = M_f[i-1] * i; 29 | 30 | underlying_type mod = M_f[0].get_modulo(); 31 | M_i[1] = 1; 32 | for (underlying_type i = 2; i <= n; ++i) 33 | M_i[i] = -value_type(mod / i) * M_i[mod % i]; 34 | 35 | M_fi[0] = 1; 36 | for (underlying_type i = 1; i <= n; ++i) 37 | M_fi[i] = M_fi[i-1] * M_i[i]; 38 | } 39 | 40 | value_type inverse(underlying_type n) const { return M_i[n]; } 41 | value_type factorial(underlying_type n) const { return M_f[n]; } 42 | value_type factorial_inverse(underlying_type n) const { return M_fi[n]; } 43 | 44 | value_type binom(underlying_type n, underlying_type k) const { 45 | if (n < 0 || n < k || k < 0) return 0; 46 | // assumes n < mod 47 | return M_f[n] * M_fi[k] * M_fi[n-k]; 48 | } 49 | }; 50 | 51 | #endif /* !defined(H_modtable) */ 52 | -------------------------------------------------------------------------------- /ModularArithmetic/operations.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_mod_operations 2 | #define H_mod_operations 3 | 4 | /** 5 | * @brief 合同算術の基本演算 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include "integer/bit.cpp" 13 | 14 | template 15 | ModInt pow(ModInt const& n, intmax_t iexp) { 16 | ModInt res(1); 17 | for (ModInt dbl = n; iexp; iexp >>= 1) { 18 | if (iexp & 1) res *= dbl; 19 | dbl *= dbl; 20 | } 21 | return res; 22 | } 23 | 24 | template 25 | ModInt sqrt(ModInt const& n) { 26 | if (n == 0) return n; 27 | 28 | using value_type = typename ModInt::value_type; 29 | 30 | intmax_t const p = n.get_modulo(); 31 | if (p % 4 == 3) { 32 | ModInt r = pow(n, (p+1) / 4); 33 | if (r * r == n) return r; 34 | throw std::logic_error("quadratic nonresidue"); 35 | } 36 | 37 | value_type s = ctz(p-1); 38 | value_type q = (p-1) >> s; 39 | 40 | ModInt z; 41 | for (value_type z0 = 2; z0 < p; ++z0) { 42 | z = ModInt(z0); 43 | if (pow(z, (p-1) / 2) == -1) break; 44 | } 45 | 46 | value_type m = s; 47 | ModInt c = pow(z, q); 48 | ModInt t = pow(n, q); 49 | ModInt r = pow(n, (q+1) / 2); 50 | 51 | while (true) { 52 | if (t == 0) return 0; 53 | if (t == 1) return r; 54 | 55 | value_type i = 0; 56 | for (auto tt = t; tt != 1; ++i) tt *= tt; 57 | if (i == m) throw std::logic_error("quadratic nonresidue"); 58 | auto b = c; 59 | for (value_type j = 0; j < m-i-1; ++j) b *= b; 60 | m = i; 61 | c = b * b; 62 | t *= c; 63 | r *= b; 64 | } 65 | } 66 | 67 | template 68 | std::vector sqrt_all(ModInt const& n) { 69 | try { 70 | auto r = sqrt(n); 71 | if (r == -r) return {r}; 72 | return {r, -r}; 73 | } catch (std::logic_error const&) { 74 | return {}; 75 | } 76 | } 77 | 78 | template 79 | ModPolynomial log(ModPolynomial const& f) { 80 | auto g = f; 81 | g.differentiate(); 82 | g *= f.inverse(f.degree()+1); 83 | g.integrate(); 84 | return g; 85 | } 86 | 87 | #endif /* !defined(H_mod_operations) */ 88 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # library 2 | 3 | [![Actions Status](https://github.com/rsk0315/library/workflows/verify/badge.svg)](https://github.com/rsk0315/library/actions) 4 | [![GitHub Pages](https://img.shields.io/static/v1?label=GitHub+Pages&message=+&color=brightgreen&logo=github)](https://rsk0315.github.io/library/) 5 | [![LICENSE](https://img.shields.io/pypi/l/online-judge-verify-helper.svg)](https://github.com/kmyk/online-judge-verify-helper/blob/master/LICENSE) 6 | -------------------------------------------------------------------------------- /String/knuth_morris_pratt_searcher.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_knuth_morris_pratt_searcher 2 | #define H_knuth_morris_pratt_searcher 3 | 4 | /** 5 | * @brief KMP 法 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | template 13 | class knuth_morris_pratt_searcher { 14 | public: 15 | using size_type = size_t; 16 | 17 | private: 18 | static constexpr size_type S_npos = -1; 19 | RandomIt1 M_pf, M_pl; 20 | std::vector M_fail; 21 | 22 | public: 23 | knuth_morris_pratt_searcher(RandomIt1 pat_first, RandomIt1 pat_last): 24 | M_pf(pat_first), M_pl(pat_last), M_fail(M_pl-M_pf+1) 25 | { 26 | M_fail[0] = S_npos; 27 | size_type n = M_pl - M_pf; 28 | for (size_type i = 0, j = S_npos; i < n;) { 29 | while (j != S_npos && M_pf[i] != M_pf[j]) j = M_fail[j]; 30 | ++i, ++j; 31 | M_fail[i] = ((i < n && (M_pf[i] == M_pf[j]))? M_fail[j]: j); 32 | } 33 | } 34 | 35 | template 36 | std::pair find_first(RandomIt2 first, RandomIt2 last) const { 37 | if (M_pf == M_pl) return {first, first}; 38 | size_type n = M_pl - M_pf; 39 | size_type j = 0; 40 | for (auto it = first; it < last;) { 41 | while (j != S_npos && M_pf[j] != *it) j = M_fail[j]; 42 | ++it; 43 | if (++j == n) return {it-n, it}; 44 | } 45 | return {last, last}; 46 | } 47 | 48 | template 49 | std::vector> find_all(RandomIt2 first, RandomIt2 last) const { 50 | std::vector> res; 51 | if (M_pf == M_pl) { 52 | for (auto it = first; it < last; ++it) res.emplace_back(it, it); 53 | res.emplace_back(last, last); 54 | return res; 55 | } 56 | 57 | size_type n = M_pl - M_pf; 58 | size_type j = 0; 59 | for (auto it = first; it < last;) { 60 | while (j != S_npos && M_pf[j] != *it) j = M_fail[j]; 61 | ++it; 62 | if (++j == n) { 63 | res.emplace_back(it-n, it); 64 | j = M_fail[j]; 65 | } 66 | } 67 | return res; 68 | } 69 | 70 | template 71 | std::pair operator ()(RandomIt2 first, RandomIt2 last) const { 72 | return find_first(first, last); 73 | } 74 | 75 | size_type operator [](size_type i) const { return M_fail[i]; } 76 | }; 77 | 78 | #if __cplusplus >= 201703L 79 | template 80 | knuth_morris_pratt_searcher(RandomIt1 pat_first, RandomIt1 pat_last) 81 | -> knuth_morris_pratt_searcher; 82 | #endif 83 | 84 | #endif /* !defined(H_knuth_morris_pratt_searcher) */ 85 | -------------------------------------------------------------------------------- /String/rolling_hash_l61m1.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_rolling_hash_l61m1 2 | #define H_rolling_hash_l61m1 3 | 4 | /** 5 | * @brief mod 2^61-1 のローリングハッシュ 6 | * @author えびちゃん 7 | * @see https://qiita.com/keymoon/items/11fac5627672a6d6a9f6 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "utility/literals.cpp" 15 | 16 | class rolling_hash_l61m1 { 17 | public: 18 | using size_type = size_t; 19 | using value_type = uintmax_t; 20 | static value_type const mod = (1_ju << 61) - 1; 21 | static size_type const npos = -1; 22 | 23 | private: 24 | value_type M_b; 25 | std::vector M_c, M_p; 26 | 27 | static value_type S_fma(value_type a, value_type b, value_type c) { 28 | value_type au = a >> 31; 29 | value_type al = a & ((1u << 31) - 1); 30 | value_type bu = b >> 31; 31 | value_type bl = b & ((1u << 31) - 1); 32 | 33 | value_type x = au*bl + al*bu; 34 | value_type xu = x >> 30; 35 | value_type xl = x & ((1u << 30) - 1); 36 | 37 | value_type y = ((au*bu) << 1) + (xu + (xl << 31)) + (al*bl); 38 | value_type yu = y >> 61; 39 | value_type yl = y & ((1_ju << 61) - 1); 40 | 41 | value_type z = yu + yl + c; 42 | if (z >= mod) z -= mod; 43 | return z; 44 | } 45 | 46 | void M_build() { 47 | for (size_type i = 1; i < M_c.size(); ++i) 48 | M_c[i] = S_fma(M_c[i-1], M_b, M_c[i]); 49 | M_c.insert(M_c.begin(), 0); 50 | 51 | M_p.assign(M_c.size(), 1); 52 | for (size_type i = 1; i < M_p.size(); ++i) 53 | M_p[i] = S_fma(M_p[i-1], M_b, 0); 54 | } 55 | 56 | public: 57 | rolling_hash_l61m1() = default; 58 | 59 | template 60 | rolling_hash_l61m1(InputIt first, InputIt last, value_type base): M_b(base) { 61 | assign(first, last); 62 | } 63 | 64 | template 65 | void assign(InputIt first, InputIt last) { 66 | M_c.assign(first, last); 67 | M_build(); 68 | } 69 | 70 | template 71 | void assign(InputIt first, InputIt last, value_type base) { 72 | M_b = base; 73 | M_c.assign(first, last); 74 | M_build(); 75 | } 76 | 77 | value_type substr(size_type pos, size_type len = npos) { 78 | size_type n = M_c.size() - 1; 79 | if (len == npos) len = n - pos; 80 | size_type endpos = pos + len; 81 | value_type hr = M_c[endpos]; 82 | value_type hl = M_c[pos]; 83 | value_type hs = hr - S_fma(hl, M_p[len], 0); 84 | if (hs >= mod) // "negative" 85 | hs += mod; 86 | return hs; 87 | } 88 | }; 89 | 90 | #endif /* !defined(H_rolling_hash_l61m1) */ 91 | -------------------------------------------------------------------------------- /String/tree_attack.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_tree_attack 2 | #define H_tree_attack 3 | 4 | /** 5 | * @brief ロリハを衝突させるやつ (tree attack) 6 | * @author えびちゃん 7 | * @see https://codeforces.com/blog/entry/60442 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "utility/literals.cpp" 18 | 19 | std::vector tree_attack(intmax_t p, intmax_t b, size_t k, int sigma = 2) { 20 | struct node { 21 | intmax_t value; 22 | size_t pos, neg; 23 | int coef; 24 | node() = default; 25 | node(intmax_t v, size_t l, size_t r, int c): value(v), pos(l), neg(r), coef(c) {} 26 | bool operator <(node const& that) const { return value < that.value; } 27 | }; 28 | 29 | std::vector> cl(k+1); 30 | size_t n = 1_zu << k; 31 | cl[0].assign(n, node(1, n-1, -1_zu, 1)); 32 | intmax_t pow = 1; 33 | for (size_t j = 1; j < n; ++j) { 34 | pow = __int128(pow) * b % p; 35 | cl[0][j].value = pow; 36 | cl[0][j].coef = 1; 37 | intmax_t cur = pow; 38 | for (int s = 2; s < sigma; ++s) { 39 | cur = __int128(cur + pow) % p; 40 | if (cur < cl[0][j].value) { 41 | cl[0][j].value = cur; 42 | cl[0][j].coef = s; 43 | } 44 | } 45 | cl[0][j].pos = n-1-j; 46 | } 47 | 48 | std::sort(cl[0].begin(), cl[0].end()); 49 | 50 | std::vector coef(n); 51 | for (size_t i = 0; i < n; ++i) 52 | coef[cl[0][i].pos] = cl[0][i].coef; 53 | 54 | for (size_t i = 1; i <= k; ++i) { 55 | cl[i].resize(n >> i); 56 | for (size_t j = 0; j < cl[i].size(); ++j) { 57 | size_t jl = j << 1 | 0; 58 | size_t jr = j << 1 | 1; 59 | if (cl[i-1][jr] < cl[i-1][jl]) { 60 | cl[i][j].value = cl[i-1][jl].value - cl[i-1][jr].value; 61 | cl[i][j].pos = jl; 62 | cl[i][j].neg = jr; 63 | } else { 64 | cl[i][j].value = cl[i-1][jr].value - cl[i-1][jl].value; 65 | cl[i][j].pos = jr; 66 | cl[i][j].neg = jl; 67 | } 68 | } 69 | std::sort(cl[i].begin(), cl[i].end()); 70 | if (cl[i][0].value > 0) continue; 71 | 72 | std::vector res(n, 0); 73 | std::queue> q; // i, j, neg? 74 | q.emplace(i-1, cl[i][0].pos, false); 75 | q.emplace(i-1, cl[i][0].neg, true); 76 | while (!q.empty()) { 77 | auto [i, j, neg] = q.front(); 78 | q.pop(); 79 | if (i == -1_zu) { 80 | if (j != -1_zu) res[j] = (neg? -coef[j]: +coef[j]); 81 | continue; 82 | } 83 | q.emplace(i-1, cl[i][j].pos, neg); 84 | q.emplace(i-1, cl[i][j].neg, !neg); 85 | } 86 | return res; 87 | } 88 | return {}; 89 | } 90 | 91 | #endif /* !defined(H_tree_attack) */ 92 | -------------------------------------------------------------------------------- /algorithm/dp_on_tree.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_dp_on_tree 2 | #define H_dp_on_tree 3 | 4 | /** 5 | * @brief 木 DP 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "utility/make/fix_point.cpp" 14 | 15 | template 16 | std::vector dp_on_tree(AdjacencyList const& g, Fn f, Monoid e = Monoid{}) { 17 | size_t n = g.size(); 18 | std::vector par(n, n); 19 | std::vector> dpl(n), dpr(n); 20 | std::vector dp(n); 21 | for (size_t i = 0; i < n; ++i) { 22 | dpl[i].resize(g[i].size()+1, e); 23 | dpr[i].resize(g[i].size()+1, e); 24 | } 25 | 26 | make_fix_point([&](auto& dfs, size_t v, size_t p) -> Monoid { 27 | Monoid res = e; 28 | typename AdjacencyList::weight_type w{}; 29 | for (size_t i = 0; i < g[v].size(); ++i) { 30 | auto const& e = g[v][i]; 31 | size_t u = e.target(); 32 | if (u == p) { 33 | par[v] = i; 34 | w = e.weight(); 35 | continue; 36 | } 37 | Monoid tmp = dfs(u, v); 38 | res += tmp; 39 | dpl[v][i+1] = dpr[v][i] = tmp; 40 | } 41 | return f(res, w); 42 | })(0, n); 43 | 44 | make_fix_point([&](auto& dfs, size_t v, size_t p, size_t pi) -> void { 45 | if (p != n) { 46 | Monoid tmp = f(dpl[p][pi] + dpr[p][pi+1], g[p][pi].weight()); 47 | dpl[v][par[v]+1] = dpr[v][par[v]] = tmp; 48 | } 49 | for (size_t i = 1; i < dpl[v].size(); ++i) 50 | dpl[v][i] = dpl[v][i-1] + std::move(dpl[v][i]); 51 | for (size_t i = dpr[v].size()-1; i--;) 52 | dpr[v][i] += dpr[v][i+1]; 53 | 54 | dp[v] = dpr[v][0]; 55 | for (size_t i = 0; i < g[v].size(); ++i){ 56 | size_t u = g[v][i].target(); 57 | if (u != p) dfs(u, v, i); 58 | } 59 | })(0, n, n); 60 | 61 | return dp; 62 | } 63 | 64 | #endif /* !defined(H_dp_on_tree) */ 65 | -------------------------------------------------------------------------------- /algorithm/mo.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_mo_algo 2 | #define H_mo_algo 3 | 4 | /** 5 | * @brief Mo's algorithm 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "integer/sqrt.cpp" 16 | 17 | template 18 | auto mo(Rf&& rf, std::vector> const& qs) 19 | -> std::vector()))> 20 | { 21 | if (qs.empty()) return {}; 22 | using value_type = decltype(rf(std::declval())); 23 | size_t n = rf.size(); 24 | size_t q = qs.size(); 25 | std::vector res(q); 26 | size_t b = n / isqrt(q); 27 | std::vector is(q); 28 | std::iota(is.begin(), is.end(), 0); 29 | std::sort(is.begin(), is.end(), [&](size_t i0, size_t i1) { 30 | size_t l0 = std::get<0>(qs[i0]) / b; 31 | size_t r0 = std::get<1>(qs[i0]); 32 | size_t l1 = std::get<0>(qs[i1]) / b; 33 | size_t r1 = std::get<1>(qs[i1]); 34 | if (l0 != l1) return l0 < l1; 35 | if (r0 != r1) return r0 < r1; 36 | return false; 37 | }); 38 | 39 | size_t l = 0; 40 | size_t r = 0; 41 | for (auto i: is) { 42 | auto const& [l0, r0, x] = qs[i]; 43 | while (r < r0) rf.push_back(), ++r; 44 | while (l > l0) rf.push_front(), --l; 45 | while (l < l0) rf.pop_front(), ++l; 46 | while (r > r0) rf.pop_back(), --r; 47 | res[i] = rf(x); 48 | l = l0; 49 | r = r0; 50 | } 51 | return res; 52 | } 53 | 54 | #endif /* !defined(H_mo_algo) */ 55 | -------------------------------------------------------------------------------- /algorithm/moebius_transform.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_moebius_transform 2 | #define H_moebius_transform 3 | 4 | /** 5 | * @brief 高速 Möbius 変換 6 | * @author えびちゃん 7 | */ 8 | 9 | #include "integer/bit.cpp" 10 | #include "utility/literals.cpp" 11 | 12 | template 13 | void moebius_transform(RandomIt first, RandomIt last) { 14 | size_t n = ctz(last-first); 15 | for (size_t j = 0; j < n; ++j) 16 | for (size_t i = 0; i < (1_zu << n); ++i) 17 | if (i >> j & 1) first[i] -= first[i ^ (1_zu << j)]; 18 | } 19 | 20 | #endif /* !defined(H_moebius_transform) */ 21 | -------------------------------------------------------------------------------- /algorithm/monotone_minima.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_monotone_minima 2 | #define H_monotone_minima 3 | 4 | /** 5 | * @brief monotone minima 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "utility/make/fix_point.cpp" 14 | 15 | template 16 | auto monotone_minima(Fn&& f, size_t h, size_t w) { 17 | using value_type = decltype(f(h, w)); 18 | std::vector res(h); 19 | 20 | make_fix_point([&](auto dfs, size_t hl, size_t hu, size_t wl, size_t wu) -> void { 21 | if (hl >= hu) return; 22 | size_t hm = (hl+hu) >> 1; 23 | value_type min = f(hm, wl); 24 | res[hm] = wl; 25 | for (size_t j = wl+1; j < wu; ++j) { 26 | value_type cur = f(hm, j); 27 | if (cur < min) { 28 | min = std::move(cur); 29 | res[hm] = j; 30 | } 31 | } 32 | if (hl == hm) return; 33 | dfs(hl, hm, wl, res[hm]+1); 34 | dfs(hm+1, hu, res[hm], wu); 35 | })(0, h, 0, w); 36 | return res; 37 | } 38 | 39 | #endif /* !defined(H_monotone_minima) */ 40 | -------------------------------------------------------------------------------- /algorithm/online_to_offline_optimization.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_online_to_offline_optimization 2 | #define H_online_to_offline_optimization 3 | 4 | /** 5 | * @brief オンライン・オフライン変換 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "algorithm/monotone_minima.cpp" 14 | #include "utility/limits.cpp" 15 | #include "utility/make/fix_point.cpp" 16 | 17 | template 18 | auto online_to_offline_optimization(Fn&& f, size_t n, decltype(f(n, n)) init = 0) { 19 | // FIXME: コスト関数 f を渡すんじゃなくて induce を渡す設計にしたいかも。 20 | // SMAWK で解きたいとか、別の性質が使えるとかありそう。 21 | // よさげなインタフェースが思いついたら変更する。 22 | 23 | using value_type = decltype(f(n, n)); 24 | std::vector dp(n, limits::max()); 25 | dp[0] = init; 26 | 27 | auto induce = [&](size_t l, size_t m, size_t r) -> void { 28 | auto g = [&](size_t i, size_t j) -> value_type { 29 | return dp[j+l] + f(j+l, i+m); 30 | }; 31 | auto argmin = monotone_minima(g, r-m, m-l); 32 | for (size_t i = m; i < r; ++i) { 33 | size_t j = argmin[i-m] + l; 34 | dp[i] = std::min(dp[i], g(i-m, j-l)); 35 | } 36 | }; 37 | 38 | make_fix_point([&](auto& solve, size_t l, size_t r) -> void { 39 | if (l+1 == r) return; 40 | if (l+2 == r) { 41 | if (r <= n) dp[l+1] = std::min(dp[l+1], dp[l] + f(l, l+1)); 42 | return; 43 | } 44 | size_t m = (l+r) >> 1; 45 | solve(l, m); 46 | induce(l, m, r); 47 | solve(m, r); 48 | })(0, n); 49 | return dp; 50 | } 51 | 52 | #endif /* !defined(H_online_to_offline_optimization) */ 53 | -------------------------------------------------------------------------------- /algorithm/parallel_binary_search.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_parallel_binary_search 2 | #define H_parallel_binary_search 3 | 4 | /** 5 | * @brief 並列二分探索 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | template 13 | std::vector parallel_binary_search( 14 | StatefulPredicate spred, RandomIt first, RandomIt last 15 | ) { 16 | // result[i] = j if spred(first[i]) returns true for state j-1 (and 17 | // before that) and returns false for state j (and after that). 18 | size_t size = spred.size(); 19 | std::vector lb(std::distance(first, last), 0); 20 | std::vector ub(lb.size(), size+1); 21 | bool determined = false; 22 | while (!determined) { 23 | determined = true; 24 | std::vector> ev(size+1); 25 | auto it = first; 26 | for (size_t i = 0; i < lb.size(); ++i) { 27 | auto cur = it++; 28 | if (!(ub[i] - lb[i] > 1)) continue; 29 | size_t mid = (lb[i] + ub[i]) >> 1; 30 | ev[mid].push_back(cur); 31 | determined = false; 32 | } 33 | auto sp = spred; 34 | for (size_t i = 0; i <= size; ++i) { 35 | for (auto const& e: ev[i]) { 36 | (sp(*e)? lb[e-first]: ub[e-first]) = i; 37 | } 38 | if (i < size) sp.next(); 39 | } 40 | } 41 | return ub; 42 | } 43 | 44 | #endif /* !defined(H_parallel_binary_search) */ 45 | -------------------------------------------------------------------------------- /algorithm/ternary_search.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_ternary_search 2 | #define H_ternary_search 3 | 4 | /** 5 | * @brief 黄金比分割の三分探索 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | template 13 | auto optimize_convex(Fn&& f, Tp xl, Tp xu, Tp err, bool maximize = true) { 14 | // Return {argmax f(x), max f(x)} if maximize, {argmin f(x), min f(x)} 15 | // otherwise. If f is not convex in [xl, xu], the behavior is undefined. 16 | Tp const phi = (1 + std::sqrt(static_cast(5))) / 2; 17 | int const iter = (std::log(xu-xl) - std::log(err)) / std::log(phi) + 1; 18 | Tp xml = (phi * xl + xu) / (1 + phi); 19 | Tp xmu = (xl + phi * xu) / (1 + phi); 20 | Tp yml = f(xml); 21 | Tp ymu = f(xmu); 22 | for (int i = 0; i < iter; ++i) { 23 | if (!maximize ^ (yml > ymu)) { 24 | xu = xmu; 25 | xmu = xml; 26 | ymu = yml; 27 | xml = (phi * xl + xu) / (1 + phi); 28 | yml = f(xml); 29 | } else { 30 | xl = xml; 31 | xml = xmu; 32 | yml = ymu; 33 | xmu = (xl + phi * xu) / (1 + phi); 34 | ymu = f(xmu); 35 | } 36 | } 37 | return std::make_pair(xml, yml); 38 | } 39 | 40 | #endif /* !defined(H_ternary_search) */ 41 | -------------------------------------------------------------------------------- /algorithm/tortoise_and_hare.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_tortoise_and_hare 2 | #define H_tortoise_and_hare 3 | 4 | /** 5 | * @brief 周期検出 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | template 13 | std::pair detect_cycle(Generator g) { 14 | Generator tortoise = g; 15 | Generator hare = g; 16 | do { 17 | tortoise.pop(); 18 | hare.pop(), hare.pop(); 19 | } while (tortoise.peek() != hare.peek()); 20 | 21 | tortoise = g; 22 | intmax_t mu = 0; 23 | while (tortoise.peek() != hare.peek()) { 24 | ++mu; 25 | tortoise.pop(); 26 | hare.pop(); 27 | } 28 | 29 | intmax_t lambda = 0; 30 | hare = tortoise; 31 | do { 32 | ++lambda; 33 | hare.pop(); 34 | } while (tortoise.peek() != hare.peek()); 35 | 36 | return {mu, lambda}; 37 | } 38 | 39 | #endif /* !defined(H_tortoise_and_hare) */ 40 | -------------------------------------------------------------------------------- /debug/sa_is.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // @ignore 5 | 6 | #include "String/sa_is.cpp" 7 | 8 | #include 9 | 10 | template 11 | void say(InputIt first, InputIt last) { 12 | while (first != last) { 13 | std::cout << *first++; 14 | std::cout << ((first != last)? ' ': '\n'); 15 | } 16 | } 17 | 18 | int main() { 19 | { 20 | std::string s = "GTCCCGATGTCATGTCAGGA"; 21 | suffix_array sa(s.begin(), s.end()); 22 | } 23 | { 24 | std::string s = "abracadabra"; 25 | suffix_array sa(s.begin(), s.end()); 26 | say(sa.begin(), sa.end()); 27 | auto lcpa = sa.lcp_array(); 28 | say(lcpa.begin(), lcpa.end()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /integer/fused_operations.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_fused_operations 2 | #define H_fused_operations 3 | 4 | /** 5 | * @brief 乗算との複合演算 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "integer/overflow.cpp" 14 | #include "integer/mul_upper.cpp" 15 | 16 | template 17 | Tp fused_mul_add(Tp x, Tp y, Tp z) { 18 | // Return x * y + z without overflow 19 | using unsigned_type = typename std::make_unsigned::type; 20 | unsigned_type ux = x, uy = y; 21 | unsigned_type lo = ux * uy; 22 | return lo + z; 23 | } 24 | 25 | template 26 | Tp fused_mul_min(Tp x, Tp y, Tp z) { 27 | // min(x * y, z) without overflow 28 | Tp w; 29 | if (mul_overflow(x, y, w)) return z; // undefined if x*y < minimum 30 | return std::min(w, z); 31 | } 32 | 33 | template 34 | Tp fused_add_mod(Tp x, Tp y, Tp z) { 35 | // (x + y) % z, same sign as z, without overflow 36 | if (std::is_signed_v) { 37 | if ((x %= z) != 0 && ((x < 0) != (z < 0))) x += z; 38 | if ((y %= z) != 0 && ((y < 0) != (z < 0))) y += z; 39 | x -= z - y; 40 | if ((x %= z) != 0 && ((x < 0) != (z < 0))) x += z; 41 | } else { 42 | x %= z; 43 | y %= z; 44 | x += ((x < z-y)? y: y-z); 45 | } 46 | return x; 47 | } 48 | 49 | template 50 | Tp fused_mul_mod(Tp x, Tp y, Tp z) { 51 | // (x * y) % z, same sign as z, without overflow 52 | using value_type = Tp; 53 | using unsigned_type = typename std::make_unsigned::type; 54 | unsigned_type ux = x, uy = y; 55 | value_type hi = mul_upper(x, y) % z; 56 | int const bits = CHAR_BIT * sizeof(Tp); 57 | for (int i = 0; i < bits; ++i) { 58 | hi = fused_add_mod(hi, hi, z); 59 | } 60 | unsigned_type uxy = ux * uy; 61 | value_type loh = uxy >> (bits/2); 62 | value_type lol = uxy & (~unsigned_type(0) >> (bits/2)); 63 | for (int i = 0; i < bits/2; ++i) { 64 | loh = fused_add_mod(loh, loh, z); 65 | } 66 | lol = fused_add_mod(loh, lol, z); 67 | return fused_add_mod(hi, lol, z); 68 | } 69 | 70 | #endif /* !defined(H_fused_operations) */ 71 | -------------------------------------------------------------------------------- /integer/gcd.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_gcd 2 | #define H_gcd 3 | 4 | /** 5 | * @brief 最大公約数 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | 11 | template 12 | Tp gcd(Tp m, Tp n) { 13 | while (n) std::swap(m %= n, n); 14 | return m; 15 | } 16 | 17 | #endif /* !defined(H_gcd) */ 18 | -------------------------------------------------------------------------------- /integer/mod_misc.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_mod_misc 2 | #define H_mod_misc 3 | 4 | // @ignore 5 | 6 | template 7 | Tp ceil_mod(Tp x, Tp y, Tp z = 0) { 8 | // returns a s.t. a-y < x <= a, a = z (mod y) 9 | } 10 | 11 | template 12 | Tp floor_mod(Tp x, Tp y, Tp z = 0) { 13 | // returns a s.t. a <= x < a+y, a = z (mod y) 14 | } 15 | 16 | #endif /* !defined(H_mod_misc) */ 17 | -------------------------------------------------------------------------------- /integer/mul_upper.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_mul_upper 2 | #define H_mul_upper 3 | 4 | /** 5 | * @brief 整数の乗算の上位ワード 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "utility/literals.cpp" 15 | 16 | template 17 | auto mul_upper(Tp u, Tp v) 18 | -> typename std::enable_if, Tp>::type 19 | { 20 | using value_type = Tp; 21 | using unsigned_type = typename std::make_unsigned::type; 22 | unsigned_type hi; 23 | int const bits = CHAR_BIT * sizeof(value_type); 24 | if (false && (sizeof u) < sizeof(uintmax_t)) { 25 | uintmax_t mul = uintmax_t(u) * v; 26 | hi = mul >> bits; 27 | // XXX unsigned only 28 | } else { 29 | int const half_bits = bits / 2; 30 | unsigned_type const half_mask = (unsigned_type(1) << half_bits) - 1; 31 | unsigned_type u0 = u & half_mask, v0 = v & half_mask; 32 | unsigned_type u1 = unsigned_type(u) >> half_bits, v1 = unsigned_type(v) >> half_bits; 33 | unsigned_type w0 = u0 * v0; 34 | unsigned_type t = u1 * v0 + (w0 >> half_bits); 35 | unsigned_type w1 = t & half_mask; 36 | unsigned_type w2 = t >> half_bits; 37 | w1 += u0 * v1; 38 | hi = u1 * v1 + w2 + (w1 >> half_bits); 39 | if (u < 0) hi -= v; 40 | if (v < 0) hi -= u; 41 | } 42 | return hi; 43 | } 44 | 45 | #endif /* !defined(H_mul_upper) */ 46 | -------------------------------------------------------------------------------- /integer/overflow.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_overflow 2 | #define H_overflow 3 | 4 | /** 5 | * @brief オーバーフロー判定つき演算 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include "integer/mul_upper.cpp" 13 | 14 | template 15 | auto add_overflow(Tp x, Tp y, Tp& z) 16 | -> typename std::enable_if, bool>::type 17 | { 18 | using unsigned_type = typename std::make_unsigned::type; 19 | unsigned_type ux = x, uy = y; 20 | unsigned_type sign_bit = unsigned_type{1} << ((CHAR_BIT * sizeof(Tp)) - 1); 21 | if ((ux & sign_bit) ^ (uy & sign_bit)) return (z = x + y), false; 22 | if (((ux + uy) & sign_bit) != (ux & sign_bit)) return true; 23 | z = x + y; 24 | return false; 25 | } 26 | 27 | template 28 | auto sub_overflow(Tp x, Tp y, Tp& z) 29 | -> typename std::enable_if, bool>::type 30 | { 31 | using unsigned_type = typename std::make_unsigned::type; 32 | if (y == 0) return (z = x), false; 33 | unsigned_type uy = y; 34 | if (~(uy | (uy-1)) == 0 && y < 0) return true; 35 | return add_overflow(x, -y, z); 36 | } 37 | 38 | template 39 | auto mul_overflow(Tp x, Tp y, Tp& z) 40 | -> typename std::enable_if, bool>::type 41 | { 42 | using unsigned_type = typename std::make_unsigned::type; 43 | unsigned_type ux = x, uy = y; 44 | unsigned_type sign_bit = ~(~unsigned_type(0) >> 1); 45 | if (((ux * uy) & sign_bit) != ((ux & sign_bit) ^ (uy & sign_bit))) return true; 46 | z = x * y; 47 | return false; 48 | } 49 | 50 | #endif /* !defined(H_overflow) */ 51 | -------------------------------------------------------------------------------- /integer/sqrt.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_int_sqrt 2 | #define H_int_sqrt 3 | 4 | /** 5 | * @brief 整数の平方根 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | 11 | template 12 | Tp isqrt(Tp n) { 13 | if (n <= 1) return n; 14 | Tp lb = 1; 15 | Tp ub = static_cast(1) << (CHAR_BIT * (sizeof(Tp) / 2)); 16 | while (ub-lb > 1) { 17 | Tp mid = (lb+ub) >> 1; 18 | ((mid*mid <= n)? lb: ub) = mid; 19 | } 20 | return lb; 21 | } 22 | 23 | #endif /* !defined(H_int_sqrt) */ 24 | -------------------------------------------------------------------------------- /misc/interface/action.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_action 2 | #define H_action 3 | 4 | /** 5 | * @brief 作用のヘルパークラス 6 | * @author えびちゃん 7 | */ 8 | 9 | #include "utility/monoid/length.cpp" 10 | 11 | template 12 | struct action { 13 | using operand_type = length_monoid; 14 | using action_type = Tp; 15 | 16 | static void act(operand_type& op, action_type const& a) { 17 | // 18 | } 19 | }; 20 | 21 | #endif /* !defined(H_action) */ 22 | -------------------------------------------------------------------------------- /misc/interface/monoid.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_monoid 2 | #define H_monoid 3 | 4 | /** 5 | * @brief モノイドクラス 6 | * @author えびちゃん 7 | */ 8 | 9 | template 10 | class monoid { 11 | public: 12 | using value_type = Tp; 13 | 14 | private: 15 | value_type M_x = /* identity */; 16 | 17 | public: 18 | monoid() = default; // identity 19 | 20 | monoid(value_type const& x): M_x(x) {} 21 | 22 | monoid& operator +=(monoid const& that) { 23 | // 24 | return *this; 25 | } 26 | friend bool operator ==(monoid const& lhs, monoid const& rhs) { 27 | return lhs.M_x == rhs.M_x; 28 | } 29 | 30 | friend monoid operator +(monoid lhs, monoid const& rhs) { return lhs += rhs; } 31 | friend bool operator !=(monoid const& lhs, monoid const& rhs) { 32 | return !(lhs == rhs); 33 | } 34 | 35 | value_type const& get() const { return M_x; } 36 | }; 37 | 38 | #endif /* !defined(H_monoid) */ 39 | -------------------------------------------------------------------------------- /preface/license.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @title LICENSE 3 | * @category !PREFACE! 4 | * @docs license.md 5 | * @see https://kimiyuki.net/blog/2020/02/14/licenses-for-kyopro-libraries/ 6 | */ 7 | -------------------------------------------------------------------------------- /preface/license.md: -------------------------------------------------------------------------------- 1 | [![GitHub](https://img.shields.io/github/license/rsk0315/library)](https://github.com/rsk0315/library/blob/master/LICENSE) 2 | 3 | このライブラリは、MIT License のもとで公開されています。 4 | ただし、競技プログラミングのために、このライブラリの一部をジャッジサーバなどに送信するとき、著作権表示および許諾表示を省略することができます。 5 | 各ライブラリには、`@author えびちゃん` のコメントがついているはずですから、その部分を含めて貼りつけてもらえば十分です。 6 | -------------------------------------------------------------------------------- /preface/todo.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @title TODO 3 | * @category !PREFACE! 4 | * @docs todo.md 5 | * @see https://online-judge-tools.github.io/verification-helper/document.ja.html 6 | * @see https://online-judge-tools.github.io/verification-helper/installer.ja.html 7 | * @see https://github.com/online-judge-tools/verification-helper/blob/master/onlinejudge_verify/docs.py 8 | */ 9 | -------------------------------------------------------------------------------- /preface/todo.md: -------------------------------------------------------------------------------- 1 | # 置きたいもの 2 | 3 | ## データ構造 4 | - CHT 5 | - 任意順 (map) 6 | - Li-Chao tree 7 | - deque 8 | - foldable wavelet matrix 9 | - splay tree 10 | - bitset 11 | - $O(z/w)$ で `rank(n)` `select(n)` などができるやつ 12 | - 部分永続 Union-find 13 | - 動的 wavelet matrix 14 | - Segment tree beats! 15 | - 完全永続配列 (いる?) 16 | - radix heap (いる?) 17 | - binary-indexed tree (いる?) 18 | - Fibonacci heap (いる?) 19 | 20 | 適宜 deduction guide も置いておくと後々うれしくなりそう 21 | 22 | ## 文字列 23 | - suffix array 24 | - 機能を増やす 25 | - Manacher 26 | - Aho-Corasick automaton 27 | - Crit-bit tree (いる?) 28 | 29 | ## グラフ 30 | - Dijkstra 31 | - Bellman-Ford 32 | - 0/1 BFS 33 | - トポロジカルソート 34 | - verify 35 | - 最小費用流 36 | - 全方位木 DP 37 | - 頂点属性? 38 | - https://codeforces.com/contest/1324/problem/F 39 | - Euler tour (いる?) 40 | 41 | ## 数学 42 | - 行列 43 | - 多項式諸々 44 | - `exp` とか `sqrt` とか 45 | - あと高速化 46 | - BSGS 47 | - $\mathbb{Z}_p$ での位数 48 | - 合成数での `dlog` 49 | 50 | ## 整数 51 | - 計算途中でオーバーフローしない複合演算 52 | - fused multiply-add など 53 | - オーバーフロー検出 54 | - `__builtin_mul_overflow` 系のやつ 55 | 56 | ## アルゴリズム 57 | - SMAWK 58 | - Mo 59 | - 5/3 のやつ 60 | - `next_combination` (いる?) 61 | - Karatsuba 法 (いる?) 62 | 63 | ## 幾何 64 | - ほんとに? 65 | 66 | ## その他 67 | - なにか 68 | -------------------------------------------------------------------------------- /script/check.sh: -------------------------------------------------------------------------------- 1 | uname -a 2 | cat /proc/cpuinfo 3 | -------------------------------------------------------------------------------- /test/.gitignore: -------------------------------------------------------------------------------- 1 | *.test 2 | *.dSYM -------------------------------------------------------------------------------- /test/.verify-helper/.gitignore: -------------------------------------------------------------------------------- 1 | cache/ 2 | include/ 3 | markdown/ 4 | timestamps.local.json 5 | -------------------------------------------------------------------------------- /test/aoj_0355.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0355" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "ModularArithmetic/modint.cpp" 11 | #include "utility/monoid/rolling_hash.cpp" 12 | #include "utility/monoid/set.cpp" 13 | #include "DataStructure/segment_tree.cpp" 14 | 15 | constexpr intmax_t mod = 998244353; 16 | using mi = modint; 17 | 18 | template 19 | struct action_set_to_rolling_hash { 20 | using operand_type = rolling_hash_monoid; 21 | using action_type = set_monoid>; 22 | 23 | static void act(operand_type& op, action_type const& a) { 24 | if (a.empty()) return; 25 | operand_type tmp(a.get().first, a.get().second); 26 | if (op.coefficient() == 1) { 27 | op = tmp; 28 | return; 29 | } 30 | while (tmp.coefficient() != op.coefficient()) tmp += tmp; 31 | op = tmp; 32 | } 33 | }; 34 | 35 | int main() { 36 | size_t n; 37 | char buf[262144]; 38 | int q; 39 | scanf("%zu %s %d", &n, buf, &q); 40 | std::string s = buf; 41 | 42 | intmax_t b1 = 2352983, b2 = 4986917; 43 | segment_tree> s1(n), s2(n); 44 | auto f = [](auto x, auto y) { 45 | return set_monoid>({x, y}); 46 | }; 47 | for (size_t i = 0; i < n; ++i) { 48 | s1.act(i, i+1, f(s[i], b1)); 49 | s2.act(i, i+1, f(s[i], b2)); 50 | } 51 | 52 | for (int i = 0; i < q; ++i) { 53 | scanf("%s", buf); 54 | std::string type = buf; 55 | if (type == "set") { 56 | size_t x, y; 57 | char z; 58 | scanf("%zu %zu %c", &x, &y, &z); 59 | --x, --y; 60 | s1.act(x, y+1, f(z, b1)); 61 | s2.act(x, y+1, f(z, b2)); 62 | } else if (type == "comp") { 63 | size_t a, b, c, d; 64 | scanf("%zu %zu %zu %zu", &a, &b, &c, &d); 65 | --a, --b, --c, --d; 66 | size_t sl = b-a+1, tl = d-c+1; 67 | auto eq = [&](size_t l) { 68 | return s1.fold(a, a+l) == s1.fold(c, c+l) && s2.fold(a, a+l) == s2.fold(c, c+l); 69 | }; 70 | if (eq(std::min(sl, tl))) { 71 | printf("%c\n", ((sl < tl)? 's': (sl > tl)? 't': 'e')); 72 | continue; 73 | } 74 | size_t lb = 0, ub = std::min(sl, tl); 75 | while (ub-lb > 1) { 76 | size_t mid = (lb+ub) >> 1; 77 | (eq(mid)? lb: ub) = mid; 78 | } 79 | int sc = s1[a+lb].get().get(), tc = s1[c+lb].get().get(); 80 | printf("%c\n", ((sc < tc)? 's': 't')); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /test/aoj_0425.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0425" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "algorithm/mo.cpp" 12 | 13 | class range_function { 14 | size_t M_n; 15 | size_t M_l = 0; 16 | size_t M_r = 0; 17 | std::vector> M_op; 18 | std::vector M_p, M_q; 19 | 20 | void M_swap(size_t a, size_t b) { 21 | std::swap(M_q[M_p[a]], M_q[M_p[b]]); 22 | std::swap(M_p[a], M_p[b]); 23 | } 24 | 25 | public: 26 | range_function() = default; 27 | range_function(size_t n, std::vector> const& ab): 28 | M_n(n), M_op(ab), M_p(n), M_q(n) 29 | { 30 | std::iota(M_p.begin(), M_p.end(), 0); 31 | std::iota(M_q.begin(), M_q.end(), 0); 32 | } 33 | 34 | void push_back() { auto [a, b] = M_op[M_r++]; M_swap(a, b); } 35 | void push_front() { auto [a, b] = M_op[--M_l]; M_swap(M_q[a], M_q[b]); } 36 | void pop_back() { auto [a, b] = M_op[--M_r]; M_swap(a, b); } 37 | void pop_front() { auto [a, b] = M_op[M_l++]; M_swap(M_q[a], M_q[b]); } 38 | size_t size() const { return M_n; } 39 | 40 | size_t operator ()(std::pair const& q) { 41 | auto [x, type] = q; 42 | return ((type == 1)? M_p[x]: M_q[x]); 43 | } 44 | }; 45 | 46 | int main() { 47 | size_t n, k, q; 48 | scanf("%zu %zu %zu", &n, &k, &q); 49 | 50 | std::vector> ab(k); 51 | for (auto& [a, b]: ab) scanf("%zu %zu", &a, &b), --a, --b; 52 | 53 | using query_type = std::tuple>; 54 | std::vector qs(q); 55 | for (auto& [s, t, p]: qs) { 56 | scanf("%d %zu %zu %zu", &p.second, &s, &t, &p.first); 57 | --s; 58 | --p.first; 59 | } 60 | 61 | for (auto res: mo(range_function(n, ab), qs)) 62 | printf("%zu\n", res+1); 63 | } 64 | -------------------------------------------------------------------------------- /test/aoj_0613.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0613" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "utility/literals.cpp" 11 | #include "DataStructure/foldable_queue.cpp" 12 | #include "utility/monoid/max.cpp" 13 | 14 | int main() { 15 | size_t n; 16 | intmax_t d; 17 | scanf("%zu %jd", &n, &d); 18 | 19 | std::vector> xy(n); 20 | for (auto& [xi, yi]: xy) 21 | scanf("%jd %jd", &xi, &yi); 22 | 23 | if (n < 3) xy.resize(3, {0, 0}); 24 | n = xy.size(); 25 | 26 | size_t n1 = (n+1)/2; 27 | 28 | auto neko = [&](auto first, auto last) { 29 | std::vector> z(first, last); 30 | std::vector> res{{0, 0}}; 31 | for (size_t i = 0; i < (1_zu << z.size()); ++i) { 32 | size_t j = i; 33 | do { 34 | intmax_t xi = 0, yi = 0; 35 | for (size_t k = 0; k < z.size(); ++k) { 36 | if (~i >> k & 1) continue; 37 | if (j >> k & 1) { 38 | xi += z[k].first; 39 | yi += z[k].second; 40 | } else { 41 | xi -= z[k].first; 42 | yi -= z[k].second; 43 | } 44 | } 45 | res.emplace_back(xi, yi); 46 | j = (j-1) & i; 47 | } while (j != i); 48 | } 49 | return res; 50 | }; 51 | 52 | auto xy1 = neko(xy.begin(), xy.begin()+n1); 53 | auto xy2 = neko(xy.begin()+n1, xy.end()); 54 | 55 | std::sort(xy1.rbegin(), xy1.rend()); 56 | std::sort(xy2.begin(), xy2.end()); 57 | intmax_t const inf = 1e18; 58 | intmax_t res = -inf; 59 | 60 | foldable_queue> y2; 61 | 62 | size_t il = 0, ir = 0; 63 | for (auto const& p: xy1) { 64 | auto [x1, y1] = p; 65 | while (ir < xy2.size() && xy2[ir].first+x1 <= d) { 66 | y2.push(xy2[ir++].second); 67 | } 68 | while (il < ir && xy2[il].first+x1 < -d) { 69 | ++il; 70 | y2.pop(); 71 | } 72 | 73 | intmax_t cur = y2.fold().get(); 74 | if (cur < -inf) continue; 75 | cur += y1; 76 | res = std::max(res, cur); 77 | } 78 | 79 | if (res < -inf) return puts("-1"), 0; 80 | printf("%jd\n", res); 81 | } 82 | -------------------------------------------------------------------------------- /test/aoj_1180.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1180&lang=jp" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "algorithm/tortoise_and_hare.cpp" 9 | 10 | class generator { 11 | int M_a, M_l; 12 | 13 | public: 14 | generator() = default; 15 | generator(int a, int l): M_a(a), M_l(l) {} 16 | 17 | int peek() const { return M_a; } 18 | void pop() { 19 | char buf[8]; 20 | snprintf(buf, sizeof buf, "%0*d", M_l, M_a); 21 | std::string s = buf; 22 | std::sort(s.begin(), s.end()); 23 | std::string t(s.rbegin(), s.rend()); 24 | M_a = std::stoi(t) - std::stoi(s); 25 | } 26 | }; 27 | 28 | int testcase_ends() { 29 | int a0, l; 30 | scanf("%d %d", &a0, &l); 31 | if (a0 == 0 && l == 0) return 1; 32 | 33 | generator g(a0, l); 34 | auto [mu, lambda] = detect_cycle(g); 35 | for (int i = 0; i < mu+lambda; ++i) g.pop(); 36 | 37 | printf("%jd %d %jd\n", mu, g.peek(), lambda); 38 | return 0; 39 | } 40 | 41 | int main() { 42 | while (!testcase_ends()) {} 43 | } 44 | -------------------------------------------------------------------------------- /test/aoj_1322.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1322" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "ModularArithmetic/modint.cpp" 11 | #include "ModularArithmetic/operations.cpp" 12 | 13 | using mi = modint<2011>; 14 | 15 | std::vector ops{"+-", "*"}; 16 | 17 | mi parse(std::vector const& s, size_t& l, size_t u, size_t b, size_t preced = 0) { 18 | size_t base; 19 | bool found = false; 20 | while (!found) { 21 | for (base = u; base < b; ++base) { 22 | if (s[base][l] != '.') { 23 | found = true; 24 | break; 25 | } 26 | } 27 | if (!found) ++l; 28 | } 29 | 30 | if (preced == ops.size()) { 31 | mi res; 32 | if (s[base][l] == '(') { 33 | ++l; 34 | assert(s[base][l] == '.'); 35 | res = parse(s, ++l, u, b, 0); 36 | assert(s[base][l] == '.'); 37 | ++l; 38 | assert(s[base][l] == ')'); 39 | ++l; 40 | } else if (isdigit(s[base][l])) { 41 | res = s[base][l++] - '0'; 42 | } else if (s[base][l] == '-' && s[base][l+1] == '.') { 43 | res = -parse(s, l += 2, u, b, preced); 44 | } else if (s[base][l] == '-' && s[base][l+1] == '-') { 45 | size_t ln = l; 46 | size_t ld = l; 47 | res = parse(s, ln, u, base, 0) / parse(s, ld, base+1, b, 0); 48 | while (s[base][l] == '-') ++l; 49 | } 50 | if (base-1 < s.size() && l < s[base-1].length() && isdigit(s[base-1][l])) 51 | res = pow(res, s[base-1][l++]-'0'); 52 | 53 | return res; 54 | } 55 | 56 | mi res = parse(s, l, u, b, preced+1); 57 | while (l < s[base].length()) { 58 | assert(s[base][l] == '.'); 59 | char op = s[base][l+1]; 60 | if (!std::count(ops[preced].begin(), ops[preced].end(), op)) break; 61 | l += 2; 62 | assert(s[base][l] == '.'); 63 | mi cur = parse(s, ++l, u, b, preced+1); 64 | if (op == '+') res += cur; 65 | if (op == '-') res -= cur; 66 | if (op == '*') res *= cur; 67 | } 68 | return res; 69 | } 70 | 71 | int testcase_ends() { 72 | size_t n; 73 | scanf("%zu", &n); 74 | if (n == 0) return 1; 75 | 76 | std::vector s(n); 77 | for (auto& si: s) { 78 | char buf[96]; 79 | scanf("%s", buf); 80 | si = buf; 81 | } 82 | 83 | size_t l = 0; 84 | printf("%d\n", parse(s, l, 0, n).get()); 85 | return 0; 86 | } 87 | 88 | int main() { 89 | while (!testcase_ends()) {} 90 | } 91 | -------------------------------------------------------------------------------- /test/aoj_1595.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1595" 2 | 3 | #include 4 | 5 | #include "algorithm/dp_on_tree.cpp" 6 | #include "Graph/adjacency_list.cpp" 7 | #include "utility/monoid/max.cpp" 8 | 9 | int main() { 10 | size_t n; 11 | scanf("%zu", &n); 12 | 13 | adjacency_list, undirected_tag> g(n); 14 | for (size_t i = 1; i < n; ++i) { 15 | size_t a, b; 16 | scanf("%zu %zu", &a, &b); 17 | --a, --b; 18 | g.emplace(a, b, 1); 19 | } 20 | 21 | auto dp = dp_on_tree>(g, [](max_monoid x, int) -> max_monoid { 22 | return x.get() + 1; 23 | }); 24 | 25 | for (size_t i = 0; i < n; ++i) { 26 | int res = 2*(n-1) - dp[i].get(); 27 | printf("%d\n", res); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /test/aoj_2178.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2178" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "utility/literals.cpp" 10 | #include "Graph/two_sat.cpp" 11 | 12 | constexpr std::array di{{-1_zu, 0, 1, 0}}; 13 | constexpr std::array dj{{0, -1_zu, 0, 1}}; 14 | 15 | int testcase_ends() { 16 | size_t n; 17 | scanf("%zu", &n); 18 | if (n == 0) return 1; 19 | 20 | using zahyo = std::pair; 21 | std::map enc; 22 | two_sat ts(n+n); 23 | 24 | for (size_t i = 0; i < n; ++i) { 25 | size_t x, y; 26 | char d; 27 | scanf("%zu %zu %c", &x, &y, &d); 28 | size_t i0 = i << 1 | 0; 29 | size_t i1 = i << 1 | 1; 30 | enc[zahyo(x, y)] = i0; 31 | size_t dx = (d == 'x')? 1: 0; 32 | size_t dy = (d == 'y')? 1: 0; 33 | enc[zahyo(x+dx, y+dy)] = i1; 34 | 35 | ts.push(i0, true, i1, true); 36 | ts.push(i0, false, i1, false); 37 | } 38 | 39 | for (auto const& p: enc) { 40 | auto [i, j] = p.first; 41 | size_t id = p.second; 42 | for (size_t k = 0; k < 4; ++k) { 43 | size_t ni = i + di[k]; 44 | size_t nj = j + dj[k]; 45 | auto it = enc.find(zahyo(ni, nj)); 46 | if (it == enc.end()) continue; 47 | size_t nid = it->second; 48 | if ((id >> 1) == (nid >> 1)) continue; 49 | 50 | ts.push(id, false, nid, true); 51 | ts.push(id, true, nid, false); 52 | } 53 | } 54 | 55 | puts(ts.satisfiable()? "Yes": "No"); 56 | return 0; 57 | } 58 | 59 | int main() { 60 | while (!testcase_ends()) {} 61 | } 62 | -------------------------------------------------------------------------------- /test/aoj_2313.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2313" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "Graph/capacitated_adjacency_list.cpp" 12 | #include "Graph/dinitz.cpp" 13 | 14 | int main() { 15 | size_t n, e, q; 16 | scanf("%zu %zu %zu", &n, &e, &q); 17 | 18 | adjacency_list, undirected_tag> g(n); 19 | std::set> es0; 20 | for (size_t i = 0; i < e; ++i) { 21 | size_t f, t; 22 | scanf("%zu %zu", &f, &t); 23 | --f, --t; 24 | g.emplace(f, t, 1); 25 | es0.insert(std::minmax(f, t)); 26 | } 27 | 28 | std::vector> qs; 29 | std::set> es; 30 | 31 | for (size_t i = 0; i < q; ++i) { 32 | int m; 33 | size_t a, b; 34 | scanf("%d %zu %zu", &m, &a, &b); 35 | --a, --b; 36 | if (a > b) std::swap(a, b); 37 | qs.emplace_back(m, a, b); 38 | if (!es0.count(std::make_pair(a, b))) es.emplace(a, b); 39 | } 40 | 41 | for (auto const& e: es) { 42 | auto [s, d] = e; 43 | g.emplace(s, d, 0); 44 | } 45 | 46 | intmax_t first = max_flow(g, 0, n-1, dinitz); 47 | 48 | for (size_t i = 0; i < q; ++i) { 49 | auto [m, a, b] = qs[i]; 50 | intmax_t df = 0; 51 | 52 | if (m == 1) { 53 | // connect 54 | for (auto& e: g[a]) { 55 | if (e.target() != b) continue; 56 | e.capacity() = 1; 57 | g[b][e.reversed()].capacity() = 1; 58 | df = max_flow(g, 0, n-1, dinitz); 59 | break; 60 | } 61 | first += df; 62 | printf("%jd\n", first); 63 | continue; 64 | } 65 | if (m == 2) { 66 | // disconnect 67 | for (auto& e: g[a]) { 68 | if (e.target() != b) continue; 69 | if (e.capacity() > 0 && g[b][e.reversed()].capacity() > 0) { 70 | e.capacity() = 0; 71 | g[b][e.reversed()].capacity() = 0; 72 | break; 73 | } 74 | if (e.capacity() == 0 || g[b][e.reversed()].capacity() == 0) { 75 | size_t u = e.source(); 76 | size_t v = e.target(); 77 | if (e.capacity() != 0) std::swap(u, v); 78 | intmax_t tmp = max_flow(g, u, v, 1, dinitz); 79 | if (tmp == 0) { 80 | df = -max_flow(g, n-1, 0, 1, dinitz); 81 | max_flow(g, u, v, 1, dinitz); 82 | } 83 | e.capacity() = 0; 84 | g[b][e.reversed()].capacity() = 0; 85 | break; 86 | } 87 | } 88 | first += df; 89 | printf("%jd\n", first); 90 | continue; 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /test/aoj_2444.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2444" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "DataStructure/foldable_deque.cpp" 9 | #include "utility/monoid/rolling_hash.cpp" 10 | #include "ModularArithmetic/modint.cpp" 11 | 12 | constexpr intmax_t mod = 998244353; 13 | using mi = modint; 14 | 15 | int main() { 16 | size_t n, m; 17 | scanf("%zu %zu", &n, &m); 18 | 19 | char buf[393216]; 20 | scanf("%s", buf); 21 | std::string s = buf; 22 | 23 | foldable_deque> dq1, dq2; 24 | std::set> seen; 25 | size_t il = 0, ir = 0; 26 | mi b1 = 80067846, b2 = 365378971; 27 | 28 | char c = s[ir++]; 29 | dq1.emplace_back(c, b1); 30 | dq2.emplace_back(c, b2); 31 | for (size_t i = 0; i < m; ++i) { 32 | scanf("%s", buf); 33 | std::string q = buf; 34 | if (q == "L++") { 35 | ++il; 36 | dq1.pop_front(); 37 | dq2.pop_front(); 38 | } else if (q == "L--") { 39 | c = s[--il]; 40 | dq1.emplace_front(c, b1); 41 | dq2.emplace_front(c, b2); 42 | } else if (q == "R++") { 43 | c = s[ir++]; 44 | dq1.emplace_back(c, b1); 45 | dq2.emplace_back(c, b2); 46 | } else if (q == "R--") { 47 | --ir; 48 | dq1.pop_back(); 49 | dq2.pop_back(); 50 | } 51 | 52 | int x1 = dq1.fold().get().get(); 53 | int x2 = dq2.fold().get().get(); 54 | seen.emplace(x1, x2); 55 | } 56 | 57 | printf("%zu\n", seen.size()); 58 | } 59 | -------------------------------------------------------------------------------- /test/aoj_2446.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2446" 2 | #define ERROR 1e-7 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "algorithm/moebius_transform.cpp" 9 | #include "utility/literals.cpp" 10 | #include "integer/gcd.cpp" 11 | 12 | bool lcm_overflow(intmax_t m, intmax_t n, intmax_t& res) { 13 | return __builtin_mul_overflow(m / gcd(m, n), n, &res); 14 | } 15 | 16 | intmax_t g(std::vector const& a, size_t i, size_t m) { 17 | intmax_t d = 1; 18 | for (size_t j = 0; j < a.size(); ++j) 19 | if (i >> j & 1) 20 | if (lcm_overflow(d, a[j], d)) return 0; 21 | return m / d; 22 | } 23 | 24 | int main() { 25 | size_t n, m; 26 | scanf("%zu %zu", &n, &m); 27 | 28 | std::vector a(n), p(n); 29 | for (auto& ai: a) scanf("%jd", &ai); 30 | for (auto& pi: p) scanf("%jd", &pi); 31 | 32 | std::vector dp(1_zu << n, 0); 33 | for (size_t i = 1; i < dp.size(); ++i) 34 | dp[i] = g(a, i, m); 35 | 36 | moebius_transform(dp.begin(), dp.end()); 37 | 38 | double res = 0; 39 | for (size_t i = 0; i < (1_zu << n); ++i) { 40 | double pi = 1; 41 | for (size_t j = 0; j < n; ++j) 42 | pi *= ((i >> j & 1)? p[j]: 100-p[j]) / 100.0; 43 | 44 | intmax_t vi = dp[i]; 45 | if (!parity(i)) vi = -vi; 46 | res += pi * vi; 47 | } 48 | 49 | printf("%.12f\n", res); 50 | } 51 | -------------------------------------------------------------------------------- /test/aoj_2450.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2450" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "DataStructure/segment_tree.cpp" 10 | #include "Graph/hl_decomposition.cpp" 11 | #include "utility/monoid/set.cpp" 12 | #include "utility/monoid/max_subsum.cpp" 13 | 14 | template 15 | struct action_set_to_max_subsum { 16 | using operand_type = max_subsum_monoid; 17 | using action_type = set_monoid; 18 | 19 | static void act(operand_type& op, action_type const& a) { 20 | if (a.empty()) return; 21 | op = operand_type(a.get(), op.length()); 22 | } 23 | }; 24 | 25 | int main() { 26 | size_t n, q; 27 | scanf("%zu %zu", &n, &q); 28 | 29 | std::vector> a(n); 30 | for (auto& ai: a) { 31 | intmax_t tmp; 32 | scanf("%jd", &tmp); 33 | ai = tmp; 34 | } 35 | 36 | std::vector> es(n-1); 37 | for (auto& [u, v]: es) scanf("%zu %zu", &u, &v), --u, --v; 38 | 39 | hl_decomposed_tree>, 40 | value_on_vertex_tag> g(a, es); 41 | 42 | for (size_t i = 0; i < q; ++i) { 43 | int t; 44 | size_t u, v; 45 | intmax_t w; 46 | scanf("%d %zu %zu %jd", &t, &u, &v, &w); 47 | --u, --v; 48 | 49 | if (t == 1) { 50 | g.act(u, v, w); 51 | } else if (t == 2) { 52 | printf("%jd\n", g.fold(u, v).get()); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /test/aoj_2580.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2580" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "utility/literals.cpp" 11 | #include "utility/make/vector.cpp" 12 | #include "utility/make/fix_point.cpp" 13 | #include "algorithm/monotone_minima.cpp" 14 | 15 | int main() { 16 | size_t n, m, d; 17 | intmax_t x; 18 | scanf("%zu %zu %zu %jd", &n, &m, &d, &x); 19 | 20 | std::vector p(n); 21 | for (auto& pi: p) scanf("%jd", &pi); 22 | 23 | std::vector q(m); 24 | for (auto& qi: q) { 25 | intmax_t a, b; 26 | scanf("%jd %jd", &a, &b); 27 | qi = a - std::abs(b); 28 | } 29 | 30 | intmax_t const inf = 1e18; 31 | intmax_t res = inf; 32 | auto dp = make_vector({n}, inf); 33 | dp[0] = 0; 34 | for (size_t dd = 0; dd < d; ++dd) { 35 | std::vector w(n+1, 0); 36 | w[0] = m; 37 | for (auto const& qi: q) { 38 | size_t i = std::upper_bound(p.begin(), p.end(), qi) - p.begin(); 39 | --w[i]; 40 | } 41 | for (size_t i = 1; i <= n; ++i) w[i] += w[i-1]; 42 | 43 | auto tmp = make_vector({n}, inf); 44 | 45 | auto f = [&](size_t i, size_t j) -> intmax_t { 46 | if (!(j < i)) return inf; 47 | return dp[j] + w[j] * (p[i]-p[j]); 48 | }; 49 | auto prev = monotone_minima(f, n, n); 50 | 51 | for (size_t i = 0; i < n; ++i) 52 | tmp[i] = f(i, prev[i]); 53 | 54 | dp = std::move(tmp); 55 | res = std::min(res, dp[n-1]); 56 | for (auto& qi: q) qi += x; 57 | } 58 | 59 | printf("%jd\n", res); 60 | } 61 | -------------------------------------------------------------------------------- /test/aoj_2748.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2748" 2 | #define ERROR 1e-5 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "Graph/adjacency_list.cpp" 10 | #include "Graph/scc.cpp" 11 | 12 | int testcase_ends() { 13 | size_t n; 14 | scanf("%zu", &n); 15 | if (n == 0) return 1; 16 | 17 | adjacency_list, directed_tag> g(n); 18 | std::vector p(n); 19 | for (size_t v = 0; v < n; ++v) { 20 | scanf("%lf", &p[v]); 21 | size_t m; 22 | scanf("%zu", &m); 23 | for (size_t i = 0; i < m; ++i) { 24 | size_t u; 25 | scanf("%zu", &u); 26 | --u; 27 | g.emplace(v, u, 1); 28 | } 29 | } 30 | 31 | auto scc = strongly_connected_components(g); 32 | size_t m = *std::max_element(scc.begin(), scc.end()) + 1; 33 | std::vector ignore(m, false); 34 | std::vector q(m, 1.0); 35 | for (size_t v = 0; v < n; ++v) { 36 | q[scc[v]] *= p[v]; 37 | for (auto const& e: g[v]) { 38 | size_t u = e.target(); 39 | if (scc[u] == scc[v]) continue; 40 | ignore[scc[u]] = true; 41 | } 42 | } 43 | 44 | double res = 1.0; 45 | for (size_t i = 0; i < m; ++i) { 46 | if (ignore[i]) continue; 47 | res *= 1.0 - q[i]; 48 | } 49 | 50 | printf("%.12f\n", res); 51 | return 0; 52 | } 53 | 54 | int main() { 55 | while (!testcase_ends()) {} 56 | } 57 | -------------------------------------------------------------------------------- /test/aoj_2880.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2880" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "DataStructure/integral_intervals.cpp" 10 | 11 | int main() { 12 | size_t n, m, q; 13 | scanf("%zu %zu %zu", &n, &m, &q); 14 | 15 | using query_type = std::tuple; 16 | std::vector qs; 17 | qs.reserve(m+q); 18 | 19 | for (size_t i = 0; i < m; ++i) { 20 | int d, a, b; 21 | scanf("%d %d %d", &d, &a, &b); 22 | qs.emplace_back(d, 1, a, b, -1); 23 | } 24 | 25 | for (size_t i = 0; i < q; ++i) { 26 | int e, s, t; 27 | scanf("%d %d %d", &e, &s, &t); 28 | qs.emplace_back(e, 0, s, t, i); 29 | } 30 | 31 | std::sort(qs.begin(), qs.end()); 32 | 33 | std::vector res(q, false); 34 | integral_intervals ii; 35 | for (auto const& qi: qs) { 36 | int d, com, s, t; 37 | size_t i; 38 | std::tie(d, com, s, t, i) = qi; 39 | 40 | if (com == 0) { 41 | if (s >= t || t <= ii.range(s).second) res[i] = true; 42 | } else if (com == 1) { 43 | ii.insert(s, t); 44 | } 45 | } 46 | 47 | for (auto ri: res) puts(ri? "Yes": "No"); 48 | } 49 | -------------------------------------------------------------------------------- /test/aoj_2911.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2911" 2 | #define ERROR 1e-6 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "utility/literals.cpp" 10 | #include "Math/lp_solver.cpp" 11 | 12 | int main() { 13 | size_t n; 14 | scanf("%zu", &n); 15 | 16 | std::vector x(n), y(n); 17 | for (size_t i = 0; i < n; ++i) 18 | scanf("%Lf %Lf", &x[i], &y[i]); 19 | 20 | std::vector d(n, std::make_pair(1e12L, -1_zu)); 21 | for (size_t i = 0; i < n; ++i) { 22 | for (size_t j = 0; j < n; ++j) { 23 | if (i == j) continue; 24 | long double d0 = std::hypot(x[i]-x[j], y[i]-y[j]); 25 | if (d[i].first > d0) d[i] = {d0, j}; 26 | } 27 | } 28 | 29 | std::vector c(n, 1.0L), b; 30 | std::vector> a; 31 | for (size_t i = 0; i < n; ++i) { 32 | for (size_t j = 0; j < i; ++j) { 33 | long double d0 = std::hypot(x[i]-x[j], y[i]-y[j]); 34 | size_t k = a.size(); 35 | if (d[i].first + d[j].first < d0) continue; 36 | 37 | a.emplace_back(n, 0.0L); 38 | a[k][i] = a[k][j] = 1.0L; 39 | b.push_back(d0); 40 | } 41 | } 42 | 43 | long double r = *lp_solver::maximize(a, b, c); 44 | long double const pi = std::acos(-1.0L); 45 | printf("%.20Lf\n", 2*pi*r); 46 | } 47 | -------------------------------------------------------------------------------- /test/aoj_2970.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2970" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "ModularArithmetic/chinese_remaindering.cpp" 8 | 9 | int main() { 10 | size_t n; 11 | scanf("%zu", &n); 12 | 13 | std::vector p(n), q(n); 14 | for (auto& pi: p) scanf("%zu", &pi), --pi; 15 | for (auto& qi: q) scanf("%zu", &qi), --qi; 16 | 17 | simultaneous_congruences sc; 18 | for (size_t i = 0; i < n; ++i) { 19 | int a = 0; 20 | int m = 0; 21 | for (size_t x = p[i], j = 0; x != i; x = q[x]) { 22 | ++a; 23 | if (j++ > n) return puts("-1"), 0; 24 | } 25 | for (size_t x = p[i], j = 0; j <= n; ++j) { 26 | ++m; 27 | x = q[x]; 28 | if (x == p[i]) break; 29 | if (j == n) return puts("-1"), 0; 30 | } 31 | if (!sc.push(a, m)) return puts("-1"), 0; 32 | } 33 | printf("%jd\n", sc.get().first); 34 | } 35 | -------------------------------------------------------------------------------- /test/aoj_2976.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2976" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "Graph/capacitated_adjacency_list.cpp" 8 | #include "Graph/dinitz.cpp" 9 | #include "DataStructure/disjoint_set.cpp" 10 | 11 | int main() { 12 | size_t n, m; 13 | scanf("%zu %zu", &n, &m); 14 | 15 | adjacency_list, directed_tag> g(n+n+2); 16 | size_t source = n+n; 17 | size_t sink = source+1; 18 | 19 | for (size_t i = 0; i < n; ++i) { 20 | g.emplace(source, i, 1); 21 | g.emplace(n+i, sink, 1); 22 | } 23 | 24 | std::vector> rs(m); 25 | for (size_t i = 0; i < m; ++i) { 26 | size_t x, y; 27 | scanf("%zu %zu", &x, &y); 28 | --x, --y; 29 | rs[i] = std::make_pair(x, y); 30 | g.emplace(x, n+y, 1); 31 | } 32 | 33 | disjoint_set ds(m); 34 | int min = m - max_flow(g, source, sink, dinitz); 35 | int max = 0; 36 | 37 | for (size_t i = 0; i < m; ++i) 38 | for (size_t j = 0; j < i; ++j) 39 | if (rs[i].first == rs[j].first || rs[i].second == rs[j].second) 40 | if (ds.unite(i, j)) ++max; 41 | 42 | printf("%d %d\n", min, max); 43 | } 44 | -------------------------------------------------------------------------------- /test/aoj_3110.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=3110" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "ModularArithmetic/modint.cpp" 8 | #include "utility/literals.cpp" 9 | #include "utility/make/vector.cpp" 10 | 11 | constexpr intmax_t mod = 1000'000'007; 12 | using mi = modint; 13 | 14 | int main() { 15 | char buf[262144]; 16 | scanf("%s", buf); 17 | std::string s = buf; 18 | scanf("%s", buf); 19 | std::string t = buf; 20 | 21 | size_t n = s.length(); 22 | auto dp0 = make_vector({n+1, 2_zu}, mi(0)); 23 | auto dp1 = make_vector({n+1, 2_zu}, mi(0)); 24 | size_t const loose = 0; 25 | size_t const tight = 1; 26 | std::array const tightness{{loose, tight}}; 27 | dp0[0][tight] = 1; 28 | for (size_t i = 0; i < n; ++i) { 29 | for (size_t j: tightness) { 30 | for (int k = 0; k <= 9; ++k) { 31 | if (t[i] != '?' && t[i] != '0'+k) continue; 32 | if (j == tight && '0'+k > s[i]) break; 33 | size_t nj = ((j == tight && '0'+k == s[i])? tight: loose); 34 | dp0[i+1][nj] += dp0[i][j]; 35 | dp1[i+1][nj] += dp1[i][j] * 10 + dp0[i][j] * k; 36 | } 37 | } 38 | } 39 | 40 | printf("%d\n", (dp1[n][loose] + dp1[n][tight]).get()); 41 | } 42 | -------------------------------------------------------------------------------- /test/aoj_3111.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=3111" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "utility/literals.cpp" 9 | #include "utility/monoid/max_subsum.cpp" 10 | #include "DataStructure/basic_segment_tree.cpp" 11 | 12 | int main() { 13 | size_t n, q; 14 | scanf("%zu %zu", &n, &q); 15 | 16 | std::vector a(n); 17 | for (auto& ai: a) scanf("%jd", &ai); 18 | 19 | basic_segment_tree> st(a.begin(), a.end()); 20 | printf("%jd\n", std::max(st.fold(0, n).get(), 0_jd)); 21 | 22 | for (size_t i = 0; i < q; ++i) { 23 | size_t k; 24 | intmax_t x; 25 | scanf("%zu %jd", &k, &x); 26 | --k; 27 | st.set(k, x); 28 | printf("%jd\n", std::max(st.fold(0, n).get(), 0_jd)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/aoj_3112.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=3112" 2 | 3 | #include 4 | #include 5 | 6 | #include "String/suffix_array.cpp" 7 | #include "utility/literals.cpp" 8 | 9 | int main() { 10 | char buf[262144]; 11 | scanf("%s", buf); 12 | std::string s = buf; 13 | scanf("%s", buf); 14 | std::string t = buf; 15 | 16 | size_t k; 17 | scanf("%zu", &k); 18 | 19 | std::string st = s + '$' + t; 20 | suffix_array sa(st.begin(), st.end()); 21 | 22 | auto lcpa = sa.get_lcpa(); 23 | 24 | size_t n = s.length(); 25 | std::vector s_lcp(n); 26 | { 27 | size_t len = 0; 28 | for (size_t i = st.length()+1; i--;) { 29 | size_t j = sa[i]; 30 | if (j >= n) { 31 | len = -1; 32 | } else { 33 | len = std::min(len, lcpa[i]); 34 | s_lcp[j] = len; 35 | } 36 | } 37 | } 38 | { 39 | size_t len = 0; 40 | for (size_t i = 0; i <= st.length(); ++i) { 41 | size_t j = sa[i]; 42 | if (j >= n) { 43 | len = lcpa[i]; 44 | } else { 45 | s_lcp[j] = std::max(s_lcp[j], len); 46 | len = std::min(len, lcpa[i]); 47 | } 48 | } 49 | } 50 | 51 | std::vector dp(n+2); 52 | dp[0] = 1; 53 | dp[1] = -1; 54 | for (size_t i = 0; i < n; ++i) { 55 | dp[i+1] += dp[i]; 56 | 57 | if (dp[i] == 0) continue; 58 | size_t k0 = s_lcp[i]; 59 | if (k0 < k) continue; 60 | ++dp[i+k]; 61 | --dp[i+k0+1]; 62 | } 63 | 64 | puts(dp[n]? "Yes": "No"); 65 | } 66 | -------------------------------------------------------------------------------- /test/aoj_3112_sa_is.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=3112" 2 | 3 | #include 4 | #include 5 | 6 | #include "String/sa_is.cpp" 7 | #include "utility/literals.cpp" 8 | 9 | int main() { 10 | char buf[262144]; 11 | scanf("%s", buf); 12 | std::string s = buf; 13 | scanf("%s", buf); 14 | std::string t = buf; 15 | 16 | size_t k; 17 | scanf("%zu", &k); 18 | 19 | std::string st = s + '$' + t; 20 | suffix_array sa(st.begin(), st.end()); 21 | 22 | auto lcpa = sa.lcp_array(); 23 | 24 | size_t n = s.length(); 25 | std::vector s_lcp(n); 26 | { 27 | size_t len = 0; 28 | for (size_t i = st.length()+1; i--;) { 29 | size_t j = sa[i]; 30 | if (j >= n) { 31 | len = -1; 32 | } else { 33 | len = std::min(len, lcpa[i]); 34 | s_lcp[j] = len; 35 | } 36 | } 37 | } 38 | { 39 | size_t len = 0; 40 | for (size_t i = 0; i <= st.length(); ++i) { 41 | size_t j = sa[i]; 42 | if (j >= n) { 43 | len = lcpa[i]; 44 | } else { 45 | s_lcp[j] = std::max(s_lcp[j], len); 46 | len = std::min(len, lcpa[i]); 47 | } 48 | } 49 | } 50 | 51 | std::vector dp(n+2); 52 | dp[0] = 1; 53 | dp[1] = -1; 54 | for (size_t i = 0; i < n; ++i) { 55 | dp[i+1] += dp[i]; 56 | 57 | if (dp[i] == 0) continue; 58 | size_t k0 = s_lcp[i]; 59 | if (k0 < k) continue; 60 | ++dp[i+k]; 61 | --dp[i+k0+1]; 62 | } 63 | 64 | puts(dp[n]? "Yes": "No"); 65 | } 66 | -------------------------------------------------------------------------------- /test/aoj_ALDS1_10_A.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_10_A" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "utility/make/fix_point.cpp" 8 | 9 | int main() { 10 | int n; 11 | scanf("%d", &n); 12 | 13 | std::vector memo(n+1); 14 | memo[0] = memo[1] = 1; 15 | make_fix_point([&](auto f, int i) { 16 | intmax_t& res = memo[i]; 17 | if (res > 0) return res; 18 | res = f(i-1) + f(i-2); 19 | return res; 20 | })(n); 21 | printf("%jd\n", memo[n]); 22 | } 23 | -------------------------------------------------------------------------------- /test/aoj_ALDS1_14_B_kmp.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_14_B" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "String/knuth_morris_pratt_searcher.cpp" 9 | 10 | int main() { 11 | char buf[1048576]; 12 | scanf("%s", buf); 13 | std::string t = buf; 14 | scanf("%s", buf); 15 | std::string p = buf; 16 | 17 | knuth_morris_pratt_searcher kmp(p.begin(), p.end()); 18 | bool matched = false; 19 | for (auto tmp: kmp.find_all(t.begin(), t.end())) { 20 | matched = true; 21 | auto first = tmp.first; 22 | printf("%td\n", first-t.begin()); 23 | } 24 | 25 | { 26 | auto first = std::search(t.begin(), t.end(), kmp); 27 | if (matched != (first != t.end())) return 1; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /test/aoj_ALDS1_14_B_l61m1.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_14_B" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "String/rolling_hash_l61m1.cpp" 9 | 10 | int main() { 11 | char buf[1048576]; 12 | scanf("%s", buf); 13 | std::string t = buf; 14 | scanf("%s", buf); 15 | std::string p = buf; 16 | 17 | std::seed_seq ss{ 18 | static_cast(std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count()), 19 | static_cast(__builtin_ia32_rdtsc()), 20 | }; 21 | std::mt19937 rng(ss); 22 | uintmax_t base = std::uniform_int_distribution(0, rolling_hash_l61m1::mod-1)(rng); 23 | 24 | uintmax_t crit = rolling_hash_l61m1(p.begin(), p.end(), base).substr(0); 25 | rolling_hash_l61m1 rt(t.begin(), t.end(), base); 26 | for (size_t i = 0; i + p.length() <= t.length(); ++i) { 27 | if (rt.substr(i, p.length()) == crit) 28 | printf("%zu\n", i); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/aoj_ALDS1_14_B_z.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_14_B" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "String/z_algorithm.cpp" 9 | 10 | int main() { 11 | char buf[1048576]; 12 | scanf("%s", buf); 13 | std::string t = buf; 14 | scanf("%s", buf); 15 | std::string p = buf; 16 | 17 | z_array z(p.begin(), p.end()); 18 | bool matched = false; 19 | for (auto tmp: z.find_all(t.begin(), t.end())) { 20 | matched = true; 21 | auto first = tmp.first; 22 | printf("%td\n", first-t.begin()); 23 | } 24 | 25 | { 26 | auto first = std::search(t.begin(), t.end(), z); 27 | if (matched != (first != t.end())) return 1; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /test/aoj_ALDS1_5_D.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_5_D" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "DataStructure/wavelet_matrix.cpp" 8 | 9 | int main() { 10 | size_t n; 11 | scanf("%zu", &n); 12 | 13 | std::vector a(n); 14 | for (auto& ai: a) scanf("%d", &ai); 15 | 16 | wavelet_matrix<31> wm(a.begin(), a.end()); 17 | intmax_t res = 0; 18 | for (size_t i = 1; i < n; ++i) { 19 | res += wm.rank_3way(a[i], 0, i)[2]; 20 | } 21 | printf("%jd\n", res); 22 | } 23 | -------------------------------------------------------------------------------- /test/aoj_DPL_1_D.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_1_D" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "DataStructure/dynamic_bitvector.cpp" 9 | #include "DataStructure/wavelet_matrix.cpp" 10 | 11 | int main() { 12 | size_t n; 13 | scanf("%zu", &n); 14 | 15 | std::vector a(n); 16 | for (auto& ai: a) scanf("%zu", &ai); 17 | 18 | wavelet_matrix<17, uintmax_t, dynamic_bitvector> wm; 19 | for (size_t i = 0; i < n; ++i) wm.insert(i, 0); 20 | 21 | std::vector p(n); 22 | std::iota(p.begin(), p.end(), 0); 23 | std::sort(p.begin(), p.end(), [&](size_t i, size_t j) { 24 | if (a[i] != a[j]) return a[i] < a[j]; 25 | return j < i; 26 | }); 27 | 28 | for (size_t i = 0; i < n; ++i) { 29 | size_t j = p[i]; 30 | auto cur = ((j > 0)? wm.quantile(j-1, 0, j): 0) + 1; 31 | wm.set(j, cur); 32 | } 33 | 34 | printf("%ju\n", wm.quantile(n-1, 0, n)); 35 | } 36 | -------------------------------------------------------------------------------- /test/aoj_DPL_1_E.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_1_E" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "utility/make/vector.cpp" 10 | 11 | int main() { 12 | char buf[1024]; 13 | scanf("%s", buf); 14 | std::string s = buf; 15 | scanf("%s", buf); 16 | std::string t = buf; 17 | 18 | size_t n = s.length(); 19 | size_t m = t.length(); 20 | auto dp = make_vector({n+1, m+1}, 0); 21 | for (size_t i = 1; i <= n; ++i) dp[i][0] = i; 22 | for (size_t j = 1; j <= m; ++j) dp[0][j] = j; 23 | 24 | for (size_t i = 1; i <= n; ++i) 25 | for (size_t j = 1; j <= m; ++j) { 26 | dp[i][j] = std::min({dp[i-1][j]+1, 27 | dp[i][j-1]+1, 28 | dp[i-1][j-1] + ((s[i-1] == t[j-1])? 0: 1)}); 29 | } 30 | 31 | printf("%d\n", dp[n][m]); 32 | } 33 | -------------------------------------------------------------------------------- /test/aoj_DPL_5_A.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_5_A" 2 | 3 | #include 4 | 5 | #include "ModularArithmetic/modint.cpp" 6 | #include "ModularArithmetic/operations.cpp" 7 | 8 | using mi = modint<1000'000'007>; 9 | 10 | int main() { 11 | intmax_t n, k; 12 | scanf("%jd %jd", &n, &k); 13 | printf("%d\n", pow(mi(k), n).get()); 14 | } 15 | -------------------------------------------------------------------------------- /test/aoj_DPL_5_B.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_5_B" 2 | 3 | #include 4 | #include 5 | 6 | #include "ModularArithmetic/modint.cpp" 7 | 8 | using mi = modint<1000'000'007>; 9 | 10 | int main() { 11 | intmax_t n, k; 12 | scanf("%jd %jd", &n, &k); 13 | 14 | if (n > k) return puts("0"), 0; 15 | 16 | mi res = 1; 17 | for (int i = 0; i < n; ++i) res *= k-i; 18 | printf("%d\n", res.get()); 19 | } 20 | -------------------------------------------------------------------------------- /test/aoj_DPL_5_C.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_5_C" 2 | 3 | #include 4 | #include 5 | 6 | #include "ModularArithmetic/modint.cpp" 7 | #include "ModularArithmetic/modtable.cpp" 8 | #include "ModularArithmetic/operations.cpp" 9 | 10 | using mi = modint<1000'000'007>; 11 | 12 | int main() { 13 | intmax_t n, k; 14 | scanf("%jd %jd", &n, &k); 15 | 16 | modtable mt(k); 17 | mi res = 0; 18 | for (int i = 1; i <= k; ++i) { 19 | mi cur = mt.binom(k, i); 20 | if ((i-1) % 2) cur = -cur; 21 | cur *= pow(mi(k-i), n); 22 | res += cur; 23 | } 24 | 25 | res = pow(mi(k), n) - res; 26 | printf("%d\n", res.get()); 27 | } 28 | -------------------------------------------------------------------------------- /test/aoj_DPL_5_D.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_5_D" 2 | 3 | #include 4 | 5 | #include "ModularArithmetic/modint.cpp" 6 | #include "ModularArithmetic/modtable.cpp" 7 | 8 | using mi = modint<1000'000'007>; 9 | 10 | int main() { 11 | intmax_t n, k; 12 | scanf("%jd %jd", &n, &k); 13 | 14 | modtable mt(n+k); 15 | printf("%d\n", mt.binom(n+k-1, k-1).get()); 16 | } 17 | -------------------------------------------------------------------------------- /test/aoj_DPL_5_E.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_5_E" 2 | 3 | #include 4 | #include 5 | 6 | #include "ModularArithmetic/modint.cpp" 7 | #include "ModularArithmetic/modtable.cpp" 8 | 9 | using mi = modint<1000'000'007>; 10 | 11 | int main() { 12 | intmax_t n, k; 13 | scanf("%jd %jd", &n, &k); 14 | 15 | modtable mt(k); 16 | printf("%d\n", mt.binom(k, n).get()); 17 | } 18 | -------------------------------------------------------------------------------- /test/aoj_DPL_5_F.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_5_F" 2 | 3 | #include 4 | #include 5 | 6 | #include "ModularArithmetic/modint.cpp" 7 | #include "ModularArithmetic/modtable.cpp" 8 | 9 | using mi = modint<1000'000'007>; 10 | 11 | int main() { 12 | intmax_t n, k; 13 | scanf("%jd %jd", &n, &k); 14 | 15 | modtable mt(n); 16 | printf("%d\n", mt.binom(n-1, k-1).get()); 17 | } 18 | -------------------------------------------------------------------------------- /test/aoj_DPL_5_G.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_5_G" 2 | 3 | #include 4 | #include 5 | 6 | #include "ModularArithmetic/modint.cpp" 7 | #include "ModularArithmetic/modtable.cpp" 8 | #include "ModularArithmetic/operations.cpp" 9 | 10 | using mi = modint<1000'000'007>; 11 | 12 | int main() { 13 | intmax_t n, k; 14 | scanf("%jd %jd", &n, &k); 15 | 16 | modtable mt(n+k); 17 | mi res = 0; 18 | for (int j = 1; j <= k; ++j) { 19 | mi res0 = 0; 20 | for (int i = 1; i <= j; ++i) { 21 | mi cur = mt.binom(j, i); 22 | if ((i-1) % 2) cur = -cur; 23 | cur *= pow(mi(j-i), n); 24 | res0 += cur; 25 | } 26 | res0 = (pow(mi(j), n) - res0) * mt.factorial_inverse(j); 27 | res += res0; 28 | } 29 | printf("%d\n", res.get()); 30 | } 31 | -------------------------------------------------------------------------------- /test/aoj_DPL_5_I.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_5_I" 2 | 3 | #include 4 | #include 5 | 6 | #include "ModularArithmetic/modint.cpp" 7 | #include "ModularArithmetic/modtable.cpp" 8 | #include "ModularArithmetic/operations.cpp" 9 | 10 | using mi = modint<1000'000'007>; 11 | 12 | int main() { 13 | intmax_t n, k; 14 | scanf("%jd %jd", &n, &k); 15 | 16 | modtable mt(n+k); 17 | mi res = 0; 18 | for (int i = 1; i <= k; ++i) { 19 | mi cur = mt.binom(k, i); 20 | if ((i-1) % 2) cur = -cur; 21 | cur *= pow(mi(k-i), n); 22 | res += cur; 23 | } 24 | res = (pow(mi(k), n) - res) * mt.factorial_inverse(k); 25 | printf("%d\n", res.get()); 26 | } 27 | -------------------------------------------------------------------------------- /test/aoj_DPL_5_J.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_5_J" 2 | 3 | #include 4 | #include 5 | 6 | #include "ModularArithmetic/modint.cpp" 7 | 8 | using mi = modint<1000'000'007>; 9 | 10 | int main() { 11 | size_t n, k; 12 | scanf("%zu %zu", &n, &k); 13 | 14 | std::vector dp(n+1, 0); 15 | dp[0] = 1; 16 | for (size_t i = 1; i <= k; ++i) 17 | for (size_t j = i; j <= n; ++j) 18 | dp[j] += dp[j-i]; 19 | 20 | printf("%d\n", dp[n].get()); 21 | } 22 | -------------------------------------------------------------------------------- /test/aoj_DPL_5_L.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_5_L" 2 | 3 | #include 4 | #include 5 | 6 | #include "ModularArithmetic/modint.cpp" 7 | 8 | using mi = modint<1000'000'007>; 9 | 10 | int main() { 11 | size_t n, k; 12 | scanf("%zu %zu", &n, &k); 13 | 14 | if (n < k) return puts("0"), 0; 15 | 16 | std::vector dp(n+1, 0); 17 | dp[0] = 1; 18 | for (size_t i = 1; i <= k; ++i) 19 | for (size_t j = i; j <= n; ++j) 20 | dp[j] += dp[j-i]; 21 | 22 | printf("%d\n", dp[n-k].get()); 23 | } 24 | -------------------------------------------------------------------------------- /test/aoj_DSL_1_A.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_1_A" 2 | 3 | #include 4 | 5 | #include "DataStructure/disjoint_set.cpp" 6 | 7 | int main() { 8 | size_t n, q; 9 | scanf("%zu %zu", &n, &q); 10 | 11 | disjoint_set ds(n); 12 | for (size_t i = 0; i < q; ++i) { 13 | int com; 14 | scanf("%d", &com); 15 | 16 | if (com == 0) { 17 | size_t x, y; 18 | scanf("%zu %zu", &x, &y); 19 | ds.unite(x, y); 20 | } else if (com == 1) { 21 | size_t x, y; 22 | scanf("%zu %zu", &x, &y); 23 | printf("%d\n", !!ds.equivalent(x, y)); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /test/aoj_DSL_1_B.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_1_B" 2 | 3 | #include 4 | 5 | #include "DataStructure/potential_function.cpp" 6 | 7 | int main() { 8 | size_t n, q; 9 | scanf("%zu %zu", &n, &q); 10 | 11 | potential_function pf(n); 12 | for (size_t i = 0; i < q; ++i) { 13 | int com; 14 | scanf("%d", &com); 15 | 16 | if (com == 0) { 17 | size_t x, y; 18 | int z; 19 | scanf("%zu %zu %d", &x, &y, &z); 20 | pf.define(x, y, z); 21 | } else if (com == 1) { 22 | size_t x, y; 23 | scanf("%zu %zu", &x, &y); 24 | if (pf.defined(x, y)) { 25 | printf("%d\n", pf(x, y)); 26 | } else { 27 | puts("?"); 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /test/aoj_DSL_2_A.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_A" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "utility/monoid/min.cpp" 8 | #include "DataStructure/basic_segment_tree.cpp" 9 | 10 | int main() { 11 | size_t n, q; 12 | scanf("%zu %zu", &n, &q); 13 | 14 | basic_segment_tree> st(n); 15 | for (size_t i = 0; i < q; ++i) { 16 | int com; 17 | scanf("%d", &com); 18 | 19 | if (com == 0) { 20 | size_t i; 21 | intmax_t x; 22 | scanf("%zu %jd", &i, &x); 23 | st.set(i, x); 24 | } else if (com == 1) { 25 | size_t x, y; 26 | scanf("%zu %zu", &x, &y); 27 | printf("%d\n", st.fold(x, y+1).get()); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/aoj_DSL_2_B.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_B" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "DataStructure/basic_segment_tree.cpp" 8 | 9 | int main() { 10 | size_t n, q; 11 | scanf("%zu %zu", &n, &q); 12 | 13 | basic_segment_tree st(n, 0); 14 | for (size_t i = 0; i < q; ++i) { 15 | int com; 16 | scanf("%d", &com); 17 | 18 | if (com == 0) { 19 | size_t i; 20 | intmax_t x; 21 | scanf("%zu %jd", &i, &x); 22 | --i; 23 | st.set(i, st[i]+x); 24 | } else if (com == 1) { 25 | size_t x, y; 26 | scanf("%zu %zu", &x, &y); 27 | --x, --y; 28 | printf("%jd\n", st.fold(x, y+1)); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /test/aoj_DSL_2_G.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_G" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "utility/action/add_sum.cpp" 8 | #include "DataStructure/segment_tree.cpp" 9 | 10 | int main() { 11 | size_t n, q; 12 | scanf("%zu %zu", &n, &q); 13 | 14 | segment_tree> st(n, 0); 15 | for (size_t i = 0; i < q; ++i) { 16 | int com; 17 | scanf("%d", &com); 18 | 19 | if (com == 0) { 20 | size_t s, t; 21 | intmax_t x; 22 | scanf("%zu %zu %jd", &s, &t, &x); 23 | --s, --t; 24 | st.act(s, t+1, x); 25 | } else if (com == 1) { 26 | size_t s, t; 27 | scanf("%zu %zu", &s, &t); 28 | --s, --t; 29 | printf("%jd\n", st.fold(s, t+1).get()); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test/aoj_DSL_2_H.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_H" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "utility/action/add_min.cpp" 8 | #include "DataStructure/segment_tree.cpp" 9 | 10 | int main() { 11 | size_t n, q; 12 | scanf("%zu %zu", &n, &q); 13 | 14 | segment_tree> st(n, 0); 15 | for (size_t i = 0; i < q; ++i) { 16 | int com; 17 | scanf("%d", &com); 18 | 19 | if (com == 0) { 20 | size_t s, t; 21 | intmax_t x; 22 | scanf("%zu %zu %jd", &s, &t, &x); 23 | st.act(s, t+1, x); 24 | } else if (com == 1) { 25 | size_t s, t; 26 | scanf("%zu %zu", &s, &t); 27 | printf("%d\n", st.fold(s, t+1).get()); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/aoj_DSL_2_I.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_I" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "DataStructure/segment_tree.cpp" 10 | #include "utility/action/set_sum.cpp" 11 | 12 | int main() { 13 | size_t n, q; 14 | scanf("%zu %zu", &n, &q); 15 | 16 | segment_tree> st(n, 0); 17 | for (size_t i = 0; i < q; ++i) { 18 | int t; 19 | scanf("%d", &t); 20 | 21 | if (t == 0) { 22 | size_t l, r; 23 | int x; 24 | scanf("%zu %zu %d", &l, &r, &x); 25 | st.act(l, r+1, x); 26 | } else if (t == 1) { 27 | size_t l, r; 28 | scanf("%zu %zu", &l, &r); 29 | printf("%d\n", st.fold(l, r+1).get()); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test/aoj_DSL_3_D.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_3_D" 2 | 3 | #include 4 | #include 5 | 6 | #include "DataStructure/foldable_queue.cpp" 7 | #include "utility/monoid/min.cpp" 8 | 9 | int main() { 10 | size_t n, k; 11 | scanf("%zu %zu", &n, &k); 12 | 13 | foldable_queue> fq; 14 | for (size_t i = 0; i < k; ++i) { 15 | int a; 16 | scanf("%d", &a); 17 | fq.push(a); 18 | } 19 | 20 | std::vector res{fq.fold().get()}; 21 | for (size_t i = k; i < n; ++i) { 22 | int a; 23 | scanf("%d", &a); 24 | fq.pop(); 25 | fq.push(a); 26 | res.push_back(fq.fold().get()); 27 | } 28 | 29 | for (size_t i = 0; i < res.size(); ++i) 30 | printf("%d%c", res[i], i+1 6 | 7 | #include "Graph/adjacency_list.cpp" 8 | #include "Graph/topological_sort.cpp" 9 | 10 | int main() { 11 | size_t n, m; 12 | scanf("%zu %zu", &n, &m); 13 | 14 | adjacency_list, directed_tag> g(n); 15 | for (size_t i = 0; i < m; ++i) { 16 | size_t u, v; 17 | scanf("%zu %zu", &u, &v); 18 | g.emplace(u, v, 1); 19 | } 20 | 21 | auto ord = topological_sort(g); 22 | for (size_t i = 0; i < n; ++i) 23 | printf("%zu\n", ord[i]); 24 | } 25 | -------------------------------------------------------------------------------- /test/aoj_GRL_5_C_segment_tree.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_5_C" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "utility/macro/stack_extend.cpp" 8 | #include "Graph/adjacency_list.cpp" 9 | #include "Graph/lowest_common_ancestor_segment_tree.cpp" 10 | 11 | int main() { 12 | BEGIN_STACK_EXTEND(128*1024*1024); 13 | 14 | size_t n; 15 | scanf("%zu", &n); 16 | 17 | adjacency_list, undirected_tag> g(n); 18 | for (size_t i = 0; i < n; ++i) { 19 | size_t k; 20 | scanf("%zu", &k); 21 | for (size_t j = 0; j < k; ++j) { 22 | size_t c; 23 | scanf("%zu", &c); 24 | g.emplace(i, c, 1); 25 | } 26 | } 27 | 28 | lowest_common_ancestor g_lca(g, 0); 29 | 30 | size_t q; 31 | scanf("%zu", &q); 32 | for (size_t i = 0; i < q; ++i) { 33 | size_t u, v; 34 | scanf("%zu %zu", &u, &v); 35 | printf("%zu\n", g_lca(u, v)); 36 | } 37 | 38 | END_STACK_EXTEND; 39 | } 40 | -------------------------------------------------------------------------------- /test/aoj_GRL_5_C_sparse_table.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_5_C" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "utility/macro/stack_extend.cpp" 8 | #include "Graph/adjacency_list.cpp" 9 | #include "Graph/lowest_common_ancestor_sparse_table.cpp" 10 | 11 | int main() { 12 | BEGIN_STACK_EXTEND(128*1024*1024); 13 | 14 | size_t n; 15 | scanf("%zu", &n); 16 | 17 | adjacency_list, undirected_tag> g(n); 18 | for (size_t i = 0; i < n; ++i) { 19 | size_t k; 20 | scanf("%zu", &k); 21 | for (size_t j = 0; j < k; ++j) { 22 | size_t c; 23 | scanf("%zu", &c); 24 | g.emplace(i, c, 1); 25 | } 26 | } 27 | 28 | lowest_common_ancestor g_lca(g, 0); 29 | 30 | size_t q; 31 | scanf("%zu", &q); 32 | for (size_t i = 0; i < q; ++i) { 33 | size_t u, v; 34 | scanf("%zu %zu", &u, &v); 35 | printf("%zu\n", g_lca(u, v)); 36 | } 37 | 38 | END_STACK_EXTEND; 39 | } 40 | -------------------------------------------------------------------------------- /test/aoj_GRL_5_C_squaring.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_5_C" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "Graph/adjacency_list.cpp" 8 | #include "Graph/lowest_common_ancestor_squaring.cpp" 9 | 10 | int main() { 11 | size_t n; 12 | scanf("%zu", &n); 13 | 14 | adjacency_list, undirected_tag> g(n); 15 | for (size_t i = 0; i < n; ++i) { 16 | size_t k; 17 | scanf("%zu", &k); 18 | for (size_t j = 0; j < k; ++j) { 19 | size_t c; 20 | scanf("%zu", &c); 21 | g.emplace(i, c, 1); 22 | } 23 | } 24 | 25 | lowest_common_ancestor g_lca(g, 0); 26 | 27 | size_t q; 28 | scanf("%zu", &q); 29 | for (size_t i = 0; i < q; ++i) { 30 | size_t u, v; 31 | scanf("%zu %zu", &u, &v); 32 | printf("%zu\n", g_lca(u, v)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /test/aoj_GRL_5_D.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_5_D" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "DataStructure/basic_segment_tree.cpp" 9 | #include "Graph/hl_decomposition.cpp" 10 | #include "utility/macro/stack_extend.cpp" 11 | 12 | int main() { 13 | BEGIN_STACK_EXTEND(128*1024*1024); 14 | size_t n; 15 | scanf("%zu", &n); 16 | 17 | std::vector par(n, n); 18 | std::vector> es; 19 | for (size_t i = 0; i < n; ++i) { 20 | size_t k; 21 | scanf("%zu", &k); 22 | for (size_t j = 0; j < k; ++j) { 23 | size_t c; 24 | scanf("%zu", &c); 25 | par[c] = i; 26 | es.emplace_back(i, c, 0); 27 | } 28 | } 29 | 30 | hl_decomposed_tree, value_on_undirected_edge_tag> g(n, es); 31 | 32 | size_t q; 33 | scanf("%zu", &q); 34 | 35 | for (size_t i = 0; i < q; ++i) { 36 | int t; 37 | scanf("%d", &t); 38 | 39 | if (t == 0) { 40 | size_t v; 41 | int w; 42 | scanf("%zu %d", &v, &w); 43 | w += g.fold(v, par[v]); 44 | g.set(v, w); 45 | } else if (t == 1) { 46 | size_t u; 47 | scanf("%zu", &u); 48 | int res = g.fold(u, 0); 49 | assert(res == g.fold(0, u)); 50 | printf("%d\n", res); 51 | } 52 | } 53 | 54 | END_STACK_EXTEND; 55 | } 56 | -------------------------------------------------------------------------------- /test/aoj_GRL_5_E.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_5_E" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "utility/action/add_sum.cpp" 10 | #include "DataStructure/segment_tree.cpp" 11 | #include "Graph/hl_decomposition.cpp" 12 | 13 | int main() { 14 | 15 | size_t n; 16 | scanf("%zu", &n); 17 | 18 | std::vector par(n, n); 19 | std::vector>> es; 20 | for (size_t i = 0; i < n; ++i) { 21 | size_t k; 22 | scanf("%zu", &k); 23 | for (size_t j = 0; j < k; ++j) { 24 | size_t c; 25 | scanf("%zu", &c); 26 | par[c] = i; 27 | es.emplace_back(i, c, 0); 28 | } 29 | } 30 | 31 | hl_decomposed_tree>, value_on_undirected_edge_tag> g(n, es); 32 | 33 | size_t q; 34 | scanf("%zu", &q); 35 | 36 | for (size_t i = 0; i < q; ++i) { 37 | int t; 38 | scanf("%d", &t); 39 | 40 | if (t == 0) { 41 | size_t v; 42 | intmax_t w; 43 | scanf("%zu %jd", &v, &w); 44 | g.act(v, 0, w); 45 | } else if (t == 1) { 46 | size_t u; 47 | scanf("%zu", &u); 48 | intmax_t res = g.fold(u, 0).get(); 49 | assert(res == g.fold(0, u).get()); 50 | printf("%jd\n", res); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /test/mini/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !*.cpp 3 | -------------------------------------------------------------------------------- /test/mini/fast_io.cpp: -------------------------------------------------------------------------------- 1 | #define IGNORE 2 | // @ignore 3 | 4 | #include 5 | 6 | #include "utility/fast_io.cpp" 7 | 8 | int main() { 9 | int a, b, c; 10 | cin.scan(a, b, c); 11 | cout.set_sep('_'); 12 | cout.set_end('X'); 13 | cout.println(a, a+b, a+b+c); 14 | } 15 | -------------------------------------------------------------------------------- /test/mini/foldable_deque.cpp: -------------------------------------------------------------------------------- 1 | #define IGNORE 2 | // @ignore 3 | 4 | #include 5 | #include 6 | 7 | #include "DataStructure/foldable_deque.cpp" 8 | 9 | int main() { 10 | foldable_deque dq; 11 | auto print = [&] { printf("%s\n", dq.fold().data()); }; 12 | auto push_back = [&](auto const& x) { dq.push_back(x); print(); }; 13 | auto push_front = [&](auto const& x) { dq.push_front(x); print(); }; 14 | auto pop_back = [&] { dq.pop_back(); print(); }; 15 | auto pop_front = [&] { dq.pop_front(); print(); }; 16 | 17 | // 2 4 18 | // qa 19 | // R++ 20 | // L++ 21 | // L-- 22 | // R-- 23 | 24 | // push_back("a"); 25 | // push_back("b"); 26 | // push_back("c"); 27 | // pop_front(); 28 | // push_front("A"); 29 | // push_front("B"); 30 | // pop_back(); 31 | // pop_back(); 32 | // pop_back(); 33 | // pop_back(); 34 | 35 | push_back("q"); 36 | push_back("a"); 37 | pop_front(); 38 | push_front("q"); 39 | pop_back(); 40 | } 41 | -------------------------------------------------------------------------------- /test/mini/modint.cpp: -------------------------------------------------------------------------------- 1 | #define IGNORE 2 | // @ignore 3 | 4 | #include 5 | #include 6 | 7 | #include "ModularArithmetic/modint.cpp" 8 | 9 | constexpr intmax_t mod = 998244353; 10 | using mi = modint; 11 | 12 | int main() { 13 | printf("%jd\n", (mi(2) - 3).get()); 14 | printf("%jd\n", (2 - mi(3)).get()); 15 | printf("%jd\n", (mi(1) / 2).get()); 16 | printf("%jd\n", (1 / mi(2)).get()); 17 | } 18 | -------------------------------------------------------------------------------- /test/mini/mul_upper.cpp: -------------------------------------------------------------------------------- 1 | #define IGNORE 2 | // @ignore 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "integer/mul_upper.cpp" 10 | 11 | template 12 | void test_one(Tp x, Tp y) { 13 | using unsigned_type = typename std::make_unsigned::type; 14 | unsigned_type mu = mul_upper(x, y); 15 | auto ml = unsigned_type(x) * unsigned_type(y); 16 | int wid = (CHAR_BIT * sizeof(Tp) / 4); 17 | std::cout << std::setw(wid) << std::setfill('0') << std::hex << mu << ' ' << ml << '\n'; 18 | } 19 | 20 | int main() { 21 | test_one(+1000000000, +1000000000); 22 | test_one(-1000000000, +1000000000); 23 | test_one(+1000000000, -1000000000); 24 | test_one(-1000000000, -1000000000); 25 | test_one(+1000000000u, +1000000000u); 26 | test_one(-1000000000u, +1000000000u); 27 | test_one(+1000000000u, -1000000000u); 28 | test_one(-1000000000u, -1000000000u); 29 | } 30 | -------------------------------------------------------------------------------- /test/mini/qq.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_qq 2 | #define H_qq 3 | 4 | // @ignore 5 | 6 | #include 7 | 8 | void qq() { 9 | for (int i = 1; i <= 9; ++i) 10 | for (int j = 1; j <= 9; ++j) 11 | printf("%dx%d=%d\n", i, j, i*j); 12 | } 13 | 14 | #endif /* !defined(H_qq) */ 15 | -------------------------------------------------------------------------------- /test/mini/rectangle_sum.cpp: -------------------------------------------------------------------------------- 1 | #define IGNORE 2 | // @ignore 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "DataStructure/rectangle_query.cpp" 9 | // #include "DataStructure/wavelet_matrix.cpp" 10 | 11 | int main() { 12 | std::vector a{3, 2, 4, 6, 1}; 13 | rectangle_query<3> rq(a.begin(), a.end()); 14 | // wavelet_matrix<3> wm(a.begin(), a.end()); 15 | 16 | while (true) { 17 | size_t s, t; 18 | uintmax_t x; 19 | scanf("%zu %zu %ju", &s, &t, &x); 20 | auto [l, e, g] = rq.sum_3way(s, t, x); 21 | // auto [l, e, g] = wm.rank_3way(x, s, t); 22 | printf("%ju %ju %ju\n", l, e, g); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/mini/twoword.cpp: -------------------------------------------------------------------------------- 1 | #define IGNORE 2 | // @ignore 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "integer/mul_upper.cpp" 9 | 10 | template 11 | void test(Tp u, Tp v) { 12 | Tp hi = mul_upper(u, v); 13 | Tp lo = u * v; 14 | fprintf(stderr, "%08x * %08x: ", u, v); 15 | fprintf(stderr, "%08x %08x == %016jx\n", hi, lo, uintmax_t(u) * v); 16 | assert((uintmax_t(hi) << 32 | lo) == uintmax_t(u) * v); 17 | } 18 | 19 | int main() { 20 | test(0xffffffffu, 0xffffffffu); 21 | test(0xffffffffu, 0x12345678u); 22 | test(0x12345678u, 0x9abcdef0u); 23 | test(1u, -1u); 24 | test(10u, -1u); 25 | test(0x10000u, -2u); 26 | test(0x123u, -0x456u); 27 | test(0x123, -0x456); 28 | } 29 | -------------------------------------------------------------------------------- /test/yc_1036.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/1036" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "DataStructure/foldable_queue.cpp" 10 | #include "utility/monoid/gcd.cpp" 11 | 12 | int main() { 13 | size_t n; 14 | scanf("%zu", &n); 15 | 16 | std::vector a(n); 17 | for (auto& ai: a) scanf("%jd", &ai); 18 | 19 | foldable_queue> q; 20 | intmax_t res = n*(n+1)/2; 21 | for (size_t il = 0, ir = 0; il < n; ++il) { 22 | while (ir < n && (q.fold() + a[ir]).get() != 1) { 23 | q.push(a[ir++]); 24 | } 25 | res -= ir-il; 26 | if (ir == il) ++ir; else q.pop(); 27 | } 28 | 29 | printf("%jd\n", res); 30 | } 31 | -------------------------------------------------------------------------------- /test/yc_1036_disjoint_sparse_table.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/1036" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "DataStructure/disjoint_sparse_table.cpp" 9 | #include "utility/monoid/gcd.cpp" 10 | 11 | int main() { 12 | size_t n; 13 | scanf("%zu", &n); 14 | 15 | std::vector a(n); 16 | for (auto& ai: a) scanf("%jd", &ai); 17 | 18 | disjoint_sparse_table> st(a.begin(), a.end()); 19 | 20 | intmax_t res = 0; 21 | for (size_t i = 0; i < n; ++i) { 22 | if (st.fold(i, n).get() > 1) break; 23 | size_t lb = i, ub = n; 24 | while (ub-lb > 1) { 25 | size_t mid = (lb+ub) / 2; 26 | ((st.fold(i, mid).get() > 1)? lb: ub) = mid; 27 | } 28 | res += n-lb; 29 | } 30 | 31 | printf("%jd\n", res); 32 | } 33 | -------------------------------------------------------------------------------- /test/yc_1036_sparse_table.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/1036" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "DataStructure/sparse_table.cpp" 9 | #include "utility/monoid/gcd.cpp" 10 | 11 | int main() { 12 | size_t n; 13 | scanf("%zu", &n); 14 | 15 | std::vector a(n); 16 | for (auto& ai: a) scanf("%jd", &ai); 17 | 18 | sparse_table> st(a.begin(), a.end()); 19 | 20 | intmax_t res = 0; 21 | for (size_t i = 0; i < n; ++i) { 22 | if (st.fold(i, n).get() > 1) break; 23 | size_t lb = i, ub = n; 24 | while (ub-lb > 1) { 25 | size_t mid = (lb+ub) / 2; 26 | ((st.fold(i, mid).get() > 1)? lb: ub) = mid; 27 | } 28 | res += n-lb; 29 | } 30 | 31 | printf("%jd\n", res); 32 | } 33 | -------------------------------------------------------------------------------- /test/yc_3014.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/3014" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "String/tree_attack.cpp" 10 | 11 | int main() { 12 | intmax_t p, b; 13 | int sigma = 26; 14 | scanf("%jd %jd %d", &p, &b, &sigma); 15 | 16 | auto h = [&](auto const& s) -> intmax_t { 17 | __int128 h = 0; 18 | for (size_t i = 0; i < s.size(); ++i) 19 | h = (h * b + s[i]) % p; 20 | return h; 21 | }; 22 | 23 | size_t k = 2; 24 | std::string s, t; 25 | do { 26 | size_t n = 1_zu << k; 27 | std::vector a = tree_attack(p, b, k, sigma); 28 | if (a.empty()) { 29 | ++k; 30 | continue; 31 | } 32 | s = t = std::string(n, 'x'); 33 | for (size_t i = 0; i < a.size(); ++i) { 34 | if (a[i] > 0) { 35 | s[i] = 'a' + a[i]; 36 | t[i] = 'a'; 37 | } 38 | if (a[i] < 0) { 39 | s[i] = 'a'; 40 | t[i] = 'a' - a[i]; 41 | } 42 | } 43 | } while (s.empty()); 44 | 45 | // for special judges 46 | // printf("%s\n", s.data()); 47 | // printf("%s\n", t.data()); 48 | 49 | std::vector u(s.length()); 50 | for (size_t i = 0; i < s.length(); ++i) 51 | u[i] = s[i]-t[i]; 52 | 53 | fprintf(stderr, "s: \"%s\"\n", s.data()); 54 | fprintf(stderr, "t: \"%s\"\n", t.data()); 55 | fprintf(stderr, "length: %zu\n", s.length()); 56 | fprintf(stderr, "h(s): %jd\n", h(s)); 57 | fprintf(stderr, "h(t): %jd\n", h(t)); 58 | fprintf(stderr, "h(s-t): %jd\n", h(u)); 59 | assert(h(u) == 0); 60 | assert(h(s) == h(t)); 61 | assert(s != t); 62 | } 63 | -------------------------------------------------------------------------------- /test/yc_306.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/306" 2 | #define ERROR 1e-6 3 | 4 | #include 5 | #include 6 | 7 | #include "algorithm/ternary_search.cpp" 8 | 9 | int main() { 10 | long double xa, ya, xb, yb; 11 | scanf("%Lf %Lf %Lf %Lf", &xa, &ya, &xb, &yb); 12 | 13 | auto f = [&](auto y) { return std::hypot(xa, y-ya) + std::hypot(xb, yb-y); }; 14 | long double y = optimize_convex(f, 0.0L, 1e3L, 1e-6L, false).first; 15 | printf("%.20Lf\n", y); 16 | } 17 | -------------------------------------------------------------------------------- /test/yc_306_maximize.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/306" 2 | #define ERROR 1e-6 3 | 4 | #include 5 | #include 6 | 7 | #include "algorithm/ternary_search.cpp" 8 | 9 | int main() { 10 | long double xa, ya, xb, yb; 11 | scanf("%Lf %Lf %Lf %Lf", &xa, &ya, &xb, &yb); 12 | 13 | auto f = [&](auto y) { return -(std::hypot(xa, y-ya) + std::hypot(xb, yb-y)); }; 14 | long double y = optimize_convex(f, 0.0L, 1e3L, 1e-6L).first; 15 | printf("%.20Lf\n", y); 16 | } 17 | -------------------------------------------------------------------------------- /test/yc_502.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/502" 2 | 3 | #include "ModularArithmetic/modint.cpp" 4 | #include "ModularArithmetic/factorial.cpp" 5 | 6 | constexpr intmax_t mod = 1000'000'007; 7 | 8 | int main() { 9 | intmax_t n; 10 | scanf("%jd", &n); 11 | printf("%d\n", factorial(n).get()); 12 | } 13 | -------------------------------------------------------------------------------- /test/yc_551.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/551" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "ModularArithmetic/modint.cpp" 9 | #include "ModularArithmetic/operations.cpp" 10 | 11 | int main() { 12 | intmax_t p; 13 | int q; 14 | scanf("%jd %*d %d", &p, &q); 15 | 16 | while (q--) { 17 | intmax_t a0, b0, c0; 18 | scanf("%jd %jd %jd", &a0, &b0, &c0); 19 | 20 | modint<0>::set_modulo(p); 21 | 22 | modint<0> a(a0), b(b0), c(c0); 23 | auto dd = sqrt_all(b*b - 4*a*c); 24 | 25 | std::vector res; 26 | for (auto d: dd) 27 | res.push_back(((-b + d) / (2*a)).get()); 28 | 29 | if (res.empty()) { 30 | puts("-1"); 31 | continue; 32 | } 33 | 34 | if (res.size() == 2 && res[0] == res[1]) res.pop_back(); 35 | std::sort(res.begin(), res.end()); 36 | for (size_t i = 0; i < res.size(); ++i) 37 | printf("%jd%c", res[i], i+1 6 | #include 7 | #include 8 | #include 9 | 10 | #include "DataStructure/li_chao_tree.cpp" 11 | 12 | int main() { 13 | size_t n; 14 | scanf("%zu", &n); 15 | 16 | std::vector a(n), x(n), y(n); 17 | for (auto& ai: a) scanf("%jd", &ai); 18 | for (auto& xi: x) scanf("%jd", &xi); 19 | for (auto& yi: y) scanf("%jd", &yi); 20 | 21 | lower_linear_envelope f(a.begin(), a.end()); 22 | 23 | std::vector dp(n+1); 24 | dp[0] = 0; 25 | for (size_t i = 0; i < n; ++i) { 26 | f.push(-2*x[i], dp[i] + x[i]*x[i] + y[i]*y[i]); 27 | dp[i+1] = f.get_nth(i) + a[i]*a[i]; 28 | } 29 | 30 | printf("%jd\n", dp[n]); 31 | } 32 | -------------------------------------------------------------------------------- /test/yc_703_onoff.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/703" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "algorithm/online_to_offline_optimization.cpp" 9 | 10 | int main() { 11 | size_t n; 12 | scanf("%zu", &n); 13 | 14 | std::vector a(n), x(n), y(n); 15 | for (auto& ai: a) scanf("%d", &ai); 16 | for (auto& xi: x) scanf("%d", &xi); 17 | for (auto& yi: y) scanf("%d", &yi); 18 | 19 | auto f = [&](size_t j, size_t i) { 20 | intmax_t dx = x[j] - a[i-1]; 21 | intmax_t dy = y[j]; 22 | return dx*dx + dy*dy; 23 | }; 24 | 25 | auto dp = online_to_offline_optimization(f, n+1); 26 | printf("%jd\n", dp[n]); 27 | } 28 | -------------------------------------------------------------------------------- /test/yc_704_onoff.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/704" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "algorithm/online_to_offline_optimization.cpp" 10 | 11 | int main() { 12 | size_t n; 13 | scanf("%zu", &n); 14 | 15 | std::vector a(n), x(n), y(n); 16 | for (auto& ai: a) scanf("%d", &ai); 17 | for (auto& xi: x) scanf("%d", &xi); 18 | for (auto& yi: y) scanf("%d", &yi); 19 | 20 | auto f = [&](size_t j, size_t i) { 21 | intmax_t dx = x[j] - a[i-1]; 22 | intmax_t dy = y[j]; 23 | return std::abs(dx) + std::abs(dy); 24 | }; 25 | 26 | auto dp = online_to_offline_optimization(f, n+1); 27 | printf("%jd\n", dp[n]); 28 | } 29 | -------------------------------------------------------------------------------- /test/yc_705_onoff.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/705" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "algorithm/online_to_offline_optimization.cpp" 10 | 11 | int main() { 12 | size_t n; 13 | scanf("%zu", &n); 14 | 15 | std::vector a(n), x(n), y(n); 16 | for (auto& ai: a) scanf("%d", &ai); 17 | for (auto& xi: x) scanf("%d", &xi); 18 | for (auto& yi: y) scanf("%d", &yi); 19 | 20 | auto f = [&](size_t j, size_t i) { 21 | intmax_t dx = x[j] - a[i-1]; 22 | intmax_t dy = y[j]; 23 | return std::abs(dx)*dx*dx + std::abs(dy)*dy*dy; 24 | }; 25 | 26 | auto dp = online_to_offline_optimization(f, n+1); 27 | printf("%jd\n", dp[n]); 28 | } 29 | -------------------------------------------------------------------------------- /test/yc_752.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/752" 2 | 3 | #include 4 | #include 5 | 6 | #include "Math/remainder_sum.cpp" 7 | 8 | int main() { 9 | intmax_t p; 10 | int q; 11 | scanf("%jd %d", &p, &q); 12 | 13 | remainder_sum_table rs(p); 14 | for (int i = 0; i < q; ++i) { 15 | intmax_t l, r; 16 | scanf("%jd %jd", &l, &r); 17 | printf("%jd\n", rs(r) - rs(l-1)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/yc_878.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/878" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "DataStructure/basic_segment_tree.cpp" 8 | #include "DataStructure/wavelet_matrix.cpp" 9 | #include "utility/monoid/max.cpp" 10 | 11 | int main() { 12 | size_t n, q; 13 | scanf("%zu %zu", &n, &q); 14 | 15 | std::vector a(n); 16 | for (auto& ai: a) scanf("%d", &ai); 17 | 18 | basic_segment_tree> st(a.begin(), a.end()); 19 | 20 | std::vector top(n); 21 | for (size_t i = 0; i < n; ++i) { 22 | auto pred = [&](auto x) { return x.get() <= a[i]; }; 23 | top[i] = st.foldr_bisect(i+1, pred)+1; 24 | } 25 | 26 | wavelet_matrix<31> wm(top.begin(), top.end()); 27 | for (size_t i = 0; i < q; ++i) { 28 | size_t l, r; 29 | scanf(" 1 %zu %zu", &l, &r); 30 | --l, --r; 31 | printf("%zu\n", wm.rank_3way(l+1, l, r+1)[0]); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/yc_878_reversed.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://yukicoder.me/problems/no/878" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "DataStructure/basic_segment_tree.cpp" 8 | #include "DataStructure/wavelet_matrix.cpp" 9 | #include "utility/monoid/max.cpp" 10 | 11 | int main() { 12 | size_t n, q; 13 | scanf("%zu %zu", &n, &q); 14 | 15 | std::vector a(n); 16 | for (auto& ai: a) scanf("%d", &ai); 17 | std::reverse(a.begin(), a.end()); 18 | 19 | basic_segment_tree> st(a.begin(), a.end()); 20 | 21 | std::vector top(n); 22 | for (size_t i = 0; i < n; ++i) { 23 | auto pred = [&](auto x) { return x.get() <= a[i]; }; 24 | top[i] = st.foldl_bisect(i, pred); 25 | } 26 | 27 | wavelet_matrix<31> wm(top.begin(), top.end()); 28 | for (size_t i = 0; i < q; ++i) { 29 | size_t l, r; 30 | scanf(" 1 %zu %zu", &r, &l); 31 | --l, --r; 32 | l = n-1-l; 33 | r = n-1-r; 34 | printf("%zu\n", wm.rank_3way(r, l, r+1)[2]); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /test/yj_bipartitematching.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/bipartitematching" 2 | 3 | #include 4 | #include 5 | 6 | #include "Graph/capacitated_adjacency_list.cpp" 7 | #include "Graph/dinitz.cpp" 8 | 9 | int main() { 10 | size_t l, r, m; 11 | scanf("%zu %zu %zu", &l, &r, &m); 12 | 13 | adjacency_list, directed_tag> g(l+r+2); 14 | size_t source = l+r; 15 | size_t sink = source+1; 16 | for (size_t i = 0; i < m; ++i) { 17 | size_t a, b; 18 | scanf("%zu %zu", &a, &b); 19 | g.emplace(a, l+b, 1); 20 | } 21 | 22 | for (size_t i = 0; i < l; ++i) g.emplace(source, i, 1); 23 | for (size_t i = 0; i < r; ++i) g.emplace(l+i, sink, 1); 24 | 25 | printf("%d\n", max_flow(g, source, sink, dinitz)); 26 | 27 | for (size_t i = 0; i < l; ++i) { 28 | for (auto const& e: g[i]) { 29 | size_t j = e.target(); 30 | if (j == source) continue; 31 | if (e.capacity() == 0) printf("%zu %zu\n", i, j-l); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /test/yj_convolution_mod.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/convolution_mod" 2 | 3 | #include 4 | #include 5 | 6 | #include "ModularArithmetic/modint.cpp" 7 | #include "ModularArithmetic/polynomial.cpp" 8 | 9 | using mi = modint<998244353>; 10 | 11 | int main() { 12 | size_t n, m; 13 | scanf("%zu %zu", &n, &m); 14 | 15 | std::vector a(n), b(m); 16 | for (auto& ai: a) scanf("%d", &ai); 17 | for (auto& bi: b) scanf("%d", &bi); 18 | 19 | polynomial f(a.begin(), a.end()), g(b.begin(), b.end()); 20 | f *= g; 21 | 22 | for (size_t i = 0; i+1 < n+m; ++i) 23 | printf("%d%c", f[i].get(), i+2 4 | #include 5 | #include 6 | 7 | #include "ModularArithmetic/modint.cpp" 8 | #include "ModularArithmetic/polynomial.cpp" 9 | #include "ModularArithmetic/garner.cpp" 10 | 11 | constexpr intmax_t mod1 = 998244353; 12 | constexpr intmax_t mod2 = 469762049; 13 | constexpr intmax_t mod3 = 167772161; 14 | constexpr intmax_t mod = 1000000007; 15 | using mi1 = modint; 16 | using mi2 = modint; 17 | using mi3 = modint; 18 | using mi = modint; 19 | 20 | int main() { 21 | size_t n, m; 22 | scanf("%zu %zu", &n, &m); 23 | 24 | std::vector a(n), b(m); 25 | for (auto& ai: a) scanf("%d", &ai); 26 | for (auto& bi: b) scanf("%d", &bi); 27 | 28 | polynomial f1(a.begin(), a.end()), g1(b.begin(), b.end()); 29 | polynomial f2(a.begin(), a.end()), g2(b.begin(), b.end()); 30 | polynomial f3(a.begin(), a.end()), g3(b.begin(), b.end()); 31 | f1 *= g1; 32 | f2 *= g2; 33 | f3 *= g3; 34 | 35 | std::vector f(n+m-1); 36 | for (size_t i = 0; i+1 < n+m; ++i) { 37 | simultaneous_congruences_garner sc; 38 | sc.push(f1[i].get(), mod1); 39 | sc.push(f2[i].get(), mod2); 40 | sc.push(f3[i].get(), mod3); 41 | f[i] = sc.get(mod); 42 | } 43 | 44 | for (size_t i = 0; i+1 < n+m; ++i) 45 | printf("%d%c", f[i].get(), i+2 4 | #include 5 | 6 | #include "ModularArithmetic/modint.cpp" 7 | #include "ModularArithmetic/polynomial.cpp" 8 | 9 | using mi = modint<998244353>; 10 | 11 | int main() { 12 | size_t n; 13 | scanf("%zu", &n); 14 | 15 | std::vector a(n); 16 | for (auto& ai: a) scanf("%d", &ai); 17 | 18 | polynomial f(a.begin(), a.end()); 19 | polynomial g = f.inverse(n); 20 | 21 | for (size_t i = 0; i < n; ++i) 22 | printf("%d%c", g[i].get(), i+1 4 | 5 | #include "Graph/adjacency_list.cpp" 6 | #include "Graph/lowest_common_ancestor_squaring.cpp" 7 | 8 | int main() { 9 | size_t n, q; 10 | scanf("%zu %zu", &n, &q); 11 | 12 | adjacency_list, undirected_tag> g(n); 13 | for (size_t i = 1; i < n; ++i) { 14 | size_t p; 15 | scanf("%zu", &p); 16 | g.emplace(i, p, 1); 17 | } 18 | 19 | lowest_common_ancestor lca(g, 0); 20 | for (size_t i = 0; i < q; ++i) { 21 | size_t u, v; 22 | scanf("%zu %zu", &u, &v); 23 | printf("%zu\n", lca(u, v)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test/yj_line_add_get_min_li_chao_tree.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/line_add_get_min" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "DataStructure/li_chao_tree.cpp" 11 | 12 | int main() { 13 | size_t n, q; 14 | scanf("%zu %zu", &n, &q); 15 | 16 | std::vector> qs; 17 | qs.reserve(n+q); 18 | std::map enc; 19 | for (size_t i = 0; i < n; ++i) { 20 | intmax_t a, b; 21 | scanf("%jd %jd", &a, &b); 22 | qs.emplace_back(0, a, b); 23 | } 24 | for (size_t i = 0; i < q; ++i) { 25 | int t; 26 | scanf("%d", &t); 27 | if (t == 0) { 28 | intmax_t a, b; 29 | scanf("%jd %jd", &a, &b); 30 | qs.emplace_back(0, a, b); 31 | } else if (t == 1) { 32 | intmax_t p; 33 | scanf("%jd", &p); 34 | enc[p]; 35 | qs.emplace_back(1, p, 0); 36 | } 37 | } 38 | 39 | size_t m = 0; 40 | std::vector xs; 41 | xs.reserve(enc.size()); 42 | for (auto& [d, e]: enc) xs.push_back(d), e = m++; 43 | 44 | lower_linear_envelope lle(xs.begin(), xs.end()); 45 | for (auto [t, a, b]: qs) { 46 | if (t == 0) { 47 | lle.push(a, b); 48 | } else if (t == 1) { 49 | intmax_t y = lle.get_nth(enc.at(a)); 50 | printf("%jd\n", y); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /test/yj_log_of_formal_power_series.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/log_of_formal_power_series" 2 | 3 | #include 4 | #include 5 | 6 | #include "ModularArithmetic/modint.cpp" 7 | #include "ModularArithmetic/polynomial.cpp" 8 | #include "ModularArithmetic/operations.cpp" 9 | 10 | using mi = modint<998244353>; 11 | 12 | int main() { 13 | size_t n; 14 | scanf("%zu", &n); 15 | 16 | std::vector a(n); 17 | for (auto& ai: a) scanf("%d", &ai); 18 | 19 | polynomial f(a.begin(), a.end()); 20 | polynomial g = log(f); 21 | for (size_t i = 0; i < n; ++i) 22 | printf("%d%c", g[i].get(), i+1 4 | 5 | #include "utility/fast_io.cpp" 6 | 7 | int main() { 8 | unsigned t; 9 | cin.scan(t); 10 | 11 | while (t--) { 12 | uintmax_t a, b; 13 | cin.scan(a, b); 14 | cout.println(a+b); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /test/yj_multipoint_evaluation.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/multipoint_evaluation" 2 | 3 | #include 4 | #include 5 | 6 | #include "ModularArithmetic/modint.cpp" 7 | #include "ModularArithmetic/polynomial.cpp" 8 | 9 | using mi = modint<998244353>; 10 | 11 | int main() { 12 | size_t n, m; 13 | scanf("%zu %zu", &n, &m); 14 | 15 | std::vector c(n), p(m); 16 | for (auto& ci: c) scanf("%d", &ci); 17 | for (auto& pi: p) scanf("%d", &pi); 18 | 19 | polynomial f(c.begin(), c.end()); 20 | std::vector xs(p.begin(), p.end()); 21 | auto ys = f.multipoint_evaluate(xs); 22 | 23 | for (size_t i = 0; i < m; ++i) 24 | printf("%d%c", ys[i].get(), i+1 4 | #include 5 | #include 6 | #include 7 | 8 | #include "utility/make/fix_point.cpp" 9 | #include "DataStructure/rollbackable_disjoint_set.cpp" 10 | 11 | int main() { 12 | size_t n, q; 13 | scanf("%zu %zu", &n, &q); 14 | 15 | std::vector>> qs(q+1); 16 | for (size_t i = 0; i < q; ++i) { 17 | int t; 18 | size_t k, u, v; 19 | scanf("%d %zu %zu %zu", &t, &k, &u, &v); 20 | qs[k+1].emplace_back(t, i+1, u, v); 21 | } 22 | 23 | rollbackable_disjoint_set ds(n); 24 | std::vector res(q+1, -1); 25 | make_fix_point([&](auto&& dfs, size_t k) -> void { 26 | for (auto [t, i, u, v]: qs[k]) { 27 | if (t == 0) ds.unite(u, v); 28 | if (t == 1) res[i] = ds.equivalent(u, v); 29 | dfs(i); 30 | if (t == 0) ds.rollback(); 31 | } 32 | })(0); 33 | 34 | for (auto ri: res) 35 | if (ri != -1) printf("%d\n", ri); 36 | } 37 | -------------------------------------------------------------------------------- /test/yj_point_add_range_sum.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/point_add_range_sum" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "DataStructure/basic_segment_tree.cpp" 8 | 9 | int main() { 10 | size_t n, q; 11 | scanf("%zu %zu", &n, &q); 12 | 13 | std::vector a(n); 14 | for (auto& ai: a) scanf("%d", &ai); 15 | 16 | basic_segment_tree st(a.begin(), a.end()); 17 | for (size_t i = 0; i < q; ++i) { 18 | int t; 19 | scanf("%d", &t); 20 | 21 | if (t == 0) { 22 | size_t p; 23 | intmax_t x; 24 | scanf("%zu %jd", &p, &x); 25 | st.set(p, st[p]+x); 26 | } else if (t == 1) { 27 | size_t l, r; 28 | scanf("%zu %zu", &l, &r); 29 | printf("%jd\n", st.fold(l, r)); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test/yj_point_set_range_composite.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/point_set_range_composite" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "DataStructure/basic_segment_tree.cpp" 8 | #include "utility/monoid/composite.cpp" 9 | #include "ModularArithmetic/modint.cpp" 10 | 11 | constexpr intmax_t mod = 998244353; 12 | using mi = modint; 13 | 14 | int main() { 15 | size_t n, q; 16 | scanf("%zu %zu", &n, &q); 17 | 18 | std::vector> f(n); 19 | for (size_t i = 0; i < n; ++i) { 20 | int a, b; 21 | scanf("%d %d", &a, &b); 22 | f[i] = {a, b}; 23 | } 24 | 25 | basic_segment_tree> st(f.begin(), f.end()); 26 | for (size_t i = 0; i < q; ++i) { 27 | int t; 28 | scanf("%d", &t); 29 | 30 | if (t == 0) { 31 | size_t p; 32 | int c, d; 33 | scanf("%zu %d %d", &p, &c, &d); 34 | st.set(p, {c, d}); 35 | } else if (t == 1) { 36 | size_t l, r; 37 | intmax_t x; 38 | scanf("%zu %zu %jd", &l, &r, &x); 39 | printf("%d\n", st.fold(l, r)(x).get()); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /test/yj_polynomial_interpolation.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/polynomial_interpolation" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "ModularArithmetic/modint.cpp" 9 | #include "ModularArithmetic/polynomial.cpp" 10 | #include "ModularArithmetic/interpolation.cpp" 11 | 12 | constexpr intmax_t mod = 998244353; 13 | using mi = modint; 14 | 15 | int main() { 16 | size_t n; 17 | scanf("%zu", &n); 18 | 19 | std::vector x(n), y(n); 20 | for (auto& xi: x) scanf("%jd", &xi); 21 | for (auto& yi: y) scanf("%jd", &yi); 22 | 23 | std::vector xs(x.begin(), x.end()), ys(y.begin(), y.end()); 24 | auto f = interpolate(xs, ys); 25 | 26 | for (size_t i = 0; i < n; ++i) 27 | printf("%d%c", f[i].get(), i+1 4 | #include 5 | 6 | #include "utility/monoid/composite.cpp" 7 | #include "ModularArithmetic/modint.cpp" 8 | #include "DataStructure/foldable_queue.cpp" 9 | 10 | constexpr intmax_t mod = 998244353; 11 | using mi = modint; 12 | 13 | int main() { 14 | size_t q; 15 | scanf("%zu", &q); 16 | 17 | foldable_queue> fq; 18 | for (size_t i = 0; i < q; ++i) { 19 | int t; 20 | scanf("%d", &t); 21 | 22 | if (t == 0) { 23 | intmax_t a, b; 24 | scanf("%jd %jd", &a, &b); 25 | fq.emplace(a, b); 26 | } else if (t == 1) { 27 | fq.pop(); 28 | } else if (t == 2) { 29 | intmax_t x; 30 | scanf("%jd", &x); 31 | printf("%d\n", fq.fold()(x).get()); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /test/yj_range_affine_range_sum.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/range_affine_range_sum" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "DataStructure/segment_tree.cpp" 8 | #include "utility/action/affine_sum.cpp" 9 | #include "ModularArithmetic/modint.cpp" 10 | 11 | constexpr intmax_t mod = 998244353; 12 | using mi = modint; 13 | 14 | int main() { 15 | size_t n, q; 16 | scanf("%zu %zu", &n, &q); 17 | 18 | std::vector a(n); 19 | for (auto& ai: a) scanf("%jd", &ai); 20 | 21 | segment_tree> st(a.begin(), a.end()); 22 | 23 | for (size_t i = 0; i < q; ++i) { 24 | int t; 25 | scanf("%d", &t); 26 | 27 | if (t == 0) { 28 | size_t l, r; 29 | int b, c; 30 | scanf("%zu %zu %d %d", &l, &r, &b, &c); 31 | st.act(l, r, {b, c}); 32 | } else if (t == 1) { 33 | size_t l, r; 34 | scanf("%zu %zu", &l, &r); 35 | printf("%d\n", st.fold(l, r).get().get()); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /test/yj_range_kth_smallest.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/range_kth_smallest" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "DataStructure/wavelet_matrix.cpp" 8 | 9 | int main() { 10 | size_t n, q; 11 | scanf("%zu %zu", &n, &q); 12 | 13 | std::vector a(n); 14 | for (auto& ai: a) scanf("%ju", &ai); 15 | 16 | wavelet_matrix<32> wm(a.begin(), a.end()); 17 | for (size_t i = 0; i < q; ++i) { 18 | size_t l, r, k; 19 | scanf("%zu %zu %zu", &l, &r, &k); 20 | printf("%ju\n", wm.quantile(k, l, r)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test/yj_rectangle_sum.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/rectangle_sum" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "DataStructure/rectangle_query.cpp" 10 | 11 | int main() { 12 | size_t n, q; 13 | scanf("%zu %zu", &n, &q); 14 | 15 | std::vector> xyz(n); 16 | for (auto& [x, y, z]: xyz) 17 | scanf("%d %d %jd", &x, &y, &z); 18 | 19 | std::sort(xyz.begin(), xyz.end()); 20 | std::vector x(n), y(n); 21 | std::vector z(n); 22 | for (size_t i = 0; i < n; ++i) 23 | std::tie(x[i], y[i], z[i]) = xyz[i]; 24 | 25 | rectangle_query<30, intmax_t> rq(y.begin(), y.end(), z.begin(), z.end()); 26 | 27 | for (size_t i = 0; i < q; ++i) { 28 | int l, d, r, u; 29 | scanf("%d %d %d %d", &l, &d, &r, &u); 30 | size_t il = std::lower_bound(x.begin(), x.end(), l) - x.begin(); 31 | size_t ir = std::lower_bound(x.begin(), x.end(), r) - x.begin(); 32 | intmax_t res = rq.sum_within(il, ir, d, u-1); 33 | printf("%jd\n", res); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /test/yj_scc.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/scc" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "Graph/adjacency_list.cpp" 8 | #include "Graph/scc.cpp" 9 | 10 | int main() { 11 | size_t n, m; 12 | scanf("%zu %zu", &n, &m); 13 | 14 | adjacency_list, directed_tag> g(n); 15 | for (size_t i = 0; i < m; ++i) { 16 | size_t u, v; 17 | scanf("%zu %zu", &u, &v); 18 | g.emplace(u, v, 1); 19 | } 20 | 21 | auto scc = strongly_connected_components(g); 22 | size_t k = *std::max_element(scc.begin(), scc.end()) + 1; 23 | 24 | std::vector> ts(k); 25 | for (size_t i = 0; i < n; ++i) 26 | ts[scc[i]].push_back(i); 27 | 28 | printf("%zu\n", k); 29 | for (size_t i = 0; i < k; ++i) { 30 | printf("%zu", ts[i].size()); 31 | for (auto v: ts[i]) printf(" %zu", v); 32 | puts(""); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /test/yj_segment_add_get_min.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/segment_add_get_min" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "utility/limits.cpp" 11 | #include "DataStructure/li_chao_tree.cpp" 12 | 13 | int main() { 14 | size_t n, q; 15 | scanf("%zu %zu", &n, &q); 16 | 17 | std::vector> qs; 18 | qs.reserve(n+q); 19 | std::map enc; 20 | for (size_t i = 0; i < n; ++i) { 21 | intmax_t l, r, a, b; 22 | scanf("%jd %jd %jd %jd", &l, &r, &a, &b); 23 | qs.emplace_back(0, l, r, a, b); 24 | } 25 | for (size_t i = 0; i < q; ++i) { 26 | int t; 27 | scanf("%d", &t); 28 | if (t == 0) { 29 | intmax_t l, r, a, b; 30 | scanf("%jd %jd %jd %jd", &l, &r, &a, &b); 31 | qs.emplace_back(0, l, r, a, b); 32 | } else if (t == 1) { 33 | intmax_t p; 34 | scanf("%jd", &p); 35 | enc[p]; 36 | qs.emplace_back(1, p, 0, 0, 0); 37 | } 38 | } 39 | 40 | intmax_t const inf = limits::max(); 41 | enc[-inf], enc[inf]; 42 | 43 | size_t m = 0; 44 | std::vector xs; 45 | xs.reserve(enc.size()); 46 | for (auto& [d, e]: enc) xs.push_back(d), e = m++; 47 | 48 | lower_linear_envelope lle(xs.begin(), xs.end()); 49 | for (auto [t, l, r, a, b]: qs) { 50 | if (t == 0) { 51 | size_t il = enc.lower_bound(l)->second; 52 | size_t ir = enc.lower_bound(r)->second; 53 | lle.push(a, b, il, ir); 54 | } else if (t == 1) { 55 | intmax_t y = lle.get_nth(enc.at(l)); 56 | if (y == inf) { 57 | puts("INFINITY"); 58 | } else { 59 | printf("%jd\n", y); 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /test/yj_static_range_sum.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/static_range_sum" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "DataStructure/basic_segment_tree.cpp" 8 | 9 | int main() { 10 | size_t n, q; 11 | scanf("%zu %zu", &n, &q); 12 | 13 | std::vector a(n); 14 | for (auto& ai: a) scanf("%jd", &ai); 15 | 16 | basic_segment_tree st(a.begin(), a.end()); 17 | for (size_t i = 0; i < q; ++i) { 18 | size_t l, r; 19 | scanf("%zu %zu", &l, &r); 20 | printf("%jd\n", st.fold(l, r)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test/yj_staticrmq.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/staticrmq" 2 | 3 | #include 4 | #include 5 | 6 | #include "DataStructure/basic_segment_tree.cpp" 7 | #include "utility/monoid/min.cpp" 8 | 9 | int main() { 10 | size_t n, q; 11 | scanf("%zu %zu", &n, &q); 12 | 13 | std::vector a(n); 14 | for (auto& ai: a) scanf("%d", &ai); 15 | 16 | basic_segment_tree> st(a.begin(), a.end()); 17 | for (size_t i = 0; i < q; ++i) { 18 | size_t l, r; 19 | scanf("%zu %zu", &l, &r); 20 | printf("%d\n", st.fold(l, r).get()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test/yj_suffixarray.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/suffixarray" 2 | 3 | #include 4 | #include 5 | 6 | #include "String/sa_is.cpp" 7 | 8 | int main() { 9 | char buf[524288]; 10 | scanf("%s", buf); 11 | std::string s = buf; 12 | 13 | size_t n = s.length(); 14 | suffix_array sa(s.begin(), s.end()); 15 | for (size_t i = 1; i <= n; ++i) 16 | printf("%zu%c", sa[i], i 4 | #include 5 | #include 6 | #include 7 | 8 | #include "Graph/two_sat.cpp" 9 | 10 | int main() { 11 | size_t n, m; 12 | scanf("p cnf %zu %zu", &n, &m); 13 | 14 | two_sat ts(n); 15 | for (size_t i = 0; i < m; ++i) { 16 | int a, b; 17 | scanf("%d %d 0", &a, &b); 18 | bool pa = (a > 0); 19 | bool pb = (b > 0); 20 | a = (pa? a: -a) - 1; 21 | b = (pb? b: -b) - 1; 22 | ts.push(a, pa, b, pb); 23 | } 24 | 25 | if (!ts.satisfiable()) 26 | return puts("s UNSATISFIABLE"), 0; 27 | 28 | puts("s SATISFIABLE"); 29 | printf("v"); 30 | for (size_t i = 0; i < n; ++i) { 31 | printf(" %s%zu", ts[i]? "": "-", i+1); 32 | } 33 | puts(" 0"); 34 | } 35 | -------------------------------------------------------------------------------- /test/yj_unionfind.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/unionfind" 2 | 3 | #include 4 | 5 | #include "DataStructure/disjoint_set.cpp" 6 | 7 | int main() { 8 | size_t n, q; 9 | scanf("%zu %zu", &n, &q); 10 | 11 | disjoint_set ds(n); 12 | for (size_t i = 0; i < q; ++i) { 13 | int t; 14 | size_t u, v; 15 | scanf("%d %zu %zu", &t, &u, &v); 16 | 17 | if (t == 0) { 18 | ds.unite(u, v); 19 | } else if (t == 1) { 20 | printf("%d\n", ds.equivalent(u, v)? 1: 0); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test/yj_vertex_add_path_sum.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/vertex_add_path_sum" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "Graph/hl_decomposition.cpp" 9 | #include "DataStructure/basic_segment_tree.cpp" 10 | 11 | int main() { 12 | size_t n, q; 13 | scanf("%zu %zu", &n, &q); 14 | 15 | std::vector a(n); 16 | for (auto& ai: a) scanf("%jd", &ai); 17 | 18 | std::vector> es; 19 | es.reserve(n-1); 20 | for (size_t i = 1; i < n; ++i) { 21 | size_t u, v; 22 | scanf("%zu %zu", &u, &v); 23 | es.emplace_back(u, v); 24 | } 25 | 26 | hl_decomposed_tree, value_on_vertex_tag> g(a, es); 27 | for (size_t i = 0; i < q; ++i) { 28 | int t; 29 | scanf("%d", &t); 30 | 31 | if (t == 0) { 32 | size_t p; 33 | intmax_t x; 34 | scanf("%zu %jd", &p, &x); 35 | a[p] += x; 36 | g.set(p, a[p]); 37 | } else if (t == 1) { 38 | size_t u, v; 39 | scanf("%zu %zu", &u, &v); 40 | printf("%jd\n", g.fold(u, v)); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /test/yj_vertex_set_path_composite.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/vertex_set_path_composite" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "Graph/hl_decomposition.cpp" 9 | #include "DataStructure/basic_segment_tree.cpp" 10 | #include "ModularArithmetic/modint.cpp" 11 | #include "utility/monoid/composite.cpp" 12 | 13 | constexpr intmax_t mod = 998244353; 14 | using mi = modint; 15 | 16 | int main() { 17 | size_t n, q; 18 | scanf("%zu %zu", &n, &q); 19 | 20 | std::vector> f(n); 21 | for (auto& fi: f) { 22 | int a, b; 23 | scanf("%d %d", &a, &b); 24 | fi = {a, b}; 25 | } 26 | 27 | std::vector> es; 28 | es.reserve(n-1); 29 | for (size_t i = 1; i < n; ++i) { 30 | size_t u, v; 31 | scanf("%zu %zu", &u, &v); 32 | es.emplace_back(u, v); 33 | } 34 | 35 | hl_decomposed_tree>, value_on_vertex_tag> g(f, es); 36 | for (size_t i = 0; i < q; ++i) { 37 | int t; 38 | scanf("%d", &t); 39 | 40 | if (t == 0) { 41 | size_t p; 42 | int c, d; 43 | scanf("%zu %d %d", &p, &c, &d); 44 | f[p] = {c, d}; 45 | g.set(p, f[p]); 46 | } else if (t == 1) { 47 | size_t u, v; 48 | int x; 49 | scanf("%zu %zu %d", &u, &v, &x); 50 | printf("%d\n", g.fold(u, v)(x).get()); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /test/yj_zalgorithm.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/zalgorithm" 2 | 3 | #include 4 | #include 5 | 6 | #include "String/z_algorithm.cpp" 7 | 8 | int main() { 9 | char buf[524288]; 10 | scanf("%s", buf); 11 | std::string s = buf; 12 | size_t n = s.length(); 13 | 14 | z_array z(s.begin(), s.end()); 15 | for (size_t i = 0; i < n; ++i) 16 | printf("%zu%c", z[i], i+1 12 | struct action_add_to_max { 13 | using operand_type = max_monoid; 14 | using action_type = Tp; 15 | 16 | static void act(operand_type& op, action_type const& a) { 17 | op = operand_type(std::move(op).get() + a); 18 | } 19 | }; 20 | 21 | #endif /* !defined(H_action_add_max) */ 22 | -------------------------------------------------------------------------------- /utility/action/add_min.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_action_add_min 2 | #define H_action_add_min 3 | 4 | /** 5 | * @brief 区間最小値・区間加算用のヘルパークラス 6 | * @author えびちゃん 7 | */ 8 | 9 | #include "utility/monoid/min.cpp" 10 | 11 | template 12 | struct action_add_to_min { 13 | using operand_type = min_monoid; 14 | using action_type = Tp; 15 | 16 | static void act(operand_type& op, action_type const& a) { 17 | op = operand_type(std::move(op).get() + a); 18 | } 19 | }; 20 | 21 | #endif /* !defined(H_action_add_min) */ 22 | -------------------------------------------------------------------------------- /utility/action/add_sum.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_action_add_sum 2 | #define H_action_add_sum 3 | 4 | /** 5 | * @brief 区間和・区間加算用のヘルパークラス 6 | * @author えびちゃん 7 | */ 8 | 9 | #include "utility/monoid/length.cpp" 10 | 11 | template 12 | struct action_add_to_sum { 13 | using operand_type = length_monoid; 14 | using action_type = Tp; 15 | 16 | static void act(operand_type& op, action_type const& a) { 17 | op += operand_type(a * op.length(), 0); 18 | } 19 | }; 20 | 21 | #endif /* !defined(H_action_add_sum) */ 22 | -------------------------------------------------------------------------------- /utility/action/affine_sum.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_action_affine_sum 2 | #define H_action_affine_sum 3 | 4 | /** 5 | * @brief 区間 Affine 変換・区間加算用のヘルパークラス 6 | * @author えびちゃん 7 | */ 8 | 9 | #include "utility/monoid/composite.cpp" 10 | #include "utility/monoid/length.cpp" 11 | 12 | #include 13 | 14 | template 15 | struct action_affine_to_sum { 16 | using operand_type = length_monoid; 17 | using action_type = composite_monoid; 18 | 19 | static void act(operand_type& op, action_type const& f) { 20 | auto [a, b] = f.get(); 21 | op = operand_type(a * op.get() + op.length() * b, op.length()); 22 | } 23 | }; 24 | 25 | #endif /* !defined(H_action_affine_sum) */ 26 | -------------------------------------------------------------------------------- /utility/action/min_min.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_action_min_min 2 | #define H_action_min_min 3 | 4 | /** 5 | * @brief 区間最小値・区間最小値更新用のヘルパークラス 6 | * @author えびちゃん 7 | */ 8 | 9 | #include "utility/monoid/min.cpp" 10 | 11 | template 12 | struct action_min_to_min { 13 | using operand_type = min_monoid; 14 | using action_type = min_monoid; 15 | 16 | static void act(operand_type& op, action_type const& a) { 17 | op += a; 18 | } 19 | }; 20 | 21 | #endif /* !defined(H_action_min_min) */ 22 | -------------------------------------------------------------------------------- /utility/action/set_sum.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_action_set_sum 2 | #define H_action_set_sum 3 | 4 | /** 5 | * @brief 区間和・区間代入用のヘルパークラス 6 | * @author えびちゃん 7 | */ 8 | 9 | #include "utility/monoid/length.cpp" 10 | #include "utility/monoid/set.cpp" 11 | 12 | template 13 | struct action_set_to_sum { 14 | using operand_type = length_monoid; 15 | using action_type = set_monoid; 16 | 17 | static void act(operand_type& op, action_type const& a) { 18 | if (a.empty()) return; 19 | op = operand_type(a.get() * op.length(), op.length()); 20 | } 21 | }; 22 | 23 | #endif /* !defined(H_action_set_sum) */ 24 | -------------------------------------------------------------------------------- /utility/four_neighbor.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_four_neighbor 2 | #define H_four_neighbor 3 | 4 | /** 5 | * @brief 4-近傍 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "utility/literals.cpp" 14 | 15 | constexpr std::array, 4> dij4{ 16 | {{-1_zu, 0}, {0, -1_zu}, {1, 0}, {0, 1}} 17 | }; 18 | 19 | #endif /* !defined(H_four_neighbor) */ 20 | -------------------------------------------------------------------------------- /utility/limits.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_limits 2 | #define H_limits 3 | 4 | /** 5 | * @brief 型依存の定数 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | template 13 | class limits: public std::numeric_limits {}; 14 | 15 | template 16 | class limits> { 17 | public: 18 | static constexpr auto min() { 19 | return std::make_pair(limits::min(), limits::min()); 20 | } 21 | static constexpr auto max() { 22 | return std::make_pair(limits::max(), limits::max()); 23 | } 24 | }; 25 | 26 | #endif /* !defined(H_limits) */ 27 | -------------------------------------------------------------------------------- /utility/literals.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_int_literals 2 | #define H_int_literals 3 | 4 | /** 5 | * @brief ユーザ定義リテラル 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | constexpr intmax_t operator ""_jd(unsigned long long n) { return n; } 13 | constexpr uintmax_t operator ""_ju(unsigned long long n) { return n; } 14 | constexpr size_t operator ""_zu(unsigned long long n) { return n; } 15 | constexpr ptrdiff_t operator ""_td(unsigned long long n) { return n; } 16 | 17 | constexpr int8_t operator ""_i8(unsigned long long n) { return n; } 18 | constexpr int16_t operator ""_i16(unsigned long long n) { return n; } 19 | constexpr int32_t operator ""_i32(unsigned long long n) { return n; } 20 | constexpr int64_t operator ""_i64(unsigned long long n) { return n; } 21 | constexpr uint8_t operator ""_u8(unsigned long long n) { return n; } 22 | constexpr uint16_t operator ""_u16(unsigned long long n) { return n; } 23 | constexpr uint32_t operator ""_u32(unsigned long long n) { return n; } 24 | constexpr uint64_t operator ""_u64(unsigned long long n) { return n; } 25 | 26 | #endif /* !defined(H_int_literals) */ 27 | -------------------------------------------------------------------------------- /utility/macro/assert_eq.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_assert_eq 2 | #define H_assert_eq 3 | 4 | /** 5 | * @brief 等値判定のテスト用マクロ 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #define assert_eq(expr, expected_) do { \ 14 | auto found = (expr); \ 15 | auto expected = (expected_); \ 16 | std::cerr << std::setw(64) << std::setfill('-') << "\n"; \ 17 | std::cerr << "expr: " << #expr << '\n'; \ 18 | std::cerr << "expected: " << expected << '\n'; \ 19 | std::cerr << "found: "; \ 20 | std::cerr << ((found != expected)? "\x1b[1;91m": "\x1b[1;92m"); \ 21 | std::cerr << found << "\x1b[m" << '\n'; \ 22 | std::cerr << std::setw(64) << std::setfill('-') << "\n"; \ 23 | assert(found == expected); \ 24 | } while (false) 25 | 26 | #endif /* !defined(H_assert_eq) */ 27 | -------------------------------------------------------------------------------- /utility/macro/stack_extend.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_stack_extend 2 | #define H_stack_extend 3 | 4 | /** 5 | * @brief スタック拡張マクロ(魔法) 6 | * @author えびちゃん 7 | * @see http://sigma425.hatenablog.com/entry/2016/03/26/221844 8 | */ 9 | 10 | #include 11 | 12 | #define BEGIN_STACK_EXTEND(size) \ 13 | void* stack_extend_memory_ = malloc(size); \ 14 | void* stack_extend_origin_memory_; \ 15 | char* stack_extend_dummy_memory_ = (char*)alloca((1+(int)(((long long)stack_extend_memory_)&127))*16); \ 16 | *stack_extend_dummy_memory_ = 0; \ 17 | asm volatile ("mov %%rsp, %%rbx\n\tmov %%rax, %%rsp":"=b"(stack_extend_origin_memory_):"a"((char*)stack_extend_memory_+(size)-1024)); 18 | 19 | #define END_STACK_EXTEND \ 20 | asm volatile ("mov %%rax, %%rsp"::"a"(stack_extend_origin_memory_)); \ 21 | free(stack_extend_memory_); 22 | 23 | #endif /* !defined(H_stack_extend) */ 24 | -------------------------------------------------------------------------------- /utility/make/fix_point.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief ラムダ式の再帰 3 | * @author えびちゃん 4 | */ 5 | 6 | #ifndef H_make_fix_point 7 | #define H_make_fix_point 8 | 9 | #include 10 | 11 | template 12 | class fix_point: Fn { 13 | public: 14 | explicit constexpr fix_point(Fn&& f) noexcept: Fn(std::forward(f)) {} 15 | 16 | template 17 | constexpr decltype(auto) operator ()(Args&&... args) const { 18 | return Fn::operator ()(*this, std::forward(args)...); 19 | } 20 | }; 21 | 22 | template 23 | static inline constexpr decltype(auto) make_fix_point(Fn&& f) noexcept { 24 | return fix_point{std::forward(f)}; 25 | } 26 | 27 | #endif /* !defined(H_make_fix_point) */ 28 | -------------------------------------------------------------------------------- /utility/make/pre17/vector.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief 多次元 vector の作成 3 | * @author えびちゃん 4 | */ 5 | 6 | #ifndef H_make_vector 7 | #define H_make_vector 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace detail { 14 | template 15 | std::vector make_vector( 16 | std::vector& sizes, 17 | typename std::enable_if<(N == 1), Tp const&>::type x 18 | ) { 19 | return std::vector(sizes[0], x); 20 | } 21 | template 22 | auto make_vector( 23 | std::vector& sizes, 24 | typename std::enable_if<(N > 1), Tp const&>::type x 25 | ) { 26 | size_t size = sizes[N-1]; 27 | sizes.pop_back(); 28 | return std::vector(sizes, x))>( 29 | size, make_vector(sizes, x) 30 | ); 31 | } 32 | } // detail:: 33 | 34 | template 35 | auto make_vector(size_t const(&sizes)[N], Tp const& x = Tp()) { 36 | std::vector s(N); 37 | for (size_t i = 0; i < N; ++i) s[i] = sizes[N-i-1]; 38 | return detail::make_vector(s, x); 39 | } 40 | 41 | #endif /* !defined(H_make_vector) */ 42 | -------------------------------------------------------------------------------- /utility/make/vector.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_make_vector 2 | #define H_make_vector 3 | 4 | /** 5 | * @brief 多次元 vector の作成 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace detail { 14 | template 15 | auto make_vector(std::vector& sizes, Tp const& x) { 16 | if constexpr (Nb == 1) { 17 | return std::vector(sizes[0], x); 18 | } else { 19 | size_t size = sizes[Nb-1]; 20 | sizes.pop_back(); 21 | return std::vector(size, make_vector(sizes, x)); 22 | } 23 | } 24 | } // detail:: 25 | 26 | template 27 | auto make_vector(size_t const(&sizes)[Nb], Tp const& x = Tp()) { 28 | std::vector s(Nb); 29 | for (size_t i = 0; i < Nb; ++i) s[i] = sizes[Nb-i-1]; 30 | return detail::make_vector(s, x); 31 | } 32 | 33 | #endif /* !defined(H_make_vector) */ 34 | -------------------------------------------------------------------------------- /utility/monoid/composite.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief 一次関数の合成を得る演算のモノイド 3 | * @author えびちゃん 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | #ifndef H_composite_monoid 10 | #define H_composite_monoid 11 | 12 | template 13 | class composite_monoid { 14 | public: 15 | using value_type = Tp; 16 | 17 | private: 18 | value_type M_a = 1; 19 | value_type M_b = 0; 20 | 21 | public: 22 | composite_monoid() = default; // identity 23 | 24 | composite_monoid(value_type a, value_type b): M_a(a), M_b(b) {}; 25 | 26 | composite_monoid& operator +=(composite_monoid that) { 27 | M_a *= that.M_a; 28 | M_b *= that.M_a; 29 | M_b += that.M_b; 30 | return *this; 31 | } 32 | 33 | composite_monoid operator +(composite_monoid const& that) const { 34 | return composite_monoid(*this) += that; 35 | } 36 | composite_monoid operator +(composite_monoid&& that) const { 37 | return composite_monoid(*this) += std::move(that); 38 | } 39 | 40 | bool operator ==(composite_monoid const& that) const { 41 | return (M_a == that.M_a && M_b == that.M_b); 42 | } 43 | bool operator !=(composite_monoid const& that) const { return !(*this == that); } 44 | 45 | auto get() const { return std::make_pair(M_a, M_b); } 46 | value_type operator ()(value_type x) const { return M_a * x + M_b; } 47 | }; 48 | 49 | #endif /* !defined(H_composite_monoid) */ 50 | -------------------------------------------------------------------------------- /utility/monoid/gcd.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_gcd_monoid 2 | #define H_gcd_monoid 3 | 4 | /** 5 | * @brief 最大公約数を得る演算のモノイド 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | 11 | template 12 | class gcd_monoid { 13 | public: 14 | using value_type = Tp; 15 | 16 | private: 17 | value_type M_x = 0; 18 | 19 | static constexpr value_type S_gcd(value_type x, value_type y) { 20 | while (y) std::swap(x %= y, y); 21 | return x; 22 | } 23 | 24 | public: 25 | gcd_monoid() = default; // identity 26 | 27 | gcd_monoid(value_type const& x): M_x(x) {} 28 | 29 | gcd_monoid& operator +=(gcd_monoid const& that) { 30 | M_x = S_gcd(M_x, that.M_x); 31 | return *this; 32 | } 33 | friend bool operator ==(gcd_monoid const& lhs, gcd_monoid const& rhs) { 34 | return lhs.M_x == rhs.m_x; 35 | } 36 | 37 | friend gcd_monoid operator +(gcd_monoid lhs, gcd_monoid const& rhs) { return lhs += rhs; } 38 | friend bool operator !=(gcd_monoid const& lhs, gcd_monoid const& rhs) { 39 | return !(lhs == rhs); 40 | } 41 | 42 | value_type const& get() const { return M_x; } 43 | }; 44 | 45 | #endif /* !defined(H_gcd_monoid) */ 46 | -------------------------------------------------------------------------------- /utility/monoid/length.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief 和と長さを得る演算のモノイド 3 | * @author えびちゃん 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | #ifndef H_length_monoid 10 | #define H_length_monoid 11 | 12 | template 13 | class length_monoid { 14 | public: 15 | using value_type = Tp; 16 | using size_type = size_t; 17 | 18 | private: 19 | value_type M_x{}; 20 | size_type M_l = 1; 21 | 22 | public: 23 | length_monoid() = default; // identity 24 | 25 | length_monoid(value_type const& x, size_type l = 1): M_x(x), M_l(l) {}; 26 | length_monoid(value_type&& x, size_type l = 1): M_x(std::move(x)), M_l(l) {}; 27 | 28 | length_monoid& operator +=(length_monoid const& that) { 29 | M_x += that.M_x; 30 | M_l += that.M_l; 31 | return *this; 32 | } 33 | length_monoid& operator +=(length_monoid&& that) { 34 | M_x += std::move(that.M_x); 35 | M_l += that.M_l; 36 | return *this; 37 | } 38 | 39 | length_monoid operator +(length_monoid const& that) const { 40 | return length_monoid(*this) += that; 41 | } 42 | length_monoid operator +(length_monoid&& that) const { 43 | return length_monoid(*this) += std::move(that); 44 | } 45 | 46 | value_type const& get() const { return M_x; } 47 | size_type length() const { return M_l; } 48 | }; 49 | 50 | #endif /* !defined(H_length_monoid) */ 51 | -------------------------------------------------------------------------------- /utility/monoid/max.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_max_monoid 2 | #define H_max_monoid 3 | 4 | /** 5 | * @brief max を得る演算のモノイド 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include "utility/limits.cpp" 13 | 14 | template 15 | class max_monoid { 16 | public: 17 | using value_type = Tp; 18 | 19 | private: 20 | value_type M_x = limits::min(); 21 | 22 | public: 23 | max_monoid() = default; // identity 24 | max_monoid(max_monoid const&) = default; 25 | max_monoid(max_monoid&&) = default; 26 | 27 | max_monoid(value_type const& x): M_x(x) {}; 28 | max_monoid(value_type&& x): M_x(std::move(x)) {}; 29 | 30 | max_monoid& operator =(max_monoid const&) = default; 31 | max_monoid& operator =(max_monoid&&) = default; 32 | 33 | max_monoid& operator +=(max_monoid const& that) { 34 | M_x = std::max(M_x, that.M_x); 35 | return *this; 36 | } 37 | max_monoid& operator +=(max_monoid&& that) { 38 | M_x = std::max(M_x, std::move(that.M_x)); 39 | return *this; 40 | } 41 | 42 | max_monoid operator +(max_monoid const& that) const { 43 | return max_monoid(*this) += that; 44 | } 45 | max_monoid operator +(max_monoid&& that) const { 46 | return max_monoid(*this) += std::move(that); 47 | } 48 | 49 | value_type const& get() const { return M_x; } 50 | }; 51 | 52 | #endif /* !defined(H_max_monoid) */ 53 | -------------------------------------------------------------------------------- /utility/monoid/max_subsum.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_max_subsum_monoid 2 | #define H_max_subsum_monoid 3 | 4 | /** 5 | * @brief 部分和の最大値を得る演算のモノイドクラス 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | template 13 | class max_subsum_monoid { 14 | public: 15 | using size_type = size_t; 16 | using value_type = Tp; 17 | 18 | private: 19 | value_type M_pre = 0, M_suf = 0, M_sub = 0, M_whole = 0; 20 | size_type M_length = 0; 21 | 22 | public: 23 | max_subsum_monoid() = default; // identity 24 | 25 | max_subsum_monoid(value_type const& x): 26 | M_pre(x), M_suf(x), M_sub(x), M_whole(x), M_length(1) {} 27 | 28 | max_subsum_monoid(value_type const& x, value_type n): 29 | M_pre(x*n), M_suf(x*n), M_sub(x*n), M_whole(x*n), M_length(n) 30 | { 31 | if (x < 0) M_pre = M_suf = M_sub = x; 32 | } 33 | 34 | max_subsum_monoid& operator +=(max_subsum_monoid const& that) { 35 | if (that.M_length == 0) return *this; 36 | if (M_length == 0) return (*this = that); 37 | M_sub = std::max({M_sub, M_suf + that.M_pre, that.M_sub}); 38 | M_suf = std::max(M_suf + that.M_whole, that.M_suf); 39 | M_pre = std::max(M_pre, M_whole + that.M_pre); 40 | M_whole += that.M_whole; 41 | M_length += that.M_length; 42 | return *this; 43 | } 44 | friend bool operator ==(max_subsum_monoid const& lhs, max_subsum_monoid const& rhs) { 45 | if (lhs.M_length == 0 && rhs.M_length == 0) return true; 46 | return ( 47 | lhs.M_length == rhs.M_length 48 | && lhs.M_pre == rhs.M_pre 49 | && lhs.M_suf == rhs.M_suf 50 | && lhs.M_sub == rhs.M_sub 51 | && lhs.M_whole == rhs.M_whole 52 | ); 53 | } 54 | 55 | friend max_subsum_monoid operator +(max_subsum_monoid lhs, max_subsum_monoid const& rhs) { 56 | return lhs += rhs; 57 | } 58 | friend bool operator !=(max_subsum_monoid const& lhs, max_subsum_monoid const& rhs) { 59 | return !(lhs == rhs); 60 | } 61 | 62 | size_type length() const noexcept { return M_length; } 63 | value_type const& get() const { return M_sub; } 64 | }; 65 | 66 | #endif /* !defined(H_max_subsum_monoid) */ 67 | -------------------------------------------------------------------------------- /utility/monoid/min.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_min_monoid 2 | #define H_min_monoid 3 | 4 | /** 5 | * @brief min を得る演算のモノイド 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include "utility/limits.cpp" 13 | 14 | template 15 | class min_monoid { 16 | public: 17 | using value_type = Tp; 18 | 19 | private: 20 | value_type M_x = limits::max(); 21 | 22 | public: 23 | min_monoid() = default; // identity 24 | 25 | min_monoid(value_type const& x): M_x(x) {} 26 | 27 | min_monoid& operator +=(min_monoid const& that) { 28 | M_x = std::min(M_x, that.M_x); 29 | return *this; 30 | } 31 | friend bool operator ==(min_monoid const& lhs, min_monoid const& rhs) { 32 | return lhs.M_x == rhs.M_x; 33 | } 34 | 35 | friend min_monoid operator +(min_monoid lhs, min_monoid const& rhs) { 36 | return lhs += rhs; 37 | } 38 | friend bool operator !=(min_monoid const& lhs, min_monoid const& rhs) { 39 | return !(lhs == rhs); 40 | } 41 | 42 | value_type const& get() const { return M_x; } 43 | }; 44 | 45 | #endif /* !defined(H_min_monoid) */ 46 | -------------------------------------------------------------------------------- /utility/monoid/rolling_hash.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_rolling_hash_monoid 2 | #define H_rolling_hash_monoid 3 | 4 | /** 5 | * @brief ロリハの演算のモノイド 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | 11 | template 12 | class rolling_hash_monoid { 13 | public: 14 | using value_type = ModInt; 15 | 16 | private: 17 | value_type M_x = 0, M_p = 1; 18 | 19 | public: 20 | rolling_hash_monoid() = default; // identity 21 | 22 | rolling_hash_monoid(value_type const& x, value_type const& p): M_x(x), M_p(p) {}; 23 | 24 | rolling_hash_monoid& operator +=(rolling_hash_monoid const& that) { 25 | M_x = M_x * that.M_p + that.M_x; 26 | M_p *= that.M_p; 27 | return *this; 28 | } 29 | friend bool operator ==(rolling_hash_monoid const& lhs, rolling_hash_monoid const& rhs) { 30 | return lhs.M_x == rhs.M_x && lhs.M_p == rhs.M_p; 31 | } 32 | 33 | friend rolling_hash_monoid operator +(rolling_hash_monoid lhs, rolling_hash_monoid const& rhs) { 34 | return lhs += rhs; 35 | } 36 | friend bool operator !=(rolling_hash_monoid const& lhs, rolling_hash_monoid const& rhs) { 37 | return !(lhs == rhs); 38 | } 39 | 40 | value_type const& get() const { return M_x; } 41 | value_type const& coefficient() const { return M_p; } 42 | }; 43 | 44 | #endif /* !defined(H_rolling_hash_monoid) */ 45 | -------------------------------------------------------------------------------- /utility/monoid/set.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_set_monoid 2 | #define H_set_monoid 3 | 4 | /** 5 | * @brief モノイドクラス 6 | * @author えびちゃん 7 | */ 8 | 9 | template 10 | class set_monoid { 11 | public: 12 | using value_type = Tp; 13 | 14 | private: 15 | bool M_empty = true; 16 | value_type M_x; 17 | 18 | public: 19 | set_monoid() = default; // identity 20 | 21 | set_monoid(value_type const& x): M_empty(false), M_x(x) {} 22 | 23 | set_monoid& operator +=(set_monoid const& that) { 24 | M_empty = that.M_empty; 25 | if (!that.M_empty) M_x = that.M_x; 26 | return *this; 27 | } 28 | friend bool operator ==(set_monoid const& lhs, set_monoid const& rhs) { 29 | if (lhs.M_empty && rhs.M_empty) return true; 30 | if (lhs.M_empty != rhs.M_empty) return false; 31 | return lhs.M_x == rhs.M_x; 32 | } 33 | 34 | friend set_monoid operator +(set_monoid lhs, set_monoid const& rhs) { return lhs += rhs; } 35 | friend bool operator !=(set_monoid const& lhs, set_monoid const& rhs) { 36 | return !(lhs == rhs); 37 | } 38 | 39 | bool empty() const noexcept { return M_empty; } 40 | value_type const& get() const { return M_x; } 41 | }; 42 | 43 | #endif /* !defined(H_set_monoid) */ 44 | -------------------------------------------------------------------------------- /utility/set_if.cpp: -------------------------------------------------------------------------------- 1 | #ifndef H_set_if 2 | #define H_set_if 3 | 4 | /** 5 | * @brief 条件つき代入 6 | * @author えびちゃん 7 | */ 8 | 9 | #include 10 | 11 | template 12 | bool set_if_less(Tp& dst, Tp const& src) { 13 | if (src < dst) return (dst = src), true; 14 | return false; 15 | } 16 | 17 | template 18 | bool set_if_greater(Tp& dst, Tp const& src) { 19 | if (dst < src) return (dst = src), true; 20 | return false; 21 | } 22 | 23 | #endif /* !defined(H_set_if) */ 24 | --------------------------------------------------------------------------------