From 26d8ff99e3aa97c3bd1fbdf84c2f3606be1338f7 Mon Sep 17 00:00:00 2001 From: github-actions <160645609+programming-team-code@users.noreply.github.com> Date: Mon, 8 Sep 2025 02:02:20 +0000 Subject: [PATCH] programming_team_code --- .../workflows/programming_team_code_ci.yml | 151 ---------- .gitmodules | 9 - .verify-helper/config.toml | 14 - .verify-helper/timestamps.remote.json | 145 ---------- {library/contest => contest}/README.md | 0 .../contest => contest}/binary_search.hpp | 5 +- {library/contest => contest}/hash.sh | 0 {library/contest => contest}/random.hpp | 1 - {library/contest => contest}/template.cpp | 0 {library/contest => contest}/tester.sh | 0 .../gcd_convolution.hpp | 10 +- .../lcm_convolution.hpp | 12 +- ..._plus_convolution_convex_and_arbitrary.hpp | 13 +- .../README.md | 0 .../binary_trie.hpp | 15 +- data_structures/bit.hpp | 33 +++ data_structures/bit_inc.hpp | 33 +++ .../bit_uncommon/next.hpp | 0 .../bit_uncommon/prev.hpp | 0 data_structures/bit_uncommon/rupq.hpp | 53 ++++ data_structures/bit_uncommon/rurq.hpp | 70 +++++ .../bit_uncommon/vector_constructor.hpp | 6 + .../bit_uncommon/walk.hpp | 4 +- .../dsu/dsu.hpp | 4 +- .../dsu/dsu_bipartite.hpp | 3 +- .../dsu/dsu_restorable.hpp | 7 +- .../dsu/kruskal_tree.hpp | 5 +- .../dsu/line_tree.hpp | 7 +- .../dsu/range_parallel_dsu.hpp | 27 +- .../range_parallel_equivalence_classes.hpp | 40 +++ data_structures/lazy_seg_tree.hpp | 162 +++++++++++ .../lazy_seg_tree.png | Bin .../lazy_seg_tree_inc.hpp | 34 ++- .../lazy_seg_tree_inc_midpoint.hpp | 1 - .../lazy_seg_tree_midpoint.hpp | 1 - .../rmq.hpp | 6 +- .../rmq_inc.hpp | 5 +- .../seg_tree.hpp | 1 - .../seg_tree.png | Bin .../seg_tree_inc.hpp | 1 - .../seg_tree_uncommon/distinct_query.hpp | 78 +++++ .../seg_tree_uncommon/find_first.hpp | 1 - .../seg_tree_uncommon/find_last.hpp | 1 - .../seg_tree_uncommon/implicit.hpp | 11 +- .../seg_tree_uncommon/kth_smallest_query.hpp | 89 ++++++ .../seg_tree_uncommon/merge_sort_tree.hpp | 15 +- .../seg_tree_uncommon/persistent.hpp | 20 +- .../seg_tree_uncommon/wavelet_bit_vec.hpp | 8 +- .../seg_tree_uncommon/wavelet_count_less.hpp | 3 +- .../seg_tree_uncommon/wavelet_matrix.hpp | 70 +++++ .../uncommon/deque_op.hpp | 33 +-- .../uncommon/disjoint_rmq.hpp | 3 +- .../uncommon/disjoint_rmq_inc.hpp | 3 +- .../uncommon/linear_rmq.hpp | 16 +- .../uncommon/mode_query.hpp | 38 +-- data_structures/uncommon/permutation_tree.hpp | 134 +++++++++ .../uncommon/priority_queue_of_updates.hpp | 17 +- {library/flow => flow}/dinic.hpp | 34 +-- {library/flow => flow}/hungarian.hpp | 34 +-- {library/flow => flow}/min_cost_max_flow.hpp | 26 +- {library/graphs => graphs}/bcc_callback.hpp | 10 +- {library/graphs => graphs}/dijkstra.hpp | 7 +- {library/graphs => graphs}/hopcroft_karp.hpp | 17 +- graphs/mst.hpp | 37 +++ {library/graphs => graphs}/scc.hpp | 8 +- .../add_edges_strongly_connected.hpp | 93 ++++++ .../offline_incremental_scc.hpp | 52 +++- graphs/uncommon/block_vertex_tree.hpp | 74 +++++ graphs/uncommon/bridge_tree.hpp | 51 ++++ .../graphs => graphs}/uncommon/bridges.hpp | 8 +- .../uncommon/complement_graph_ccs.hpp | 11 +- {library/graphs => graphs}/uncommon/cuts.hpp | 8 +- .../uncommon/enumerate_triangles.hpp | 9 +- .../uncommon/functional_graph_processor.hpp | 38 +++ hackpack-cpp | 1 - kactl | 1 - library/data_structures/bit.hpp | 21 -- library/data_structures/bit_inc.hpp | 21 -- library/data_structures/bit_uncommon/rupq.hpp | 22 -- library/data_structures/bit_uncommon/rurq.hpp | 37 --- .../bit_uncommon/vector_constructor.hpp | 7 - .../range_parallel_equivalence_classes.hpp | 17 -- library/data_structures/lazy_seg_tree.hpp | 52 ---- .../seg_tree_uncommon/distinct_query.hpp | 26 -- .../seg_tree_uncommon/kth_smallest_query.hpp | 37 --- .../seg_tree_uncommon/wavelet_matrix.hpp | 36 --- .../uncommon/permutation_tree.hpp | 87 ------ library/graphs/mst.hpp | 28 -- .../add_edges_strongly_connected.hpp | 64 ----- library/graphs/uncommon/block_vertex_tree.hpp | 36 --- library/graphs/uncommon/bridge_tree.hpp | 17 -- .../uncommon/functional_graph_processor.hpp | 35 --- library/loops/chooses.hpp | 8 - .../count_paths/count_paths_rectangle.hpp | 35 --- .../math/count_paths/count_paths_triangle.hpp | 28 -- library/math/matrix_related/row_reduce.hpp | 39 --- .../math/matrix_related/solve_linear_mod.hpp | 31 -- .../xor_basis_unordered_intersection.hpp | 20 -- .../n_choose_k/large_n_choose_small_k.hpp | 12 - library/math/n_choose_k/lucas_theorem.hpp | 12 - library/math/n_choose_k/n_choose_k.hpp | 12 - library/math/n_choose_k/pascals_identity.hpp | 8 - .../math/prime_sieve/calc_linear_sieve.hpp | 13 - library/math/prime_sieve/calc_sieve.hpp | 9 - .../math/prime_sieve/get_prime_factors.hpp | 6 - library/math/prime_sieve/is_prime.hpp | 7 - library/math/prime_sieve/mobius.hpp | 7 - library/monotonic_stack/count_rectangles.hpp | 34 --- .../monotonic_stack/max_rect_histogram.hpp | 13 - library/monotonic_stack/monotonic_range.hpp | 16 -- .../lcs_queries.hpp | 45 --- library/strings/manacher/is_palindrome.hpp | 11 - .../strings/manacher/longest_from_index.hpp | 19 -- .../suffix_array/suffix_array_query.hpp | 37 --- library/trees/lca_rmq.hpp | 40 --- .../trees/uncommon/contour_range_query.hpp | 63 ---- .../trees/uncommon/contour_range_update.hpp | 59 ---- .../trees/uncommon/count_paths_per_length.hpp | 29 -- .../trees/uncommon/count_paths_per_node.hpp | 43 --- .../trees/uncommon/ladder_decomposition.hpp | 56 ---- loops/chooses.hpp | 16 ++ {library/loops => loops}/next_subset.hpp | 1 - {library/loops => loops}/quotients.hpp | 4 +- {library/loops => loops}/submasks.hpp | 1 - {library/loops => loops}/supermasks.hpp | 1 - {library/math => math}/count_paths/README.md | 0 math/count_paths/count_paths_rectangle.hpp | 133 +++++++++ .../count_paths/count_paths_rectangle.png | Bin math/count_paths/count_paths_triangle.hpp | 160 +++++++++++ .../count_paths/count_paths_triangle.png | Bin {library/math => math}/derangements.hpp | 9 +- {library/math => math}/fibonacci.hpp | 7 +- .../matrix_related/binary_matrix_mult.hpp | 6 +- .../matrix_related/matrix_mult.hpp | 9 +- math/matrix_related/row_reduce.hpp | 53 ++++ math/matrix_related/solve_linear_mod.hpp | 84 ++++++ .../matrix_related/xor_basis_ordered.hpp | 1 - .../matrix_related/xor_basis_unordered.hpp | 1 - .../xor_basis_unordered_intersection.hpp | 40 +++ {library/math => math}/mod_division.hpp | 1 - {library/math => math}/n_choose_k/grow.hpp | 7 +- math/n_choose_k/large_n_choose_small_k.hpp | 22 ++ math/n_choose_k/lucas_theorem.hpp | 31 ++ math/n_choose_k/n_choose_k.hpp | 21 ++ math/n_choose_k/pascals_identity.hpp | 8 + .../num_distinct_subsequences.hpp | 7 +- {library/math => math}/partitions.hpp | 9 +- math/prime_sieve/calc_linear_sieve.hpp | 12 + math/prime_sieve/calc_sieve.hpp | 8 + math/prime_sieve/get_prime_factors.hpp | 12 + math/prime_sieve/is_prime.hpp | 13 + math/prime_sieve/mobius.hpp | 7 + {library/math => math}/tetration_mod.hpp | 24 +- {library/math => math}/totient.hpp | 1 - .../README.md | 0 .../cartesian_binary_tree.hpp | 26 +- .../cartesian_binary_tree_after.png | Bin .../cartesian_binary_tree_before.png | Bin .../cartesian_k_ary_tree.hpp | 24 +- monotonic_stack/count_rectangles.hpp | 65 +++++ monotonic_stack/max_rect_histogram.hpp | 41 +++ .../mono_stack_le.png | Bin .../mono_stack_ri.png | Bin monotonic_stack/monotonic_range.hpp | 29 ++ .../monotonic_stack.hpp | 10 +- notebook-generator | 1 - {library/strings => strings}/kmp.hpp | 23 +- .../longest_common_subsequence/lcs_dp.hpp | 11 +- .../lcs_queries.hpp | 94 ++++++ strings/manacher/is_palindrome.hpp | 40 +++ strings/manacher/longest_from_index.hpp | 57 ++++ .../manacher/longest_palindrome_query.hpp | 69 ++++- .../strings => strings}/manacher/manacher.hpp | 9 +- .../strings => strings}/prefix_function.hpp | 7 +- .../compare/compare_substrings.hpp | 17 +- .../suffix_array/compare/compare_suffixes.hpp | 1 - .../suffix_array/find/find_string_bs.hpp | 6 +- .../suffix_array/find/find_string_bs_fast.hpp | 25 +- .../suffix_array/find/find_substring.hpp | 6 +- .../find/find_substrings_concatenated.hpp | 15 +- .../suffix_array/find/match.hpp | 1 - .../suffix_array/suffix_array.hpp | 17 +- strings/suffix_array/suffix_array_query.hpp | 271 ++++++++++++++++++ .../suffix_array/suffix_array_short.hpp | 16 +- {library/strings => strings}/trie.hpp | 5 +- .../wildcard_pattern_matching.hpp | 17 +- tests/.config/.astylerc | 19 -- tests/.config/.clang-format | 94 ------ tests/.config/.clang-tidy | 122 -------- tests/.config/.clang_compile_flags | 15 - .../.config/.code_snippet_excluded_file_list | 24 -- tests/.config/.cppcheck_suppression_list | 62 ---- tests/.config/.gcc_compile_flags | 13 - tests/.gitignore | 9 - tests/Makefile | 59 ---- tests/README.md | 32 --- tests/images/south_dakota_mines_logo.png | Bin 26216 -> 0 bytes .../library_checker_aizu_tests/cd_asserts.hpp | 29 -- .../compress_tree_asserts.hpp | 42 --- .../convolution/gcd_convolution.test.cpp | 19 -- .../convolution/lcm_convolution.test.cpp | 19 -- .../convolution/min_plus_convolution.test.cpp | 19 -- .../binary_search_example.test.cpp | 36 --- .../data_structures/binary_trie.test.cpp | 34 --- .../data_structures/bit.test.cpp | 64 ----- .../data_structures/bit_inc.test.cpp | 29 -- .../data_structures/bit_ordered_set.test.cpp | 63 ---- .../data_structures/bit_rupq.test.cpp | 35 --- .../data_structures/bit_rurq.test.cpp | 29 -- .../data_structures/bit_walk.test.cpp | 85 ------ .../data_structures/deque.test.cpp | 38 --- .../data_structures/deque_index.test.cpp | 32 --- .../data_structures/deque_op.test.cpp | 61 ---- .../deque_sliding_window.test.cpp | 22 -- .../data_structures/disjoint_rmq_inc.test.cpp | 17 -- .../disjoint_rmq_inc_lines.test.cpp | 47 --- .../disjoint_rmq_lines.test.cpp | 47 --- .../data_structures/disjoint_rmq_sum.test.cpp | 17 -- .../data_structures/distinct_query.test.cpp | 18 -- .../data_structures/dsu.test.cpp | 16 -- .../data_structures/dsu_bipartite.test.cpp | 50 ---- .../data_structures/dsu_restorable.test.cpp | 39 --- .../dsu_segtree_undo_trick.test.cpp | 127 -------- .../implicit_seg_tree.test.cpp | 43 --- .../kruskal_tree_aizu.test.cpp | 50 ---- .../data_structures/kth_smallest_pst.test.cpp | 39 --- .../kth_smallest_wavelet_matrix.test.cpp | 21 -- .../lazy_segment_tree.test.cpp | 41 --- .../lazy_segment_tree_constructor.test.cpp | 44 --- .../lazy_segment_tree_inc.test.cpp | 23 -- ...lazy_segment_tree_inc_constructor.test.cpp | 28 -- .../data_structures/line_tree_aizu.test.cpp | 47 --- .../line_tree_lib_checker.test.cpp | 41 --- .../data_structures/merge_sort_tree.test.cpp | 22 -- .../data_structures/mode_query.test.cpp | 33 --- .../data_structures/permutation_tree.test.cpp | 30 -- .../persistent_queue_tree.test.cpp | 39 --- .../persistent_seg_tree.test.cpp | 35 --- .../pq_ds_undo_sliding_window.test.cpp | 36 --- .../pq_ds_undo_with_dsu.test.cpp | 77 ----- .../range_parallel_dsu.test.cpp | 44 --- .../rmq_disjoint_sparse_table.test.cpp | 16 -- .../data_structures/rmq_linear.test.cpp | 37 --- .../data_structures/rmq_sparse_table.test.cpp | 19 -- .../rmq_sparse_table_inc.test.cpp | 16 -- .../data_structures/simple_tree.test.cpp | 25 -- .../data_structures/simple_tree_inc.test.cpp | 25 -- .../simple_tree_inc_line.test.cpp | 36 --- .../data_structures/simple_tree_line.test.cpp | 38 --- .../dinic_asserts.hpp | 42 --- .../edge_cd_asserts.hpp | 50 ---- .../flow/dinic_aizu.test.cpp | 20 -- .../flow/hungarian.test.cpp | 17 -- .../flow/min_cost_max_flow.test.cpp | 18 -- .../graphs/bcc_callback_aizu_bcc.test.cpp | 24 -- .../bcc_callback_aizu_two_edge_cc.test.cpp | 32 --- .../bcc_callback_lib_checker_bcc.test.cpp | 33 --- .../bcc_callback_lib_checker_two_cc.test.cpp | 46 --- .../graphs/biconnected_components.test.cpp | 77 ----- ...ed_components_of_complement_graph.test.cpp | 27 -- .../graphs/dijkstra_aizu.test.cpp | 24 -- .../graphs/dijkstra_lib_checker.test.cpp | 47 --- .../graphs/directed_cycle.test.cpp | 60 ---- .../graphs/enumerate_triangles.test.cpp | 24 -- .../graphs/hopcroft_karp_aizu.test.cpp | 47 --- .../graphs/hopcroft_karp_lib_checker.test.cpp | 49 ---- .../graphs/mst.test.cpp | 16 -- .../graphs/offline_incremental_scc.test.cpp | 42 --- ...trongly_connected_components_aizu.test.cpp | 26 -- ..._connected_components_lib_checker.test.cpp | 27 -- .../graphs/two_edge_components.test.cpp | 70 ----- .../handmade_tests/count_paths.test.cpp | 51 ---- .../handmade_tests/dsu.test.cpp | 51 ---- .../handmade_tests/dsu_size.test.cpp | 54 ---- .../edge_cd_small_trees.test.cpp | 50 ---- .../handmade_tests/fib_matrix_expo.test.cpp | 37 --- .../handmade_tests/functional_graph.test.cpp | 155 ---------- .../handmade_tests/manacher.test.cpp | 78 ----- .../merge_st_and_wavelet.test.cpp | 41 --- .../handmade_tests/mobius.test.cpp | 30 -- .../handmade_tests/mod_division.test.cpp | 21 -- .../handmade_tests/n_choose_k.test.cpp | 42 --- .../permutation_tree_small.test.cpp | 17 -- .../handmade_tests/rmq_small_n.test.cpp | 41 --- .../handmade_tests/sa_find_subarray.test.cpp | 68 ----- .../handmade_tests/seg_tree_find.test.cpp | 75 ----- .../seg_tree_find_small.test.cpp | 58 ---- .../kactl_macros.hpp | 6 - .../loops/chooses.test.cpp | 17 -- .../loops/quotients.test.cpp | 27 -- .../loops/submasks.test.cpp | 28 -- .../loops/supermasks.test.cpp | 26 -- .../math/binary_matrix_mult.test.cpp | 27 -- .../math/count_paths.test.cpp | 70 ----- .../math/derangement.test.cpp | 13 - .../math/matrix_determinant.test.cpp | 15 - .../math/matrix_mult.test.cpp | 31 -- .../math/n_choose_k.test.cpp | 33 --- .../math/num_subsequences.test.cpp | 15 - .../math/partitions.test.cpp | 12 - .../math/prime_sieve.test.cpp | 42 --- .../math/solve_linear_mod.test.cpp | 38 --- .../math/tetration.test.cpp | 15 - .../math/totient.test.cpp | 11 - .../math/xor_basis.test.cpp | 99 ------- .../math/xor_basis_intersection.test.cpp | 46 --- .../mono_st_asserts.hpp | 89 ------ .../cartesian_binary_tree.test.cpp | 15 - .../cartesian_k_ary_tree.test.cpp | 31 -- .../count_rectangles.test.cpp | 62 ---- .../max_rect_histogram.test.cpp | 15 - .../perm_tree_asserts.hpp | 129 --------- .../scc_asserts.hpp | 38 --- .../strings/kmp.test.cpp | 14 - .../strings/lcp_array.test.cpp | 31 -- .../strings/lcp_query_palindrome.test.cpp | 20 -- .../strings/lcp_query_zfunc.test.cpp | 49 ---- .../strings/lcs_dp.test.cpp | 23 -- .../strings/lcs_queries.test.cpp | 20 -- .../lcs_queries_merge_sort_tree.test.cpp | 36 --- .../strings/manacher.test.cpp | 48 ---- .../strings/multi_matching_bs.test.cpp | 42 --- .../strings/prefix_function.test.cpp | 29 -- .../strings/sa_cmp.test.cpp | 26 -- .../strings/sa_sort_pairs.test.cpp | 37 --- .../strings/single_matching_bs.test.cpp | 83 ------ .../strings/suffix_array.test.cpp | 53 ---- .../strings/suffix_array_short.test.cpp | 19 -- .../strings/trie.test.cpp | 17 -- .../wildcard_pattern_matching.test.cpp | 34 --- tests/library_checker_aizu_tests/template.hpp | 37 --- .../trees/count_paths_per_length.test.cpp | 20 -- .../edge_cd_contour_range_query.test.cpp | 41 --- .../edge_cd_contour_range_update.test.cpp | 38 --- .../edge_cd_count_paths_per_length.test.cpp | 22 -- .../trees/edge_cd_reroot_dp.test.cpp | 102 ------- .../trees/hld_aizu1.test.cpp | 44 --- .../trees/hld_aizu2.test.cpp | 45 --- .../trees/hld_lib_checker_path.test.cpp | 38 --- .../hld_lib_checker_subtree_edges.test.cpp | 37 --- .../hld_lib_checker_subtree_nodes.test.cpp | 36 --- .../trees/kth_path_ladder.test.cpp | 35 --- .../trees/kth_path_linear.test.cpp | 44 --- .../trees/kth_path_tree_lift.test.cpp | 46 --- .../trees/lca_all_methods_aizu.test.cpp | 42 --- .../lca_all_methods_lib_checker.test.cpp | 39 --- .../shallowest_aizu_tree_height.test.cpp | 45 --- ...t_lib_checker_tree_path_composite.test.cpp | 100 ------- .../trees/subtree_isomorphism.test.cpp | 23 -- tests/scripts/README.md | 22 -- tests/scripts/build_pdf.sh | 98 ------- tests/scripts/clangtidy.sh | 13 - tests/scripts/compile_clang.sh | 12 - tests/scripts/compile_commented_snippets.sh | 40 --- tests/scripts/compile_gcc.sh | 9 - tests/scripts/do_format.sh | 5 - tests/scripts/find_files_without_tests.sh | 19 -- tests/scripts/grep_clangformat_cppcheck.sh | 60 ---- tests/scripts/print_which_tests_havent_run.sh | 25 -- tests/scripts/shellcheck_shfmt.sh | 33 --- tests/scripts/update_main.sh | 29 -- {library/trees => trees}/edge_cd.hpp | 16 +- {library/trees => trees}/edge_cd.png | Bin .../trees => trees}/extra_members/dist.hpp | 0 .../extra_members/in_subtree.hpp | 0 .../extra_members/next_on_path.hpp | 1 - .../trees => trees}/extra_members/on_path.hpp | 0 .../extra_members/virtual_tree.hpp | 9 +- {library/trees => trees}/hld.hpp | 8 +- trees/lca_rmq.hpp | 121 ++++++++ {library/trees => trees}/linear_kth_par.hpp | 13 +- {library/trees => trees}/linear_lca.hpp | 13 +- .../shallowest_decomp_tree.hpp | 5 +- {library/trees => trees}/tree_lift.hpp | 9 +- .../uncommon/centroid_decomp.hpp | 5 +- trees/uncommon/contour_range_query.hpp | 182 ++++++++++++ trees/uncommon/contour_range_update.hpp | 198 +++++++++++++ trees/uncommon/count_paths_per_length.hpp | 154 ++++++++++ trees/uncommon/count_paths_per_node.hpp | 78 +++++ trees/uncommon/ladder_decomposition.hpp | 93 ++++++ .../uncommon/subtree_isomorphism.hpp | 11 +- .../trees => trees}/uncommon/sum_adjacent.hpp | 14 +- 382 files changed, 3707 insertions(+), 8832 deletions(-) delete mode 100644 .github/workflows/programming_team_code_ci.yml delete mode 100644 .gitmodules delete mode 100644 .verify-helper/config.toml delete mode 100644 .verify-helper/timestamps.remote.json rename {library/contest => contest}/README.md (100%) rename {library/contest => contest}/binary_search.hpp (73%) rename {library/contest => contest}/hash.sh (100%) rename {library/contest => contest}/random.hpp (97%) rename {library/contest => contest}/template.cpp (100%) rename {library/contest => contest}/tester.sh (100%) rename {library/convolution => convolution}/gcd_convolution.hpp (76%) rename {library/convolution => convolution}/lcm_convolution.hpp (72%) rename {library/convolution => convolution}/min_plus_convolution_convex_and_arbitrary.hpp (77%) rename {library/data_structures => data_structures}/README.md (100%) rename {library/data_structures => data_structures}/binary_trie.hpp (72%) create mode 100644 data_structures/bit.hpp create mode 100644 data_structures/bit_inc.hpp rename {library/data_structures => data_structures}/bit_uncommon/next.hpp (100%) rename {library/data_structures => data_structures}/bit_uncommon/prev.hpp (100%) create mode 100644 data_structures/bit_uncommon/rupq.hpp create mode 100644 data_structures/bit_uncommon/rurq.hpp create mode 100644 data_structures/bit_uncommon/vector_constructor.hpp rename {library/data_structures => data_structures}/bit_uncommon/walk.hpp (73%) rename {library/data_structures => data_structures}/dsu/dsu.hpp (80%) rename {library/data_structures => data_structures}/dsu/dsu_bipartite.hpp (96%) rename {library/data_structures => data_structures}/dsu/dsu_restorable.hpp (92%) rename {library/data_structures => data_structures}/dsu/kruskal_tree.hpp (89%) rename {library/data_structures => data_structures}/dsu/line_tree.hpp (90%) rename {library/data_structures => data_structures}/dsu/range_parallel_dsu.hpp (60%) create mode 100644 data_structures/dsu/range_parallel_equivalence_classes.hpp create mode 100644 data_structures/lazy_seg_tree.hpp rename {library/data_structures => data_structures}/lazy_seg_tree.png (100%) rename {library/data_structures => data_structures}/lazy_seg_tree_inc.hpp (58%) rename {library/data_structures => data_structures}/lazy_seg_tree_inc_midpoint.hpp (95%) rename {library/data_structures => data_structures}/lazy_seg_tree_midpoint.hpp (91%) rename {library/data_structures => data_structures}/rmq.hpp (80%) rename {library/data_structures => data_structures}/rmq_inc.hpp (86%) rename {library/data_structures => data_structures}/seg_tree.hpp (98%) rename {library/data_structures => data_structures}/seg_tree.png (100%) rename {library/data_structures => data_structures}/seg_tree_inc.hpp (98%) create mode 100644 data_structures/seg_tree_uncommon/distinct_query.hpp rename {library/data_structures => data_structures}/seg_tree_uncommon/find_first.hpp (99%) rename {library/data_structures => data_structures}/seg_tree_uncommon/find_last.hpp (99%) rename {library/data_structures => data_structures}/seg_tree_uncommon/implicit.hpp (87%) create mode 100644 data_structures/seg_tree_uncommon/kth_smallest_query.hpp rename {library/data_structures => data_structures}/seg_tree_uncommon/merge_sort_tree.hpp (70%) rename {library/data_structures => data_structures}/seg_tree_uncommon/persistent.hpp (77%) rename {library/data_structures => data_structures}/seg_tree_uncommon/wavelet_bit_vec.hpp (70%) rename {library/data_structures => data_structures}/seg_tree_uncommon/wavelet_count_less.hpp (88%) create mode 100644 data_structures/seg_tree_uncommon/wavelet_matrix.hpp rename {library/data_structures => data_structures}/uncommon/deque_op.hpp (67%) rename {library/data_structures => data_structures}/uncommon/disjoint_rmq.hpp (93%) rename {library/data_structures => data_structures}/uncommon/disjoint_rmq_inc.hpp (93%) rename {library/data_structures => data_structures}/uncommon/linear_rmq.hpp (81%) rename {library/data_structures => data_structures}/uncommon/mode_query.hpp (63%) create mode 100644 data_structures/uncommon/permutation_tree.hpp rename {library/data_structures => data_structures}/uncommon/priority_queue_of_updates.hpp (82%) rename {library/flow => flow}/dinic.hpp (66%) rename {library/flow => flow}/hungarian.hpp (54%) rename {library/flow => flow}/min_cost_max_flow.hpp (76%) rename {library/graphs => graphs}/bcc_callback.hpp (90%) rename {library/graphs => graphs}/dijkstra.hpp (78%) rename {library/graphs => graphs}/hopcroft_karp.hpp (83%) create mode 100644 graphs/mst.hpp rename {library/graphs => graphs}/scc.hpp (81%) create mode 100644 graphs/strongly_connected_components/add_edges_strongly_connected.hpp rename {library/graphs => graphs}/strongly_connected_components/offline_incremental_scc.hpp (50%) create mode 100644 graphs/uncommon/block_vertex_tree.hpp create mode 100644 graphs/uncommon/bridge_tree.hpp rename {library/graphs => graphs}/uncommon/bridges.hpp (84%) rename {library/graphs => graphs}/uncommon/complement_graph_ccs.hpp (82%) rename {library/graphs => graphs}/uncommon/cuts.hpp (85%) rename {library/graphs => graphs}/uncommon/enumerate_triangles.hpp (80%) create mode 100644 graphs/uncommon/functional_graph_processor.hpp delete mode 160000 hackpack-cpp delete mode 160000 kactl delete mode 100644 library/data_structures/bit.hpp delete mode 100644 library/data_structures/bit_inc.hpp delete mode 100644 library/data_structures/bit_uncommon/rupq.hpp delete mode 100644 library/data_structures/bit_uncommon/rurq.hpp delete mode 100644 library/data_structures/bit_uncommon/vector_constructor.hpp delete mode 100644 library/data_structures/dsu/range_parallel_equivalence_classes.hpp delete mode 100644 library/data_structures/lazy_seg_tree.hpp delete mode 100644 library/data_structures/seg_tree_uncommon/distinct_query.hpp delete mode 100644 library/data_structures/seg_tree_uncommon/kth_smallest_query.hpp delete mode 100644 library/data_structures/seg_tree_uncommon/wavelet_matrix.hpp delete mode 100644 library/data_structures/uncommon/permutation_tree.hpp delete mode 100644 library/graphs/mst.hpp delete mode 100644 library/graphs/strongly_connected_components/add_edges_strongly_connected.hpp delete mode 100644 library/graphs/uncommon/block_vertex_tree.hpp delete mode 100644 library/graphs/uncommon/bridge_tree.hpp delete mode 100644 library/graphs/uncommon/functional_graph_processor.hpp delete mode 100644 library/loops/chooses.hpp delete mode 100644 library/math/count_paths/count_paths_rectangle.hpp delete mode 100644 library/math/count_paths/count_paths_triangle.hpp delete mode 100644 library/math/matrix_related/row_reduce.hpp delete mode 100644 library/math/matrix_related/solve_linear_mod.hpp delete mode 100644 library/math/matrix_related/xor_basis_unordered_intersection.hpp delete mode 100644 library/math/n_choose_k/large_n_choose_small_k.hpp delete mode 100644 library/math/n_choose_k/lucas_theorem.hpp delete mode 100644 library/math/n_choose_k/n_choose_k.hpp delete mode 100644 library/math/n_choose_k/pascals_identity.hpp delete mode 100644 library/math/prime_sieve/calc_linear_sieve.hpp delete mode 100644 library/math/prime_sieve/calc_sieve.hpp delete mode 100644 library/math/prime_sieve/get_prime_factors.hpp delete mode 100644 library/math/prime_sieve/is_prime.hpp delete mode 100644 library/math/prime_sieve/mobius.hpp delete mode 100644 library/monotonic_stack/count_rectangles.hpp delete mode 100644 library/monotonic_stack/max_rect_histogram.hpp delete mode 100644 library/monotonic_stack/monotonic_range.hpp delete mode 100644 library/strings/longest_common_subsequence/lcs_queries.hpp delete mode 100644 library/strings/manacher/is_palindrome.hpp delete mode 100644 library/strings/manacher/longest_from_index.hpp delete mode 100644 library/strings/suffix_array/suffix_array_query.hpp delete mode 100644 library/trees/lca_rmq.hpp delete mode 100644 library/trees/uncommon/contour_range_query.hpp delete mode 100644 library/trees/uncommon/contour_range_update.hpp delete mode 100644 library/trees/uncommon/count_paths_per_length.hpp delete mode 100644 library/trees/uncommon/count_paths_per_node.hpp delete mode 100644 library/trees/uncommon/ladder_decomposition.hpp create mode 100644 loops/chooses.hpp rename {library/loops => loops}/next_subset.hpp (96%) rename {library/loops => loops}/quotients.hpp (81%) rename {library/loops => loops}/submasks.hpp (94%) rename {library/loops => loops}/supermasks.hpp (95%) rename {library/math => math}/count_paths/README.md (100%) create mode 100644 math/count_paths/count_paths_rectangle.hpp rename {library/math => math}/count_paths/count_paths_rectangle.png (100%) create mode 100644 math/count_paths/count_paths_triangle.hpp rename {library/math => math}/count_paths/count_paths_triangle.png (100%) rename {library/math => math}/derangements.hpp (56%) rename {library/math => math}/fibonacci.hpp (80%) rename {library/math => math}/matrix_related/binary_matrix_mult.hpp (73%) rename {library/math => math}/matrix_related/matrix_mult.hpp (56%) create mode 100644 math/matrix_related/row_reduce.hpp create mode 100644 math/matrix_related/solve_linear_mod.hpp rename {library/math => math}/matrix_related/xor_basis_ordered.hpp (97%) rename {library/math => math}/matrix_related/xor_basis_unordered.hpp (97%) create mode 100644 math/matrix_related/xor_basis_unordered_intersection.hpp rename {library/math => math}/mod_division.hpp (96%) rename {library/math => math}/n_choose_k/grow.hpp (56%) create mode 100644 math/n_choose_k/large_n_choose_small_k.hpp create mode 100644 math/n_choose_k/lucas_theorem.hpp create mode 100644 math/n_choose_k/n_choose_k.hpp create mode 100644 math/n_choose_k/pascals_identity.hpp rename {library/math => math}/num_distinct_subsequences.hpp (77%) rename {library/math => math}/partitions.hpp (79%) create mode 100644 math/prime_sieve/calc_linear_sieve.hpp create mode 100644 math/prime_sieve/calc_sieve.hpp create mode 100644 math/prime_sieve/get_prime_factors.hpp create mode 100644 math/prime_sieve/is_prime.hpp create mode 100644 math/prime_sieve/mobius.hpp rename {library/math => math}/tetration_mod.hpp (61%) rename {library/math => math}/totient.hpp (95%) rename {library/monotonic_stack => monotonic_stack}/README.md (100%) rename {library/monotonic_stack => monotonic_stack}/cartesian_binary_tree.hpp (55%) rename {library/monotonic_stack => monotonic_stack}/cartesian_binary_tree_after.png (100%) rename {library/monotonic_stack => monotonic_stack}/cartesian_binary_tree_before.png (100%) rename {library/monotonic_stack => monotonic_stack}/cartesian_k_ary_tree.hpp (68%) create mode 100644 monotonic_stack/count_rectangles.hpp create mode 100644 monotonic_stack/max_rect_histogram.hpp rename {library/monotonic_stack => monotonic_stack}/mono_stack_le.png (100%) rename {library/monotonic_stack => monotonic_stack}/mono_stack_ri.png (100%) create mode 100644 monotonic_stack/monotonic_range.hpp rename {library/monotonic_stack => monotonic_stack}/monotonic_stack.hpp (50%) delete mode 160000 notebook-generator rename {library/strings => strings}/kmp.hpp (55%) rename {library/strings => strings}/longest_common_subsequence/lcs_dp.hpp (66%) create mode 100644 strings/longest_common_subsequence/lcs_queries.hpp create mode 100644 strings/manacher/is_palindrome.hpp create mode 100644 strings/manacher/longest_from_index.hpp rename {library/strings => strings}/manacher/longest_palindrome_query.hpp (52%) rename {library/strings => strings}/manacher/manacher.hpp (81%) rename {library/strings => strings}/prefix_function.hpp (66%) rename {library/strings => strings}/suffix_array/compare/compare_substrings.hpp (56%) rename {library/strings => strings}/suffix_array/compare/compare_suffixes.hpp (96%) rename {library/strings => strings}/suffix_array/find/find_string_bs.hpp (79%) rename {library/strings => strings}/suffix_array/find/find_string_bs_fast.hpp (51%) rename {library/strings => strings}/suffix_array/find/find_substring.hpp (83%) rename {library/strings => strings}/suffix_array/find/find_substrings_concatenated.hpp (76%) rename {library/strings => strings}/suffix_array/find/match.hpp (95%) rename {library/strings => strings}/suffix_array/suffix_array.hpp (81%) create mode 100644 strings/suffix_array/suffix_array_query.hpp rename {library/strings => strings}/suffix_array/suffix_array_short.hpp (72%) rename {library/strings => strings}/trie.hpp (88%) rename {library/strings => strings}/wildcard_pattern_matching.hpp (71%) delete mode 100644 tests/.config/.astylerc delete mode 100644 tests/.config/.clang-format delete mode 100644 tests/.config/.clang-tidy delete mode 100644 tests/.config/.clang_compile_flags delete mode 100644 tests/.config/.code_snippet_excluded_file_list delete mode 100644 tests/.config/.cppcheck_suppression_list delete mode 100644 tests/.config/.gcc_compile_flags delete mode 100644 tests/.gitignore delete mode 100644 tests/Makefile delete mode 100644 tests/README.md delete mode 100644 tests/images/south_dakota_mines_logo.png delete mode 100644 tests/library_checker_aizu_tests/cd_asserts.hpp delete mode 100644 tests/library_checker_aizu_tests/compress_tree_asserts.hpp delete mode 100644 tests/library_checker_aizu_tests/convolution/gcd_convolution.test.cpp delete mode 100644 tests/library_checker_aizu_tests/convolution/lcm_convolution.test.cpp delete mode 100644 tests/library_checker_aizu_tests/convolution/min_plus_convolution.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/binary_search_example.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/binary_trie.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/bit.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/bit_inc.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/bit_ordered_set.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/bit_rupq.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/bit_rurq.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/bit_walk.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/deque.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/deque_index.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/deque_op.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/deque_sliding_window.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/disjoint_rmq_inc.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/disjoint_rmq_inc_lines.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/disjoint_rmq_lines.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/disjoint_rmq_sum.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/distinct_query.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/dsu.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/dsu_bipartite.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/dsu_restorable.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/dsu_segtree_undo_trick.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/implicit_seg_tree.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/kruskal_tree_aizu.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/kth_smallest_pst.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/kth_smallest_wavelet_matrix.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/lazy_segment_tree.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/lazy_segment_tree_constructor.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/lazy_segment_tree_inc.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/lazy_segment_tree_inc_constructor.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/line_tree_aizu.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/line_tree_lib_checker.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/merge_sort_tree.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/mode_query.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/permutation_tree.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/persistent_queue_tree.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/persistent_seg_tree.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/pq_ds_undo_sliding_window.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/pq_ds_undo_with_dsu.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/range_parallel_dsu.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/rmq_disjoint_sparse_table.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/rmq_linear.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/rmq_sparse_table.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/rmq_sparse_table_inc.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/simple_tree.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/simple_tree_inc.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/simple_tree_inc_line.test.cpp delete mode 100644 tests/library_checker_aizu_tests/data_structures/simple_tree_line.test.cpp delete mode 100644 tests/library_checker_aizu_tests/dinic_asserts.hpp delete mode 100644 tests/library_checker_aizu_tests/edge_cd_asserts.hpp delete mode 100644 tests/library_checker_aizu_tests/flow/dinic_aizu.test.cpp delete mode 100644 tests/library_checker_aizu_tests/flow/hungarian.test.cpp delete mode 100644 tests/library_checker_aizu_tests/flow/min_cost_max_flow.test.cpp delete mode 100644 tests/library_checker_aizu_tests/graphs/bcc_callback_aizu_bcc.test.cpp delete mode 100644 tests/library_checker_aizu_tests/graphs/bcc_callback_aizu_two_edge_cc.test.cpp delete mode 100644 tests/library_checker_aizu_tests/graphs/bcc_callback_lib_checker_bcc.test.cpp delete mode 100644 tests/library_checker_aizu_tests/graphs/bcc_callback_lib_checker_two_cc.test.cpp delete mode 100644 tests/library_checker_aizu_tests/graphs/biconnected_components.test.cpp delete mode 100644 tests/library_checker_aizu_tests/graphs/connected_components_of_complement_graph.test.cpp delete mode 100644 tests/library_checker_aizu_tests/graphs/dijkstra_aizu.test.cpp delete mode 100644 tests/library_checker_aizu_tests/graphs/dijkstra_lib_checker.test.cpp delete mode 100644 tests/library_checker_aizu_tests/graphs/directed_cycle.test.cpp delete mode 100644 tests/library_checker_aizu_tests/graphs/enumerate_triangles.test.cpp delete mode 100644 tests/library_checker_aizu_tests/graphs/hopcroft_karp_aizu.test.cpp delete mode 100644 tests/library_checker_aizu_tests/graphs/hopcroft_karp_lib_checker.test.cpp delete mode 100644 tests/library_checker_aizu_tests/graphs/mst.test.cpp delete mode 100644 tests/library_checker_aizu_tests/graphs/offline_incremental_scc.test.cpp delete mode 100644 tests/library_checker_aizu_tests/graphs/strongly_connected_components_aizu.test.cpp delete mode 100644 tests/library_checker_aizu_tests/graphs/strongly_connected_components_lib_checker.test.cpp delete mode 100644 tests/library_checker_aizu_tests/graphs/two_edge_components.test.cpp delete mode 100644 tests/library_checker_aizu_tests/handmade_tests/count_paths.test.cpp delete mode 100644 tests/library_checker_aizu_tests/handmade_tests/dsu.test.cpp delete mode 100644 tests/library_checker_aizu_tests/handmade_tests/dsu_size.test.cpp delete mode 100644 tests/library_checker_aizu_tests/handmade_tests/edge_cd_small_trees.test.cpp delete mode 100644 tests/library_checker_aizu_tests/handmade_tests/fib_matrix_expo.test.cpp delete mode 100644 tests/library_checker_aizu_tests/handmade_tests/functional_graph.test.cpp delete mode 100644 tests/library_checker_aizu_tests/handmade_tests/manacher.test.cpp delete mode 100644 tests/library_checker_aizu_tests/handmade_tests/merge_st_and_wavelet.test.cpp delete mode 100644 tests/library_checker_aizu_tests/handmade_tests/mobius.test.cpp delete mode 100644 tests/library_checker_aizu_tests/handmade_tests/mod_division.test.cpp delete mode 100644 tests/library_checker_aizu_tests/handmade_tests/n_choose_k.test.cpp delete mode 100644 tests/library_checker_aizu_tests/handmade_tests/permutation_tree_small.test.cpp delete mode 100644 tests/library_checker_aizu_tests/handmade_tests/rmq_small_n.test.cpp delete mode 100644 tests/library_checker_aizu_tests/handmade_tests/sa_find_subarray.test.cpp delete mode 100644 tests/library_checker_aizu_tests/handmade_tests/seg_tree_find.test.cpp delete mode 100644 tests/library_checker_aizu_tests/handmade_tests/seg_tree_find_small.test.cpp delete mode 100644 tests/library_checker_aizu_tests/kactl_macros.hpp delete mode 100644 tests/library_checker_aizu_tests/loops/chooses.test.cpp delete mode 100644 tests/library_checker_aizu_tests/loops/quotients.test.cpp delete mode 100644 tests/library_checker_aizu_tests/loops/submasks.test.cpp delete mode 100644 tests/library_checker_aizu_tests/loops/supermasks.test.cpp delete mode 100644 tests/library_checker_aizu_tests/math/binary_matrix_mult.test.cpp delete mode 100644 tests/library_checker_aizu_tests/math/count_paths.test.cpp delete mode 100644 tests/library_checker_aizu_tests/math/derangement.test.cpp delete mode 100644 tests/library_checker_aizu_tests/math/matrix_determinant.test.cpp delete mode 100644 tests/library_checker_aizu_tests/math/matrix_mult.test.cpp delete mode 100644 tests/library_checker_aizu_tests/math/n_choose_k.test.cpp delete mode 100644 tests/library_checker_aizu_tests/math/num_subsequences.test.cpp delete mode 100644 tests/library_checker_aizu_tests/math/partitions.test.cpp delete mode 100644 tests/library_checker_aizu_tests/math/prime_sieve.test.cpp delete mode 100644 tests/library_checker_aizu_tests/math/solve_linear_mod.test.cpp delete mode 100644 tests/library_checker_aizu_tests/math/tetration.test.cpp delete mode 100644 tests/library_checker_aizu_tests/math/totient.test.cpp delete mode 100644 tests/library_checker_aizu_tests/math/xor_basis.test.cpp delete mode 100644 tests/library_checker_aizu_tests/math/xor_basis_intersection.test.cpp delete mode 100644 tests/library_checker_aizu_tests/mono_st_asserts.hpp delete mode 100644 tests/library_checker_aizu_tests/monotonic_stack_related/cartesian_binary_tree.test.cpp delete mode 100644 tests/library_checker_aizu_tests/monotonic_stack_related/cartesian_k_ary_tree.test.cpp delete mode 100644 tests/library_checker_aizu_tests/monotonic_stack_related/count_rectangles.test.cpp delete mode 100644 tests/library_checker_aizu_tests/monotonic_stack_related/max_rect_histogram.test.cpp delete mode 100644 tests/library_checker_aizu_tests/perm_tree_asserts.hpp delete mode 100644 tests/library_checker_aizu_tests/scc_asserts.hpp delete mode 100644 tests/library_checker_aizu_tests/strings/kmp.test.cpp delete mode 100644 tests/library_checker_aizu_tests/strings/lcp_array.test.cpp delete mode 100644 tests/library_checker_aizu_tests/strings/lcp_query_palindrome.test.cpp delete mode 100644 tests/library_checker_aizu_tests/strings/lcp_query_zfunc.test.cpp delete mode 100644 tests/library_checker_aizu_tests/strings/lcs_dp.test.cpp delete mode 100644 tests/library_checker_aizu_tests/strings/lcs_queries.test.cpp delete mode 100644 tests/library_checker_aizu_tests/strings/lcs_queries_merge_sort_tree.test.cpp delete mode 100644 tests/library_checker_aizu_tests/strings/manacher.test.cpp delete mode 100644 tests/library_checker_aizu_tests/strings/multi_matching_bs.test.cpp delete mode 100644 tests/library_checker_aizu_tests/strings/prefix_function.test.cpp delete mode 100644 tests/library_checker_aizu_tests/strings/sa_cmp.test.cpp delete mode 100644 tests/library_checker_aizu_tests/strings/sa_sort_pairs.test.cpp delete mode 100644 tests/library_checker_aizu_tests/strings/single_matching_bs.test.cpp delete mode 100644 tests/library_checker_aizu_tests/strings/suffix_array.test.cpp delete mode 100644 tests/library_checker_aizu_tests/strings/suffix_array_short.test.cpp delete mode 100644 tests/library_checker_aizu_tests/strings/trie.test.cpp delete mode 100644 tests/library_checker_aizu_tests/strings/wildcard_pattern_matching.test.cpp delete mode 100644 tests/library_checker_aizu_tests/template.hpp delete mode 100644 tests/library_checker_aizu_tests/trees/count_paths_per_length.test.cpp delete mode 100644 tests/library_checker_aizu_tests/trees/edge_cd_contour_range_query.test.cpp delete mode 100644 tests/library_checker_aizu_tests/trees/edge_cd_contour_range_update.test.cpp delete mode 100644 tests/library_checker_aizu_tests/trees/edge_cd_count_paths_per_length.test.cpp delete mode 100644 tests/library_checker_aizu_tests/trees/edge_cd_reroot_dp.test.cpp delete mode 100644 tests/library_checker_aizu_tests/trees/hld_aizu1.test.cpp delete mode 100644 tests/library_checker_aizu_tests/trees/hld_aizu2.test.cpp delete mode 100644 tests/library_checker_aizu_tests/trees/hld_lib_checker_path.test.cpp delete mode 100644 tests/library_checker_aizu_tests/trees/hld_lib_checker_subtree_edges.test.cpp delete mode 100644 tests/library_checker_aizu_tests/trees/hld_lib_checker_subtree_nodes.test.cpp delete mode 100644 tests/library_checker_aizu_tests/trees/kth_path_ladder.test.cpp delete mode 100644 tests/library_checker_aizu_tests/trees/kth_path_linear.test.cpp delete mode 100644 tests/library_checker_aizu_tests/trees/kth_path_tree_lift.test.cpp delete mode 100644 tests/library_checker_aizu_tests/trees/lca_all_methods_aizu.test.cpp delete mode 100644 tests/library_checker_aizu_tests/trees/lca_all_methods_lib_checker.test.cpp delete mode 100644 tests/library_checker_aizu_tests/trees/shallowest_aizu_tree_height.test.cpp delete mode 100644 tests/library_checker_aizu_tests/trees/shallowest_lib_checker_tree_path_composite.test.cpp delete mode 100644 tests/library_checker_aizu_tests/trees/subtree_isomorphism.test.cpp delete mode 100644 tests/scripts/README.md delete mode 100755 tests/scripts/build_pdf.sh delete mode 100755 tests/scripts/clangtidy.sh delete mode 100755 tests/scripts/compile_clang.sh delete mode 100755 tests/scripts/compile_commented_snippets.sh delete mode 100755 tests/scripts/compile_gcc.sh delete mode 100755 tests/scripts/do_format.sh delete mode 100755 tests/scripts/find_files_without_tests.sh delete mode 100755 tests/scripts/grep_clangformat_cppcheck.sh delete mode 100755 tests/scripts/print_which_tests_havent_run.sh delete mode 100755 tests/scripts/shellcheck_shfmt.sh delete mode 100755 tests/scripts/update_main.sh rename {library/trees => trees}/edge_cd.hpp (81%) rename {library/trees => trees}/edge_cd.png (100%) rename {library/trees => trees}/extra_members/dist.hpp (100%) rename {library/trees => trees}/extra_members/in_subtree.hpp (100%) rename {library/trees => trees}/extra_members/next_on_path.hpp (95%) rename {library/trees => trees}/extra_members/on_path.hpp (100%) rename {library/trees => trees}/extra_members/virtual_tree.hpp (78%) rename {library/trees => trees}/hld.hpp (88%) create mode 100644 trees/lca_rmq.hpp rename {library/trees => trees}/linear_kth_par.hpp (83%) rename {library/trees => trees}/linear_lca.hpp (81%) rename {library/trees => trees}/shallowest_decomp_tree.hpp (87%) rename {library/trees => trees}/tree_lift.hpp (85%) rename {library/trees => trees}/uncommon/centroid_decomp.hpp (93%) create mode 100644 trees/uncommon/contour_range_query.hpp create mode 100644 trees/uncommon/contour_range_update.hpp create mode 100644 trees/uncommon/count_paths_per_length.hpp create mode 100644 trees/uncommon/count_paths_per_node.hpp create mode 100644 trees/uncommon/ladder_decomposition.hpp rename {library/trees => trees}/uncommon/subtree_isomorphism.hpp (75%) rename {library/trees => trees}/uncommon/sum_adjacent.hpp (77%) diff --git a/.github/workflows/programming_team_code_ci.yml b/.github/workflows/programming_team_code_ci.yml deleted file mode 100644 index 73944837..00000000 --- a/.github/workflows/programming_team_code_ci.yml +++ /dev/null @@ -1,151 +0,0 @@ -name: programming team code CI - -on: push - -permissions: - contents: write - -jobs: - library_checker_aizu: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: pip3 install -U online-judge-verify-helper - - name: Set up Rust (nightly) - run: | - rustup set profile minimal - rustup install nightly - rustup override set nightly - - name: Set up git submodules - run: | - git submodule init - git submodule update - rm -rf hackpack-cpp/tests/ - - name: Run library checker and aizu tests - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: oj-verify all --tle 60 --timeout 21600 - - grep_clangformat_cppcheck: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Set up LLVM repository - run: | - sudo apt update - sudo apt install -y wget software-properties-common - wget -O - https://apt.llvm.org/llvm.sh | sudo bash - - name: Install dependencies - run: sudo apt update && sudo apt install -y clang-format-19 cppcheck - - name: grep, clang-format, cppcheck - run: make --directory=tests/ grep_clangformat_cppcheck - - clangtidy: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Set up LLVM repository - run: | - sudo apt update - sudo apt install -y wget software-properties-common - wget -O - https://apt.llvm.org/llvm.sh | sudo bash - - name: Install dependencies - run: sudo apt update && sudo apt install -y clang-tidy-19 - - name: clang-tidy - run: make --directory=tests/ clangtidy - - compile_gcc: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: g++ with gcc - run: make --directory=tests/ compile_gcc - - compile_clang: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Set up LLVM repository - run: wget -qO- https://apt.llvm.org/llvm.sh | sudo bash -s -- 19 - - name: Install dependencies - run: sudo apt update && sudo apt install -y clang-19 - - name: g++ with clang - run: make --directory=tests/ compile_clang - - find_files_without_tests: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: find files without tests - run: make --directory=tests/ find_files_without_tests - - build_pdf: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Install texlive, rename, nodejs, npm, clang - run: | - sudo apt update - sudo apt install texlive texlive-latex-extra rename nodejs npm - wget -qO- https://apt.llvm.org/llvm.sh | sudo bash -s -- 19 - sudo apt update && sudo apt install -y clang-19 - - name: build pdf - run: make --directory=tests/ build_pdf - - uses: actions/upload-artifact@v4 - with: - name: ptc - path: tests/ptc.pdf - - publish_pdf: - runs-on: ubuntu-latest - needs: [library_checker_aizu, grep_clangformat_cppcheck, clangtidy, compile_gcc, compile_clang, find_files_without_tests, build_pdf] - if: github.ref == 'refs/heads/dev' && github.event_name == 'push' - steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4 - with: - name: ptc - path: tests/ptc.pdf - - uses: marvinpinto/action-automatic-releases@latest - with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - automatic_release_tag: ptc - prerelease: false - title: ptc - files: tests/ptc.pdf - - update_main: - runs-on: ubuntu-latest - needs: [library_checker_aizu, grep_clangformat_cppcheck, clangtidy, compile_gcc, compile_clang, find_files_without_tests] - if: github.ref == 'refs/heads/dev' && github.event_name == 'push' - steps: - - uses: actions/checkout@v4 - - name: Set up LLVM repository - run: | - sudo apt update - sudo apt install -y wget software-properties-common - wget -O - https://apt.llvm.org/llvm.sh | sudo bash - - name: Install dependencies - run: sudo apt update && sudo apt install -y clang-format-19 - - name: Combine includes and force push to main branch - run: | - git config --local user.name github-actions - git config --local user.email 160645609+programming-team-code@users.noreply.github.com - make --directory=tests/ update_main - git rm -rf library/ tests/ .verify-helper/ .gitmodules kactl/ hackpack-cpp/ notebook-generator/ .github/ - git add --all - git commit --message "programming_team_code" - git checkout -b main - git push origin main --force - - shellcheck_shfmt: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Install dependencies - run: sudo apt install shfmt shellcheck - - name: shellcheck, shfmt - run: make --directory=tests/ shellcheck_shfmt diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index e28d462b..00000000 --- a/.gitmodules +++ /dev/null @@ -1,9 +0,0 @@ -[submodule "notebook-generator"] - path = notebook-generator - url = https://github.com/programming-team-code/notebook-generator -[submodule "hackpack-cpp"] - path = hackpack-cpp - url = https://github.com/ucf-programming-team/hackpack-cpp -[submodule "kactl"] - path = kactl - url = https://github.com/kth-competitive-programming/kactl diff --git a/.verify-helper/config.toml b/.verify-helper/config.toml deleted file mode 100644 index 70d17462..00000000 --- a/.verify-helper/config.toml +++ /dev/null @@ -1,14 +0,0 @@ -[[languages.cpp.environments]] -CXX = "g++" -CXXFLAGS = [ - "-O2", - "-std=c++20", - "-fsanitize=address,undefined", - "-fno-sanitize-recover=all", - "-fstack-protector", - "-D_GLIBCXX_DEBUG", - "-D_GLIBCXX_SANITIZE_VECTOR", - "-D_GLIBCXX_DEBUG_PEDANTIC", - "-D_GLIBCXX_ASSERTIONS", - "-D_FORTIFY_SOURCE=2", -] diff --git a/.verify-helper/timestamps.remote.json b/.verify-helper/timestamps.remote.json deleted file mode 100644 index 5e41bede..00000000 --- a/.verify-helper/timestamps.remote.json +++ /dev/null @@ -1,145 +0,0 @@ -{ -"tests/library_checker_aizu_tests/convolution/gcd_convolution.test.cpp": "2025-08-28 13:19:16 -0600", -"tests/library_checker_aizu_tests/convolution/lcm_convolution.test.cpp": "2025-08-28 13:19:16 -0600", -"tests/library_checker_aizu_tests/convolution/min_plus_convolution.test.cpp": "2024-11-17 14:04:03 -0600", -"tests/library_checker_aizu_tests/data_structures/binary_search_example.test.cpp": "2024-11-18 10:51:39 -0600", -"tests/library_checker_aizu_tests/data_structures/binary_trie.test.cpp": "2025-08-06 18:45:47 -0600", -"tests/library_checker_aizu_tests/data_structures/bit.test.cpp": "2025-08-06 19:02:15 -0600", -"tests/library_checker_aizu_tests/data_structures/bit_inc.test.cpp": "2025-08-06 19:02:15 -0600", -"tests/library_checker_aizu_tests/data_structures/bit_ordered_set.test.cpp": "2025-08-06 19:02:15 -0600", -"tests/library_checker_aizu_tests/data_structures/bit_rupq.test.cpp": "2025-08-06 19:02:15 -0600", -"tests/library_checker_aizu_tests/data_structures/bit_rurq.test.cpp": "2025-08-06 19:02:15 -0600", -"tests/library_checker_aizu_tests/data_structures/bit_walk.test.cpp": "2025-08-06 19:02:15 -0600", -"tests/library_checker_aizu_tests/data_structures/deque.test.cpp": "2025-08-06 18:57:15 -0600", -"tests/library_checker_aizu_tests/data_structures/deque_index.test.cpp": "2025-08-22 11:48:31 -0600", -"tests/library_checker_aizu_tests/data_structures/deque_op.test.cpp": "2025-08-06 18:57:15 -0600", -"tests/library_checker_aizu_tests/data_structures/deque_sliding_window.test.cpp": "2025-08-06 18:57:15 -0600", -"tests/library_checker_aizu_tests/data_structures/disjoint_rmq_inc.test.cpp": "2024-12-14 15:47:13 -0600", -"tests/library_checker_aizu_tests/data_structures/disjoint_rmq_inc_lines.test.cpp": "2024-12-14 15:47:13 -0600", -"tests/library_checker_aizu_tests/data_structures/disjoint_rmq_lines.test.cpp": "2024-12-14 15:47:13 -0600", -"tests/library_checker_aizu_tests/data_structures/disjoint_rmq_sum.test.cpp": "2024-12-14 15:47:13 -0600", -"tests/library_checker_aizu_tests/data_structures/distinct_query.test.cpp": "2024-12-05 10:41:42 -0600", -"tests/library_checker_aizu_tests/data_structures/dsu.test.cpp": "2025-08-22 13:14:15 -0600", -"tests/library_checker_aizu_tests/data_structures/dsu_bipartite.test.cpp": "2025-08-05 15:52:46 -0600", -"tests/library_checker_aizu_tests/data_structures/dsu_restorable.test.cpp": "2024-11-17 14:04:03 -0600", -"tests/library_checker_aizu_tests/data_structures/dsu_segtree_undo_trick.test.cpp": "2024-12-14 19:50:29 -0600", -"tests/library_checker_aizu_tests/data_structures/implicit_seg_tree.test.cpp": "2025-08-28 13:51:20 -0600", -"tests/library_checker_aizu_tests/data_structures/kruskal_tree_aizu.test.cpp": "2025-08-05 13:14:30 -0600", -"tests/library_checker_aizu_tests/data_structures/kth_smallest_pst.test.cpp": "2024-12-05 10:41:42 -0600", -"tests/library_checker_aizu_tests/data_structures/kth_smallest_wavelet_matrix.test.cpp": "2025-07-10 12:34:21 -0600", -"tests/library_checker_aizu_tests/data_structures/lazy_segment_tree.test.cpp": "2024-12-14 19:50:29 -0600", -"tests/library_checker_aizu_tests/data_structures/lazy_segment_tree_constructor.test.cpp": "2024-12-14 19:50:29 -0600", -"tests/library_checker_aizu_tests/data_structures/lazy_segment_tree_inc.test.cpp": "2024-12-05 10:41:42 -0600", -"tests/library_checker_aizu_tests/data_structures/lazy_segment_tree_inc_constructor.test.cpp": "2024-12-05 10:41:42 -0600", -"tests/library_checker_aizu_tests/data_structures/line_tree_aizu.test.cpp": "2025-02-10 14:50:36 -0700", -"tests/library_checker_aizu_tests/data_structures/line_tree_lib_checker.test.cpp": "2025-08-05 13:14:30 -0600", -"tests/library_checker_aizu_tests/data_structures/merge_sort_tree.test.cpp": "2025-08-04 17:01:28 -0600", -"tests/library_checker_aizu_tests/data_structures/mode_query.test.cpp": "2025-08-04 17:01:28 -0600", -"tests/library_checker_aizu_tests/data_structures/permutation_tree.test.cpp": "2025-08-14 12:01:15 -0600", -"tests/library_checker_aizu_tests/data_structures/persistent_queue_tree.test.cpp": "2025-02-10 14:50:36 -0700", -"tests/library_checker_aizu_tests/data_structures/persistent_seg_tree.test.cpp": "2024-12-05 10:41:42 -0600", -"tests/library_checker_aizu_tests/data_structures/pq_ds_undo_sliding_window.test.cpp": "2025-02-10 14:50:36 -0700", -"tests/library_checker_aizu_tests/data_structures/pq_ds_undo_with_dsu.test.cpp": "2025-02-10 14:50:36 -0700", -"tests/library_checker_aizu_tests/data_structures/range_parallel_dsu.test.cpp": "2025-09-07 15:50:55 -0600", -"tests/library_checker_aizu_tests/data_structures/rmq_disjoint_sparse_table.test.cpp": "2024-12-15 14:34:10 -0600", -"tests/library_checker_aizu_tests/data_structures/rmq_linear.test.cpp": "2025-08-14 12:01:15 -0600", -"tests/library_checker_aizu_tests/data_structures/rmq_sparse_table.test.cpp": "2025-08-14 12:01:15 -0600", -"tests/library_checker_aizu_tests/data_structures/rmq_sparse_table_inc.test.cpp": "2024-12-15 14:34:10 -0600", -"tests/library_checker_aizu_tests/data_structures/simple_tree.test.cpp": "2024-12-14 15:47:13 -0600", -"tests/library_checker_aizu_tests/data_structures/simple_tree_inc.test.cpp": "2024-12-21 00:23:10 -0500", -"tests/library_checker_aizu_tests/data_structures/simple_tree_inc_line.test.cpp": "2024-12-21 00:23:10 -0500", -"tests/library_checker_aizu_tests/data_structures/simple_tree_line.test.cpp": "2024-12-14 15:47:13 -0600", -"tests/library_checker_aizu_tests/flow/dinic_aizu.test.cpp": "2024-11-17 14:04:03 -0600", -"tests/library_checker_aizu_tests/flow/hungarian.test.cpp": "2024-11-17 14:04:03 -0600", -"tests/library_checker_aizu_tests/flow/min_cost_max_flow.test.cpp": "2024-12-05 10:41:42 -0600", -"tests/library_checker_aizu_tests/graphs/bcc_callback_aizu_bcc.test.cpp": "2025-08-14 10:27:46 -0600", -"tests/library_checker_aizu_tests/graphs/bcc_callback_aizu_two_edge_cc.test.cpp": "2025-08-14 10:27:46 -0600", -"tests/library_checker_aizu_tests/graphs/bcc_callback_lib_checker_bcc.test.cpp": "2025-08-14 10:27:46 -0600", -"tests/library_checker_aizu_tests/graphs/bcc_callback_lib_checker_two_cc.test.cpp": "2025-08-22 13:14:15 -0600", -"tests/library_checker_aizu_tests/graphs/biconnected_components.test.cpp": "2025-08-14 10:27:46 -0600", -"tests/library_checker_aizu_tests/graphs/connected_components_of_complement_graph.test.cpp": "2025-08-14 10:27:46 -0600", -"tests/library_checker_aizu_tests/graphs/dijkstra_aizu.test.cpp": "2025-08-14 10:27:46 -0600", -"tests/library_checker_aizu_tests/graphs/dijkstra_lib_checker.test.cpp": "2025-08-14 10:27:46 -0600", -"tests/library_checker_aizu_tests/graphs/directed_cycle.test.cpp": "2025-08-14 10:27:46 -0600", -"tests/library_checker_aizu_tests/graphs/enumerate_triangles.test.cpp": "2025-08-06 16:18:37 -0600", -"tests/library_checker_aizu_tests/graphs/hopcroft_karp_aizu.test.cpp": "2025-08-14 10:27:46 -0600", -"tests/library_checker_aizu_tests/graphs/hopcroft_karp_lib_checker.test.cpp": "2025-08-14 10:27:46 -0600", -"tests/library_checker_aizu_tests/graphs/mst.test.cpp": "2025-08-22 13:27:42 -0600", -"tests/library_checker_aizu_tests/graphs/offline_incremental_scc.test.cpp": "2025-09-07 15:50:55 -0600", -"tests/library_checker_aizu_tests/graphs/strongly_connected_components_aizu.test.cpp": "2025-08-14 10:27:46 -0600", -"tests/library_checker_aizu_tests/graphs/strongly_connected_components_lib_checker.test.cpp": "2025-08-14 10:27:46 -0600", -"tests/library_checker_aizu_tests/graphs/two_edge_components.test.cpp": "2025-08-14 10:27:46 -0600", -"tests/library_checker_aizu_tests/handmade_tests/count_paths.test.cpp": "2025-08-28 13:57:36 -0600", -"tests/library_checker_aizu_tests/handmade_tests/dsu.test.cpp": "2025-08-22 13:14:15 -0600", -"tests/library_checker_aizu_tests/handmade_tests/dsu_size.test.cpp": "2024-12-14 19:50:29 -0600", -"tests/library_checker_aizu_tests/handmade_tests/edge_cd_small_trees.test.cpp": "2025-09-07 15:50:55 -0600", -"tests/library_checker_aizu_tests/handmade_tests/fib_matrix_expo.test.cpp": "2025-08-28 13:19:16 -0600", -"tests/library_checker_aizu_tests/handmade_tests/functional_graph.test.cpp": "2025-08-06 16:18:37 -0600", -"tests/library_checker_aizu_tests/handmade_tests/manacher.test.cpp": "2024-12-14 19:50:29 -0600", -"tests/library_checker_aizu_tests/handmade_tests/merge_st_and_wavelet.test.cpp": "2025-08-04 17:01:28 -0600", -"tests/library_checker_aizu_tests/handmade_tests/mobius.test.cpp": "2025-02-10 14:50:36 -0700", -"tests/library_checker_aizu_tests/handmade_tests/mod_division.test.cpp": "2025-09-07 16:12:35 -0600", -"tests/library_checker_aizu_tests/handmade_tests/n_choose_k.test.cpp": "2025-08-28 13:19:16 -0600", -"tests/library_checker_aizu_tests/handmade_tests/permutation_tree_small.test.cpp": "2025-08-14 12:01:15 -0600", -"tests/library_checker_aizu_tests/handmade_tests/rmq_small_n.test.cpp": "2025-08-14 12:01:15 -0600", -"tests/library_checker_aizu_tests/handmade_tests/sa_find_subarray.test.cpp": "2025-02-10 14:50:36 -0700", -"tests/library_checker_aizu_tests/handmade_tests/seg_tree_find.test.cpp": "2025-08-06 19:02:15 -0600", -"tests/library_checker_aizu_tests/handmade_tests/seg_tree_find_small.test.cpp": "2024-12-14 19:50:29 -0600", -"tests/library_checker_aizu_tests/loops/chooses.test.cpp": "2025-02-10 14:50:36 -0700", -"tests/library_checker_aizu_tests/loops/quotients.test.cpp": "2024-11-17 14:04:03 -0600", -"tests/library_checker_aizu_tests/loops/submasks.test.cpp": "2025-02-10 14:50:36 -0700", -"tests/library_checker_aizu_tests/loops/supermasks.test.cpp": "2025-02-10 14:50:36 -0700", -"tests/library_checker_aizu_tests/math/binary_matrix_mult.test.cpp": "2024-11-17 14:04:03 -0600", -"tests/library_checker_aizu_tests/math/count_paths.test.cpp": "2025-08-28 13:19:16 -0600", -"tests/library_checker_aizu_tests/math/derangement.test.cpp": "2024-11-17 14:04:03 -0600", -"tests/library_checker_aizu_tests/math/matrix_determinant.test.cpp": "2025-09-07 16:12:35 -0600", -"tests/library_checker_aizu_tests/math/matrix_mult.test.cpp": "2024-11-17 14:04:03 -0600", -"tests/library_checker_aizu_tests/math/n_choose_k.test.cpp": "2025-08-28 13:19:16 -0600", -"tests/library_checker_aizu_tests/math/num_subsequences.test.cpp": "2024-11-17 14:04:03 -0600", -"tests/library_checker_aizu_tests/math/partitions.test.cpp": "2025-08-28 13:19:16 -0600", -"tests/library_checker_aizu_tests/math/prime_sieve.test.cpp": "2024-11-22 11:54:52 -0600", -"tests/library_checker_aizu_tests/math/solve_linear_mod.test.cpp": "2025-09-07 16:12:35 -0600", -"tests/library_checker_aizu_tests/math/tetration.test.cpp": "2024-11-17 14:04:03 -0600", -"tests/library_checker_aizu_tests/math/totient.test.cpp": "2024-11-17 14:04:03 -0600", -"tests/library_checker_aizu_tests/math/xor_basis.test.cpp": "2025-08-04 20:35:27 -0600", -"tests/library_checker_aizu_tests/math/xor_basis_intersection.test.cpp": "2025-08-04 20:35:27 -0600", -"tests/library_checker_aizu_tests/monotonic_stack_related/cartesian_binary_tree.test.cpp": "2025-02-10 14:50:36 -0700", -"tests/library_checker_aizu_tests/monotonic_stack_related/cartesian_k_ary_tree.test.cpp": "2025-08-14 12:01:15 -0600", -"tests/library_checker_aizu_tests/monotonic_stack_related/count_rectangles.test.cpp": "2025-08-14 12:01:15 -0600", -"tests/library_checker_aizu_tests/monotonic_stack_related/max_rect_histogram.test.cpp": "2025-08-14 12:01:15 -0600", -"tests/library_checker_aizu_tests/strings/kmp.test.cpp": "2025-08-05 19:19:23 -0600", -"tests/library_checker_aizu_tests/strings/lcp_array.test.cpp": "2025-08-05 19:19:23 -0600", -"tests/library_checker_aizu_tests/strings/lcp_query_palindrome.test.cpp": "2025-08-05 19:19:23 -0600", -"tests/library_checker_aizu_tests/strings/lcp_query_zfunc.test.cpp": "2025-08-05 19:19:23 -0600", -"tests/library_checker_aizu_tests/strings/lcs_dp.test.cpp": "2025-08-05 19:19:23 -0600", -"tests/library_checker_aizu_tests/strings/lcs_queries.test.cpp": "2025-08-06 19:02:15 -0600", -"tests/library_checker_aizu_tests/strings/lcs_queries_merge_sort_tree.test.cpp": "2025-08-05 19:19:23 -0600", -"tests/library_checker_aizu_tests/strings/manacher.test.cpp": "2025-08-05 19:19:23 -0600", -"tests/library_checker_aizu_tests/strings/multi_matching_bs.test.cpp": "2025-08-05 19:19:23 -0600", -"tests/library_checker_aizu_tests/strings/prefix_function.test.cpp": "2025-08-05 19:19:23 -0600", -"tests/library_checker_aizu_tests/strings/sa_cmp.test.cpp": "2025-02-10 14:50:36 -0700", -"tests/library_checker_aizu_tests/strings/sa_sort_pairs.test.cpp": "2025-02-10 14:50:36 -0700", -"tests/library_checker_aizu_tests/strings/single_matching_bs.test.cpp": "2025-08-05 19:19:23 -0600", -"tests/library_checker_aizu_tests/strings/suffix_array.test.cpp": "2025-08-14 12:01:15 -0600", -"tests/library_checker_aizu_tests/strings/suffix_array_short.test.cpp": "2025-08-05 19:19:23 -0600", -"tests/library_checker_aizu_tests/strings/trie.test.cpp": "2025-08-06 19:26:46 -0600", -"tests/library_checker_aizu_tests/strings/wildcard_pattern_matching.test.cpp": "2025-08-05 19:19:23 -0600", -"tests/library_checker_aizu_tests/trees/count_paths_per_length.test.cpp": "2025-08-14 10:27:46 -0600", -"tests/library_checker_aizu_tests/trees/edge_cd_contour_range_query.test.cpp": "2025-08-14 10:27:46 -0600", -"tests/library_checker_aizu_tests/trees/edge_cd_contour_range_update.test.cpp": "2025-08-14 10:27:46 -0600", -"tests/library_checker_aizu_tests/trees/edge_cd_count_paths_per_length.test.cpp": "2025-08-14 10:27:46 -0600", -"tests/library_checker_aizu_tests/trees/edge_cd_reroot_dp.test.cpp": "2025-09-07 15:50:55 -0600", -"tests/library_checker_aizu_tests/trees/hld_aizu1.test.cpp": "2025-08-24 19:27:23 -0600", -"tests/library_checker_aizu_tests/trees/hld_aizu2.test.cpp": "2025-08-24 19:27:23 -0600", -"tests/library_checker_aizu_tests/trees/hld_lib_checker_path.test.cpp": "2025-08-24 19:27:23 -0600", -"tests/library_checker_aizu_tests/trees/hld_lib_checker_subtree_edges.test.cpp": "2025-08-24 19:27:23 -0600", -"tests/library_checker_aizu_tests/trees/hld_lib_checker_subtree_nodes.test.cpp": "2025-08-24 19:27:23 -0600", -"tests/library_checker_aizu_tests/trees/kth_path_ladder.test.cpp": "2025-08-14 12:01:15 -0600", -"tests/library_checker_aizu_tests/trees/kth_path_linear.test.cpp": "2025-08-21 12:17:27 -0600", -"tests/library_checker_aizu_tests/trees/kth_path_tree_lift.test.cpp": "2025-08-14 10:27:46 -0600", -"tests/library_checker_aizu_tests/trees/lca_all_methods_aizu.test.cpp": "2025-08-21 12:17:27 -0600", -"tests/library_checker_aizu_tests/trees/lca_all_methods_lib_checker.test.cpp": "2025-08-21 12:17:27 -0600", -"tests/library_checker_aizu_tests/trees/shallowest_aizu_tree_height.test.cpp": "2025-09-03 10:32:09 -0600", -"tests/library_checker_aizu_tests/trees/shallowest_lib_checker_tree_path_composite.test.cpp": "2025-09-07 15:50:55 -0600", -"tests/library_checker_aizu_tests/trees/subtree_isomorphism.test.cpp": "2025-08-14 10:27:46 -0600" -} \ No newline at end of file diff --git a/library/contest/README.md b/contest/README.md similarity index 100% rename from library/contest/README.md rename to contest/README.md diff --git a/library/contest/binary_search.hpp b/contest/binary_search.hpp similarity index 73% rename from library/contest/binary_search.hpp rename to contest/binary_search.hpp index e373de66..d1a37eba 100644 --- a/library/contest/binary_search.hpp +++ b/contest/binary_search.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://codeforces.com/blog/entry/134777 //! returns first x in [lo, hi) such that lambda returns 0, //! or hi if it doesn't exist. Be careful to make sure the @@ -7,5 +6,5 @@ //! //! @time O(log(hi-lo)) //! @space O(1) -ll res = *ranges::partition_point(views::iota(lo, hi), - [&](ll x) -> bool { return x < 0; }); +int64_t res = *ranges::partition_point(views::iota(lo, hi), + [&](int64_t x) -> bool { return x < 0; }); diff --git a/library/contest/hash.sh b/contest/hash.sh similarity index 100% rename from library/contest/hash.sh rename to contest/hash.sh diff --git a/library/contest/random.hpp b/contest/random.hpp similarity index 97% rename from library/contest/random.hpp rename to contest/random.hpp index 9a868d3e..9709f814 100644 --- a/library/contest/random.hpp +++ b/contest/random.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://codeforces.com/blog/entry/61675 //! @code //! //mt19937_64 rng(chrono...); diff --git a/library/contest/template.cpp b/contest/template.cpp similarity index 100% rename from library/contest/template.cpp rename to contest/template.cpp diff --git a/library/contest/tester.sh b/contest/tester.sh similarity index 100% rename from library/contest/tester.sh rename to contest/tester.sh diff --git a/library/convolution/gcd_convolution.hpp b/convolution/gcd_convolution.hpp similarity index 76% rename from library/convolution/gcd_convolution.hpp rename to convolution/gcd_convolution.hpp index 6af1f424..7948c936 100644 --- a/library/convolution/gcd_convolution.hpp +++ b/convolution/gcd_convolution.hpp @@ -1,4 +1,3 @@ -#pragma once //! @code //! auto gcd_conv = gcd_convolution(a, b); //! @endcode @@ -8,11 +7,12 @@ //! @time O(n log n) //! @space O(n) const int mod = 998'244'353; -vi gcd_convolution(const vi& a, const vi& b) { - int n = sz(a); - vi c(n); +vector gcd_convolution(const vector& a, + const vector& b) { + int n = ssize(a); + vector c(n); for (int g = n - 1; g >= 1; g--) { - ll sum_a = 0, sum_b = 0; + int64_t sum_a = 0, sum_b = 0; for (int i = g; i < n; i += g) { sum_a += a[i], sum_b += b[i]; if ((c[g] -= c[i]) < 0) c[g] += mod; diff --git a/library/convolution/lcm_convolution.hpp b/convolution/lcm_convolution.hpp similarity index 72% rename from library/convolution/lcm_convolution.hpp rename to convolution/lcm_convolution.hpp index 85449dc2..8f2cc8ee 100644 --- a/library/convolution/lcm_convolution.hpp +++ b/convolution/lcm_convolution.hpp @@ -1,4 +1,3 @@ -#pragma once //! @code //! auto lcm_conv = lcm_convolution(a, b); //! @endcode @@ -8,11 +7,12 @@ //! @time O(n log n) //! @space O(n) const int mod = 998'244'353; -vi lcm_convolution(const vi& a, const vi& b) { - int n = sz(a); - vector sum_a(n), sum_b(n); - vi c(n); - rep(i, 1, n) { +vector lcm_convolution(const vector& a, + const vector& b) { + int n = ssize(a); + vector sum_a(n), sum_b(n); + vector c(n); + for (int i = 1; i < n; i++) { for (int j = i; j < n; j += i) sum_a[j] += a[i], sum_b[j] += b[i]; sum_a[i] %= mod, sum_b[i] %= mod; diff --git a/library/convolution/min_plus_convolution_convex_and_arbitrary.hpp b/convolution/min_plus_convolution_convex_and_arbitrary.hpp similarity index 77% rename from library/convolution/min_plus_convolution_convex_and_arbitrary.hpp rename to convolution/min_plus_convolution_convex_and_arbitrary.hpp index dd26c4df..fc6d93db 100644 --- a/library/convolution/min_plus_convolution_convex_and_arbitrary.hpp +++ b/convolution/min_plus_convolution_convex_and_arbitrary.hpp @@ -1,20 +1,21 @@ -#pragma once //! @param convex,arbitrary arrays where convex satisfies //! convex[i+1]-convex[i] <= convex[i+2]-convex[i+1] //! @returns array `res` where `res[k]` = the min of //! (a[i]+b[j]) for all pairs (i,j) where i+j==k //! @time O((n + m) log (n + m)) //! @space O(n + m) -vi min_plus(const vi& convex, const vi& arbitrary) { - int n = sz(convex); - int m = sz(arbitrary); - vi res(n + m - 1, INT_MAX); +vector min_plus(const vector& convex, + const vector& arbitrary) { + int n = ssize(convex); + int m = ssize(arbitrary); + vector res(n + m - 1, INT_MAX); auto dnc = [&](auto&& self, int res_le, int res_ri, int arb_le, int arb_ri) -> void { if (res_le >= res_ri) return; int mid_res = (res_le + res_ri) / 2; int op_arb = arb_le; - rep(i, arb_le, min(mid_res + 1, arb_ri)) { + for (int i = arb_le; i < min(mid_res + 1, arb_ri); + i++) { int j = mid_res - i; if (j >= n) continue; if (res[mid_res] > convex[j] + arbitrary[i]) { diff --git a/library/data_structures/README.md b/data_structures/README.md similarity index 100% rename from library/data_structures/README.md rename to data_structures/README.md diff --git a/library/data_structures/binary_trie.hpp b/data_structures/binary_trie.hpp similarity index 72% rename from library/data_structures/binary_trie.hpp rename to data_structures/binary_trie.hpp index 1ab72dbc..025a71e1 100644 --- a/library/data_structures/binary_trie.hpp +++ b/data_structures/binary_trie.hpp @@ -1,4 +1,3 @@ -#pragma once //! @code //! binary_trie bt; //! bt.update(num, 1); // insert @@ -6,7 +5,7 @@ //! @endcode //! @time O(q * mx_bit) //! @space O(q * mx_bit) -const ll mx_bit = 1LL << 60; +const int64_t mx_bit = 1LL << 60; struct binary_trie { struct node { int siz = 0; @@ -14,22 +13,22 @@ struct binary_trie { }; deque t; binary_trie(): t(1) {} - void update(ll num, int delta) { + void update(int64_t num, int delta) { int v = 0; - for (ll bit = mx_bit; bit; bit /= 2) { + for (int64_t bit = mx_bit; bit; bit /= 2) { bool b = num & bit; if (t[v].next[b] == -1) { - t[v].next[b] = sz(t); + t[v].next[b] = ssize(t); t.emplace_back(); } v = t[v].next[b]; t[v].siz += delta; } } - ll walk(ll num) { + int64_t walk(int64_t num) { int v = 0; - ll res = 0; - for (ll bit = mx_bit; bit; bit /= 2) { + int64_t res = 0; + for (int64_t bit = mx_bit; bit; bit /= 2) { bool b = num & bit; int u = t[v].next[b]; if (u != -1 && t[u].siz > 0) v = u, res |= num & bit; diff --git a/data_structures/bit.hpp b/data_structures/bit.hpp new file mode 100644 index 00000000..daef2244 --- /dev/null +++ b/data_structures/bit.hpp @@ -0,0 +1,33 @@ +//! @time O(n + q log n) +//! @space O(n) +struct BIT { + vector s; + BIT(int n): s(n) {} + BIT(const vector& a): s(a) { + for (int i = 0; i < ssize(a); i++) { + int j = i | (i + 1); + if (j < ssize(a)) s[j] += s[i]; + } + } + void update(int i, int64_t d) { + for (; i < ssize(s); i |= i + 1) s[i] += d; + } + int64_t query(int r) { // [0, r) + int64_t ret = 0; + for (; r > 0; r &= r - 1) ret += s[r - 1]; + return ret; + } + int64_t query(int l, int r) { // [l, r) + return query(r) - query(l); + } + //! Requires s[i] >= 0 + //! max r such that sum of [0,r) < sum, or -1 + int walk(int64_t sum) { + if (sum <= 0) return -1; + int r = 0; + for (int pw = bit_floor(size(s)); pw; pw >>= 1) + if (r + pw <= ssize(s) && s[r + pw - 1] < sum) + sum -= s[(r += pw) - 1]; + return r; + } +}; diff --git a/data_structures/bit_inc.hpp b/data_structures/bit_inc.hpp new file mode 100644 index 00000000..8ea3c539 --- /dev/null +++ b/data_structures/bit_inc.hpp @@ -0,0 +1,33 @@ +//! @time O(n + q log n) +//! @space O(n) +struct bit_inc { + vector s; + bit_inc(int n): s(n) {} + void update(int i, int64_t d) { + for (; i < ssize(s); i |= i + 1) s[i] += d; + } + int64_t query(int i) { // [0, i] + int64_t ret = 0; + for (; i >= 0; (i &= i + 1)--) ret += s[i]; + return ret; + } + int64_t query(int l, int r) { // [l, r] + return query(r) - query(l - 1); + } + //! Requires s[i] >= 0 + //! max r such that sum of [0,r) < sum, or -1 + int walk(int64_t sum) { + if (sum <= 0) return -1; + int r = 0; + for (int pw = bit_floor(size(s)); pw; pw >>= 1) + if (r + pw <= ssize(s) && s[r + pw - 1] < sum) + sum -= s[(r += pw) - 1]; + return r; + } + //! Requires s[i] >= 0 + //! max j such that j<=i && query(j,j)>0, or -1 + int prev(int i) { return walk(query(i)); } + //! Requires s[i] >= 0 + //! min j such that j>=i && query(j,j)>0, or sz(s) + int next(int i) { return walk(query(i - 1) + 1); } +}; diff --git a/library/data_structures/bit_uncommon/next.hpp b/data_structures/bit_uncommon/next.hpp similarity index 100% rename from library/data_structures/bit_uncommon/next.hpp rename to data_structures/bit_uncommon/next.hpp diff --git a/library/data_structures/bit_uncommon/prev.hpp b/data_structures/bit_uncommon/prev.hpp similarity index 100% rename from library/data_structures/bit_uncommon/prev.hpp rename to data_structures/bit_uncommon/prev.hpp diff --git a/data_structures/bit_uncommon/rupq.hpp b/data_structures/bit_uncommon/rupq.hpp new file mode 100644 index 00000000..3ea69162 --- /dev/null +++ b/data_structures/bit_uncommon/rupq.hpp @@ -0,0 +1,53 @@ +//! @time O(n + q log n) +//! @space O(n) +struct BIT { + vector s; + BIT(int n): s(n) {} + BIT(const vector& a): s(a) { + for (int i = 0; i < ssize(a); i++) { + int j = i | (i + 1); + if (j < ssize(a)) s[j] += s[i]; + } + } + void update(int i, int64_t d) { + for (; i < ssize(s); i |= i + 1) s[i] += d; + } + int64_t query(int r) { // [0, r) + int64_t ret = 0; + for (; r > 0; r &= r - 1) ret += s[r - 1]; + return ret; + } + int64_t query(int l, int r) { // [l, r) + return query(r) - query(l); + } + //! Requires s[i] >= 0 + //! max r such that sum of [0,r) < sum, or -1 + int walk(int64_t sum) { + if (sum <= 0) return -1; + int r = 0; + for (int pw = bit_floor(size(s)); pw; pw >>= 1) + if (r + pw <= ssize(s) && s[r + pw - 1] < sum) + sum -= s[(r += pw) - 1]; + return r; + } +}; +struct bit_rupq { + int n; + BIT bit = {0}; + bit_rupq(int n): n(n), bit(n) {} + bit_rupq(vector a): n(ssize(a)) { + adjacent_difference(begin(a), end(a), begin(a)); + bit = {a}; + } + //! does a[l]+=d, a[l+1]+=d, .., a[r-1]+=d + //! @time O(log n) + //! @space O(1) + void update(int l, int r, int64_t d) { + if (l < n) bit.update(l, d); + if (r < n) bit.update(r, -d); + } + //! @returns a[i] + //! @time O(log n) + //! @space O(1) + int64_t get_index(int i) { return bit.query(i + 1); } +}; diff --git a/data_structures/bit_uncommon/rurq.hpp b/data_structures/bit_uncommon/rurq.hpp new file mode 100644 index 00000000..c4bee6e4 --- /dev/null +++ b/data_structures/bit_uncommon/rurq.hpp @@ -0,0 +1,70 @@ +//! @time O(n + q log n) +//! @space O(n) +struct BIT { + vector s; + BIT(int n): s(n) {} + BIT(const vector& a): s(a) { + for (int i = 0; i < ssize(a); i++) { + int j = i | (i + 1); + if (j < ssize(a)) s[j] += s[i]; + } + } + void update(int i, int64_t d) { + for (; i < ssize(s); i |= i + 1) s[i] += d; + } + int64_t query(int r) { // [0, r) + int64_t ret = 0; + for (; r > 0; r &= r - 1) ret += s[r - 1]; + return ret; + } + int64_t query(int l, int r) { // [l, r) + return query(r) - query(l); + } + //! Requires s[i] >= 0 + //! max r such that sum of [0,r) < sum, or -1 + int walk(int64_t sum) { + if (sum <= 0) return -1; + int r = 0; + for (int pw = bit_floor(size(s)); pw; pw >>= 1) + if (r + pw <= ssize(s) && s[r + pw - 1] < sum) + sum -= s[(r += pw) - 1]; + return r; + } +}; +//! https://blog.mitrichev.ch/2013/05/fenwick-tree-range-updates.html +struct bit_rurq { + int n; + BIT bit1 = {0}, bit2 = {0}; + bit_rurq(int n): n(n), bit1(n), bit2(n) {} + bit_rurq(vector a): n(ssize(a)) { + adjacent_difference(begin(a), end(a), begin(a)); + bit1 = {a}; + for (int i = 0; i < n; i++) a[i] *= i; + bit2 = {a}; + } + //! does a[l]+=d, a[l+1]+=d, ..., a[r-1]+=d + //! @time O(log n) + //! @space O(1) + void update(int l, int r, int64_t d) { + if (l < n) { + bit1.update(l, d); + bit2.update(l, d * l); + } + if (r < n) { + bit1.update(r, -d); + bit2.update(r, -d * r); + } + } + //! @returns a[0]+a[1]+...+a[r-1] + //! @time O(log n) + //! @space O(1) + int64_t query(int r) { + return bit1.query(r) * r - bit2.query(r); + } + //! @returns a[l]+a[l+1]+...+a[r-1] + //! @time O(log n) + //! @space O(1) + int64_t query(int l, int r) { + return query(r) - query(l); + } +}; diff --git a/data_structures/bit_uncommon/vector_constructor.hpp b/data_structures/bit_uncommon/vector_constructor.hpp new file mode 100644 index 00000000..3ed8e3e3 --- /dev/null +++ b/data_structures/bit_uncommon/vector_constructor.hpp @@ -0,0 +1,6 @@ +BIT(const vector& a): s(a) { + for (int i = 0; i < ssize(a); i++) { + int j = i | (i + 1); + if (j < ssize(a)) s[j] += s[i]; + } +} diff --git a/library/data_structures/bit_uncommon/walk.hpp b/data_structures/bit_uncommon/walk.hpp similarity index 73% rename from library/data_structures/bit_uncommon/walk.hpp rename to data_structures/bit_uncommon/walk.hpp index dd75d1a2..3c3ffcb5 100644 --- a/library/data_structures/bit_uncommon/walk.hpp +++ b/data_structures/bit_uncommon/walk.hpp @@ -1,10 +1,10 @@ //! Requires s[i] >= 0 //! max r such that sum of [0,r) < sum, or -1 -int walk(ll sum) { +int walk(int64_t sum) { if (sum <= 0) return -1; int r = 0; for (int pw = bit_floor(size(s)); pw; pw >>= 1) - if (r + pw <= sz(s) && s[r + pw - 1] < sum) + if (r + pw <= ssize(s) && s[r + pw - 1] < sum) sum -= s[(r += pw) - 1]; return r; } diff --git a/library/data_structures/dsu/dsu.hpp b/data_structures/dsu/dsu.hpp similarity index 80% rename from library/data_structures/dsu/dsu.hpp rename to data_structures/dsu/dsu.hpp index dc7e99dd..b31b2f24 100644 --- a/library/data_structures/dsu/dsu.hpp +++ b/data_structures/dsu/dsu.hpp @@ -1,7 +1,5 @@ -#pragma once -// NOLINTNEXTLINE(readability-identifier-naming) struct DSU { - vi e; + vector e; DSU(int n): e(n, -1) {} int size(int x) { return -e[go(x)]; } int go(int x) { return e[x] < 0 ? x : e[x] = go(e[x]); } diff --git a/library/data_structures/dsu/dsu_bipartite.hpp b/data_structures/dsu/dsu_bipartite.hpp similarity index 96% rename from library/data_structures/dsu/dsu_bipartite.hpp rename to data_structures/dsu/dsu_bipartite.hpp index 8cbb199e..82048425 100644 --- a/library/data_structures/dsu/dsu_bipartite.hpp +++ b/data_structures/dsu/dsu_bipartite.hpp @@ -1,10 +1,9 @@ -#pragma once //! https://cp-algorithms.com/data_structures/disjoint_set_union.html#support-the-parity-of-the-path-length-checking-bipartiteness-online //! DSU with support for parity of path to root for online //! bipartite check struct dsu_bipartite { int num_sets; - vi p, is_bi, parity; + vector p, is_bi, parity; dsu_bipartite(int n): num_sets(n), p(n, -1), is_bi(n, 1), parity(n) {} int find(int v) { diff --git a/library/data_structures/dsu/dsu_restorable.hpp b/data_structures/dsu/dsu_restorable.hpp similarity index 92% rename from library/data_structures/dsu/dsu_restorable.hpp rename to data_structures/dsu/dsu_restorable.hpp index e06d411d..436eef46 100644 --- a/library/data_structures/dsu/dsu_restorable.hpp +++ b/data_structures/dsu/dsu_restorable.hpp @@ -1,11 +1,10 @@ -#pragma once //! https://github.com/ucf-programming-team/hackpack-cpp/blob/master/content/data-structures/DSURestorable.h //! DSU without path compression, so non-amortized. Most //! operations are O(log n) struct dsu_restorable { int num_sets; - vi p; - vector subtree; + vector p; + vector subtree; vector>> st; dsu_restorable(int n): num_sets(n), p(n, -1), subtree(n) {} @@ -34,7 +33,7 @@ struct dsu_restorable { bool same_set(int u, int v) { return find(u) == find(v); } - ll sum(int v) { return subtree[find(v)]; } + int64_t sum(int v) { return subtree[find(v)]; } void add(int v, int d) { while (v >= 0) subtree[v] += d, v = p[v]; } diff --git a/library/data_structures/dsu/kruskal_tree.hpp b/data_structures/dsu/kruskal_tree.hpp similarity index 89% rename from library/data_structures/dsu/kruskal_tree.hpp rename to data_structures/dsu/kruskal_tree.hpp index 745517c2..5d7fdc84 100644 --- a/library/data_structures/dsu/kruskal_tree.hpp +++ b/data_structures/dsu/kruskal_tree.hpp @@ -1,11 +1,10 @@ -#pragma once //! https://mzhang2021.github.io/cp-blog/kruskal/ //! @time O(n log n) //! @space O(n) struct kr_tree { int id; - vi p; - vector adj; + vector p; + vector> adj; kr_tree(int n): id(n), p(2 * n, -1), adj(2 * n) {} int find(int v) { return p[v] < 0 ? v : p[v] = find(p[v]); diff --git a/library/data_structures/dsu/line_tree.hpp b/data_structures/dsu/line_tree.hpp similarity index 90% rename from library/data_structures/dsu/line_tree.hpp rename to data_structures/dsu/line_tree.hpp index 11cc34be..a4b29bd8 100644 --- a/library/data_structures/dsu/line_tree.hpp +++ b/data_structures/dsu/line_tree.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://codeforces.com/blog/entry/71568?#comment-559304 //! @code //! ranges::sort(w_eds); @@ -17,10 +16,10 @@ //! @space O(n + m) struct line_tree { int id = 0; - vi p, last; - vector edge; + vector p, last; + vector> edge; line_tree(int n): p(n, -1), last(n), edge(n, {-1, -1}) { - iota(all(last), 0); + iota(begin(last), end(last), 0); } int size(int v) { return -p[find(v)]; } int find(int v) { diff --git a/library/data_structures/dsu/range_parallel_dsu.hpp b/data_structures/dsu/range_parallel_dsu.hpp similarity index 60% rename from library/data_structures/dsu/range_parallel_dsu.hpp rename to data_structures/dsu/range_parallel_dsu.hpp index e945a35b..92167d2d 100644 --- a/library/data_structures/dsu/range_parallel_dsu.hpp +++ b/data_structures/dsu/range_parallel_dsu.hpp @@ -1,5 +1,28 @@ -#pragma once -#include "../../../kactl/content/data-structures/UnionFind.h" +/** + * Author: Lukas Polacek + * Date: 2009-10-26 + * License: CC0 + * Source: folklore + * Description: Disjoint-set data structure. + * Time: $O(\alpha(N))$ + */ +struct UF { + vector e; + UF(int n): e(n, -1) {} + bool sameSet(int a, int b) { return find(a) == find(b); } + int size(int x) { return -e[find(x)]; } + int find(int x) { + return e[x] < 0 ? x : e[x] = find(e[x]); + } + bool join(int a, int b) { + a = find(a), b = find(b); + if (a == b) return false; + if (e[a] > e[b]) swap(a, b); + e[a] += e[b]; + e[b] = a; + return true; + } +}; //! Given l1,l2,len; joins (l1,l2), (l1+1,l2+1), //! ..., (l1+len-1,l2+len-1) //! `f` is called at most n-1 times diff --git a/data_structures/dsu/range_parallel_equivalence_classes.hpp b/data_structures/dsu/range_parallel_equivalence_classes.hpp new file mode 100644 index 00000000..7f58f619 --- /dev/null +++ b/data_structures/dsu/range_parallel_equivalence_classes.hpp @@ -0,0 +1,40 @@ +/** + * Author: Lukas Polacek + * Date: 2009-10-26 + * License: CC0 + * Source: folklore + * Description: Disjoint-set data structure. + * Time: $O(\alpha(N))$ + */ +struct UF { + vector e; + UF(int n): e(n, -1) {} + bool sameSet(int a, int b) { return find(a) == find(b); } + int size(int x) { return -e[find(x)]; } + int find(int x) { + return e[x] < 0 ? x : e[x] = find(e[x]); + } + bool join(int a, int b) { + a = find(a), b = find(b); + if (a == b) return false; + if (e[a] > e[b]) swap(a, b); + e[a] += e[b]; + e[b] = a; + return true; + } +}; +//! Given triplets (l1,l2,len); joins (l1,l2), +//! (l1+1,l2+1), ..., (l1+len-1,l2+len-1) +//! @time O((n + q) * \alpha(n)) +//! @space O(n + q) +UF get_rp_dsu(const vector>& rests, int n) { + vector>> rests_by_len(n + 1); + for (auto [l1, l2, len] : rests) + rests_by_len[len].emplace_back(l1, l2); + UF uf(n); + for (int len = n; len > 0; len--) + for (auto [l1, l2] : rests_by_len[len]) + if (uf.join(l1, l2)) + rests_by_len[len - 1].emplace_back(l1 + 1, l2 + 1); + return uf; +} diff --git a/data_structures/lazy_seg_tree.hpp b/data_structures/lazy_seg_tree.hpp new file mode 100644 index 00000000..5f6cdcf1 --- /dev/null +++ b/data_structures/lazy_seg_tree.hpp @@ -0,0 +1,162 @@ +//! https://codeforces.com/blog/entry/112755 +int split(int tl, int tr) { + int pw2 = 1 << __lg(tr - tl); + return min(tl + pw2, tr - pw2 / 2); +} +int64_t op(int64_t vl, int64_t vr) { return vl + vr; } +struct seg_tree { + int n; + vector tree, lazy; + seg_tree(int n): n(n), tree(2 * n), lazy(n) {} + seg_tree(const vector& a): + n(ssize(a)), tree(2 * n), lazy(n) { + int pw2 = bit_ceil(size(a)); + for (int i = 0; i < n; i++) + tree[(i + pw2) % n + n] = a[i]; + for (int i = n - 1; i >= 1; i--) + tree[i] = op(tree[2 * i], tree[2 * i + 1]); + } + void apply(int64_t change, int tl, int tr, int v) { + tree[v] += (tr - tl) * change; + if (v < n) lazy[v] += change; + } + void push(int tl, int tm, int tr, int v) { + if (lazy[v]) { + apply(lazy[v], tl, tm, 2 * v); + apply(lazy[v], tm, tr, 2 * v + 1); + lazy[v] = 0; + } + } + void update(int l, int r, int64_t change) { // [l, r) + update_impl(l, r, change, 0, n, 1); + } + void update_impl(int l, int r, int64_t change, int tl, + int tr, int v) { + if (r <= tl || tr <= l) return; + if (l <= tl && tr <= r) + return apply(change, tl, tr, v); + int tm = split(tl, tr); + push(tl, tm, tr, v); + update_impl(l, r, change, tl, tm, 2 * v); + update_impl(l, r, change, tm, tr, 2 * v + 1); + tree[v] = op(tree[2 * v], tree[2 * v + 1]); + } + int64_t query(int l, int r) { // [l, r) + return query_impl(l, r, 0, n, 1); + } + int64_t query_impl(int l, int r, int tl, int tr, int v) { + if (r <= tl || tr <= l) return 0; + if (l <= tl && tr <= r) return tree[v]; + int tm = split(tl, tr); + push(tl, tm, tr, v); + return op(query_impl(l, r, tl, tm, 2 * v), + query_impl(l, r, tm, tr, 2 * v + 1)); + } + //! @code + //! seg_tree st(n); + //! st.find_first(l, r, [&](ll x, int tl, int tr) -> + //! bool { + //! }); + //! @endcode + //! @param l,r defines range [l, r) + //! @param f defines a function that returns 1 if the + //! subtree contains an element that satisfies the + //! condition + //! + //! guarantee: `f` is called in order on the subtrees + //! (tls are weakly increasing) and at most once on each + //! subtree + //! + //! if `f` returns 1 then every subsequent call to `f` + //! will be a subtree of the previous call; otherwise the + //! next call will be a subsequent range of the previous + //! range + //! + //! seg_tree_find.test.cpp for more details + //! + //! @returns the index of the first element in the range + //! that satisfies the condition described in `f`, if no + //! such element exists then `r` is returned + //! @time O(log(n)) + //! @space O(log(n)) for recursion stack + int find_first(int l, int r, const auto& f) { + return find_first_in_range(l, r, f, 0, n, 1); + } + //! invariant: f(tree[v], tl, tr) is 1 + int find_first_in_subtree(const auto& f, int tl, int tr, + int v) { + if (v >= n) return tl; + int tm = split(tl, tr); + push(tl, tm, tr, v); + if (f(tree[2 * v], tl, tm)) + return find_first_in_subtree(f, tl, tm, 2 * v); + return find_first_in_subtree(f, tm, tr, 2 * v + 1); + } + int find_first_in_range(int l, int r, const auto& f, + int tl, int tr, int v) { + if (r <= tl || tr <= l) return r; + if (l <= tl && tr <= r) + return f(tree[v], tl, tr) + ? find_first_in_subtree(f, tl, tr, v) + : r; + int tm = split(tl, tr); + push(tl, tm, tr, v); + int res = find_first_in_range(l, r, f, tl, tm, 2 * v); + if (res < r) return res; + return find_first_in_range(l, r, f, tm, tr, 2 * v + 1); + } + //! @code + //! seg_tree st(n); + //! st.find_last(l, r, [&](ll x, int tl, int tr) -> + //! bool { + //! }); + //! @endcode + //! @param l,r defines range [l, r) + //! @param f defines a function that returns 1 if the + //! subtree contains an element that satisfies the + //! condition + //! + //! guarantee: `f` is called in order on the subtrees + //! (trs are weakly decreasing) and at most once on each + //! subtree + //! + //! if `f` returns 1 then every subsequent call to `f` + //! will be a subtree of the previous call; otherwise the + //! next call will be a subsequent range of the previous + //! range + //! + //! seg_tree_find.test.cpp for more details + //! + //! @returns the index of the last element in the range + //! that satisfies the condition described in `f`, if no + //! such element exists then (l - 1) is returned + //! @time O(log(n)) + //! @space O(log(n)) for recursion stack + int find_last(int l, int r, const auto& f) { + return find_last_in_range(l, r, f, 0, n, 1); + } + //! invariant: f(tree[v], tl, tr) is 1 + int find_last_in_subtree(const auto& f, int tl, int tr, + int v) { + if (v >= n) return tl; + int tm = split(tl, tr); + push(tl, tm, tr, v); + if (f(tree[2 * v + 1], tm, tr)) + return find_last_in_subtree(f, tm, tr, 2 * v + 1); + return find_last_in_subtree(f, tl, tm, 2 * v); + } + int find_last_in_range(int l, int r, const auto& f, + int tl, int tr, int v) { + if (r <= tl || tr <= l) return l - 1; + if (l <= tl && tr <= r) + return f(tree[v], tl, tr) + ? find_last_in_subtree(f, tl, tr, v) + : l - 1; + int tm = split(tl, tr); + push(tl, tm, tr, v); + int res = + find_last_in_range(l, r, f, tm, tr, 2 * v + 1); + if (res >= l) return res; + return find_last_in_range(l, r, f, tl, tm, 2 * v); + } +}; diff --git a/library/data_structures/lazy_seg_tree.png b/data_structures/lazy_seg_tree.png similarity index 100% rename from library/data_structures/lazy_seg_tree.png rename to data_structures/lazy_seg_tree.png diff --git a/library/data_structures/lazy_seg_tree_inc.hpp b/data_structures/lazy_seg_tree_inc.hpp similarity index 58% rename from library/data_structures/lazy_seg_tree_inc.hpp rename to data_structures/lazy_seg_tree_inc.hpp index 098dace8..56ada5e8 100644 --- a/library/data_structures/lazy_seg_tree_inc.hpp +++ b/data_structures/lazy_seg_tree_inc.hpp @@ -1,18 +1,26 @@ -#pragma once -#include "lazy_seg_tree_inc_midpoint.hpp" -ll op_inc(ll vl, ll vr) { return vl + vr; } +//! https://codeforces.com/blog/entry/112755 +//! @code +//! int tm = split_inc(tl, tr); +//! // [tl,tr] splits into [tl,tm] and [tm+1,tr] +//! @endcode +int split_inc(int tl, int tr) { + int pw2 = 1 << __lg(tr - tl + 1); + return min(tl + pw2 - 1, tr - pw2 / 2); +} +int64_t op_inc(int64_t vl, int64_t vr) { return vl + vr; } struct seg_tree_inc { int n; - vector tree, lazy; + vector tree, lazy; seg_tree_inc(int n): n(n), tree(2 * n), lazy(n) {} - seg_tree_inc(const vi& a): - n(sz(a)), tree(2 * n), lazy(n) { + seg_tree_inc(const vector& a): + n(ssize(a)), tree(2 * n), lazy(n) { int pw2 = bit_ceil(size(a)); - rep(i, 0, n) tree[(i + pw2) % n + n] = a[i]; + for (int i = 0; i < n; i++) + tree[(i + pw2) % n + n] = a[i]; for (int i = n - 1; i >= 1; i--) tree[i] = op_inc(tree[2 * i], tree[2 * i + 1]); } - void apply(ll change, int tl, int tr, int v) { + void apply(int64_t change, int tl, int tr, int v) { tree[v] += (tr - tl + 1) * change; if (v < n) lazy[v] += change; } @@ -23,11 +31,11 @@ struct seg_tree_inc { lazy[v] = 0; } } - void update(int l, int r, ll change) { // [l, r] + void update(int l, int r, int64_t change) { // [l, r] update_impl(l, r, change, 0, n - 1, 1); } - void update_impl(int l, int r, ll change, int tl, int tr, - int v) { + void update_impl(int l, int r, int64_t change, int tl, + int tr, int v) { if (r < tl || tr < l) return; if (l <= tl && tr <= r) return apply(change, tl, tr, v); @@ -37,10 +45,10 @@ struct seg_tree_inc { update_impl(l, r, change, tm + 1, tr, 2 * v + 1); tree[v] = op_inc(tree[2 * v], tree[2 * v + 1]); } - ll query(int l, int r) { // [l, r] + int64_t query(int l, int r) { // [l, r] return query_impl(l, r, 0, n - 1, 1); } - ll query_impl(int l, int r, int tl, int tr, int v) { + int64_t query_impl(int l, int r, int tl, int tr, int v) { if (r < tl || tr < l) return 0; if (l <= tl && tr <= r) return tree[v]; int tm = split_inc(tl, tr); diff --git a/library/data_structures/lazy_seg_tree_inc_midpoint.hpp b/data_structures/lazy_seg_tree_inc_midpoint.hpp similarity index 95% rename from library/data_structures/lazy_seg_tree_inc_midpoint.hpp rename to data_structures/lazy_seg_tree_inc_midpoint.hpp index e4af4900..0f40843f 100644 --- a/library/data_structures/lazy_seg_tree_inc_midpoint.hpp +++ b/data_structures/lazy_seg_tree_inc_midpoint.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://codeforces.com/blog/entry/112755 //! @code //! int tm = split_inc(tl, tr); diff --git a/library/data_structures/lazy_seg_tree_midpoint.hpp b/data_structures/lazy_seg_tree_midpoint.hpp similarity index 91% rename from library/data_structures/lazy_seg_tree_midpoint.hpp rename to data_structures/lazy_seg_tree_midpoint.hpp index 933aaf02..c86dc2a5 100644 --- a/library/data_structures/lazy_seg_tree_midpoint.hpp +++ b/data_structures/lazy_seg_tree_midpoint.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://codeforces.com/blog/entry/112755 int split(int tl, int tr) { int pw2 = 1 << __lg(tr - tl); diff --git a/library/data_structures/rmq.hpp b/data_structures/rmq.hpp similarity index 80% rename from library/data_structures/rmq.hpp rename to data_structures/rmq.hpp index cd96d87c..336a527f 100644 --- a/library/data_structures/rmq.hpp +++ b/data_structures/rmq.hpp @@ -1,4 +1,3 @@ -#pragma once //! @code //! RMQ rmq1(a, ranges::min); //! RMQ rmq2(a, [&](auto& x, auto& y) { @@ -10,13 +9,12 @@ //! @endcode //! @time O(nlogn + q) //! @space O(nlogn) -// NOLINTNEXTLINE(readability-identifier-naming) template struct RMQ { vector> dp; F op; RMQ(const vector& a, F op): dp(1, a), op(op) { - for (int i = 0; (2 << i) <= sz(a); i++) { - dp.emplace_back(sz(a) - (2 << i) + 1); + for (int i = 0; (2 << i) <= ssize(a); i++) { + dp.emplace_back(ssize(a) - (2 << i) + 1); ranges::transform(dp[i], dp[i] | views::drop(1 << i), begin(dp[i + 1]), op); } diff --git a/library/data_structures/rmq_inc.hpp b/data_structures/rmq_inc.hpp similarity index 86% rename from library/data_structures/rmq_inc.hpp rename to data_structures/rmq_inc.hpp index 3b6f7351..e0324307 100644 --- a/library/data_structures/rmq_inc.hpp +++ b/data_structures/rmq_inc.hpp @@ -1,4 +1,3 @@ -#pragma once //! @code //! rmq_inc rmq1(a, ranges::min); //! rmq_inc rmq2(a, [&](auto& x, auto& y) { @@ -14,8 +13,8 @@ template struct rmq_inc { vector> dp; F op; rmq_inc(const vector& a, F op): dp(1, a), op(op) { - for (int i = 0; (2 << i) <= sz(a); i++) { - dp.emplace_back(sz(a) - (2 << i) + 1); + for (int i = 0; (2 << i) <= ssize(a); i++) { + dp.emplace_back(ssize(a) - (2 << i) + 1); ranges::transform(dp[i], dp[i] | views::drop(1 << i), begin(dp[i + 1]), op); } diff --git a/library/data_structures/seg_tree.hpp b/data_structures/seg_tree.hpp similarity index 98% rename from library/data_structures/seg_tree.hpp rename to data_structures/seg_tree.hpp index 6d2d781a..824aea54 100644 --- a/library/data_structures/seg_tree.hpp +++ b/data_structures/seg_tree.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://github.com/kth-competitive-programming/kactl/blob/main/content/data-structures/SegmentTree.h //! @code //! tree st1(n, INT_MAX, ranges::min); diff --git a/library/data_structures/seg_tree.png b/data_structures/seg_tree.png similarity index 100% rename from library/data_structures/seg_tree.png rename to data_structures/seg_tree.png diff --git a/library/data_structures/seg_tree_inc.hpp b/data_structures/seg_tree_inc.hpp similarity index 98% rename from library/data_structures/seg_tree_inc.hpp rename to data_structures/seg_tree_inc.hpp index 2a06383d..ddd37822 100644 --- a/library/data_structures/seg_tree_inc.hpp +++ b/data_structures/seg_tree_inc.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://codeforces.com/blog/entry/118682 //! @code //! { diff --git a/data_structures/seg_tree_uncommon/distinct_query.hpp b/data_structures/seg_tree_uncommon/distinct_query.hpp new file mode 100644 index 00000000..d44b3d86 --- /dev/null +++ b/data_structures/seg_tree_uncommon/distinct_query.hpp @@ -0,0 +1,78 @@ +//! https://cp-algorithms.com/data_structures/segment_tree.html#preserving-the-history-of-its-values-persistent-segment-tree +//! @code +//! PST pst(root_l, root_r); +//! @endcode +//! root's range is [root_l, root_r) +//! pst.tree[pst.roots[i]] = root at version i +//! @time O(q * log n), n = root_r-root_l +//! @space O(q * log n) +struct PST { + struct node { + int64_t sum; + int lch, rch; + node(int64_t sum, int lch, int rch): + sum(sum), lch(lch), rch(rch) {} + }; + int root_l, root_r; + vector roots; + deque tree; + PST(int root_l, int root_r): + root_l(root_l), root_r(root_r), roots(1), + tree(1, {0LL, 0, 0}) {} + void update(int idx, int64_t change, int version) { + roots.push_back(update_impl(idx, change, root_l, + root_r, roots[version])); + } + int update_impl(int idx, int64_t change, int tl, int tr, + int v) { + if (tr - tl == 1) { + tree.emplace_back(tree[v].sum + change, 0, 0); + return ssize(tree) - 1; + } + int tm = tl + (tr - tl) / 2; + int lch = tree[v].lch; + int rch = tree[v].rch; + if (idx < tm) + lch = update_impl(idx, change, tl, tm, lch); + else rch = update_impl(idx, change, tm, tr, rch); + tree.emplace_back(tree[lch].sum + tree[rch].sum, lch, + rch); + return ssize(tree) - 1; + } + int64_t query(int l, int r, int version) { // [l, r) + return query_impl(l, r, root_l, root_r, + roots[version]); + } + int64_t query_impl(int l, int r, int tl, int tr, int v) { + if (v == 0 || r <= tl || tr <= l) return 0; + if (l <= tl && tr <= r) return tree[v].sum; + int tm = tl + (tr - tl) / 2; + return query_impl(l, r, tl, tm, tree[v].lch) + + query_impl(l, r, tm, tr, tree[v].rch); + } +}; +//! https://cp-algorithms.com/data_structures/segment_tree.html#preserving-the-history-of-its-values-persistent-segment-tree +struct distinct_query { + int n; + PST pst; + //! @param a static array; can't handle updates + //! @time O(n log n) + //! @space O(n log n) + distinct_query(const vector& a): + n(ssize(a)), pst(0, n + 1) { + map last_idx; + for (int i = 0; i < n; i++) { + int& idx = last_idx[a[i]]; + pst.update(idx, 1, i); + idx = i + 1; + } + } + //! @param l,r defines range [l, r) + //! @returns number of distinct elements in range; + //! query(i, i) returns 0. + //! @time O(log n) + //! @space O(log n) + int query(int l, int r) { + return pst.query(0, l + 1, r) - pst.query(0, l + 1, l); + } +}; diff --git a/library/data_structures/seg_tree_uncommon/find_first.hpp b/data_structures/seg_tree_uncommon/find_first.hpp similarity index 99% rename from library/data_structures/seg_tree_uncommon/find_first.hpp rename to data_structures/seg_tree_uncommon/find_first.hpp index dcc78aa2..71c205ce 100644 --- a/library/data_structures/seg_tree_uncommon/find_first.hpp +++ b/data_structures/seg_tree_uncommon/find_first.hpp @@ -1,4 +1,3 @@ -#pragma once //! @code //! seg_tree st(n); //! st.find_first(l, r, [&](ll x, int tl, int tr) -> diff --git a/library/data_structures/seg_tree_uncommon/find_last.hpp b/data_structures/seg_tree_uncommon/find_last.hpp similarity index 99% rename from library/data_structures/seg_tree_uncommon/find_last.hpp rename to data_structures/seg_tree_uncommon/find_last.hpp index 74ee92c3..d9e679d8 100644 --- a/library/data_structures/seg_tree_uncommon/find_last.hpp +++ b/data_structures/seg_tree_uncommon/find_last.hpp @@ -1,4 +1,3 @@ -#pragma once //! @code //! seg_tree st(n); //! st.find_last(l, r, [&](ll x, int tl, int tr) -> diff --git a/library/data_structures/seg_tree_uncommon/implicit.hpp b/data_structures/seg_tree_uncommon/implicit.hpp similarity index 87% rename from library/data_structures/seg_tree_uncommon/implicit.hpp rename to data_structures/seg_tree_uncommon/implicit.hpp index 76a6570b..b97ca2ea 100644 --- a/library/data_structures/seg_tree_uncommon/implicit.hpp +++ b/data_structures/seg_tree_uncommon/implicit.hpp @@ -1,9 +1,8 @@ -#pragma once //! @code //! implicit_seg_tree<10'000'000> ist(l, r); //! @endcode template struct implicit_seg_tree { - using dt = array; //!< min, number of mins + using dt = array; //!< min, number of mins static dt op(const dt& l, const dt& r) { if (l[0] == r[0]) return {l[0], l[1] + r[1]}; return min(l, r); @@ -11,14 +10,14 @@ template struct implicit_seg_tree { static constexpr dt unit{LLONG_MAX, 0LL}; struct node { dt num; - ll lazy = 0; + int64_t lazy = 0; int lch = -1, rch = -1; } tree[N]; int ptr = 0, root_l, root_r; implicit_seg_tree(int l, int r): root_l(l), root_r(r) { tree[ptr++].num = {0, r - l}; } - void apply(ll add, int v) { + void apply(int64_t add, int v) { tree[v].num[0] += add; tree[v].lazy += add; } @@ -35,10 +34,10 @@ template struct implicit_seg_tree { tree[v].lazy = 0; } } - void update(int l, int r, ll add) { // [l, r) + void update(int l, int r, int64_t add) { // [l, r) update(l, r, add, root_l, root_r, 0); } - void update(int l, int r, ll add, int tl, int tr, + void update(int l, int r, int64_t add, int tl, int tr, int v) { if (r <= tl || tr <= l) return; if (l <= tl && tr <= r) return apply(add, v); diff --git a/data_structures/seg_tree_uncommon/kth_smallest_query.hpp b/data_structures/seg_tree_uncommon/kth_smallest_query.hpp new file mode 100644 index 00000000..57fd2232 --- /dev/null +++ b/data_structures/seg_tree_uncommon/kth_smallest_query.hpp @@ -0,0 +1,89 @@ +//! https://cp-algorithms.com/data_structures/segment_tree.html#preserving-the-history-of-its-values-persistent-segment-tree +//! @code +//! PST pst(root_l, root_r); +//! @endcode +//! root's range is [root_l, root_r) +//! pst.tree[pst.roots[i]] = root at version i +//! @time O(q * log n), n = root_r-root_l +//! @space O(q * log n) +struct PST { + struct node { + int64_t sum; + int lch, rch; + node(int64_t sum, int lch, int rch): + sum(sum), lch(lch), rch(rch) {} + }; + int root_l, root_r; + vector roots; + deque tree; + PST(int root_l, int root_r): + root_l(root_l), root_r(root_r), roots(1), + tree(1, {0LL, 0, 0}) {} + void update(int idx, int64_t change, int version) { + roots.push_back(update_impl(idx, change, root_l, + root_r, roots[version])); + } + int update_impl(int idx, int64_t change, int tl, int tr, + int v) { + if (tr - tl == 1) { + tree.emplace_back(tree[v].sum + change, 0, 0); + return ssize(tree) - 1; + } + int tm = tl + (tr - tl) / 2; + int lch = tree[v].lch; + int rch = tree[v].rch; + if (idx < tm) + lch = update_impl(idx, change, tl, tm, lch); + else rch = update_impl(idx, change, tm, tr, rch); + tree.emplace_back(tree[lch].sum + tree[rch].sum, lch, + rch); + return ssize(tree) - 1; + } + int64_t query(int l, int r, int version) { // [l, r) + return query_impl(l, r, root_l, root_r, + roots[version]); + } + int64_t query_impl(int l, int r, int tl, int tr, int v) { + if (v == 0 || r <= tl || tr <= l) return 0; + if (l <= tl && tr <= r) return tree[v].sum; + int tm = tl + (tr - tl) / 2; + return query_impl(l, r, tl, tm, tree[v].lch) + + query_impl(l, r, tm, tr, tree[v].rch); + } +}; +//! https://cp-algorithms.com/data_structures/segment_tree.html#preserving-the-history-of-its-values-persistent-segment-tree +struct kth_smallest { + PST pst; + //! @param a,minv,maxv must satisfy: minv <= a[i] < maxv + //! @time O(n log(maxv - minv)) + //! @space O(n log(maxv - minv)) nodes are pushed back + //! onto PST::tree + kth_smallest(const vector& a, int minv, int maxv): + pst(minv, maxv) { + for (int i = 0; i < ssize(a); i++) + pst.update(a[i], 1, i); + } + //! @param l,r defines range [l, r) + //! @param k must satisfy 1 <= k <= r - l + //! @returns kth smallest number in range. + //! - query(l,r,1) returns the min + //! - query(l,r,(r-l)) returns the max + //! @time O(log(maxv - minv)) + //! @space O(log(maxv - minv)) for recursion stack; no + //! new nodes are allocated + int query(int l, int r, int k) { + return query_impl(k, pst.root_l, pst.root_r, + pst.roots[l], pst.roots[r]); + } + int query_impl(int k, int tl, int tr, int vl, int vr) { + if (tr - tl == 1) return tl; + int tm = tl + (tr - tl) / 2; + int left_count = pst.tree[pst.tree[vr].lch].sum - + pst.tree[pst.tree[vl].lch].sum; + if (left_count >= k) + return query_impl(k, tl, tm, pst.tree[vl].lch, + pst.tree[vr].lch); + return query_impl(k - left_count, tm, tr, + pst.tree[vl].rch, pst.tree[vr].rch); + } +}; diff --git a/library/data_structures/seg_tree_uncommon/merge_sort_tree.hpp b/data_structures/seg_tree_uncommon/merge_sort_tree.hpp similarity index 70% rename from library/data_structures/seg_tree_uncommon/merge_sort_tree.hpp rename to data_structures/seg_tree_uncommon/merge_sort_tree.hpp index 868f8466..404272a4 100644 --- a/library/data_structures/seg_tree_uncommon/merge_sort_tree.hpp +++ b/data_structures/seg_tree_uncommon/merge_sort_tree.hpp @@ -1,11 +1,16 @@ -#pragma once -#include "../lazy_seg_tree_midpoint.hpp" +//! https://codeforces.com/blog/entry/112755 +int split(int tl, int tr) { + int pw2 = 1 << __lg(tr - tl); + return min(tl + pw2, tr - pw2 / 2); +} struct merge_sort_tree { int n; - vector tree; - merge_sort_tree(const vi& a): n(sz(a)), tree(2 * n) { + vector> tree; + merge_sort_tree(const vector& a): + n(ssize(a)), tree(2 * n) { int pw2 = bit_ceil(size(a)); - rep(i, 0, n) tree[(i + pw2) % n + n] = {a[i]}; + for (int i = 0; i < n; i++) + tree[(i + pw2) % n + n] = {a[i]}; for (int i = n - 1; i >= 1; i--) ranges::merge(tree[2 * i], tree[2 * i + 1], back_inserter(tree[i])); diff --git a/library/data_structures/seg_tree_uncommon/persistent.hpp b/data_structures/seg_tree_uncommon/persistent.hpp similarity index 77% rename from library/data_structures/seg_tree_uncommon/persistent.hpp rename to data_structures/seg_tree_uncommon/persistent.hpp index 722aa780..12d860cb 100644 --- a/library/data_structures/seg_tree_uncommon/persistent.hpp +++ b/data_structures/seg_tree_uncommon/persistent.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://cp-algorithms.com/data_structures/segment_tree.html#preserving-the-history-of-its-values-persistent-segment-tree //! @code //! PST pst(root_l, root_r); @@ -7,29 +6,28 @@ //! pst.tree[pst.roots[i]] = root at version i //! @time O(q * log n), n = root_r-root_l //! @space O(q * log n) -// NOLINTNEXTLINE(readability-identifier-naming) struct PST { struct node { - ll sum; + int64_t sum; int lch, rch; - node(ll sum, int lch, int rch): + node(int64_t sum, int lch, int rch): sum(sum), lch(lch), rch(rch) {} }; int root_l, root_r; - vi roots; + vector roots; deque tree; PST(int root_l, int root_r): root_l(root_l), root_r(root_r), roots(1), tree(1, {0LL, 0, 0}) {} - void update(int idx, ll change, int version) { + void update(int idx, int64_t change, int version) { roots.push_back(update_impl(idx, change, root_l, root_r, roots[version])); } - int update_impl(int idx, ll change, int tl, int tr, + int update_impl(int idx, int64_t change, int tl, int tr, int v) { if (tr - tl == 1) { tree.emplace_back(tree[v].sum + change, 0, 0); - return sz(tree) - 1; + return ssize(tree) - 1; } int tm = tl + (tr - tl) / 2; int lch = tree[v].lch; @@ -39,13 +37,13 @@ struct PST { else rch = update_impl(idx, change, tm, tr, rch); tree.emplace_back(tree[lch].sum + tree[rch].sum, lch, rch); - return sz(tree) - 1; + return ssize(tree) - 1; } - ll query(int l, int r, int version) { // [l, r) + int64_t query(int l, int r, int version) { // [l, r) return query_impl(l, r, root_l, root_r, roots[version]); } - ll query_impl(int l, int r, int tl, int tr, int v) { + int64_t query_impl(int l, int r, int tl, int tr, int v) { if (v == 0 || r <= tl || tr <= l) return 0; if (l <= tl && tr <= r) return tree[v].sum; int tm = tl + (tr - tl) / 2; diff --git a/library/data_structures/seg_tree_uncommon/wavelet_bit_vec.hpp b/data_structures/seg_tree_uncommon/wavelet_bit_vec.hpp similarity index 70% rename from library/data_structures/seg_tree_uncommon/wavelet_bit_vec.hpp rename to data_structures/seg_tree_uncommon/wavelet_bit_vec.hpp index e03d1d58..387de56a 100644 --- a/library/data_structures/seg_tree_uncommon/wavelet_bit_vec.hpp +++ b/data_structures/seg_tree_uncommon/wavelet_bit_vec.hpp @@ -1,4 +1,3 @@ -#pragma once //! @code //! vector a(n); //! bit_vec bv(a); @@ -9,12 +8,13 @@ using ull = uint64_t; struct bit_vec { vector> b; - bit_vec(const vector& a): b(sz(a) / 64 + 1) { - rep(i, 0, sz(a)) { + bit_vec(const vector& a): b(ssize(a) / 64 + 1) { + for (int i = 0; i < ssize(a); i++) { auto& [x, y] = b[i >> 6]; x |= ull(a[i]) << (i & 63), y += a[i]; } - rep(i, 1, sz(b)) b[i].second += b[i - 1].second; + for (int i = 1; i < ssize(b); i++) + b[i].second += b[i - 1].second; } int cnt(int r) { auto [x, y] = b[r >> 6]; diff --git a/library/data_structures/seg_tree_uncommon/wavelet_count_less.hpp b/data_structures/seg_tree_uncommon/wavelet_count_less.hpp similarity index 88% rename from library/data_structures/seg_tree_uncommon/wavelet_count_less.hpp rename to data_structures/seg_tree_uncommon/wavelet_count_less.hpp index 2416ad02..4bc56251 100644 --- a/library/data_structures/seg_tree_uncommon/wavelet_count_less.hpp +++ b/data_structures/seg_tree_uncommon/wavelet_count_less.hpp @@ -1,10 +1,9 @@ -#pragma once //! count of i in [l..r) such that a[i] < ub //! @time O(log(max_val)) //! @space O(1) int count(int l, int r, ull ub) { int res = 0; - for (int h = sz(bv); h--;) { + for (int h = ssize(bv); h--;) { int l0 = bv[h].cnt(l), r0 = bv[h].cnt(r); if ((~ub >> h) & 1) l = l0, r = r0; else diff --git a/data_structures/seg_tree_uncommon/wavelet_matrix.hpp b/data_structures/seg_tree_uncommon/wavelet_matrix.hpp new file mode 100644 index 00000000..b004178f --- /dev/null +++ b/data_structures/seg_tree_uncommon/wavelet_matrix.hpp @@ -0,0 +1,70 @@ +//! @code +//! vector a(n); +//! bit_vec bv(a); +//! bv.cnt(r); // a[0] + a[1] + ... + a[r - 1] +//! @endcode +//! @time O(n + q) +//! @space O(n / 64) +using ull = uint64_t; +struct bit_vec { + vector> b; + bit_vec(const vector& a): b(ssize(a) / 64 + 1) { + for (int i = 0; i < ssize(a); i++) { + auto& [x, y] = b[i >> 6]; + x |= ull(a[i]) << (i & 63), y += a[i]; + } + for (int i = 1; i < ssize(b); i++) + b[i].second += b[i - 1].second; + } + int cnt(int r) { + auto [x, y] = b[r >> 6]; + return y - popcount(x & -1ULL << (r & 63)); + } +}; +//! @code +//! vector a(n); +//! wavelet_matrix wm(a, 1e9); // requires a[i] <= 1e9 +//! wm.kth(l, r, k); //(k+1)th smallest number in [l,r) +//! wm.kth(l, r, 0); //min in [l,r) +//! @endcode +//! @time O(n * log(max_val) + q * log(max_val)) +//! @space O(n * log(max_val) / 64) +struct wavelet_matrix { + int n; + vector bv; + wavelet_matrix(vector a, ull max_val): + n(ssize(a)), bv(bit_width(max_val), {{}}) { + for (int h = ssize(bv); h--;) { + int i = 0; + vector b(n); + ranges::stable_partition(a, + [&](ull x) { return b[i++] = (~x >> h) & 1; }); + bv[h] = b; + } + } + ull kth(int l, int r, int k) { + int64_t res = 0; + for (int h = ssize(bv); h--;) { + int l0 = bv[h].cnt(l), r0 = bv[h].cnt(r); + if (k < r0 - l0) l = l0, r = r0; + else + k -= r0 - l0, res |= 1ULL << h, + l += bv[h].cnt(n) - l0, r += bv[h].cnt(n) - r0; + } + return res; + } + //! count of i in [l..r) such that a[i] < ub + //! @time O(log(max_val)) + //! @space O(1) + int count(int l, int r, ull ub) { + int res = 0; + for (int h = ssize(bv); h--;) { + int l0 = bv[h].cnt(l), r0 = bv[h].cnt(r); + if ((~ub >> h) & 1) l = l0, r = r0; + else + res += r0 - l0, l += bv[h].cnt(n) - l0, + r += bv[h].cnt(n) - r0; + } + return res; + } +}; diff --git a/library/data_structures/uncommon/deque_op.hpp b/data_structures/uncommon/deque_op.hpp similarity index 67% rename from library/data_structures/uncommon/deque_op.hpp rename to data_structures/uncommon/deque_op.hpp index 43d17176..b172fc93 100644 --- a/library/data_structures/uncommon/deque_op.hpp +++ b/data_structures/uncommon/deque_op.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://github.com/suisen-cp/cp-library-cpp/blob/main/library/datastructure/deque_aggregation.hpp //! @code //! deq dq(a, ranges::min); @@ -10,7 +9,7 @@ template struct deq { F op; vector
l, r; deq(const vector& a, F op): op(op) { - rebuild(a, sz(a) / 2); + rebuild(a, ssize(a) / 2); } T query() { if (empty(l)) return r.back()[1]; @@ -18,22 +17,22 @@ template struct deq { return op(l.back()[1], r.back()[1]); } T operator[](int i) { - return ( - i < sz(l) ? l[sz(l) - i - 1] : r[i - sz(l)])[0]; + return (i < ssize(l) ? l[ssize(l) - i - 1] + : r[i - ssize(l)])[0]; } T front() { return (empty(l) ? r[0] : l.back())[0]; } T back() { return (empty(r) ? l[0] : r.back())[0]; } - int siz() { return sz(l) + sz(r); } + int siz() { return ssize(l) + ssize(r); } void push_back(T elem) { r.push_back( {elem, empty(r) ? elem : op(r.back()[1], elem)}); } void pop_back() { if (empty(r)) { - vector a(sz(l)); - transform(all(l), rbegin(a), + vector a(ssize(l)); + transform(begin(l), end(l), rbegin(a), [](dt& x) { return x[0]; }); - rebuild(a, sz(a) / 2); + rebuild(a, ssize(a) / 2); } r.pop_back(); } @@ -43,24 +42,26 @@ template struct deq { } void pop_front() { if (empty(l)) { - vector a(sz(r)); - transform(all(r), begin(a), + vector a(ssize(r)); + transform(begin(r), end(r), begin(a), [](dt& x) { return x[0]; }); - rebuild(a, (sz(a) + 1) / 2); + rebuild(a, (ssize(a) + 1) / 2); } l.pop_back(); } void rebuild(const vector& a, int sz_le) { - vector presum(sz(a)); + vector presum(ssize(a)); partial_sum(rend(a) - sz_le, rend(a), rend(presum) - sz_le, [&](T x, T y) { return op(y, x); }); - partial_sum(sz_le + all(a), begin(presum) + sz_le, op); + partial_sum(sz_le + begin(a), end(a), + begin(presum) + sz_le, op); l.resize(sz_le); - r.resize(sz(a) - sz_le); + r.resize(ssize(a) - sz_le); transform(begin(a), begin(a) + sz_le, begin(presum), rbegin(l), [](T x, T y) { return dt{x, y}; }); - transform(sz_le + all(a), begin(presum) + sz_le, - begin(r), [](T x, T y) { return dt{x, y}; }); + transform(sz_le + begin(a), end(a), + begin(presum) + sz_le, begin(r), + [](T x, T y) { return dt{x, y}; }); } }; diff --git a/library/data_structures/uncommon/disjoint_rmq.hpp b/data_structures/uncommon/disjoint_rmq.hpp similarity index 93% rename from library/data_structures/uncommon/disjoint_rmq.hpp rename to data_structures/uncommon/disjoint_rmq.hpp index d18eb0b4..a4fe87ab 100644 --- a/library/data_structures/uncommon/disjoint_rmq.hpp +++ b/data_structures/uncommon/disjoint_rmq.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://codeforces.com/blog/entry/87940 //! Disjoint RMQ is like normal RMQ except //! the 2 query ranges never overlap. @@ -13,7 +12,7 @@ template struct disjoint_rmq { vector> dp; F op; disjoint_rmq(const vector& a, F op): op(op) { - for (int len = 1, n = sz(a); len <= n; len *= 2) { + for (int len = 1, n = ssize(a); len <= n; len *= 2) { dp.emplace_back(n); for (int l = 0; l < n; l += 2 * len) { int mi = min(n, l + len), r = min(n, l + 2 * len); diff --git a/library/data_structures/uncommon/disjoint_rmq_inc.hpp b/data_structures/uncommon/disjoint_rmq_inc.hpp similarity index 93% rename from library/data_structures/uncommon/disjoint_rmq_inc.hpp rename to data_structures/uncommon/disjoint_rmq_inc.hpp index 25dd533f..67faa5ae 100644 --- a/library/data_structures/uncommon/disjoint_rmq_inc.hpp +++ b/data_structures/uncommon/disjoint_rmq_inc.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://codeforces.com/blog/entry/87940 //! Disjoint RMQ is like normal RMQ except //! the 2 query ranges never overlap. @@ -13,7 +12,7 @@ template struct disjoint_rmq_inc { vector> dp; F op; disjoint_rmq_inc(const vector& a, F op): op(op) { - for (int len = 1, n = sz(a); len <= n; len *= 2) { + for (int len = 1, n = ssize(a); len <= n; len *= 2) { dp.emplace_back(n); for (int l = 0; l < n; l += 2 * len) { int mi = min(n, l + len), r = min(n, l + 2 * len); diff --git a/library/data_structures/uncommon/linear_rmq.hpp b/data_structures/uncommon/linear_rmq.hpp similarity index 81% rename from library/data_structures/uncommon/linear_rmq.hpp rename to data_structures/uncommon/linear_rmq.hpp index bd98626b..f1fc2f50 100644 --- a/library/data_structures/uncommon/linear_rmq.hpp +++ b/data_structures/uncommon/linear_rmq.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://codeforces.com/blog/entry/125371?#comment-1173604 //! @code //! linear_rmq rmq1(a, less()); //right-most min @@ -15,13 +14,14 @@ template struct linear_rmq { int n; vector a; F cmp; - vi in, asc, head; + vector in, asc, head; linear_rmq(const vector& a, F cmp): - n(sz(a)), a(a), cmp(cmp), in(n), asc(n), head(n + 1) { - vi st{-1}; - rep(i, 0, n + 1) { + n(ssize(a)), a(a), cmp(cmp), in(n), asc(n), + head(n + 1) { + vector st{-1}; + for (int i = 0; i < n + 1; i++) { int prev = 0; - while (sz(st) > 1 && + while (ssize(st) > 1 && (i == n || !cmp(a[st.back()], a[i]))) { head[prev] = st.back(); auto j = end(st)[-2] + 1u, k = bit_floor(i ^ j); @@ -30,8 +30,8 @@ template struct linear_rmq { } st.push_back(head[prev] = i); } - rep(i, 1, n) asc[i] = - (asc[i] | asc[i - 1]) & -(in[i] & -in[i]); + for (int i = 1; i < n; i++) + asc[i] = (asc[i] | asc[i - 1]) & -(in[i] & -in[i]); } int idx(int l, int r) { // [l, r] if (unsigned j = in[l] ^ in[r]; j) { diff --git a/library/data_structures/uncommon/mode_query.hpp b/data_structures/uncommon/mode_query.hpp similarity index 63% rename from library/data_structures/uncommon/mode_query.hpp rename to data_structures/uncommon/mode_query.hpp index 1c1e205b..6d454c2c 100644 --- a/library/data_structures/uncommon/mode_query.hpp +++ b/data_structures/uncommon/mode_query.hpp @@ -1,26 +1,25 @@ -#pragma once const int b = 318; //!< sqrt(1e5) //! https://noshi91.hatenablog.com/entry/2020/10/26/140105 struct mode_query { int n; - vi a, cnt, index_into_index; - vector index; - vector> + vector a, cnt, index_into_index; + vector> index; + vector>> mode_blocks; //!< {mode, cnt} of range of blocks //! @param a compressed array: 0 <= a[i] < n //! @time O(n * sqrt(n)) //! @space O(n) - mode_query(const vi& a): - n(sz(a)), a(a), cnt(n), index_into_index(n), index(n), - mode_blocks((n + b - 1) / b, - vector((n + b - 1) / b)) { - rep(i, 0, n) { - index_into_index[i] = sz(index[a[i]]); + mode_query(const vector& a): + n(ssize(a)), a(a), cnt(n), index_into_index(n), + index(n), mode_blocks((n + b - 1) / b, + vector>((n + b - 1) / b)) { + for (int i = 0; i < n; i++) { + index_into_index[i] = ssize(index[a[i]]); index[a[i]].push_back(i); } for (int start = 0; start < n; start += b) { int mode = a[start]; - rep(i, start, n) { + for (int i = start; i < n; i++) { cnt[a[i]]++; if (cnt[a[i]] > cnt[mode]) mode = a[i]; if ( @@ -28,37 +27,38 @@ struct mode_query { mode_blocks[start / b][i / b] = { mode, cnt[mode]}; } - rep(i, start, n) cnt[a[i]]--; + for (int i = start; i < n; i++) cnt[a[i]]--; } } //! @param l,r defines range [l, r) //! @returns {mode, cnt of mode} //! @time O(sqrt(n)) //! @space O(1) - pii query(int l, int r) { + pair query(int l, int r) { assert(l < r); if (l / b >= (r - 1) / b - 1) { int mode = a[l]; - rep(i, l, r) { + for (int i = l; i < r; i++) { cnt[a[i]]++; if (cnt[a[i]] > cnt[mode]) mode = a[i]; } int cnt_mode = cnt[mode]; - rep(i, l, r) cnt[a[i]]--; + for (int i = l; i < r; i++) cnt[a[i]]--; return {mode, cnt_mode}; } - pii res = mode_blocks[l / b + 1][(r - 1) / b - 1]; + pair res = + mode_blocks[l / b + 1][(r - 1) / b - 1]; for (int i = l / b * b + b - 1; i >= l; i--) cnt[a[i]]++; for (int i = l / b * b + b - 1; i >= l; i--) { int idx = index_into_index[i]; - if (idx + res.second < sz(index[a[i]]) && + if (idx + res.second < ssize(index[a[i]]) && index[a[i]][idx + res.second] < r) res = {a[i], cnt[a[i]] + res.second}; cnt[a[i]]--; } - rep(i, (r - 1) / b * b, r) cnt[a[i]]++; - rep(i, (r - 1) / b * b, r) { + for (int i = (r - 1) / b * b; i < r; i++) cnt[a[i]]++; + for (int i = (r - 1) / b * b; i < r; i++) { int idx = index_into_index[i]; if (idx >= res.second && index[a[i]][idx - res.second] >= l) diff --git a/data_structures/uncommon/permutation_tree.hpp b/data_structures/uncommon/permutation_tree.hpp new file mode 100644 index 00000000..ec080dae --- /dev/null +++ b/data_structures/uncommon/permutation_tree.hpp @@ -0,0 +1,134 @@ +//! https://codeforces.com/blog/entry/125371?#comment-1173604 +//! @code +//! linear_rmq rmq1(a, less()); //right-most min +//! linear_rmq rmq2(a, less_equal()); //left-most min +//! linear_rmq rmq3(a, greater()); //right-most max +//! linear_rmq rmq4(a, greater_equal()); //left-most max +//! linear_rmq rmq5(a, [&](auto& x, auto& y) { +//! return x < y; +//! }); +//! @endcode +//! @time O(n + q) +//! @space O(n) +template struct linear_rmq { + int n; + vector a; + F cmp; + vector in, asc, head; + linear_rmq(const vector& a, F cmp): + n(ssize(a)), a(a), cmp(cmp), in(n), asc(n), + head(n + 1) { + vector st{-1}; + for (int i = 0; i < n + 1; i++) { + int prev = 0; + while (ssize(st) > 1 && + (i == n || !cmp(a[st.back()], a[i]))) { + head[prev] = st.back(); + auto j = end(st)[-2] + 1u, k = bit_floor(i ^ j); + in[st.back()] = prev = i & -k, asc[j] |= k; + st.pop_back(); + } + st.push_back(head[prev] = i); + } + for (int i = 1; i < n; i++) + asc[i] = (asc[i] | asc[i - 1]) & -(in[i] & -in[i]); + } + int idx(int l, int r) { // [l, r] + if (unsigned j = in[l] ^ in[r]; j) { + j = asc[l] & asc[r] & -bit_floor(j); + if (unsigned k = asc[l] ^ j; k) + k = bit_floor(k), l = head[(in[l] & -k) | k]; + if (unsigned k = asc[r] ^ j; k) + k = bit_floor(k), r = head[(in[r] & -k) | k]; + } + return cmp(a[l], a[r]) ? l : r; + } + T query(int l, int r) { return a[idx(l, r)]; } +}; +//! https://codeforces.com/blog/entry/78898 +//! @code +//! auto [p, root, ch] = perm_tree(a); +//! @endcode +//! [p[v].mn_idx, p[v].mn_idx+p[v].len) index range +//! [p[v].mn_num, p[v].mn_num+p[v].len) number range +//! indexes [0, n) of ch are leaves +//! indexes [n, sz(ch)) of ch are internal nodes +//! @time O(n) +//! @space O(n) +struct perm_tree { + struct node { + int mn_idx, mn_num, len; + bool is_join; + }; + vector p; + int root; + vector> ch; + bool touches(int u, int v) { + return p[u].mn_num == p[v].mn_num + p[v].len || + p[v].mn_num == p[u].mn_num + p[u].len; + } + int allocate(int mn_i, int mn_v, int ln, bool join, + const vector& chs) { + p.push_back({mn_i, mn_v, ln, join}); + ch.push_back(chs); + return ssize(ch) - 1; + } + perm_tree(const vector& a) { + int n = ssize(a); + vector mn_i(n), mx_i(n); + { + vector a_inv(n, -1); + for (int i = 0; i < n; i++) a_inv[a[i]] = i; + linear_rmq rmq_min(a_inv, less()); + linear_rmq rmq_max(a_inv, greater()); + for (int i = 1; i < n; i++) { + mn_i[i] = a_inv[rmq_min.idx(a[i - 1], a[i])]; + mx_i[i] = a_inv[rmq_max.idx(a[i - 1], a[i])]; + } + } + for (int i = 0; i < n; i++) + allocate(i, a[i], 1, 0, {}); + vector> st; + for (int i = 0; i < n; i++) { + int v = i; + while (!empty(st)) { + int u = st.back()[0]; + if (!empty(ch[u]) && touches(ch[u].back(), v)) { + p[u].mn_num = min(p[u].mn_num, p[v].mn_num); + p[u].len += p[v].len; + ch[u].push_back(v); + v = u; + st.pop_back(); + continue; + } + if (touches(v, u)) { + v = allocate(p[u].mn_idx, + min(p[v].mn_num, p[u].mn_num), + p[v].len + p[u].len, 1, {u, v}); + st.pop_back(); + continue; + } + int l = min(p[u].mn_idx, mn_i[p[v].mn_idx]), + r = max(i, mx_i[p[v].mn_idx]), + idx = ssize(st) - 1; + while (r == i && l != p[st[idx][0]].mn_idx) + l = min(l, st[idx][1]), r = max(r, st[idx][2]), + idx = st[idx][3]; + if (r > i) { + st.push_back({v, l, r, idx}); + break; + } + int min_num = p[v].mn_num; + vector chs(1 + ssize(st) - idx, v); + for (int j = idx; j < ssize(st); j++) + min_num = min(min_num, + p[chs[j - idx] = st[j][0]].mn_num); + v = allocate(l, min_num, i - l + 1, 0, chs); + st.resize(idx); + } + if (empty(st)) st.push_back({v, -1, -1, -1}); + } + assert(ssize(st) == 1); + root = st[0][0]; + } +}; diff --git a/library/data_structures/uncommon/priority_queue_of_updates.hpp b/data_structures/uncommon/priority_queue_of_updates.hpp similarity index 82% rename from library/data_structures/uncommon/priority_queue_of_updates.hpp rename to data_structures/uncommon/priority_queue_of_updates.hpp index 7796a03d..c3db60f6 100644 --- a/library/data_structures/uncommon/priority_queue_of_updates.hpp +++ b/data_structures/uncommon/priority_queue_of_updates.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://codeforces.com/blog/entry/111117 //! @code //! dsu_restorable dsu_r(n); @@ -32,22 +31,22 @@ template struct pq_updates { //! variables decreases by 1 void pop_update() { vector extra; - int idx = sz(upd_st) - 1, lowest_pri = INT_MAX; + int idx = ssize(upd_st) - 1, lowest_pri = INT_MAX; for (auto it = rbegin(mp); - 2 * sz(extra) < sz(upd_st) - idx; it++) { + 2 * ssize(extra) < ssize(upd_st) - idx; it++) { auto [pri, idx_sk] = *it; extra.push_back(upd_st[idx_sk]); idx = min(idx, idx_sk), lowest_pri = pri; } - auto it = - remove_if(idx + all(upd_st), [&](auto& curr) { + auto it = remove_if(idx + begin(upd_st), end(upd_st), + [&](auto& curr) { return curr.second->first >= lowest_pri; }); - reverse_copy(all(extra), it); - rep(i, idx, sz(upd_st)) ds.undo(); + reverse_copy(begin(extra), end(extra), it); + for (int i = idx; i < ssize(upd_st); i++) ds.undo(); upd_st.pop_back(); mp.erase(prev(end(mp))); - rep(i, idx, sz(upd_st)) { + for (int i = idx; i < ssize(upd_st); i++) { apply(&DS::join, tuple_cat(make_tuple(&ds), upd_st[i].first)); upd_st[i].second->second = i; @@ -60,7 +59,7 @@ template struct pq_updates { //! `upd_st`, `mp` member variables void push_update(ARGS... args, int priority) { ds.join(args...); - auto [it, ins] = mp.emplace(priority, sz(upd_st)); + auto [it, ins] = mp.emplace(priority, ssize(upd_st)); assert(ins); upd_st.emplace_back(make_tuple(args...), it); } diff --git a/library/flow/dinic.hpp b/flow/dinic.hpp similarity index 66% rename from library/flow/dinic.hpp rename to flow/dinic.hpp index 7d09a687..3819036e 100644 --- a/library/flow/dinic.hpp +++ b/flow/dinic.hpp @@ -13,39 +13,39 @@ struct dinic { struct edge { int v, to; - ll c, cap; - ll flow() { return cap - c; } + int64_t c, cap; + int64_t flow() { return cap - c; } }; - ll max_cap = 1; - vi lvl, ptr, q; - vector adj; + int64_t max_cap = 1; + vector lvl, ptr, q; + vector> adj; vector edges; dinic(int n): lvl(n), ptr(n), q(n), adj(n) {} - int add_edge(int a, int b, ll c) { - adj[a].push_back(sz(edges)); + int add_edge(int a, int b, int64_t c) { + adj[a].push_back(ssize(edges)); edges.push_back({a, b, c, c}); - adj[b].push_back(sz(edges)); + adj[b].push_back(ssize(edges)); edges.push_back({-1, a, 0, -1}); max_cap = max(max_cap, c); - return sz(edges) - 2; + return ssize(edges) - 2; } - ll dfs(int v, int t, ll f) { + int64_t dfs(int v, int t, int64_t f) { if (v == t || !f) return f; - for (int& i = ptr[v]; i < sz(adj[v]); i++) { + for (int& i = ptr[v]; i < ssize(adj[v]); i++) { edge& e = edges[adj[v][i]]; if (lvl[e.to] == lvl[v] + 1) - if (ll p = dfs(e.to, t, min(f, e.c))) { + if (int64_t p = dfs(e.to, t, min(f, e.c))) { e.c -= p, edges[adj[v][i] ^ 1].c += p; return p; } } return 0; } - ll calc(int s, int t) { - ll flow = 0; + int64_t calc(int s, int t) { + int64_t flow = 0; q[0] = s; - for (ll i = max_cap; i; i /= 2) do { - lvl = ptr = vi(sz(q)); + for (int64_t i = max_cap; i; i /= 2) do { + lvl = ptr = vector(ssize(q)); int qi = 0, qe = lvl[s] = 1; while (qi < qe && !lvl[t]) { int v = q[qi++]; @@ -53,7 +53,7 @@ struct dinic { if (edge e = edges[id]; !lvl[e.to] && e.c >= i) q[qe++] = e.to, lvl[e.to] = lvl[v] + 1; } - while (ll p = dfs(s, t, LLONG_MAX)) flow += p; + while (int64_t p = dfs(s, t, LLONG_MAX)) flow += p; } while (lvl[t]); return flow; } diff --git a/library/flow/hungarian.hpp b/flow/hungarian.hpp similarity index 54% rename from library/flow/hungarian.hpp rename to flow/hungarian.hpp index c2f47486..7f2c8b35 100644 --- a/library/flow/hungarian.hpp +++ b/flow/hungarian.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://e-maxx.ru/algo/assignment_hungary //! @code //! vector cost(n+1,vector(m+1,(ll)0)); @@ -10,28 +9,29 @@ //! 1<=v<=n; 1<=l_to_r[v]<=m //! @time O(n^2 * m) //! @space O(n + m) -pair hungarian(const vector>& cost) { - int n = sz(cost), m = sz(cost[0]); - vi p(m), way(m); - vector u(n), v(m); - rep(i, 1, n) { +pair> hungarian( + const vector>& cost) { + int n = ssize(cost), m = ssize(cost[0]); + vector p(m), way(m); + vector u(n), v(m); + for (int i = 1; i < n; i++) { p[0] = i; int j0 = 0; vector minv(m, LLONG_MAX); - vi used(m); + vector used(m); do { used[j0] = 1; int i0 = p[j0], j1 = 0; - ll delta = LLONG_MAX; - rep(j, 1, m) if (!used[j]) { - ll cur = cost[i0][j] - u[i0] - v[j]; - if (cur < minv[j]) minv[j] = cur, way[j] = j0; - if (minv[j] < delta) delta = minv[j], j1 = j; - } - rep(j, 0, m) { + int64_t delta = LLONG_MAX; + for (int j = 1; j < m; j++) + if (!used[j]) { + int64_t cur = cost[i0][j] - u[i0] - v[j]; + if (cur < minv[j]) minv[j] = cur, way[j] = j0; + if (minv[j] < delta) delta = minv[j], j1 = j; + } + for (int j = 0; j < m; j++) if (used[j]) u[p[j]] += delta, v[j] -= delta; else minv[j] -= delta; - } j0 = j1; } while (p[j0] != 0); do { @@ -40,7 +40,7 @@ pair hungarian(const vector>& cost) { j0 = j1; } while (j0); } - vi l_to_r(n); - rep(j, 1, m) l_to_r[p[j]] = j; + vector l_to_r(n); + for (int j = 1; j < m; j++) l_to_r[p[j]] = j; return {-v[0], l_to_r}; } diff --git a/library/flow/min_cost_max_flow.hpp b/flow/min_cost_max_flow.hpp similarity index 76% rename from library/flow/min_cost_max_flow.hpp rename to flow/min_cost_max_flow.hpp index f2028a7f..71180123 100644 --- a/library/flow/min_cost_max_flow.hpp +++ b/flow/min_cost_max_flow.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://e-maxx.ru/algo/min_cost_flow //! @code //! mcmf f(n); @@ -13,25 +12,26 @@ struct mcmf { struct edge { int u, v; - ll cap, cost, flow, back; + int64_t cap, cost, flow, back; }; int n; vector e; - vector adj; + vector> adj; mcmf(int n): n(n), adj(n) {} - void add_edge(int u, int v, ll cap, ll cost) { - edge e1 = {u, v, cap, cost, 0, sz(adj[v])}; - edge e2 = {v, u, 0, -cost, 0, sz(adj[u])}; - adj[u].push_back(sz(e)); + void add_edge(int u, int v, int64_t cap, int64_t cost) { + edge e1 = {u, v, cap, cost, 0, ssize(adj[v])}; + edge e2 = {v, u, 0, -cost, 0, ssize(adj[u])}; + adj[u].push_back(ssize(e)); e.push_back(e1); - adj[v].push_back(sz(e)); + adj[v].push_back(ssize(e)); e.push_back(e2); } - array get_flow(int s, int t, ll total_flow) { - ll flow = 0, cost = 0; + array get_flow(int s, int t, + int64_t total_flow) { + int64_t flow = 0, cost = 0; while (flow < total_flow) { vector d(n, LLONG_MAX); - vi p_edge(n), id(n), q(n), p(n); + vector p_edge(n), id(n), q(n), p(n); int qh = 0, qt = 0; q[qt++] = s; d[s] = 0; @@ -39,7 +39,7 @@ struct mcmf { int u = q[qh++]; id[u] = 2; if (qh == n) qh = 0; - rep(i, 0, sz(adj[u])) { + for (int i = 0; i < ssize(adj[u]); i++) { edge& r = e[adj[u][i]]; if (r.flow < r.cap && d[u] + r.cost < d[r.v]) { d[r.v] = d[u] + r.cost; @@ -57,7 +57,7 @@ struct mcmf { } } if (d[t] == LLONG_MAX) break; - ll addflow = total_flow - flow; + int64_t addflow = total_flow - flow; for (int u = t; u != s; u = p[u]) { int pv = p[u], pr = p_edge[u]; addflow = min(addflow, diff --git a/library/graphs/bcc_callback.hpp b/graphs/bcc_callback.hpp similarity index 90% rename from library/graphs/bcc_callback.hpp rename to graphs/bcc_callback.hpp index f751b908..831d941f 100644 --- a/library/graphs/bcc_callback.hpp +++ b/graphs/bcc_callback.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://cp-algorithms.com/graph/cutpoints.html //! @code //! { @@ -42,8 +41,8 @@ //! @time O(n + m) //! @space O(n) void bcc_callback(const auto& adj, auto f) { - int n = sz(adj), q = 0, s = 0; - vi t(n), st(n); + int n = ssize(adj), q = 0, s = 0; + vector t(n), st(n); auto dfs = [&](auto&& self, int v) -> int { int l = t[v] = ++q; for (int u : adj[v]) { @@ -51,11 +50,12 @@ void bcc_callback(const auto& adj, auto f) { l = min(l, t[u] ?: (lu = self(self, st[s++] = u))); if (lu >= t[v]) { st[s++] = v; - f({siz + all(st) - n + s}); + f({siz + begin(st), end(st) - n + s}); s = siz; } } return l; }; - rep(i, 0, n) if (!t[i]) dfs(dfs, i); + for (int i = 0; i < n; i++) + if (!t[i]) dfs(dfs, i); } diff --git a/library/graphs/dijkstra.hpp b/graphs/dijkstra.hpp similarity index 78% rename from library/graphs/dijkstra.hpp rename to graphs/dijkstra.hpp index c5c4ec40..4dbc152c 100644 --- a/library/graphs/dijkstra.hpp +++ b/graphs/dijkstra.hpp @@ -1,4 +1,3 @@ -#pragma once //! @code //! vector>> adj(n); //! auto d = dijkstra(adj, source); @@ -6,11 +5,11 @@ //! d[v] = min dist from source->..->v //! @time O(n + (m log m)) //! @space O(n + m) -vector dijkstra(const auto& adj, int s) { - using p = pair; +vector dijkstra(const auto& adj, int s) { + using p = pair; priority_queue, greater<>> pq; pq.emplace(0, s); - vector d(sz(adj), LLONG_MAX); + vector d(ssize(adj), LLONG_MAX); while (!empty(pq)) { auto [d_v, v] = pq.top(); pq.pop(); diff --git a/library/graphs/hopcroft_karp.hpp b/graphs/hopcroft_karp.hpp similarity index 83% rename from library/graphs/hopcroft_karp.hpp rename to graphs/hopcroft_karp.hpp index 9d504347..77a67090 100644 --- a/library/graphs/hopcroft_karp.hpp +++ b/graphs/hopcroft_karp.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://github.com/foreverbell/acm-icpc-cheat-sheet/blob/master/src/graph-algorithm/hopcroft-karp.cpp //! @code //! vector> adj(lsz); @@ -15,16 +14,16 @@ //! @space O(n) struct hopcroft_karp { int m_sz = 0; - vi to_r, to_l; + vector to_r, to_l; vector mvc_l, mvc_r; hopcroft_karp(const auto& adj, int rsz): - to_r(sz(adj), -1), to_l(rsz, -1) { - int lsz = sz(adj); + to_r(ssize(adj), -1), to_l(rsz, -1) { + int lsz = ssize(adj); while (1) { queue q; - vi level(lsz, -1); - rep(i, 0, lsz) if (to_r[i] == -1) level[i] = 0, - q.push(i); + vector level(lsz, -1); + for (int i = 0; i < lsz; i++) + if (to_r[i] == -1) level[i] = 0, q.push(i); bool found = 0; mvc_l.assign(lsz, 1); mvc_r.assign(rsz, 0); @@ -56,8 +55,8 @@ struct hopcroft_karp { level[v] = INT_MAX; return 0; }; - rep(i, 0, lsz) m_sz += - (to_r[i] == -1 && dfs(dfs, i)); + for (int i = 0; i < lsz; i++) + m_sz += (to_r[i] == -1 && dfs(dfs, i)); } } }; diff --git a/graphs/mst.hpp b/graphs/mst.hpp new file mode 100644 index 00000000..9567759f --- /dev/null +++ b/graphs/mst.hpp @@ -0,0 +1,37 @@ +struct DSU { + vector e; + DSU(int n): e(n, -1) {} + int size(int x) { return -e[go(x)]; } + int go(int x) { return e[x] < 0 ? x : e[x] = go(e[x]); } + bool join(int a, int b) { + if ((a = go(a)) == (b = go(b))) return 0; + if (e[a] > e[b]) swap(a, b); + return e[a] += e[b], e[b] = a, 1; + } +}; +//! @code +//! auto [mst_cost, ids] = mst(w_eds, n); +//! @endcode +//! mst_cost = sum of edge weights in MST +//! w_eds[ids[i]] = edge in MST +//! @time O(n \alpha(n) + m log m) +//! @space O(n + m) +pair> mst( + const vector>& w_eds, int n) { + vector order(ssize(w_eds)); + iota(begin(order), end(order), 0); + ranges::sort(order, [&](int i, int j) { + return w_eds[i][2] < w_eds[j][2]; + }); + DSU dsu(n); + vector ids; + int64_t cost = 0; + for (int it : order) { + auto [u, v, w] = w_eds[it]; + if (dsu.join(u, v)) { + cost += w; + ids.push_back(it); + } + } + return {cost, ids}; +} diff --git a/library/graphs/scc.hpp b/graphs/scc.hpp similarity index 81% rename from library/graphs/scc.hpp rename to graphs/scc.hpp index 4691e704..dee74a00 100644 --- a/library/graphs/scc.hpp +++ b/graphs/scc.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://github.com/kth-competitive-programming/kactl/blob/main/content/graph/SCC.h //! @code //! vector> adj(n); @@ -9,8 +8,8 @@ //! @time O(n + m) //! @space O(n) auto sccs(const auto& adj) { - int n = sz(adj), num_sccs = 0, q = 0, s = 0; - vi scc_id(n, -1), tin(n), st(n); + int n = ssize(adj), num_sccs = 0, q = 0, s = 0; + vector scc_id(n, -1), tin(n), st(n); auto dfs = [&](auto&& self, int v) -> int { int low = tin[v] = ++q; st[s++] = v; @@ -23,6 +22,7 @@ auto sccs(const auto& adj) { } return low; }; - rep(i, 0, n) if (!tin[i]) dfs(dfs, i); + for (int i = 0; i < n; i++) + if (!tin[i]) dfs(dfs, i); return pair{num_sccs, scc_id}; } diff --git a/graphs/strongly_connected_components/add_edges_strongly_connected.hpp b/graphs/strongly_connected_components/add_edges_strongly_connected.hpp new file mode 100644 index 00000000..ed8ad047 --- /dev/null +++ b/graphs/strongly_connected_components/add_edges_strongly_connected.hpp @@ -0,0 +1,93 @@ +//! https://github.com/kth-competitive-programming/kactl/blob/main/content/graph/SCC.h +//! @code +//! vector> adj(n); +//! auto [num_sccs, scc_id] = sccs(adj); +//! @endcode +//! scc_id[v] = id, 0<=id v: scc_id[u] >= scc_id[v] +//! @time O(n + m) +//! @space O(n) +auto sccs(const auto& adj) { + int n = ssize(adj), num_sccs = 0, q = 0, s = 0; + vector scc_id(n, -1), tin(n), st(n); + auto dfs = [&](auto&& self, int v) -> int { + int low = tin[v] = ++q; + st[s++] = v; + for (int u : adj[v]) + if (scc_id[u] < 0) + low = min(low, tin[u] ?: self(self, u)); + if (tin[v] == low) { + while (scc_id[v] < 0) scc_id[st[--s]] = num_sccs; + num_sccs++; + } + return low; + }; + for (int i = 0; i < n; i++) + if (!tin[i]) dfs(dfs, i); + return pair{num_sccs, scc_id}; +} +//! https://codeforces.com/blog/entry/15102 +//! Add minimum extra directed edges to directed graph to +//! make it strongly connected. If the directed graph is +//! not initially strongly connected, then the edge list's +//! size is max(# zero indegree SCCs, # zero outdegree +//! SCCs) +//! +//! @code +//! auto [num_sccs, scc_id] = sccs(adj); +//! vector edges = extra_edges(adj, +//! num_sccs, scc_id); +//! @endcode +//! @param adj,num_sccs,scc_id directed graph and its SCCs +//! @returns directed edge list: edges[i][0] -> edges[i][1] +//! @time O(n + m) +//! @space An O(n) edge list is allocated and returned, but +//! multiple O(n + m) vectors are allocated temporarily +vector> extra_edges(const auto& adj, + int num_sccs, const vector& scc_id) { + if (num_sccs == 1) return {}; + int n = ssize(adj); + vector> scc_adj(num_sccs); + vector zero_in(num_sccs, 1); + for (int i = 0; i < n; i++) + for (int u : adj[i]) { + if (scc_id[i] == scc_id[u]) continue; + scc_adj[scc_id[i]].push_back(scc_id[u]); + zero_in[scc_id[u]] = 0; + } + vector vis(num_sccs); + auto dfs = [&](auto&& self, int v) { + if (empty(scc_adj[v])) return v; + for (int u : scc_adj[v]) + if (!vis[u]) { + vis[u] = 1; + int zero_out = self(self, u); + if (zero_out != -1) return zero_out; + } + return -1; + }; + vector> edges; + vector in_unused; + for (int i = 0; i < num_sccs; i++) + if (zero_in[i]) { + vis[i] = 1; + int zero_out = dfs(dfs, i); + if (zero_out != -1) edges.emplace_back(zero_out, i); + else in_unused.push_back(i); + } + for (int i = 1; i < ssize(edges); i++) + swap(edges[i].first, edges[i - 1].first); + for (int i = 0; i < num_sccs; i++) + if (empty(scc_adj[i]) && !vis[i]) { + if (!empty(in_unused)) { + edges.emplace_back(i, in_unused.back()); + in_unused.pop_back(); + } else edges.emplace_back(i, num_sccs - 1); + } + for (int v : in_unused) edges.emplace_back(0, v); + vector to_node(num_sccs); + for (int i = 0; i < n; i++) to_node[scc_id[i]] = i; + for (auto& [u, v] : edges) + u = to_node[u], v = to_node[v]; + return edges; +} diff --git a/library/graphs/strongly_connected_components/offline_incremental_scc.hpp b/graphs/strongly_connected_components/offline_incremental_scc.hpp similarity index 50% rename from library/graphs/strongly_connected_components/offline_incremental_scc.hpp rename to graphs/strongly_connected_components/offline_incremental_scc.hpp index 2c5d623c..2b525920 100644 --- a/library/graphs/strongly_connected_components/offline_incremental_scc.hpp +++ b/graphs/strongly_connected_components/offline_incremental_scc.hpp @@ -1,5 +1,31 @@ -#pragma once -#include "../scc.hpp" +//! https://github.com/kth-competitive-programming/kactl/blob/main/content/graph/SCC.h +//! @code +//! vector> adj(n); +//! auto [num_sccs, scc_id] = sccs(adj); +//! @endcode +//! scc_id[v] = id, 0<=id v: scc_id[u] >= scc_id[v] +//! @time O(n + m) +//! @space O(n) +auto sccs(const auto& adj) { + int n = ssize(adj), num_sccs = 0, q = 0, s = 0; + vector scc_id(n, -1), tin(n), st(n); + auto dfs = [&](auto&& self, int v) -> int { + int low = tin[v] = ++q; + st[s++] = v; + for (int u : adj[v]) + if (scc_id[u] < 0) + low = min(low, tin[u] ?: self(self, u)); + if (tin[v] == low) { + while (scc_id[v] < 0) scc_id[st[--s]] = num_sccs; + num_sccs++; + } + return low; + }; + for (int i = 0; i < n; i++) + if (!tin[i]) dfs(dfs, i); + return pair{num_sccs, scc_id}; +} //! https://codeforces.com/blog/entry/91608 //! @code //! auto joins = offline_incremental_scc(eds, n); @@ -10,12 +36,13 @@ //! joins[i] = -1 if eds[i][0] == eds[i][1] //! @time O((n + m) log m) //! @space O(n + m) -vi offline_incremental_scc(vector> eds, - int n) { - int m = sz(eds); - vi ids(n, -1), joins(m, m), idx(m), vs(n), scc_id; - iota(all(idx), 0); - vector adj; +vector offline_incremental_scc( + vector> eds, int n) { + int m = ssize(eds); + vector ids(n, -1), joins(m, m), idx(m), vs(n), + scc_id; + iota(begin(idx), end(idx), 0); + vector> adj; auto divide_and_conquer = [&](auto&& self, auto el, auto er, int tl, int tr) { adj.clear(); @@ -24,14 +51,14 @@ vi offline_incremental_scc(vector> eds, auto& [u, v] = eds[*it]; for (int w : {u, v}) { if (ids[w] != -1) continue; - ids[w] = sz(adj); - vs[sz(adj)] = w; + ids[w] = ssize(adj); + vs[ssize(adj)] = w; adj.emplace_back(); } u = ids[u], v = ids[v]; if (*it <= mid) adj[u].push_back(v); } - rep(i, 0, sz(adj)) ids[vs[i]] = -1; + for (int i = 0; i < ssize(adj); i++) ids[vs[i]] = -1; scc_id = sccs(adj).second; auto split = partition(el, er, [&](int i) { return scc_id[eds[i][0]] == scc_id[eds[i][1]]; @@ -47,6 +74,7 @@ vi offline_incremental_scc(vector> eds, }; // uses -1 as the lower bound to correctly handle // self-edges - divide_and_conquer(divide_and_conquer, all(idx), -1, m); + divide_and_conquer(divide_and_conquer, begin(idx), + end(idx), -1, m); return joins; } diff --git a/graphs/uncommon/block_vertex_tree.hpp b/graphs/uncommon/block_vertex_tree.hpp new file mode 100644 index 00000000..b975fc57 --- /dev/null +++ b/graphs/uncommon/block_vertex_tree.hpp @@ -0,0 +1,74 @@ +//! https://cp-algorithms.com/graph/cutpoints.html +//! @code +//! vector>> adj(n); +//! rep (i, 0, m) { +//! int u, v; +//! cin >> u >> v; +//! u--, v--; +//! //self edges not allowed +//! adj[u] += {v, i}; +//! adj[v] += {u, i}; +//! } +//! auto [num_bccs, bcc_id, is_cut] = cuts(adj, m); +//! @endcode +//! is_cut[v] = 1 iff cut node +//! bcc_id[edge id] = id, 0<=id bcc_id(m, -1), is_cut(n), tin(n), st(m); + auto dfs = [&](auto&& self, int v, int p) -> int { + int low = tin[v] = ++q; + for (auto [u, e] : adj[v]) { + assert(v != u); + if (e == p) continue; + if (tin[u] < tin[v]) st[s++] = e; + int lu = -1; + low = min(low, tin[u] ?: (lu = self(self, u, e))); + if (lu >= tin[v]) { + is_cut[v] = p >= 0 || tin[v] + 1 < tin[u]; + while (bcc_id[e] < 0) bcc_id[st[--s]] = num_bccs; + num_bccs++; + } + } + return low; + }; + for (int i = 0; i < n; i++) + if (!tin[i]) dfs(dfs, i, -1); + return tuple{num_bccs, bcc_id, is_cut}; +} +//! @code +//! vector>> adj(n); +//! auto [num_bccs, bcc_id, is_cut] = cuts(adj, m); +//! auto bvt = block_vertex_tree(adj, num_bccs, bcc_id); +//! +//! //to loop over each unique bcc containing a node u: +//! for (int bccid : bvt[v]) { +//! bccid -= n; +//! } +//! //to loop over each unique node inside a bcc: +//! for (int v : bvt[bccid + n]) {} +//! @endcode +//! [0, n) are original nodes +//! [n, n + num_bccs) are BCC nodes +//! @time O(n + m) +//! @time O(n) +auto block_vertex_tree(const auto& adj, int num_bccs, + const vector& bcc_id) { + int n = ssize(adj); + vector> bvt(n + num_bccs); + vector vis(num_bccs); + for (int i = 0; i < n; i++) { + for (auto [_, e_id] : adj[i]) { + int bccid = bcc_id[e_id]; + if (!vis[bccid]) { + vis[bccid] = 1; + bvt[i].push_back(bccid + n); + bvt[bccid + n].push_back(i); + } + } + for (int bccid : bvt[i]) vis[bccid - n] = 0; + } + return bvt; +} diff --git a/graphs/uncommon/bridge_tree.hpp b/graphs/uncommon/bridge_tree.hpp new file mode 100644 index 00000000..6191620b --- /dev/null +++ b/graphs/uncommon/bridge_tree.hpp @@ -0,0 +1,51 @@ +//! https://cp-algorithms.com/graph/bridge-searching.html +//! @code +//! vector>> adj(n); +//! rep (i, 0, m) { +//! int u, v; +//! cin >> u >> v; +//! u--, v--; +//! adj[u] += {v, i}; +//! adj[v] += {u, i}; +//! } +//! auto [num_ccs, br_id, is_br] = bridges(adj, m); +//! @endcode +//! is_br[edge id] = 1 iff bridge edge +//! br_id[v] = id, 0<=id br_id(n, -1), is_br(m), tin(n), st(n); + auto dfs = [&](auto&& self, int v, int p) -> int { + int low = tin[v] = ++q; + st[s++] = v; + for (auto [u, e] : adj[v]) + if (e != p && br_id[u] < 0) + low = min(low, tin[u] ?: self(self, u, e)); + if (tin[v] == low) { + if (p != -1) is_br[p] = 1; + while (br_id[v] < 0) br_id[st[--s]] = num_ccs; + num_ccs++; + } + return low; + }; + for (int i = 0; i < n; i++) + if (!tin[i]) dfs(dfs, i, -1); + return tuple{num_ccs, br_id, is_br}; +} +//! @code +//! vector>> adj(n); +//! auto [num_ccs, br_id, is_br] = bridges(adj, m); +//! auto bt = bridge_tree(adj, num_ccs, br_id, is_br); +//! @endcode +//! @time O(n + m) +//! @space O(n) +auto bridge_tree(const auto& adj, int num_ccs, + const vector& br_id, const vector& is_br) { + vector> tree(num_ccs); + for (int i = 0; i < ssize(adj); i++) + for (auto [u, e_id] : adj[i]) + if (is_br[e_id]) tree[br_id[i]].push_back(br_id[u]); + return tree; +} diff --git a/library/graphs/uncommon/bridges.hpp b/graphs/uncommon/bridges.hpp similarity index 84% rename from library/graphs/uncommon/bridges.hpp rename to graphs/uncommon/bridges.hpp index 5b2ddcb5..3cb32088 100644 --- a/library/graphs/uncommon/bridges.hpp +++ b/graphs/uncommon/bridges.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://cp-algorithms.com/graph/bridge-searching.html //! @code //! vector>> adj(n); @@ -16,8 +15,8 @@ //! @time O(n + m) //! @space O(n + m) auto bridges(const auto& adj, int m) { - int n = sz(adj), num_ccs = 0, q = 0, s = 0; - vi br_id(n, -1), is_br(m), tin(n), st(n); + int n = ssize(adj), num_ccs = 0, q = 0, s = 0; + vector br_id(n, -1), is_br(m), tin(n), st(n); auto dfs = [&](auto&& self, int v, int p) -> int { int low = tin[v] = ++q; st[s++] = v; @@ -31,6 +30,7 @@ auto bridges(const auto& adj, int m) { } return low; }; - rep(i, 0, n) if (!tin[i]) dfs(dfs, i, -1); + for (int i = 0; i < n; i++) + if (!tin[i]) dfs(dfs, i, -1); return tuple{num_ccs, br_id, is_br}; } diff --git a/library/graphs/uncommon/complement_graph_ccs.hpp b/graphs/uncommon/complement_graph_ccs.hpp similarity index 82% rename from library/graphs/uncommon/complement_graph_ccs.hpp rename to graphs/uncommon/complement_graph_ccs.hpp index 864a8de7..480dd081 100644 --- a/library/graphs/uncommon/complement_graph_ccs.hpp +++ b/graphs/uncommon/complement_graph_ccs.hpp @@ -1,4 +1,3 @@ -#pragma once //! @code //! vector> adj; //! vi cc_id = get_complement_graph_ccs(adj); @@ -9,10 +8,10 @@ //! cc in the compliment graph //! @time O(n + m) //! @space O(n) -vi get_complement_graph_ccs(const auto& adj) { - int n = sz(adj); - vi cc_id(n), unseen(n); - iota(all(unseen), 0); +vector get_complement_graph_ccs(const auto& adj) { + int n = ssize(adj); + vector cc_id(n), unseen(n); + iota(begin(unseen), end(unseen), 0); vector is_adj(n); for (int cnt = 0; !empty(unseen); cnt++) { int s = unseen.back(); @@ -22,7 +21,7 @@ vi get_complement_graph_ccs(const auto& adj) { int v = q.front(); q.pop(); for (int u : adj[v]) is_adj[u] = 1; - vi nxt_unseen; + vector nxt_unseen; for (int u : unseen) { if (is_adj[u]) { nxt_unseen.push_back(u); diff --git a/library/graphs/uncommon/cuts.hpp b/graphs/uncommon/cuts.hpp similarity index 85% rename from library/graphs/uncommon/cuts.hpp rename to graphs/uncommon/cuts.hpp index 1f7068a0..6507cab0 100644 --- a/library/graphs/uncommon/cuts.hpp +++ b/graphs/uncommon/cuts.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://cp-algorithms.com/graph/cutpoints.html //! @code //! vector>> adj(n); @@ -17,8 +16,8 @@ //! @time O(n + m) //! @space O(n + m) auto cuts(const auto& adj, int m) { - int n = sz(adj), num_bccs = 0, q = 0, s = 0; - vi bcc_id(m, -1), is_cut(n), tin(n), st(m); + int n = ssize(adj), num_bccs = 0, q = 0, s = 0; + vector bcc_id(m, -1), is_cut(n), tin(n), st(m); auto dfs = [&](auto&& self, int v, int p) -> int { int low = tin[v] = ++q; for (auto [u, e] : adj[v]) { @@ -35,6 +34,7 @@ auto cuts(const auto& adj, int m) { } return low; }; - rep(i, 0, n) if (!tin[i]) dfs(dfs, i, -1); + for (int i = 0; i < n; i++) + if (!tin[i]) dfs(dfs, i, -1); return tuple{num_bccs, bcc_id, is_cut}; } diff --git a/library/graphs/uncommon/enumerate_triangles.hpp b/graphs/uncommon/enumerate_triangles.hpp similarity index 80% rename from library/graphs/uncommon/enumerate_triangles.hpp rename to graphs/uncommon/enumerate_triangles.hpp index 5c50437d..9dc3c42f 100644 --- a/library/graphs/uncommon/enumerate_triangles.hpp +++ b/graphs/uncommon/enumerate_triangles.hpp @@ -1,4 +1,3 @@ -#pragma once //! @code //! enumerate_triangles(edges, n, //! [&](int u, int v, int w) { @@ -7,11 +6,11 @@ //! @endcode //! @time O(n + m ^ (3/2)) //! @space O(n + m) -void enumerate_triangles(const vector& edges, int n, - auto f) { - vi deg(n); +void enumerate_triangles( + const vector>& edges, int n, auto f) { + vector deg(n); for (auto [u, v] : edges) deg[u]++, deg[v]++; - vector adj(n); + vector> adj(n); for (auto [u, v] : edges) { if (tie(deg[u], u) > tie(deg[v], v)) swap(u, v); adj[u].push_back(v); diff --git a/graphs/uncommon/functional_graph_processor.hpp b/graphs/uncommon/functional_graph_processor.hpp new file mode 100644 index 00000000..9edac8d7 --- /dev/null +++ b/graphs/uncommon/functional_graph_processor.hpp @@ -0,0 +1,38 @@ +//! https://github.com/Aeren1564/Algorithms/blob/master/Algorithm_Implementations_Cpp/Graph_Theory/Special_Graphs/functional_graph_processor.sublime-snippet +//! @code +//! // 0 <= a[i] < n +//! auto [root_of, cycle, childs] = func_graph(a); +//! auto [cyc_id, cyc_pos] = root_of[v]; +//! int root = cycle[cyc_id][cyc_pos]; +//! bool is_on_cycle = (v == root); +//! @endcode +//! root = first reachable node on cycle from v +//! t[v].childs = forest of reversed edges not in cycles +//! @time O(n) +//! @space O(n) +struct func_graph { + vector> root_of; + vector> cycle, childs; + func_graph(const vector& a): + root_of(ssize(a)), childs(ssize(a)) { + vector vis(ssize(a)); + for (int i = 0; i < ssize(a); i++) + if (!vis[i]) { + int u = i; + for (; !vis[u]; u = a[u]) vis[u] = 1; + if (vis[u] == 1) + for (cycle.emplace_back(); vis[u] == 1; + u = a[u]) { + root_of[u] = { + ssize(cycle) - 1, ssize(cycle.back())}; + cycle.back().push_back(u); + vis[u] = 2; + } + for (int v = i; vis[v] == 1; v = a[v]) { + root_of[v] = root_of[u]; + childs[a[v]].push_back(v); + vis[v] = 2; + } + } + } +}; diff --git a/hackpack-cpp b/hackpack-cpp deleted file mode 160000 index 79e769ca..00000000 --- a/hackpack-cpp +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 79e769ca88b409ee24e4ea58f5e28bd9614061f4 diff --git a/kactl b/kactl deleted file mode 160000 index c52bac76..00000000 --- a/kactl +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c52bac765cdd9cda1def052c698ffa7bd3318d29 diff --git a/library/data_structures/bit.hpp b/library/data_structures/bit.hpp deleted file mode 100644 index 4a2ed094..00000000 --- a/library/data_structures/bit.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -//! @time O(n + q log n) -//! @space O(n) -// NOLINTNEXTLINE(readability-identifier-naming) -struct BIT { - vector s; - BIT(int n): s(n) {} -#include "bit_uncommon/vector_constructor.hpp" - void update(int i, ll d) { - for (; i < sz(s); i |= i + 1) s[i] += d; - } - ll query(int r) { // [0, r) - ll ret = 0; - for (; r > 0; r &= r - 1) ret += s[r - 1]; - return ret; - } - ll query(int l, int r) { // [l, r) - return query(r) - query(l); - } -#include "bit_uncommon/walk.hpp" -}; diff --git a/library/data_structures/bit_inc.hpp b/library/data_structures/bit_inc.hpp deleted file mode 100644 index b4a4527a..00000000 --- a/library/data_structures/bit_inc.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -//! @time O(n + q log n) -//! @space O(n) -struct bit_inc { - vector s; - bit_inc(int n): s(n) {} - void update(int i, ll d) { - for (; i < sz(s); i |= i + 1) s[i] += d; - } - ll query(int i) { // [0, i] - ll ret = 0; - for (; i >= 0; (i &= i + 1)--) ret += s[i]; - return ret; - } - ll query(int l, int r) { // [l, r] - return query(r) - query(l - 1); - } -#include "bit_uncommon/walk.hpp" -#include "bit_uncommon/prev.hpp" -#include "bit_uncommon/next.hpp" -}; diff --git a/library/data_structures/bit_uncommon/rupq.hpp b/library/data_structures/bit_uncommon/rupq.hpp deleted file mode 100644 index f2268f19..00000000 --- a/library/data_structures/bit_uncommon/rupq.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -#include "../bit.hpp" -struct bit_rupq { - int n; - BIT bit = {0}; - bit_rupq(int n): n(n), bit(n) {} - bit_rupq(vector a): n(sz(a)) { - adjacent_difference(all(a), begin(a)); - bit = {a}; - } - //! does a[l]+=d, a[l+1]+=d, .., a[r-1]+=d - //! @time O(log n) - //! @space O(1) - void update(int l, int r, ll d) { - if (l < n) bit.update(l, d); - if (r < n) bit.update(r, -d); - } - //! @returns a[i] - //! @time O(log n) - //! @space O(1) - ll get_index(int i) { return bit.query(i + 1); } -}; diff --git a/library/data_structures/bit_uncommon/rurq.hpp b/library/data_structures/bit_uncommon/rurq.hpp deleted file mode 100644 index eabf67e2..00000000 --- a/library/data_structures/bit_uncommon/rurq.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once -#include "../bit.hpp" -//! https://blog.mitrichev.ch/2013/05/fenwick-tree-range-updates.html -struct bit_rurq { - int n; - BIT bit1 = {0}, bit2 = {0}; - bit_rurq(int n): n(n), bit1(n), bit2(n) {} - bit_rurq(vector a): n(sz(a)) { - adjacent_difference(all(a), begin(a)); - bit1 = {a}; - rep(i, 0, n) a[i] *= i; - bit2 = {a}; - } - //! does a[l]+=d, a[l+1]+=d, ..., a[r-1]+=d - //! @time O(log n) - //! @space O(1) - void update(int l, int r, ll d) { - if (l < n) { - bit1.update(l, d); - bit2.update(l, d * l); - } - if (r < n) { - bit1.update(r, -d); - bit2.update(r, -d * r); - } - } - //! @returns a[0]+a[1]+...+a[r-1] - //! @time O(log n) - //! @space O(1) - ll query(int r) { - return bit1.query(r) * r - bit2.query(r); - } - //! @returns a[l]+a[l+1]+...+a[r-1] - //! @time O(log n) - //! @space O(1) - ll query(int l, int r) { return query(r) - query(l); } -}; diff --git a/library/data_structures/bit_uncommon/vector_constructor.hpp b/library/data_structures/bit_uncommon/vector_constructor.hpp deleted file mode 100644 index 35fef530..00000000 --- a/library/data_structures/bit_uncommon/vector_constructor.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once -BIT(const vector& a): s(a) { - rep(i, 0, sz(a)) { - int j = i | (i + 1); - if (j < sz(a)) s[j] += s[i]; - } -} diff --git a/library/data_structures/dsu/range_parallel_equivalence_classes.hpp b/library/data_structures/dsu/range_parallel_equivalence_classes.hpp deleted file mode 100644 index 7d30fbd7..00000000 --- a/library/data_structures/dsu/range_parallel_equivalence_classes.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "../../../kactl/content/data-structures/UnionFind.h" -//! Given triplets (l1,l2,len); joins (l1,l2), -//! (l1+1,l2+1), ..., (l1+len-1,l2+len-1) -//! @time O((n + q) * \alpha(n)) -//! @space O(n + q) -UF get_rp_dsu(const vector>& rests, int n) { - vector> rests_by_len(n + 1); - for (auto [l1, l2, len] : rests) - rests_by_len[len].emplace_back(l1, l2); - UF uf(n); - for (int len = n; len > 0; len--) - for (auto [l1, l2] : rests_by_len[len]) - if (uf.join(l1, l2)) - rests_by_len[len - 1].emplace_back(l1 + 1, l2 + 1); - return uf; -} diff --git a/library/data_structures/lazy_seg_tree.hpp b/library/data_structures/lazy_seg_tree.hpp deleted file mode 100644 index 817ecaa9..00000000 --- a/library/data_structures/lazy_seg_tree.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once -#include "lazy_seg_tree_midpoint.hpp" -ll op(ll vl, ll vr) { return vl + vr; } -struct seg_tree { - int n; - vector tree, lazy; - seg_tree(int n): n(n), tree(2 * n), lazy(n) {} - seg_tree(const vi& a): n(sz(a)), tree(2 * n), lazy(n) { - int pw2 = bit_ceil(size(a)); - rep(i, 0, n) tree[(i + pw2) % n + n] = a[i]; - for (int i = n - 1; i >= 1; i--) - tree[i] = op(tree[2 * i], tree[2 * i + 1]); - } - void apply(ll change, int tl, int tr, int v) { - tree[v] += (tr - tl) * change; - if (v < n) lazy[v] += change; - } - void push(int tl, int tm, int tr, int v) { - if (lazy[v]) { - apply(lazy[v], tl, tm, 2 * v); - apply(lazy[v], tm, tr, 2 * v + 1); - lazy[v] = 0; - } - } - void update(int l, int r, ll change) { // [l, r) - update_impl(l, r, change, 0, n, 1); - } - void update_impl(int l, int r, ll change, int tl, int tr, - int v) { - if (r <= tl || tr <= l) return; - if (l <= tl && tr <= r) - return apply(change, tl, tr, v); - int tm = split(tl, tr); - push(tl, tm, tr, v); - update_impl(l, r, change, tl, tm, 2 * v); - update_impl(l, r, change, tm, tr, 2 * v + 1); - tree[v] = op(tree[2 * v], tree[2 * v + 1]); - } - ll query(int l, int r) { // [l, r) - return query_impl(l, r, 0, n, 1); - } - ll query_impl(int l, int r, int tl, int tr, int v) { - if (r <= tl || tr <= l) return 0; - if (l <= tl && tr <= r) return tree[v]; - int tm = split(tl, tr); - push(tl, tm, tr, v); - return op(query_impl(l, r, tl, tm, 2 * v), - query_impl(l, r, tm, tr, 2 * v + 1)); - } -#include "seg_tree_uncommon/find_first.hpp" -#include "seg_tree_uncommon/find_last.hpp" -}; diff --git a/library/data_structures/seg_tree_uncommon/distinct_query.hpp b/library/data_structures/seg_tree_uncommon/distinct_query.hpp deleted file mode 100644 index 2bd2172a..00000000 --- a/library/data_structures/seg_tree_uncommon/distinct_query.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include "persistent.hpp" -//! https://cp-algorithms.com/data_structures/segment_tree.html#preserving-the-history-of-its-values-persistent-segment-tree -struct distinct_query { - int n; - PST pst; - //! @param a static array; can't handle updates - //! @time O(n log n) - //! @space O(n log n) - distinct_query(const vi& a): n(sz(a)), pst(0, n + 1) { - map last_idx; - rep(i, 0, n) { - int& idx = last_idx[a[i]]; - pst.update(idx, 1, i); - idx = i + 1; - } - } - //! @param l,r defines range [l, r) - //! @returns number of distinct elements in range; - //! query(i, i) returns 0. - //! @time O(log n) - //! @space O(log n) - int query(int l, int r) { - return pst.query(0, l + 1, r) - pst.query(0, l + 1, l); - } -}; diff --git a/library/data_structures/seg_tree_uncommon/kth_smallest_query.hpp b/library/data_structures/seg_tree_uncommon/kth_smallest_query.hpp deleted file mode 100644 index 51d9a9b4..00000000 --- a/library/data_structures/seg_tree_uncommon/kth_smallest_query.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once -#include "persistent.hpp" -//! https://cp-algorithms.com/data_structures/segment_tree.html#preserving-the-history-of-its-values-persistent-segment-tree -struct kth_smallest { - PST pst; - //! @param a,minv,maxv must satisfy: minv <= a[i] < maxv - //! @time O(n log(maxv - minv)) - //! @space O(n log(maxv - minv)) nodes are pushed back - //! onto PST::tree - kth_smallest(const vi& a, int minv, int maxv): - pst(minv, maxv) { - rep(i, 0, sz(a)) pst.update(a[i], 1, i); - } - //! @param l,r defines range [l, r) - //! @param k must satisfy 1 <= k <= r - l - //! @returns kth smallest number in range. - //! - query(l,r,1) returns the min - //! - query(l,r,(r-l)) returns the max - //! @time O(log(maxv - minv)) - //! @space O(log(maxv - minv)) for recursion stack; no - //! new nodes are allocated - int query(int l, int r, int k) { - return query_impl(k, pst.root_l, pst.root_r, - pst.roots[l], pst.roots[r]); - } - int query_impl(int k, int tl, int tr, int vl, int vr) { - if (tr - tl == 1) return tl; - int tm = tl + (tr - tl) / 2; - int left_count = pst.tree[pst.tree[vr].lch].sum - - pst.tree[pst.tree[vl].lch].sum; - if (left_count >= k) - return query_impl(k, tl, tm, pst.tree[vl].lch, - pst.tree[vr].lch); - return query_impl(k - left_count, tm, tr, - pst.tree[vl].rch, pst.tree[vr].rch); - } -}; diff --git a/library/data_structures/seg_tree_uncommon/wavelet_matrix.hpp b/library/data_structures/seg_tree_uncommon/wavelet_matrix.hpp deleted file mode 100644 index 681e90ae..00000000 --- a/library/data_structures/seg_tree_uncommon/wavelet_matrix.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once -#include "wavelet_bit_vec.hpp" -//! @code -//! vector a(n); -//! wavelet_matrix wm(a, 1e9); // requires a[i] <= 1e9 -//! wm.kth(l, r, k); //(k+1)th smallest number in [l,r) -//! wm.kth(l, r, 0); //min in [l,r) -//! @endcode -//! @time O(n * log(max_val) + q * log(max_val)) -//! @space O(n * log(max_val) / 64) -struct wavelet_matrix { - int n; - vector bv; - wavelet_matrix(vector a, ull max_val): - n(sz(a)), bv(bit_width(max_val), {{}}) { - for (int h = sz(bv); h--;) { - int i = 0; - vector b(n); - ranges::stable_partition(a, - [&](ull x) { return b[i++] = (~x >> h) & 1; }); - bv[h] = b; - } - } - ull kth(int l, int r, int k) { - ll res = 0; - for (int h = sz(bv); h--;) { - int l0 = bv[h].cnt(l), r0 = bv[h].cnt(r); - if (k < r0 - l0) l = l0, r = r0; - else - k -= r0 - l0, res |= 1ULL << h, - l += bv[h].cnt(n) - l0, r += bv[h].cnt(n) - r0; - } - return res; - } -#include "wavelet_count_less.hpp" -}; diff --git a/library/data_structures/uncommon/permutation_tree.hpp b/library/data_structures/uncommon/permutation_tree.hpp deleted file mode 100644 index ee951b21..00000000 --- a/library/data_structures/uncommon/permutation_tree.hpp +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once -#include "linear_rmq.hpp" -//! https://codeforces.com/blog/entry/78898 -//! @code -//! auto [p, root, ch] = perm_tree(a); -//! @endcode -//! [p[v].mn_idx, p[v].mn_idx+p[v].len) index range -//! [p[v].mn_num, p[v].mn_num+p[v].len) number range -//! indexes [0, n) of ch are leaves -//! indexes [n, sz(ch)) of ch are internal nodes -//! @time O(n) -//! @space O(n) -struct perm_tree { - struct node { - int mn_idx, mn_num, len; - bool is_join; - }; - vector p; - int root; - vector ch; - bool touches(int u, int v) { - return p[u].mn_num == p[v].mn_num + p[v].len || - p[v].mn_num == p[u].mn_num + p[u].len; - } - int allocate(int mn_i, int mn_v, int ln, bool join, - const vi& chs) { - p.push_back({mn_i, mn_v, ln, join}); - ch.push_back(chs); - return sz(ch) - 1; - } - perm_tree(const vi& a) { - int n = sz(a); - vi mn_i(n), mx_i(n); - { - vi a_inv(n, -1); - rep(i, 0, n) a_inv[a[i]] = i; - linear_rmq rmq_min(a_inv, less()); - linear_rmq rmq_max(a_inv, greater()); - rep(i, 1, n) { - mn_i[i] = a_inv[rmq_min.idx(a[i - 1], a[i])]; - mx_i[i] = a_inv[rmq_max.idx(a[i - 1], a[i])]; - } - } - rep(i, 0, n) allocate(i, a[i], 1, 0, {}); - vector> st; - rep(i, 0, n) { - int v = i; - while (!empty(st)) { - int u = st.back()[0]; - if (!empty(ch[u]) && touches(ch[u].back(), v)) { - p[u].mn_num = min(p[u].mn_num, p[v].mn_num); - p[u].len += p[v].len; - ch[u].push_back(v); - v = u; - st.pop_back(); - continue; - } - if (touches(v, u)) { - v = allocate(p[u].mn_idx, - min(p[v].mn_num, p[u].mn_num), - p[v].len + p[u].len, 1, {u, v}); - st.pop_back(); - continue; - } - int l = min(p[u].mn_idx, mn_i[p[v].mn_idx]), - r = max(i, mx_i[p[v].mn_idx]), - idx = sz(st) - 1; - while (r == i && l != p[st[idx][0]].mn_idx) - l = min(l, st[idx][1]), r = max(r, st[idx][2]), - idx = st[idx][3]; - if (r > i) { - st.push_back({v, l, r, idx}); - break; - } - int min_num = p[v].mn_num; - vi chs(1 + sz(st) - idx, v); - rep(j, idx, sz(st)) min_num = - min(min_num, p[chs[j - idx] = st[j][0]].mn_num); - v = allocate(l, min_num, i - l + 1, 0, chs); - st.resize(idx); - } - if (empty(st)) st.push_back({v, -1, -1, -1}); - } - assert(sz(st) == 1); - root = st[0][0]; - } -}; diff --git a/library/graphs/mst.hpp b/library/graphs/mst.hpp deleted file mode 100644 index 0f1add26..00000000 --- a/library/graphs/mst.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once -#include "../data_structures/dsu/dsu.hpp" -//! @code -//! auto [mst_cost, ids] = mst(w_eds, n); -//! @endcode -//! mst_cost = sum of edge weights in MST -//! w_eds[ids[i]] = edge in MST -//! @time O(n \alpha(n) + m log m) -//! @space O(n + m) -pair mst(const vector>& w_eds, - int n) { - vi order(sz(w_eds)); - iota(all(order), 0); - ranges::sort(order, [&](int i, int j) { - return w_eds[i][2] < w_eds[j][2]; - }); - DSU dsu(n); - vi ids; - ll cost = 0; - for (int it : order) { - auto [u, v, w] = w_eds[it]; - if (dsu.join(u, v)) { - cost += w; - ids.push_back(it); - } - } - return {cost, ids}; -} diff --git a/library/graphs/strongly_connected_components/add_edges_strongly_connected.hpp b/library/graphs/strongly_connected_components/add_edges_strongly_connected.hpp deleted file mode 100644 index c4d56556..00000000 --- a/library/graphs/strongly_connected_components/add_edges_strongly_connected.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once -#include "../scc.hpp" -//! https://codeforces.com/blog/entry/15102 -//! Add minimum extra directed edges to directed graph to -//! make it strongly connected. If the directed graph is -//! not initially strongly connected, then the edge list's -//! size is max(# zero indegree SCCs, # zero outdegree -//! SCCs) -//! -//! @code -//! auto [num_sccs, scc_id] = sccs(adj); -//! vector edges = extra_edges(adj, -//! num_sccs, scc_id); -//! @endcode -//! @param adj,num_sccs,scc_id directed graph and its SCCs -//! @returns directed edge list: edges[i][0] -> edges[i][1] -//! @time O(n + m) -//! @space An O(n) edge list is allocated and returned, but -//! multiple O(n + m) vectors are allocated temporarily -vector extra_edges(const auto& adj, int num_sccs, - const vi& scc_id) { - if (num_sccs == 1) return {}; - int n = sz(adj); - vector scc_adj(num_sccs); - vector zero_in(num_sccs, 1); - rep(i, 0, n) for (int u : adj[i]) { - if (scc_id[i] == scc_id[u]) continue; - scc_adj[scc_id[i]].push_back(scc_id[u]); - zero_in[scc_id[u]] = 0; - } - vector vis(num_sccs); - auto dfs = [&](auto&& self, int v) { - if (empty(scc_adj[v])) return v; - for (int u : scc_adj[v]) - if (!vis[u]) { - vis[u] = 1; - int zero_out = self(self, u); - if (zero_out != -1) return zero_out; - } - return -1; - }; - vector edges; - vi in_unused; - rep(i, 0, num_sccs) if (zero_in[i]) { - vis[i] = 1; - int zero_out = dfs(dfs, i); - if (zero_out != -1) edges.emplace_back(zero_out, i); - else in_unused.push_back(i); - } - rep(i, 1, sz(edges)) - swap(edges[i].first, edges[i - 1].first); - rep(i, 0, num_sccs) if (empty(scc_adj[i]) && !vis[i]) { - if (!empty(in_unused)) { - edges.emplace_back(i, in_unused.back()); - in_unused.pop_back(); - } else edges.emplace_back(i, num_sccs - 1); - } - for (int v : in_unused) edges.emplace_back(0, v); - vi to_node(num_sccs); - rep(i, 0, n) to_node[scc_id[i]] = i; - for (auto& [u, v] : edges) - u = to_node[u], v = to_node[v]; - return edges; -} diff --git a/library/graphs/uncommon/block_vertex_tree.hpp b/library/graphs/uncommon/block_vertex_tree.hpp deleted file mode 100644 index e69b839f..00000000 --- a/library/graphs/uncommon/block_vertex_tree.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once -#include "cuts.hpp" -//! @code -//! vector>> adj(n); -//! auto [num_bccs, bcc_id, is_cut] = cuts(adj, m); -//! auto bvt = block_vertex_tree(adj, num_bccs, bcc_id); -//! -//! //to loop over each unique bcc containing a node u: -//! for (int bccid : bvt[v]) { -//! bccid -= n; -//! } -//! //to loop over each unique node inside a bcc: -//! for (int v : bvt[bccid + n]) {} -//! @endcode -//! [0, n) are original nodes -//! [n, n + num_bccs) are BCC nodes -//! @time O(n + m) -//! @time O(n) -auto block_vertex_tree(const auto& adj, int num_bccs, - const vi& bcc_id) { - int n = sz(adj); - vector bvt(n + num_bccs); - vector vis(num_bccs); - rep(i, 0, n) { - for (auto [_, e_id] : adj[i]) { - int bccid = bcc_id[e_id]; - if (!vis[bccid]) { - vis[bccid] = 1; - bvt[i].push_back(bccid + n); - bvt[bccid + n].push_back(i); - } - } - for (int bccid : bvt[i]) vis[bccid - n] = 0; - } - return bvt; -} diff --git a/library/graphs/uncommon/bridge_tree.hpp b/library/graphs/uncommon/bridge_tree.hpp deleted file mode 100644 index 3386ef3e..00000000 --- a/library/graphs/uncommon/bridge_tree.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "bridges.hpp" -//! @code -//! vector>> adj(n); -//! auto [num_ccs, br_id, is_br] = bridges(adj, m); -//! auto bt = bridge_tree(adj, num_ccs, br_id, is_br); -//! @endcode -//! @time O(n + m) -//! @space O(n) -auto bridge_tree(const auto& adj, int num_ccs, - const vi& br_id, const vi& is_br) { - vector tree(num_ccs); - rep(i, 0, sz(adj)) for (auto [u, e_id] : adj[i]) if ( - is_br[e_id]) tree[br_id[i]] - .push_back(br_id[u]); - return tree; -} diff --git a/library/graphs/uncommon/functional_graph_processor.hpp b/library/graphs/uncommon/functional_graph_processor.hpp deleted file mode 100644 index db659e0d..00000000 --- a/library/graphs/uncommon/functional_graph_processor.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once -//! https://github.com/Aeren1564/Algorithms/blob/master/Algorithm_Implementations_Cpp/Graph_Theory/Special_Graphs/functional_graph_processor.sublime-snippet -//! @code -//! // 0 <= a[i] < n -//! auto [root_of, cycle, childs] = func_graph(a); -//! auto [cyc_id, cyc_pos] = root_of[v]; -//! int root = cycle[cyc_id][cyc_pos]; -//! bool is_on_cycle = (v == root); -//! @endcode -//! root = first reachable node on cycle from v -//! t[v].childs = forest of reversed edges not in cycles -//! @time O(n) -//! @space O(n) -struct func_graph { - vector root_of; - vector cycle, childs; - func_graph(const vi& a): root_of(sz(a)), childs(sz(a)) { - vi vis(sz(a)); - rep(i, 0, sz(a)) if (!vis[i]) { - int u = i; - for (; !vis[u]; u = a[u]) vis[u] = 1; - if (vis[u] == 1) - for (cycle.emplace_back(); vis[u] == 1; u = a[u]) { - root_of[u] = {sz(cycle) - 1, sz(cycle.back())}; - cycle.back().push_back(u); - vis[u] = 2; - } - for (int v = i; vis[v] == 1; v = a[v]) { - root_of[v] = root_of[u]; - childs[a[v]].push_back(v); - vis[v] = 2; - } - } - } -}; diff --git a/library/loops/chooses.hpp b/library/loops/chooses.hpp deleted file mode 100644 index 3b98c752..00000000 --- a/library/loops/chooses.hpp +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -#include "next_subset.hpp" -//! loop over all submasks of 2^n-1 with -//! k bits set, increasing -//! @time O(n choose k) -//! @space O(1) -for (int mask = (1 << k) - 1; mask < (1 << n); - mask = next_subset(mask)) diff --git a/library/math/count_paths/count_paths_rectangle.hpp b/library/math/count_paths/count_paths_rectangle.hpp deleted file mode 100644 index 52286404..00000000 --- a/library/math/count_paths/count_paths_rectangle.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once -#include "../../../kactl/content/numerical/NumberTheoreticTransform.h" -#include "../n_choose_k/n_choose_k.hpp" -//! https://noshi91.hatenablog.com/entry/2023/07/21/235339 -//! @code -//! auto [right, top] = get_right_and_top(left, bottom); -//! @endcode -//! @time O((n + m)log(n + m)) -//! @space O(n + m) -array get_right_and_top(vl left, vl bottom) { - array ret; - for (vl& res : ret) { - { - vl tr(sz(left)); - rep(i, 0, sz(tr)) tr[i] = C(i + sz(bottom) - 1, i); - res = conv(left, tr); - res.resize(sz(left)); - } - { - vl tr(sz(left) + sz(bottom)); - grow(sz(tr)); - rep(i, 0, sz(tr)) tr[i] = t[i].fact; - vl dp(sz(bottom)); - rep(i, 0, sz(dp)) dp[i] = - bottom[i] * t[sz(dp) - 1 - i].inv_fact % mod; - vl tmp_res = conv(dp, tr); - rep(i, 0, sz(res)) res[i] = - (res[i] + - tmp_res[i + sz(bottom) - 1] * t[i].inv_fact) % - mod; - } - swap(left, bottom); - } - return ret; -} diff --git a/library/math/count_paths/count_paths_triangle.hpp b/library/math/count_paths/count_paths_triangle.hpp deleted file mode 100644 index a9c59c56..00000000 --- a/library/math/count_paths/count_paths_triangle.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once -#include "count_paths_rectangle.hpp" -//! https://noshi91.hatenablog.com/entry/2023/07/21/235339 -//! @time O((n + m)log^2(n + m)): n = sz(h); m = h.back() -//! @space O(n + m) -vl divide_and_conquer(vl h, vl bottom) { - { - int start = - ranges::find_if(h, [](ll x) { return x; }) - - begin(h); - h.erase(begin(h), begin(h) + start); - bottom.erase(begin(bottom), begin(bottom) + start); - } - int n = sz(h); - if (n == 0) return {}; - if (n == 1) return vl(h[0], bottom[0]); - int mid = n / 2; - auto rect_left = - divide_and_conquer(vl(begin(h), begin(h) + mid), - vl(begin(bottom), begin(bottom) + mid)); - auto [rect_right, rect_top] = - get_right_and_top(rect_left, vl(mid + all(bottom))); - vl h_right(mid + all(h)); - for (ll& hh : h_right) hh -= h[mid - 1]; - auto upper_right = divide_and_conquer(h_right, rect_top); - rect_right.insert(end(rect_right), all(upper_right)); - return rect_right; -} diff --git a/library/math/matrix_related/row_reduce.hpp b/library/math/matrix_related/row_reduce.hpp deleted file mode 100644 index 1019a968..00000000 --- a/library/math/matrix_related/row_reduce.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once -#include "../mod_division.hpp" -//! @code -//! auto [rank, det] = row_reduce(mat, cols); -//! @endcode -//! columns [0,cols) of mat represent a matrix -//! columns [cols,m) of mat are also -//! affected by row operations -//! @time O(n * m * min(cols, n)) -//! @space O(1) -pii row_reduce(vector& mat, int cols) { - int n = sz(mat), m = sz(mat[0]), rank = 0; - int det = 1; - for (int col = 0; col < cols && rank < n; col++) { - auto it = find_if(rank + all(mat), - [&](auto& v) { return v[col]; }); - if (it == end(mat)) { - det = 0; - continue; - } - if (it != begin(mat) + rank) { - det = (mod - det) % mod; - iter_swap(begin(mat) + rank, it); - } - det = 1LL * det * mat[rank][col] % mod; - int a_inv = mod_div(1, mat[rank][col]); - for (int& num : mat[rank]) - num = 1LL * num * a_inv % mod; - rep(i, 0, n) if (i != rank && mat[i][col] != 0) { - int num = mat[i][col]; - rep(j, 0, m) mat[i][j] = - ((mat[i][j] - 1LL * mat[rank][j] * num) % mod + - mod) % - mod; - } - rank++; - } - return {rank, det}; -} diff --git a/library/math/matrix_related/solve_linear_mod.hpp b/library/math/matrix_related/solve_linear_mod.hpp deleted file mode 100644 index a4a0016d..00000000 --- a/library/math/matrix_related/solve_linear_mod.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#include "row_reduce.hpp" -//! @code -//! auto [rank, det, sol] = solve_linear_mod(mat, rhs); -//! @endcode -//! for each i, 0<=i& mat, const vi& rhs) { - int n = sz(mat), m = sz(mat[0]); - rep(i, 0, n) mat[i].push_back(rhs[i]); - tie(rank, det) = row_reduce(mat, m); - if (any_of(rank + all(mat), - [](vi& v) { return v.back(); })) { - return; - } - sol.resize(m); - int j = 0; - for_each(begin(mat), begin(mat) + rank, [&](vi& v) { - while (!v[j]) j++; - sol[j] = v.back(); - }); - } -}; diff --git a/library/math/matrix_related/xor_basis_unordered_intersection.hpp b/library/math/matrix_related/xor_basis_unordered_intersection.hpp deleted file mode 100644 index 8dffb9ea..00000000 --- a/library/math/matrix_related/xor_basis_unordered_intersection.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once -#include "xor_basis_unordered.hpp" -//! https://github.com/suisen-cp/cp-library-cpp/blob/main/library/linear_algebra/xor_base.hpp -//! @time O(32^2) or O(64^2); -//! @space O(32) or O(64) -template -basis intersection(const basis& u, - const basis& v) { - vector> w(sz(u.b)); - rep(i, 0, sz(w)) w[i] = {u.b[i], u.b[i]}; - basis res; - for (T e : v.b) { - T s = 0; - for (auto [x, y] : w) - if ((e ^ x) < e) e ^= x, s ^= y; - if (e) w.emplace_back(e, s); - else res.insert(s); - } - return res; -} diff --git a/library/math/n_choose_k/large_n_choose_small_k.hpp b/library/math/n_choose_k/large_n_choose_small_k.hpp deleted file mode 100644 index f0963aef..00000000 --- a/library/math/n_choose_k/large_n_choose_small_k.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include "grow.hpp" -//! n arbitrarily large; k < mod -//! @time O(k) amortized -//! @space O(1) amortized -ll c_small_k(ll n, int k) { - if (k < 0 || n < k || (n %= mod) < k) return 0; - grow(k); - ll res = t[k].inv_fact; - rep(i, 0, k) res = res * (n - i) % mod; - return res; -} diff --git a/library/math/n_choose_k/lucas_theorem.hpp b/library/math/n_choose_k/lucas_theorem.hpp deleted file mode 100644 index e1967324..00000000 --- a/library/math/n_choose_k/lucas_theorem.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include "n_choose_k.hpp" -//! n,k arbitrarily large -//! @time O(log(k)) amortized -//! @space O(1) amortized -ll lucas(ll n, ll k) { - if (k < 0 || n < k) return 0; - ll res = 1; - for (; k && k < n && res; n /= mod, k /= mod) - res = res * C(n % mod, k % mod) % mod; - return res; -} diff --git a/library/math/n_choose_k/n_choose_k.hpp b/library/math/n_choose_k/n_choose_k.hpp deleted file mode 100644 index 3f493072..00000000 --- a/library/math/n_choose_k/n_choose_k.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include "grow.hpp" -//! n,k < mod -//! @time O(1) amortized -//! @space O(1) amortized -// NOLINTNEXTLINE(readability-identifier-naming) -ll C(int n, int k) { - if (k < 0 || n < k) return 0; - grow(n); - return t[n].fact * t[k].inv_fact % mod * - t[n - k].inv_fact % mod; -} diff --git a/library/math/n_choose_k/pascals_identity.hpp b/library/math/n_choose_k/pascals_identity.hpp deleted file mode 100644 index 1a0b412b..00000000 --- a/library/math/n_choose_k/pascals_identity.hpp +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -const int mod = 17; //!< composite ok -vector> ch(1010); //!< ch[n][k] = n choose k -rep(i, 0, sz(ch)) { - ch[i].resize(i + 1, 1); - rep(j, 1, i) ch[i][j] = - (ch[i - 1][j] + ch[i - 1][j - 1]) % mod; -} diff --git a/library/math/prime_sieve/calc_linear_sieve.hpp b/library/math/prime_sieve/calc_linear_sieve.hpp deleted file mode 100644 index 0104524c..00000000 --- a/library/math/prime_sieve/calc_linear_sieve.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -//! @time O(mx) -//! @space O(mx) -vi primes, sieve(1001); //!< min prime factor -iota(all(sieve), 0); -rep(i, 2, sz(sieve)) { - if (sieve[i] == i) primes.push_back(i); - for (int prime : primes) { - if (prime * i >= sz(sieve)) break; - sieve[prime * i] = prime; - if (i % prime == 0) break; - } -} diff --git a/library/math/prime_sieve/calc_sieve.hpp b/library/math/prime_sieve/calc_sieve.hpp deleted file mode 100644 index 3fcbc1b0..00000000 --- a/library/math/prime_sieve/calc_sieve.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -//! @time O(mx * log(log mx)) -//! @space O(mx) -vi sieve(1001); //!< min prime factor -iota(all(sieve), 0); -for (int i = 2; i * i < sz(sieve); i++) - if (sieve[i] == i) - for (int j = i * i; j < sz(sieve); j += i) - sieve[j] = min(sieve[j], i); diff --git a/library/math/prime_sieve/get_prime_factors.hpp b/library/math/prime_sieve/get_prime_factors.hpp deleted file mode 100644 index 7ea9284b..00000000 --- a/library/math/prime_sieve/get_prime_factors.hpp +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once -#include "calc_sieve.hpp" -//! `p` will be all prime factors of num, increasing -//! @time O(log(num)) -//! @space O(1) -for (int cpy = num, p; (p = sieve[cpy]) > 1; cpy /= p) \ No newline at end of file diff --git a/library/math/prime_sieve/is_prime.hpp b/library/math/prime_sieve/is_prime.hpp deleted file mode 100644 index 9fb0150e..00000000 --- a/library/math/prime_sieve/is_prime.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once -#include "calc_sieve.hpp" -//! @time O(1) -//! @space O(1) -auto is_prime = [&](int num) -> bool { - return num >= 2 && sieve[num] == num; -}; diff --git a/library/math/prime_sieve/mobius.hpp b/library/math/prime_sieve/mobius.hpp deleted file mode 100644 index 433e77bd..00000000 --- a/library/math/prime_sieve/mobius.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once -//! @time O(mx log mx) -//! @space O(mx) -vi mobius(100'005); -mobius[1] = 1; -rep(i, 1, sz(mobius)) for (int j = i + i; j < sz(mobius); - j += i) mobius[j] -= mobius[i]; diff --git a/library/monotonic_stack/count_rectangles.hpp b/library/monotonic_stack/count_rectangles.hpp deleted file mode 100644 index c489e356..00000000 --- a/library/monotonic_stack/count_rectangles.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once -#include "monotonic_range.hpp" -//! @code -//! auto cnt = count_rectangles(grid); -//! @endcode -//! -//! cnt[i][j] = the number of times an i-by-j -//! sub rectangle appears in the matrix such that -//! all i*j cells in the sub rectangle are 1 -//! -//! cnt[i][0] and cnt[0][j] will contain garbage numbers. -//! @time O(n * m) -//! @space O(n * m) -vector count_rectangles( - const vector>& grid) { - int n = sz(grid), m = sz(grid[0]); - vector cnt(n + 1, vector(m + 1, 0)); - vi h(m); - rep(i, 0, n) { - rep(j, 0, m) h[j] = grid[i][j] * (h[j] + 1); - vi l(mono_st(h, less())), r(mono_range(l)); - rep(j, 0, m) { - int cnt_l = j - l[j] - 1, cnt_r = r[j] - j - 1; - cnt[h[j]][cnt_l + cnt_r + 1]++; - cnt[h[j]][cnt_l]--; - cnt[h[j]][cnt_r]--; - } - } - rep(i, 1, n + 1) rep(k, 0, 2) for (int j = m; j > 1; j--) - cnt[i][j - 1] += cnt[i][j]; - for (int i = n; i > 1; i--) - rep(j, 1, m + 1) cnt[i - 1][j] += cnt[i][j]; - return cnt; -} diff --git a/library/monotonic_stack/max_rect_histogram.hpp b/library/monotonic_stack/max_rect_histogram.hpp deleted file mode 100644 index fadeb391..00000000 --- a/library/monotonic_stack/max_rect_histogram.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include "monotonic_range.hpp" -//! returns largest integer x such that there exists a -//! subarray a[l,r) with: (r-l) * min(a[l,r)) == x -//! @time O(n) -//! @space O(n) -ll max_rect_histogram(const vi& a) { - vi l(mono_st(a, less())), r(mono_range(l)); - ll max_area = 0; - rep(i, 0, sz(a)) max_area = - max(max_area, ll(a[i]) * (r[i] - l[i] - 1)); - return max_area; -} diff --git a/library/monotonic_stack/monotonic_range.hpp b/library/monotonic_stack/monotonic_range.hpp deleted file mode 100644 index 0af8ffb9..00000000 --- a/library/monotonic_stack/monotonic_range.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once -#include "monotonic_stack.hpp" -//! @code -//! vi le = mono_st(a, less()), ri = mono_range(le); -//! // less_equal(), greater(), greater_equal() -//! @endcode -//! when cmp == less(): -//! a[le[i]] < a[i] >= a[ri[i]] -//! @time O(n) -//! @space O(n) -vi mono_range(const vi& l) { - vi r(sz(l), sz(l)); - rep(i, 0, sz(l)) for (int j = i - 1; j != l[i]; j = l[j]) - r[j] = i; - return r; -} diff --git a/library/strings/longest_common_subsequence/lcs_queries.hpp b/library/strings/longest_common_subsequence/lcs_queries.hpp deleted file mode 100644 index 25c2872d..00000000 --- a/library/strings/longest_common_subsequence/lcs_queries.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once -#include "../../data_structures/bit.hpp" -#include "lcs_dp.hpp" -//! @code -//! string s,t; -//! vi lcs_len = lcs_queries(s, t, queries); -//! vi s_vec,t_vec; -//! vi lcs_len1 = lcs_queries(s_vec, t_vec, queries); -//! @endcode -//! lcs_len[i] = size(LCS( -//! s[0,queries[i][0]), -//! t[queries[i][1],queries[i][2]) -//! )) -//! @time O(n*m*log(m) + q*log(m) + q*log(q)) -//! @space O(n + m + q) -vi lcs_queries(const auto& s, const auto& t, - const vector>& queries) { - int n = sz(s), m = sz(t), q = sz(queries); - vector>> qs(n); - rep(i, 0, q) { - auto [s_r, t_le, t_ri] = queries[i]; - if (s_r == 0 || t_le == m) continue; - qs[s_r - 1].push_back({t_le, t_ri, i}); - } - lcs_dp lcs(t); - vi res(q); - rep(i, 0, n) { - lcs.push_onto_s(s[i]); - BIT bit(m); - vi dp_inv(m, -1); - rep(j, 0, m) { - if (lcs.dp[j] == -1) bit.update(j, 1); - else dp_inv[lcs.dp[j]] = j; - } - ranges::sort(qs[i]); - int j = 0; - rep(t_le, 0, m) { - while (j < sz(qs[i]) && qs[i][j][0] == t_le) - res[qs[i][j][2]] = bit.query(t_le, qs[i][j][1]), - j++; - if (dp_inv[t_le] != -1) bit.update(dp_inv[t_le], 1); - } - } - return res; -} diff --git a/library/strings/manacher/is_palindrome.hpp b/library/strings/manacher/is_palindrome.hpp deleted file mode 100644 index f5a483c6..00000000 --- a/library/strings/manacher/is_palindrome.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once -#include "manacher.hpp" -//! @time O(n + q) -//! @space O(n) -struct pal_query { - vi man; - pal_query(const auto& s): man(manacher(s)) {}; - bool is_pal(int l, int r) { // [l, r] - return man[l + r] <= l; - } -}; diff --git a/library/strings/manacher/longest_from_index.hpp b/library/strings/manacher/longest_from_index.hpp deleted file mode 100644 index cceede51..00000000 --- a/library/strings/manacher/longest_from_index.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include "is_palindrome.hpp" -//! https://github.com/brunomaletta/Biblioteca/blob/master/Codigo/Strings/manacher.cpp -//! @code -//! auto r = longest_from_index(pq); -//! @endcode -//! r[i] = max index such that [i, r[i]] -//! is a palindrome -//! @time O(n) -//! @space O(n) -vi longest_from_index(pal_query& pq) { - int n = (sz(pq.man) + 1) / 2; - vector longest(n, n - 1); - for (int i = n - 2; i >= 0; i--) { - longest[i] = min(longest[i + 1] + 1, n - 1); - while (!pq.is_pal(i, longest[i])) longest[i]--; - } - return longest; -} diff --git a/library/strings/suffix_array/suffix_array_query.hpp b/library/strings/suffix_array/suffix_array_query.hpp deleted file mode 100644 index 8444b010..00000000 --- a/library/strings/suffix_array/suffix_array_query.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once -#include "suffix_array.hpp" -#include "../../data_structures/rmq.hpp" -#include "find/match.hpp" -//! @code -//! string s; -//! auto [sa, sa_inv, lcp] = get_sa(s, 256); -//! sa_query saq(s, sa, sa_inv, lcp); -//! vi s_vec; -//! auto [sa1, sa_inv1, lcp1] = sa_short(s_vec); -//! sa_query saq1(s_vec, sa1, sa_inv1, lcp1); -//! @endcode -template struct sa_query { - int n; - T s; - vi sa, sa_inv, lcp; - RMQ> rmq; - sa_query(const T& s, const vi& sa, const vi& sa_inv, - const vi& lcp): - n(sz(s)), s(s), sa(sa), sa_inv(sa_inv), lcp(lcp), - rmq(lcp, ranges::min) {} - //! returns max integer k such that - //! s.substr(i1, k) == s.substr(i2, k) - //! @time O(1) - //! @space O(1) - int len_lcp(int i1, int i2) { - if (i1 == i2) return n - i1; - auto [l, r] = minmax(sa_inv[i1], sa_inv[i2]); - return rmq.query(l, r); - } -#include "compare/compare_suffixes.hpp" -#include "compare/compare_substrings.hpp" -#include "find/find_string_bs.hpp" -#include "find/find_string_bs_fast.hpp" -#include "find/find_substring.hpp" -#include "find/find_substrings_concatenated.hpp" -}; diff --git a/library/trees/lca_rmq.hpp b/library/trees/lca_rmq.hpp deleted file mode 100644 index 5db4bd4b..00000000 --- a/library/trees/lca_rmq.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#include "../monotonic_stack/monotonic_stack.hpp" -#include "../data_structures/rmq.hpp" -//! https://github.com/kth-competitive-programming/kactl/blob/main/content/graph/LCA.h -//! @code -//! vector> adj(n); -//! LCA lca(adj); -//! @endcode -//! @time O(nlogn + q) -//! @space O(nlogn) -// NOLINTNEXTLINE(readability-identifier-naming) -struct LCA { - int n; - vi tin, siz, d, p; - RMQ> rmq = {{}, NULL}; - LCA(const auto& adj): - n(sz(adj)), tin(n), siz(n, 1), d(n), p(n) { - vi order; - auto dfs = [&](auto&& self, int v) -> void { - tin[v] = sz(order), order.push_back(v); - for (int u : adj[v]) - if (u != p[v]) - d[u] = d[p[u] = v] + 1, self(self, u), - siz[v] += siz[u]; - }; - dfs(dfs, 0); - rmq = {order, - [&](int u, int v) { return d[u] < d[v] ? u : v; }}; - } - int lca(int u, int v) { - if (u == v) return u; - auto [x, y] = minmax(tin[u], tin[v]); - return p[rmq.query(x + 1, y + 1)]; - } -#include "extra_members/dist.hpp" -#include "extra_members/in_subtree.hpp" -#include "extra_members/on_path.hpp" -#include "extra_members/next_on_path.hpp" -#include "extra_members/virtual_tree.hpp" -}; diff --git a/library/trees/uncommon/contour_range_query.hpp b/library/trees/uncommon/contour_range_query.hpp deleted file mode 100644 index 4e5d8b80..00000000 --- a/library/trees/uncommon/contour_range_query.hpp +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once -#include "../../data_structures/bit.hpp" -#include "../edge_cd.hpp" -#include "sum_adjacent.hpp" -//! https://judge.yosupo.jp/problem/vertex_add_range_contour_sum_on_tree -struct contour_range_query { - int n; - sum_adj sum_a; - vector>> info; - vector> bits; - //! @param adj unrooted, undirected tree - //! @param a a[v] = initial number for node v - //! @time O(n logφ n) - //! @space O(n logφ n) for `info` and `bits` - contour_range_query(const vector& adj, - const vector& a): - n(sz(a)), sum_a(adj, a), info(n) { - edge_cd(adj, - [&](const vector& cd_adj, int cent, int split) { - vector> sum_num(2, vector(1)); - auto dfs = [&](auto&& self, int v, int p, int d, - int side) -> void { - info[v].push_back({int(sz(bits)), d, side}); - if (sz(sum_num[side]) == d) - sum_num[side].push_back(0); - sum_num[side][d] += a[v]; - for (int u : cd_adj[v]) - if (u != p) self(self, u, v, 1 + d, side); - }; - rep(i, 0, sz(cd_adj[cent])) - dfs(dfs, cd_adj[cent][i], cent, 1, i < split); - bits.push_back({BIT(sum_num[0]), BIT(sum_num[1])}); - }); - } - //! @param v node - //! @param delta number to add to node v's number - //! @time O(logφ(n) * log2(n)) - //! @space O(1) - void update(int v, ll delta) { - sum_a.update(v, delta); - for (auto [decomp, d, side] : info[v]) - bits[decomp][side].update(d, delta); - } - //! @param v node - //! @param l,r defines range [l, r) - //! @returns sum of node u's number over all u such that - //! l - //! <= dist_edges(u, v) < r - //! @time O(logφ(n) * log2(n)) - //! @space O(1) - ll query(int v, int l, int r) { - ll sum = 0; - if (l <= 0 && 0 < r) sum += sum_a.sum[v]; - if (l <= 1 && 1 < r) sum += sum_a.query(v); - for (auto [decomp, d, side] : info[v]) { - auto& bit = bits[decomp][!side]; - int my_l = clamp(l - d, 1, sz(bit.s)); - int my_r = clamp(r - d, 1, sz(bit.s)); - sum += bit.query(my_l, my_r); - } - return sum; - } -}; diff --git a/library/trees/uncommon/contour_range_update.hpp b/library/trees/uncommon/contour_range_update.hpp deleted file mode 100644 index c7972172..00000000 --- a/library/trees/uncommon/contour_range_update.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once -#include "../../data_structures/bit_uncommon/rupq.hpp" -#include "../edge_cd.hpp" -#include "sum_adjacent.hpp" -//! https://judge.yosupo.jp/problem/vertex_get_range_contour_add_on_tree -struct contour_range_update { - int n; - vector a; - sum_adj sum_a; - vector>> info; - vector> bits; - //! @param adj unrooted, undirected tree - //! @param a a[v] = initial number for node v - //! @time O(n logφ n) - //! @space O(n logφ n) for `info` and `bits` - contour_range_update(const vector& adj, - const vector& a): - n(sz(a)), a(a), sum_a(adj, vector(n)), info(n) { - edge_cd(adj, - [&](const vector& cd_adj, int cent, int split) { - array mx_d = {0, 0}; - auto dfs = [&](auto&& self, int v, int p, int d, - int side) -> void { - mx_d[side] = max(mx_d[side], d); - info[v].push_back({int(sz(bits)), d, side}); - for (int u : cd_adj[v]) - if (u != p) self(self, u, v, 1 + d, side); - }; - rep(i, 0, sz(cd_adj[cent])) - dfs(dfs, cd_adj[cent][i], cent, 1, i < split); - bits.push_back( - {bit_rupq(mx_d[0] + 1), bit_rupq(mx_d[1] + 1)}); - }); - } - //! @param v,l,r,delta add delta to all nodes u such - //! that l <= dist_edges(v, u) < r - //! @time O(logφ(n) * log2(n)) - //! @space O(1) - void update(int v, int l, int r, ll delta) { - if (l <= 0 && 0 < r) a[v] += delta; - if (l <= 1 && 1 < r) sum_a.update(v, delta); - for (auto [decomp_id, d, side] : info[v]) { - auto& bit = bits[decomp_id][!side]; - int my_l = clamp(l - d, 1, bit.n); - int my_r = clamp(r - d, 1, bit.n); - bit.update(my_l, my_r, delta); - } - } - //! @param v node - //! @returns number of node v - //! @time O(logφ(n) * log2(n)) - //! @space O(1) - ll query(int v) { - ll sum = a[v] + sum_a.query(v); - for (auto [decomp_id, d, side] : info[v]) - sum += bits[decomp_id][side].get_index(d); - return sum; - } -}; diff --git a/library/trees/uncommon/count_paths_per_length.hpp b/library/trees/uncommon/count_paths_per_length.hpp deleted file mode 100644 index b98e0145..00000000 --- a/library/trees/uncommon/count_paths_per_length.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once -#include "../../../kactl/content/numerical/FastFourierTransform.h" -#include "../edge_cd.hpp" -//! @param adj unrooted, connected tree -//! @returns array `num_paths` where `num_paths[i]` = # of -//! paths in tree with `i` edges. `num_paths[1]` = # edges -//! @time O(n * logφ(n) * log2(n)) -//! @space this function allocates/returns various vectors -//! which are each O(n) -vector count_paths_per_length(const vector& adj) { - vector num_paths(sz(adj)); - if (sz(adj) >= 2) num_paths[1] = sz(adj) - 1; - edge_cd(adj, - [&](const vector& cd_adj, int cent, int split) { - vector> cnt(2, vector(1)); - auto dfs = [&](auto&& self, int v, int p, int d, - int side) -> void { - if (sz(cnt[side]) == d) cnt[side].push_back(0.0); - cnt[side][d]++; - for (int u : cd_adj[v]) - if (u != p) self(self, u, v, 1 + d, side); - }; - rep(i, 0, sz(cd_adj[cent])) - dfs(dfs, cd_adj[cent][i], cent, 1, i < split); - vector prod = conv(cnt[0], cnt[1]); - rep(i, 0, sz(prod)) num_paths[i] += llround(prod[i]); - }); - return num_paths; -} diff --git a/library/trees/uncommon/count_paths_per_node.hpp b/library/trees/uncommon/count_paths_per_node.hpp deleted file mode 100644 index 9f96ca1c..00000000 --- a/library/trees/uncommon/count_paths_per_node.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once -#include "centroid_decomp.hpp" -//! @param adj unrooted, connected forest -//! @param k number of edges -//! @returns array `num_paths` where `num_paths[i]` = -//! number of paths with k edges where node `i` is on the -//! path. 0-based nodes. -//! @time O(n log n) -//! @space this function allocates/returns various vectors -//! which are all O(n) -vector count_paths_per_node(const vector& adj, - int k) { - vector num_paths(sz(adj)); - centroid(adj, - [&](const vector& cd_adj, int cent, int) { - vector pre_d{1}, cur_d{0}; - auto dfs = [&](auto&& self, int v, int p, - int d) -> ll { - if (d > k) return 0LL; - if (sz(cur_d) <= d) cur_d.push_back(0); - cur_d[d]++; - ll cnt = 0; - if (k - d < sz(pre_d)) cnt += pre_d[k - d]; - for (int u : cd_adj[v]) - if (u != p) cnt += self(self, u, v, d + 1); - num_paths[v] += cnt; - return cnt; - }; - auto dfs_child = [&](int child) -> ll { - ll cnt = dfs(dfs, child, cent, 1); - pre_d.resize(sz(cur_d)); - for (int i = 1; i < sz(cur_d) && cur_d[i]; i++) - pre_d[i] += cur_d[i], cur_d[i] = 0; - return cnt; - }; - for (int child : cd_adj[cent]) - num_paths[cent] += dfs_child(child); - pre_d = cur_d = {0}; - for (int child : cd_adj[cent] | views::reverse) - dfs_child(child); - }); - return num_paths; -} diff --git a/library/trees/uncommon/ladder_decomposition.hpp b/library/trees/uncommon/ladder_decomposition.hpp deleted file mode 100644 index 945d44aa..00000000 --- a/library/trees/uncommon/ladder_decomposition.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once -#include "../../../kactl/content/graph/BinaryLifting.h" -//! https://codeforces.com/blog/entry/71567#comment-559299 -//! https://youtu.be/0rCFkuQS968 -//! @code -//! ladder ld(adj); -//! // KACTL functions -//! int kth_par = jmp(ld.jmp, v, k); -//! int curr_lca = lca(ld.jmp, ld.d, u, v); -//! @endcode -struct ladder { - int n; - vi d, p, leaf, idx, lad; - vector jmp; - //! @param adj forest (rooted or unrooted) - //! @time O(n log n) - //! @space O(n log n) for jmp. Everything else is O(n) - ladder(const auto& adj): - n(sz(adj)), d(n), p(n), leaf(n), idx(n), lad(2 * n) { - auto dfs = [&](auto&& self, int v) -> void { - leaf[v] = v; - for (int u : adj[v]) - if (u != p[v]) { - d[u] = d[p[u] = v] + 1; - self(self, u); - if (d[leaf[v]] < d[leaf[u]]) leaf[v] = leaf[u]; - } - }; - dfs(dfs, 0); - int pos = 0; - rep(i, 0, n) if (p[i] == i || leaf[p[i]] != leaf[i]) { - int l = leaf[i]; - int len = min((d[l] - d[i]) * 2, d[l] + 1); - idx[l] = pos; - for (; len--; l = p[l]) lad[pos++] = l; - } - jmp = treeJump(p); - } - //! @param v query node - //! @param k number of edges - //! @returns a node k edges up from v. With k=1, this - //! returns v's parent. - //! @time O(1) - //! @space O(1) - int kth_par(int v, int k) { - assert(0 <= k && k <= d[v]); - if (k == 0) return v; - int bit = __lg(k); - v = jmp[bit][v], k -= (1 << bit); - int l = idx[leaf[v]] + d[leaf[v]] - d[v]; - assert(lad[l] == v); - // subarray [l, l+k] of lad corresponds to the rest - // of the jump - return lad[l + k]; - } -}; diff --git a/loops/chooses.hpp b/loops/chooses.hpp new file mode 100644 index 00000000..ec01d713 --- /dev/null +++ b/loops/chooses.hpp @@ -0,0 +1,16 @@ +//! https://github.com/kth-competitive-programming/kactl/blob/main/content/various/chapter.tex +//! returns the smallest number x such that: +//! - popcount(x)==popcount(mask) +//! - x > mask +//! @time O(1) +//! @space O(1) +int next_subset(int mask) { + int c = mask & -mask, r = mask + c; + return r | (((r ^ mask) >> 2) / c); +} +//! loop over all submasks of 2^n-1 with +//! k bits set, increasing +//! @time O(n choose k) +//! @space O(1) +for (int mask = (1 << k) - 1; mask < (1 << n); + mask = next_subset(mask)) diff --git a/library/loops/next_subset.hpp b/loops/next_subset.hpp similarity index 96% rename from library/loops/next_subset.hpp rename to loops/next_subset.hpp index 2a432352..366db0da 100644 --- a/library/loops/next_subset.hpp +++ b/loops/next_subset.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://github.com/kth-competitive-programming/kactl/blob/main/content/various/chapter.tex //! returns the smallest number x such that: //! - popcount(x)==popcount(mask) diff --git a/library/loops/quotients.hpp b/loops/quotients.hpp similarity index 81% rename from library/loops/quotients.hpp rename to loops/quotients.hpp index 9958301b..65cd7a31 100644 --- a/library/loops/quotients.hpp +++ b/loops/quotients.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://github.com/tfg50/Competitive-Programming/blob/master/Biblioteca/Math/DivisionTrick.cpp //! i-th iteration gives an interval [le_i, ri_i]: //! - for all i in [le_i, ri_i]: n / i is the same @@ -7,4 +6,5 @@ //! - ri_i + 1 = le_(i+1) //! @time O(sqrt(n)) //! @space O(1) -for (ll l = 1, r; l <= n && (r = n / (n / l)); l = r + 1) \ No newline at end of file +for (int64_t l = 1, r; l <= n && (r = n / (n / l)); + l = r + 1) diff --git a/library/loops/submasks.hpp b/loops/submasks.hpp similarity index 94% rename from library/loops/submasks.hpp rename to loops/submasks.hpp index 200777c1..582189d5 100644 --- a/library/loops/submasks.hpp +++ b/loops/submasks.hpp @@ -1,4 +1,3 @@ -#pragma once //! loops over submasks in decreasing order //! @param mask a submask of 2^n-1 //! @time O(3^n) to iterate every submask diff --git a/library/loops/supermasks.hpp b/loops/supermasks.hpp similarity index 95% rename from library/loops/supermasks.hpp rename to loops/supermasks.hpp index 05864afc..3a440287 100644 --- a/library/loops/supermasks.hpp +++ b/loops/supermasks.hpp @@ -1,4 +1,3 @@ -#pragma once //! loops over supermasks in increasing order //! @param mask a submask of (2^n)-1 //! @param n total number of bits diff --git a/library/math/count_paths/README.md b/math/count_paths/README.md similarity index 100% rename from library/math/count_paths/README.md rename to math/count_paths/README.md diff --git a/math/count_paths/count_paths_rectangle.hpp b/math/count_paths/count_paths_rectangle.hpp new file mode 100644 index 00000000..2da6003f --- /dev/null +++ b/math/count_paths/count_paths_rectangle.hpp @@ -0,0 +1,133 @@ +/** + * Author: chilli + * Date: 2019-04-16 + * License: CC0 + * Source: based on KACTL's FFT + * Description: ntt(a) computes $\hat f(k) = \sum_x a[x] + g^{xk}$ for all $k$, where $g=\text{root}^{(mod-1)/N}$. + * N must be a power of 2. + * Useful for convolution modulo specific nice primes of + the form $2^a b+1$, + * where the convolution result has size at most $2^a$. For + arbitrary modulo, see FFTMod. + \texttt{conv(a, b) = c}, where $c[x] = \sum a[i]b[x-i]$. + For manual convolution: NTT the inputs, multiply + pointwise, divide by n, reverse(start+1, end), NTT back. + * Inputs must be in [0, mod). + * Time: O(N \log N) + * Status: stress-tested + */ +/** + * Author: Noam527 + * Date: 2019-04-24 + * License: CC0 + * Source: folklore + * Description: + * Status: tested + */ +const int64_t mod = 1000000007; // faster if const +int64_t modpow(int64_t b, int64_t e) { + int64_t ans = 1; + for (; e; b = b * b % mod, e /= 2) + if (e & 1) ans = ans * b % mod; + return ans; +} +const int64_t mod = (119 << 23) + 1, + root = 62; // = 998244353 +// For p < 2^30 there is also e.g. 5 << 25, 7 << 26, 479 << +// 21 and 483 << 21 (same root). The last two are > 10^9. +typedef vector vl; +void ntt(vl &a) { + int n = ssize(a), L = 31 - __builtin_clz(n); + static vl rt(2, 1); + for (static int k = 2, s = 2; k < n; k *= 2, s++) { + rt.resize(n); + int64_t z[] = {1, modpow(root, mod >> s)}; + for (int i = k; i < 2 * k; i++) + rt[i] = rt[i / 2] * z[i & 1] % mod; + } + vector rev(n); + for (int i = 0; i < n; i++) + rev[i] = (rev[i / 2] | (i & 1) << L) / 2; + for (int i = 0; i < n; i++) + if (i < rev[i]) swap(a[i], a[rev[i]]); + for (int k = 1; k < n; k *= 2) + for (int i = 0; i < n; i += 2 * k) + for (int j = 0; j < k; j++) { + int64_t z = rt[j + k] * a[i + j + k] % mod, + &ai = a[i + j]; + a[i + j + k] = ai - z + (z > ai ? mod : 0); + ai += (ai + z >= mod ? z - mod : z); + } +} +vl conv(const vl &a, const vl &b) { + if (a.empty() || b.empty()) return {}; + int s = ssize(a) + ssize(b) - 1, + B = 32 - __builtin_clz(s), n = 1 << B; + int inv = modpow(n, mod - 2); + vl L(a), R(b), out(n); + L.resize(n), R.resize(n); + ntt(L), ntt(R); + for (int i = 0; i < n; i++) + out[-i & (n - 1)] = + (int64_t)L[i] * R[i] % mod * inv % mod; + ntt(out); + return {out.begin(), out.begin() + s}; +} +const int mod = 17; //!< must be prime +struct comb { + int64_t inv = 1, fact = 1, inv_fact = 1; +}; +vector t(2); +void grow(int n) { + for (int i = ssize(t); i < n + 1; i++) { + int64_t inv = mod - (mod / i) * t[mod % i].inv % mod; + t.push_back({inv, i * t[i - 1].fact % mod, + inv * t[i - 1].inv_fact % mod}); + } +} +//! n,k < mod +//! @time O(1) amortized +//! @space O(1) amortized +int64_t C(int n, int k) { + if (k < 0 || n < k) return 0; + grow(n); + return t[n].fact * t[k].inv_fact % mod * + t[n - k].inv_fact % mod; +} +//! https://noshi91.hatenablog.com/entry/2023/07/21/235339 +//! @code +//! auto [right, top] = get_right_and_top(left, bottom); +//! @endcode +//! @time O((n + m)log(n + m)) +//! @space O(n + m) +array get_right_and_top(vl left, vl bottom) { + array ret; + for (vl &res : ret) { + { + vl tr(ssize(left)); + for (int i = 0; i < ssize(tr); i++) + tr[i] = C(i + ssize(bottom) - 1, i); + res = conv(left, tr); + res.resize(ssize(left)); + } + { + vl tr(ssize(left) + ssize(bottom)); + grow(ssize(tr)); + for (int i = 0; i < ssize(tr); i++) + tr[i] = t[i].fact; + vl dp(ssize(bottom)); + for (int i = 0; i < ssize(dp); i++) + dp[i] = + bottom[i] * t[ssize(dp) - 1 - i].inv_fact % mod; + vl tmp_res = conv(dp, tr); + for (int i = 0; i < ssize(res); i++) + res[i] = (res[i] + + tmp_res[i + ssize(bottom) - 1] * + t[i].inv_fact) % + mod; + } + swap(left, bottom); + } + return ret; +} diff --git a/library/math/count_paths/count_paths_rectangle.png b/math/count_paths/count_paths_rectangle.png similarity index 100% rename from library/math/count_paths/count_paths_rectangle.png rename to math/count_paths/count_paths_rectangle.png diff --git a/math/count_paths/count_paths_triangle.hpp b/math/count_paths/count_paths_triangle.hpp new file mode 100644 index 00000000..14d6b935 --- /dev/null +++ b/math/count_paths/count_paths_triangle.hpp @@ -0,0 +1,160 @@ +/** + * Author: chilli + * Date: 2019-04-16 + * License: CC0 + * Source: based on KACTL's FFT + * Description: ntt(a) computes $\hat f(k) = \sum_x a[x] + g^{xk}$ for all $k$, where $g=\text{root}^{(mod-1)/N}$. + * N must be a power of 2. + * Useful for convolution modulo specific nice primes of + the form $2^a b+1$, + * where the convolution result has size at most $2^a$. For + arbitrary modulo, see FFTMod. + \texttt{conv(a, b) = c}, where $c[x] = \sum a[i]b[x-i]$. + For manual convolution: NTT the inputs, multiply + pointwise, divide by n, reverse(start+1, end), NTT back. + * Inputs must be in [0, mod). + * Time: O(N \log N) + * Status: stress-tested + */ +/** + * Author: Noam527 + * Date: 2019-04-24 + * License: CC0 + * Source: folklore + * Description: + * Status: tested + */ +const int64_t mod = 1000000007; // faster if const +int64_t modpow(int64_t b, int64_t e) { + int64_t ans = 1; + for (; e; b = b * b % mod, e /= 2) + if (e & 1) ans = ans * b % mod; + return ans; +} +const int64_t mod = (119 << 23) + 1, + root = 62; // = 998244353 +// For p < 2^30 there is also e.g. 5 << 25, 7 << 26, 479 << +// 21 and 483 << 21 (same root). The last two are > 10^9. +typedef vector vl; +void ntt(vl &a) { + int n = ssize(a), L = 31 - __builtin_clz(n); + static vl rt(2, 1); + for (static int k = 2, s = 2; k < n; k *= 2, s++) { + rt.resize(n); + int64_t z[] = {1, modpow(root, mod >> s)}; + for (int i = k; i < 2 * k; i++) + rt[i] = rt[i / 2] * z[i & 1] % mod; + } + vector rev(n); + for (int i = 0; i < n; i++) + rev[i] = (rev[i / 2] | (i & 1) << L) / 2; + for (int i = 0; i < n; i++) + if (i < rev[i]) swap(a[i], a[rev[i]]); + for (int k = 1; k < n; k *= 2) + for (int i = 0; i < n; i += 2 * k) + for (int j = 0; j < k; j++) { + int64_t z = rt[j + k] * a[i + j + k] % mod, + &ai = a[i + j]; + a[i + j + k] = ai - z + (z > ai ? mod : 0); + ai += (ai + z >= mod ? z - mod : z); + } +} +vl conv(const vl &a, const vl &b) { + if (a.empty() || b.empty()) return {}; + int s = ssize(a) + ssize(b) - 1, + B = 32 - __builtin_clz(s), n = 1 << B; + int inv = modpow(n, mod - 2); + vl L(a), R(b), out(n); + L.resize(n), R.resize(n); + ntt(L), ntt(R); + for (int i = 0; i < n; i++) + out[-i & (n - 1)] = + (int64_t)L[i] * R[i] % mod * inv % mod; + ntt(out); + return {out.begin(), out.begin() + s}; +} +const int mod = 17; //!< must be prime +struct comb { + int64_t inv = 1, fact = 1, inv_fact = 1; +}; +vector t(2); +void grow(int n) { + for (int i = ssize(t); i < n + 1; i++) { + int64_t inv = mod - (mod / i) * t[mod % i].inv % mod; + t.push_back({inv, i * t[i - 1].fact % mod, + inv * t[i - 1].inv_fact % mod}); + } +} +//! n,k < mod +//! @time O(1) amortized +//! @space O(1) amortized +int64_t C(int n, int k) { + if (k < 0 || n < k) return 0; + grow(n); + return t[n].fact * t[k].inv_fact % mod * + t[n - k].inv_fact % mod; +} +//! https://noshi91.hatenablog.com/entry/2023/07/21/235339 +//! @code +//! auto [right, top] = get_right_and_top(left, bottom); +//! @endcode +//! @time O((n + m)log(n + m)) +//! @space O(n + m) +array get_right_and_top(vl left, vl bottom) { + array ret; + for (vl &res : ret) { + { + vl tr(ssize(left)); + for (int i = 0; i < ssize(tr); i++) + tr[i] = C(i + ssize(bottom) - 1, i); + res = conv(left, tr); + res.resize(ssize(left)); + } + { + vl tr(ssize(left) + ssize(bottom)); + grow(ssize(tr)); + for (int i = 0; i < ssize(tr); i++) + tr[i] = t[i].fact; + vl dp(ssize(bottom)); + for (int i = 0; i < ssize(dp); i++) + dp[i] = + bottom[i] * t[ssize(dp) - 1 - i].inv_fact % mod; + vl tmp_res = conv(dp, tr); + for (int i = 0; i < ssize(res); i++) + res[i] = (res[i] + + tmp_res[i + ssize(bottom) - 1] * + t[i].inv_fact) % + mod; + } + swap(left, bottom); + } + return ret; +} +//! https://noshi91.hatenablog.com/entry/2023/07/21/235339 +//! @time O((n + m)log^2(n + m)): n = sz(h); m = h.back() +//! @space O(n + m) +vl divide_and_conquer(vl h, vl bottom) { + { + int start = + ranges::find_if(h, [](int64_t x) { return x; }) - + begin(h); + h.erase(begin(h), begin(h) + start); + bottom.erase(begin(bottom), begin(bottom) + start); + } + int n = ssize(h); + if (n == 0) return {}; + if (n == 1) return vl(h[0], bottom[0]); + int mid = n / 2; + auto rect_left = + divide_and_conquer(vl(begin(h), begin(h) + mid), + vl(begin(bottom), begin(bottom) + mid)); + auto [rect_right, rect_top] = get_right_and_top( + rect_left, vl(mid + begin(bottom), end(bottom))); + vl h_right(mid + begin(h), end(h)); + for (int64_t &hh : h_right) hh -= h[mid - 1]; + auto upper_right = divide_and_conquer(h_right, rect_top); + rect_right.insert(end(rect_right), begin(upper_right), + end(upper_right)); + return rect_right; +} diff --git a/library/math/count_paths/count_paths_triangle.png b/math/count_paths/count_paths_triangle.png similarity index 100% rename from library/math/count_paths/count_paths_triangle.png rename to math/count_paths/count_paths_triangle.png diff --git a/library/math/derangements.hpp b/math/derangements.hpp similarity index 56% rename from library/math/derangements.hpp rename to math/derangements.hpp index ee95f5fb..d383a209 100644 --- a/library/math/derangements.hpp +++ b/math/derangements.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://oeis.org/A000166 //! @code //! auto der = derangements(n, mod); @@ -6,10 +5,10 @@ //! der[i] = number of permutations p with p[i]!=i //! @time O(n) //! @space O(n) -vector derangements(int n, int mod) { - vector dp(n); +vector derangements(int n, int mod) { + vector dp(n); dp[0] = 1; - rep(i, 2, n) dp[i] = - (i - 1) * (dp[i - 1] + dp[i - 2]) % mod; + for (int i = 2; i < n; i++) + dp[i] = (i - 1) * (dp[i - 1] + dp[i - 2]) % mod; return dp; } diff --git a/library/math/fibonacci.hpp b/math/fibonacci.hpp similarity index 80% rename from library/math/fibonacci.hpp rename to math/fibonacci.hpp index f0de2014..be176169 100644 --- a/library/math/fibonacci.hpp +++ b/math/fibonacci.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://codeforces.com/blog/entry/14516 //! https://cp-algorithms.com/algebra/fibonacci-numbers.html#fast-doubling-method //! @code @@ -12,11 +11,11 @@ //! @time O(log n) //! @space O(log n) const int mod = 998'244'353; -array fib(ll n) { +array fib(int64_t n) { if (n == 0) return {0LL, 1LL}; auto [x, y] = fib(n >> 1); - ll c = x * (2 * y - x + mod) % mod, - d = (x * x + y * y) % mod; + int64_t c = x * (2 * y - x + mod) % mod, + d = (x * x + y * y) % mod; if (n & 1) return {d, (c + d) % mod}; return {c, d}; } diff --git a/library/math/matrix_related/binary_matrix_mult.hpp b/math/matrix_related/binary_matrix_mult.hpp similarity index 73% rename from library/math/matrix_related/binary_matrix_mult.hpp rename to math/matrix_related/binary_matrix_mult.hpp index 3da36a8c..e6358116 100644 --- a/library/math/matrix_related/binary_matrix_mult.hpp +++ b/math/matrix_related/binary_matrix_mult.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://codeforces.com/blog/entry/80195 //! @time O(n*m*k / 64) //! @space O((n*k + n*m + m*k) / 64) @@ -7,7 +6,8 @@ template array, N> operator*(const array, N>& a, const array, M>& b) { array, N> c; - rep(i, 0, int(N)) rep(j, 0, int(M)) if (a[i][j]) c[i] ^= - b[j]; + for (int i = 0; i < int(N); i++) + for (int j = 0; j < int(M); j++) + if (a[i][j]) c[i] ^= b[j]; return c; } diff --git a/library/math/matrix_related/matrix_mult.hpp b/math/matrix_related/matrix_mult.hpp similarity index 56% rename from library/math/matrix_related/matrix_mult.hpp rename to math/matrix_related/matrix_mult.hpp index 201af30f..8ad4cf98 100644 --- a/library/math/matrix_related/matrix_mult.hpp +++ b/math/matrix_related/matrix_mult.hpp @@ -1,13 +1,14 @@ -#pragma once //! https://codeforces.com/blog/entry/80195 //! @time O(n * m * inner) //! @space O(n * m) template vector> operator*(const vector>& a, const vector>& b) { - int n = sz(a), m = sz(b[0]), inner = sz(b); + int n = ssize(a), m = ssize(b[0]), inner = ssize(b); vector> c(n, vector(m)); - rep(i, 0, n) rep(k, 0, inner) rep(j, 0, m) c[i][j] += - a[i][k] * b[k][j]; + for (int i = 0; i < n; i++) + for (int k = 0; k < inner; k++) + for (int j = 0; j < m; j++) + c[i][j] += a[i][k] * b[k][j]; return c; } diff --git a/math/matrix_related/row_reduce.hpp b/math/matrix_related/row_reduce.hpp new file mode 100644 index 00000000..27c55101 --- /dev/null +++ b/math/matrix_related/row_reduce.hpp @@ -0,0 +1,53 @@ +//! https://nor-blog.pages.dev/posts/2023-11-27-std-exchange-cpp/ +//! @code +//! int quotient = mod_div(x, y); // returns x * y^-1 +//! @endcode +//! @time O(log(y)) +//! @space O(1) +const int mod = 998244353; +int mod_div(int x, int y) { + int m = mod, u = 1, v = 0; + while (m) swap(u -= y / m * v, v), swap(y %= m, m); + assert(y == 1); + return 1LL * x * (u + mod) % mod; +} +//! @code +//! auto [rank, det] = row_reduce(mat, cols); +//! @endcode +//! columns [0,cols) of mat represent a matrix +//! columns [cols,m) of mat are also +//! affected by row operations +//! @time O(n * m * min(cols, n)) +//! @space O(1) +pair row_reduce(vector>& mat, + int cols) { + int n = ssize(mat), m = ssize(mat[0]), rank = 0; + int det = 1; + for (int col = 0; col < cols && rank < n; col++) { + auto it = find_if(rank + begin(mat), end(mat), + [&](auto& v) { return v[col]; }); + if (it == end(mat)) { + det = 0; + continue; + } + if (it != begin(mat) + rank) { + det = (mod - det) % mod; + iter_swap(begin(mat) + rank, it); + } + det = 1LL * det * mat[rank][col] % mod; + int a_inv = mod_div(1, mat[rank][col]); + for (int& num : mat[rank]) + num = 1LL * num * a_inv % mod; + for (int i = 0; i < n; i++) + if (i != rank && mat[i][col] != 0) { + int num = mat[i][col]; + for (int j = 0; j < m; j++) + mat[i][j] = + ((mat[i][j] - 1LL * mat[rank][j] * num) % mod + + mod) % + mod; + } + rank++; + } + return {rank, det}; +} diff --git a/math/matrix_related/solve_linear_mod.hpp b/math/matrix_related/solve_linear_mod.hpp new file mode 100644 index 00000000..df944e40 --- /dev/null +++ b/math/matrix_related/solve_linear_mod.hpp @@ -0,0 +1,84 @@ +//! https://nor-blog.pages.dev/posts/2023-11-27-std-exchange-cpp/ +//! @code +//! int quotient = mod_div(x, y); // returns x * y^-1 +//! @endcode +//! @time O(log(y)) +//! @space O(1) +const int mod = 998244353; +int mod_div(int x, int y) { + int m = mod, u = 1, v = 0; + while (m) swap(u -= y / m * v, v), swap(y %= m, m); + assert(y == 1); + return 1LL * x * (u + mod) % mod; +} +//! @code +//! auto [rank, det] = row_reduce(mat, cols); +//! @endcode +//! columns [0,cols) of mat represent a matrix +//! columns [cols,m) of mat are also +//! affected by row operations +//! @time O(n * m * min(cols, n)) +//! @space O(1) +pair row_reduce(vector>& mat, + int cols) { + int n = ssize(mat), m = ssize(mat[0]), rank = 0; + int det = 1; + for (int col = 0; col < cols && rank < n; col++) { + auto it = find_if(rank + begin(mat), end(mat), + [&](auto& v) { return v[col]; }); + if (it == end(mat)) { + det = 0; + continue; + } + if (it != begin(mat) + rank) { + det = (mod - det) % mod; + iter_swap(begin(mat) + rank, it); + } + det = 1LL * det * mat[rank][col] % mod; + int a_inv = mod_div(1, mat[rank][col]); + for (int& num : mat[rank]) + num = 1LL * num * a_inv % mod; + for (int i = 0; i < n; i++) + if (i != rank && mat[i][col] != 0) { + int num = mat[i][col]; + for (int j = 0; j < m; j++) + mat[i][j] = + ((mat[i][j] - 1LL * mat[rank][j] * num) % mod + + mod) % + mod; + } + rank++; + } + return {rank, det}; +} +//! @code +//! auto [rank, det, sol] = solve_linear_mod(mat, rhs); +//! @endcode +//! for each i, 0<=i sol; + solve_linear_mod(vector>& mat, + const vector& rhs) { + int n = ssize(mat), m = ssize(mat[0]); + for (int i = 0; i < n; i++) mat[i].push_back(rhs[i]); + tie(rank, det) = row_reduce(mat, m); + if (any_of(rank + begin(mat), end(mat), + [](vector& v) { return v.back(); })) { + return; + } + sol.resize(m); + int j = 0; + for_each(begin(mat), begin(mat) + rank, + [&](vector& v) { + while (!v[j]) j++; + sol[j] = v.back(); + }); + } +}; diff --git a/library/math/matrix_related/xor_basis_ordered.hpp b/math/matrix_related/xor_basis_ordered.hpp similarity index 97% rename from library/math/matrix_related/xor_basis_ordered.hpp rename to math/matrix_related/xor_basis_ordered.hpp index a8f58b8e..1b42d5c5 100644 --- a/library/math/matrix_related/xor_basis_ordered.hpp +++ b/math/matrix_related/xor_basis_ordered.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://codeforces.com/blog/entry/68953 //! https://github.com/ssk4988/Hackpack/blob/main/content/numerical/XORBasis.h //! @code diff --git a/library/math/matrix_related/xor_basis_unordered.hpp b/math/matrix_related/xor_basis_unordered.hpp similarity index 97% rename from library/math/matrix_related/xor_basis_unordered.hpp rename to math/matrix_related/xor_basis_unordered.hpp index ed8e0e5e..80520456 100644 --- a/library/math/matrix_related/xor_basis_unordered.hpp +++ b/math/matrix_related/xor_basis_unordered.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://codeforces.com/blog/entry/68953 //! https://codeforces.com/blog/entry/100066?#comment-887897 //! @code diff --git a/math/matrix_related/xor_basis_unordered_intersection.hpp b/math/matrix_related/xor_basis_unordered_intersection.hpp new file mode 100644 index 00000000..c4e34dde --- /dev/null +++ b/math/matrix_related/xor_basis_unordered_intersection.hpp @@ -0,0 +1,40 @@ +//! https://codeforces.com/blog/entry/68953 +//! https://codeforces.com/blog/entry/100066?#comment-887897 +//! @code +//! basis b1; +//! basis b2; +//! @endcode +//! b.shrink(v) == b.shrink(b.shrink(v)) +//! for x in b.b: (bit_floor(x)&b.shrink(v))==0 +//! for 0<=i struct basis { + vector b; + T shrink(T v) { + for (T x : b) v = min(v, v ^ x); + return v; + } + bool insert(T v) { + return (v = shrink(v)) ? b.push_back(v), 1 : 0; + } +}; +//! https://github.com/suisen-cp/cp-library-cpp/blob/main/library/linear_algebra/xor_base.hpp +//! @time O(32^2) or O(64^2); +//! @space O(32) or O(64) +template +basis intersection(const basis& u, + const basis& v) { + vector> w(ssize(u.b)); + for (int i = 0; i < ssize(w); i++) + w[i] = {u.b[i], u.b[i]}; + basis res; + for (T e : v.b) { + T s = 0; + for (auto [x, y] : w) + if ((e ^ x) < e) e ^= x, s ^= y; + if (e) w.emplace_back(e, s); + else res.insert(s); + } + return res; +} diff --git a/library/math/mod_division.hpp b/math/mod_division.hpp similarity index 96% rename from library/math/mod_division.hpp rename to math/mod_division.hpp index 44796981..da7cafd3 100644 --- a/library/math/mod_division.hpp +++ b/math/mod_division.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://nor-blog.pages.dev/posts/2023-11-27-std-exchange-cpp/ //! @code //! int quotient = mod_div(x, y); // returns x * y^-1 diff --git a/library/math/n_choose_k/grow.hpp b/math/n_choose_k/grow.hpp similarity index 56% rename from library/math/n_choose_k/grow.hpp rename to math/n_choose_k/grow.hpp index 563ddf91..ae8466dd 100644 --- a/library/math/n_choose_k/grow.hpp +++ b/math/n_choose_k/grow.hpp @@ -1,12 +1,11 @@ -#pragma once const int mod = 17; //!< must be prime struct comb { - ll inv = 1, fact = 1, inv_fact = 1; + int64_t inv = 1, fact = 1, inv_fact = 1; }; vector t(2); void grow(int n) { - rep(i, sz(t), n + 1) { - ll inv = mod - (mod / i) * t[mod % i].inv % mod; + for (int i = ssize(t); i < n + 1; i++) { + int64_t inv = mod - (mod / i) * t[mod % i].inv % mod; t.push_back({inv, i * t[i - 1].fact % mod, inv * t[i - 1].inv_fact % mod}); } diff --git a/math/n_choose_k/large_n_choose_small_k.hpp b/math/n_choose_k/large_n_choose_small_k.hpp new file mode 100644 index 00000000..ab0a57d2 --- /dev/null +++ b/math/n_choose_k/large_n_choose_small_k.hpp @@ -0,0 +1,22 @@ +const int mod = 17; //!< must be prime +struct comb { + int64_t inv = 1, fact = 1, inv_fact = 1; +}; +vector t(2); +void grow(int n) { + for (int i = ssize(t); i < n + 1; i++) { + int64_t inv = mod - (mod / i) * t[mod % i].inv % mod; + t.push_back({inv, i * t[i - 1].fact % mod, + inv * t[i - 1].inv_fact % mod}); + } +} +//! n arbitrarily large; k < mod +//! @time O(k) amortized +//! @space O(1) amortized +int64_t c_small_k(int64_t n, int k) { + if (k < 0 || n < k || (n %= mod) < k) return 0; + grow(k); + int64_t res = t[k].inv_fact; + for (int i = 0; i < k; i++) res = res * (n - i) % mod; + return res; +} diff --git a/math/n_choose_k/lucas_theorem.hpp b/math/n_choose_k/lucas_theorem.hpp new file mode 100644 index 00000000..ab71f509 --- /dev/null +++ b/math/n_choose_k/lucas_theorem.hpp @@ -0,0 +1,31 @@ +const int mod = 17; //!< must be prime +struct comb { + int64_t inv = 1, fact = 1, inv_fact = 1; +}; +vector t(2); +void grow(int n) { + for (int i = ssize(t); i < n + 1; i++) { + int64_t inv = mod - (mod / i) * t[mod % i].inv % mod; + t.push_back({inv, i * t[i - 1].fact % mod, + inv * t[i - 1].inv_fact % mod}); + } +} +//! n,k < mod +//! @time O(1) amortized +//! @space O(1) amortized +int64_t C(int n, int k) { + if (k < 0 || n < k) return 0; + grow(n); + return t[n].fact * t[k].inv_fact % mod * + t[n - k].inv_fact % mod; +} +//! n,k arbitrarily large +//! @time O(log(k)) amortized +//! @space O(1) amortized +int64_t lucas(int64_t n, int64_t k) { + if (k < 0 || n < k) return 0; + int64_t res = 1; + for (; k && k < n && res; n /= mod, k /= mod) + res = res * C(n % mod, k % mod) % mod; + return res; +} diff --git a/math/n_choose_k/n_choose_k.hpp b/math/n_choose_k/n_choose_k.hpp new file mode 100644 index 00000000..e45fb6eb --- /dev/null +++ b/math/n_choose_k/n_choose_k.hpp @@ -0,0 +1,21 @@ +const int mod = 17; //!< must be prime +struct comb { + int64_t inv = 1, fact = 1, inv_fact = 1; +}; +vector t(2); +void grow(int n) { + for (int i = ssize(t); i < n + 1; i++) { + int64_t inv = mod - (mod / i) * t[mod % i].inv % mod; + t.push_back({inv, i * t[i - 1].fact % mod, + inv * t[i - 1].inv_fact % mod}); + } +} +//! n,k < mod +//! @time O(1) amortized +//! @space O(1) amortized +int64_t C(int n, int k) { + if (k < 0 || n < k) return 0; + grow(n); + return t[n].fact * t[k].inv_fact % mod * + t[n - k].inv_fact % mod; +} diff --git a/math/n_choose_k/pascals_identity.hpp b/math/n_choose_k/pascals_identity.hpp new file mode 100644 index 00000000..969030af --- /dev/null +++ b/math/n_choose_k/pascals_identity.hpp @@ -0,0 +1,8 @@ +const int mod = 17; //!< composite ok +vector> ch( + 1010); //!< ch[n][k] = n choose k +for (int i = 0; i < ssize(ch); i++) { + ch[i].resize(i + 1, 1); + for (int j = 1; j < i; j++) + ch[i][j] = (ch[i - 1][j] + ch[i - 1][j - 1]) % mod; +} diff --git a/library/math/num_distinct_subsequences.hpp b/math/num_distinct_subsequences.hpp similarity index 77% rename from library/math/num_distinct_subsequences.hpp rename to math/num_distinct_subsequences.hpp index fdbff729..fa56cd00 100644 --- a/library/math/num_distinct_subsequences.hpp +++ b/math/num_distinct_subsequences.hpp @@ -1,12 +1,11 @@ -#pragma once //! returns the number of distinct subsequences //! of a, including the empty subsquence //! @time O(n log n) //! @space O(n) -int num_subsequences(const vi& a, int mod) { - vector dp(sz(a) + 1, 1); +int num_subsequences(const vector& a, int mod) { + vector dp(ssize(a) + 1, 1); map last; - rep(i, 0, sz(a)) { + for (int i = 0; i < ssize(a); i++) { int& curr = dp[i + 1] = 2 * dp[i]; if (curr >= mod) curr -= mod; auto it = last.find(a[i]); diff --git a/library/math/partitions.hpp b/math/partitions.hpp similarity index 79% rename from library/math/partitions.hpp rename to math/partitions.hpp index 822ed670..60e7d22d 100644 --- a/library/math/partitions.hpp +++ b/math/partitions.hpp @@ -1,4 +1,3 @@ -#pragma once const int mod = 998'244'353; //! https://oeis.org/A000041 //! @code @@ -7,10 +6,10 @@ const int mod = 998'244'353; //! p[i] = number of partitions of i numbers //! @time O(n sqrt n) //! @space O(n) -vector partitions(int n) { - vector dp(n, 1); - rep(i, 1, n) { - ll sum = 0; +vector partitions(int n) { + vector dp(n, 1); + for (int i = 1; i < n; i++) { + int64_t sum = 0; for (int j = 1, pent = 1, sign = 1; pent <= i; j++, pent += 3 * j - 2, sign = -sign) { if (pent + j <= i) diff --git a/math/prime_sieve/calc_linear_sieve.hpp b/math/prime_sieve/calc_linear_sieve.hpp new file mode 100644 index 00000000..2b7459da --- /dev/null +++ b/math/prime_sieve/calc_linear_sieve.hpp @@ -0,0 +1,12 @@ +//! @time O(mx) +//! @space O(mx) +vector primes, sieve(1001); //!< min prime factor +iota(begin(sieve), end(sieve), 0); +for (int i = 2; i < ssize(sieve); i++) { + if (sieve[i] == i) primes.push_back(i); + for (int prime : primes) { + if (prime * i >= ssize(sieve)) break; + sieve[prime * i] = prime; + if (i % prime == 0) break; + } +} diff --git a/math/prime_sieve/calc_sieve.hpp b/math/prime_sieve/calc_sieve.hpp new file mode 100644 index 00000000..7224da11 --- /dev/null +++ b/math/prime_sieve/calc_sieve.hpp @@ -0,0 +1,8 @@ +//! @time O(mx * log(log mx)) +//! @space O(mx) +vector sieve(1001); //!< min prime factor +iota(begin(sieve), end(sieve), 0); +for (int i = 2; i * i < ssize(sieve); i++) + if (sieve[i] == i) + for (int j = i * i; j < ssize(sieve); j += i) + sieve[j] = min(sieve[j], i); diff --git a/math/prime_sieve/get_prime_factors.hpp b/math/prime_sieve/get_prime_factors.hpp new file mode 100644 index 00000000..3fe5ebdd --- /dev/null +++ b/math/prime_sieve/get_prime_factors.hpp @@ -0,0 +1,12 @@ +//! @time O(mx * log(log mx)) +//! @space O(mx) +vector sieve(1001); //!< min prime factor +iota(begin(sieve), end(sieve), 0); +for (int i = 2; i * i < ssize(sieve); i++) + if (sieve[i] == i) + for (int j = i * i; j < ssize(sieve); j += i) + sieve[j] = min(sieve[j], i); +//! `p` will be all prime factors of num, increasing +//! @time O(log(num)) +//! @space O(1) +for (int cpy = num, p; (p = sieve[cpy]) > 1; cpy /= p) \ No newline at end of file diff --git a/math/prime_sieve/is_prime.hpp b/math/prime_sieve/is_prime.hpp new file mode 100644 index 00000000..78d2279d --- /dev/null +++ b/math/prime_sieve/is_prime.hpp @@ -0,0 +1,13 @@ +//! @time O(mx * log(log mx)) +//! @space O(mx) +vector sieve(1001); //!< min prime factor +iota(begin(sieve), end(sieve), 0); +for (int i = 2; i * i < ssize(sieve); i++) + if (sieve[i] == i) + for (int j = i * i; j < ssize(sieve); j += i) + sieve[j] = min(sieve[j], i); +//! @time O(1) +//! @space O(1) +auto is_prime = [&](int num) -> bool { + return num >= 2 && sieve[num] == num; +}; diff --git a/math/prime_sieve/mobius.hpp b/math/prime_sieve/mobius.hpp new file mode 100644 index 00000000..478a0d29 --- /dev/null +++ b/math/prime_sieve/mobius.hpp @@ -0,0 +1,7 @@ +//! @time O(mx log mx) +//! @space O(mx) +vector mobius(100'005); +mobius[1] = 1; +for (int i = 1; i < ssize(mobius); i++) + for (int j = i + i; j < ssize(mobius); j += i) + mobius[j] -= mobius[i]; diff --git a/library/math/tetration_mod.hpp b/math/tetration_mod.hpp similarity index 61% rename from library/math/tetration_mod.hpp rename to math/tetration_mod.hpp index 426931b4..748f63ab 100644 --- a/library/math/tetration_mod.hpp +++ b/math/tetration_mod.hpp @@ -1,5 +1,17 @@ -#pragma once -#include "totient.hpp" +//! returns number of integers x (1<=x<=n) +//! such that gcd(x,n)==1 +//! @time O(sqrt n) +//! @space O(1) +int totient(int n) { + int res = n; + for (int i = 2; i * i <= n; i++) + if (n % i == 0) { + while (n % i == 0) n /= i; + res -= res / i; + } + if (n > 1) res -= res / n; + return res; +} //! https://cp-algorithms.com/algebra/phi-function.html#generalization //! Let t = totient(mod). //! If log2(mod) <= e then @@ -10,14 +22,14 @@ // //! @time O(sqrt(mod) * log(mod)) //! @space O(log(mod)) -ll bin_exp(ll b, ll e, int mod) { - ll res = 1; +int64_t bin_exp(int64_t b, int64_t e, int mod) { + int64_t res = 1; if ((b %= mod) < 0) b += mod; for (; e; b = b * b % mod, e /= 2) if (e & 1) res = res * b % mod; return res; } -ll tetration(ll b, ll e, int mod) { +int64_t tetration(int64_t b, int64_t e, int mod) { if (mod == 1) return 0; if (b == 0) return (e + 1) % 2 % mod; if (b == 1 || e == 0) return 1; @@ -26,6 +38,6 @@ ll tetration(ll b, ll e, int mod) { if (b == 2 && e == 3) return 16 % mod; if (b == 3 && e == 2) return 27 % mod; int t = totient(mod); - ll exp = tetration(b, e - 1, t); + int64_t exp = tetration(b, e - 1, t); return bin_exp(b, exp + t, mod); } diff --git a/library/math/totient.hpp b/math/totient.hpp similarity index 95% rename from library/math/totient.hpp rename to math/totient.hpp index 43a34b43..fa8a7414 100644 --- a/library/math/totient.hpp +++ b/math/totient.hpp @@ -1,4 +1,3 @@ -#pragma once //! returns number of integers x (1<=x<=n) //! such that gcd(x,n)==1 //! @time O(sqrt n) diff --git a/library/monotonic_stack/README.md b/monotonic_stack/README.md similarity index 100% rename from library/monotonic_stack/README.md rename to monotonic_stack/README.md diff --git a/library/monotonic_stack/cartesian_binary_tree.hpp b/monotonic_stack/cartesian_binary_tree.hpp similarity index 55% rename from library/monotonic_stack/cartesian_binary_tree.hpp rename to monotonic_stack/cartesian_binary_tree.hpp index 67355f4e..31e72c45 100644 --- a/library/monotonic_stack/cartesian_binary_tree.hpp +++ b/monotonic_stack/cartesian_binary_tree.hpp @@ -1,5 +1,18 @@ -#pragma once -#include "monotonic_stack.hpp" +//! @code +//! vi le = mono_st(a, less()); +//! // less_equal(), greater(), greater_equal() +//! @endcode +//! when cmp == less(): +//! a[le[i]] < a[i] +//! @time O(n) +//! @space O(n) +vector mono_st(const auto& a, const auto& cmp) { + vector l(ssize(a)); + for (int i = 0; i < ssize(a); i++) + for (l[i] = i - 1; l[i] >= 0 && !cmp(a[l[i]], a[i]);) + l[i] = l[l[i]]; + return l; +} //! @code //! // right-most min is root //! auto le = mono_st(a, less()); @@ -21,9 +34,10 @@ //! 0 1 2 3 4 5 6 7 8 9 10 //! @time O(n) //! @space O(n) -vi cart_binary_tree(const vi& l) { - vi p(l); - rep(i, 0, sz(p)) for (int j = i - 1; j != l[i]; - j = l[j]) if (l[j] == l[i]) p[j] = i; +vector cart_binary_tree(const vector& l) { + vector p(l); + for (int i = 0; i < ssize(p); i++) + for (int j = i - 1; j != l[i]; j = l[j]) + if (l[j] == l[i]) p[j] = i; return p; } diff --git a/library/monotonic_stack/cartesian_binary_tree_after.png b/monotonic_stack/cartesian_binary_tree_after.png similarity index 100% rename from library/monotonic_stack/cartesian_binary_tree_after.png rename to monotonic_stack/cartesian_binary_tree_after.png diff --git a/library/monotonic_stack/cartesian_binary_tree_before.png b/monotonic_stack/cartesian_binary_tree_before.png similarity index 100% rename from library/monotonic_stack/cartesian_binary_tree_before.png rename to monotonic_stack/cartesian_binary_tree_before.png diff --git a/library/monotonic_stack/cartesian_k_ary_tree.hpp b/monotonic_stack/cartesian_k_ary_tree.hpp similarity index 68% rename from library/monotonic_stack/cartesian_k_ary_tree.hpp rename to monotonic_stack/cartesian_k_ary_tree.hpp index dc3d3184..f925d271 100644 --- a/library/monotonic_stack/cartesian_k_ary_tree.hpp +++ b/monotonic_stack/cartesian_k_ary_tree.hpp @@ -1,5 +1,18 @@ -#pragma once -#include "monotonic_stack.hpp" +//! @code +//! vi le = mono_st(a, less()); +//! // less_equal(), greater(), greater_equal() +//! @endcode +//! when cmp == less(): +//! a[le[i]] < a[i] +//! @time O(n) +//! @space O(n) +vector mono_st(const auto& a, const auto& cmp) { + vector l(ssize(a)); + for (int i = 0; i < ssize(a); i++) + for (l[i] = i - 1; l[i] >= 0 && !cmp(a[l[i]], a[i]);) + l[i] = l[l[i]]; + return l; +} //! when cmp is less(): //! a = {2, 1, 3, 1, 1, 0, 1, 2, 2, 0, 2} //! (---------------------------x---) @@ -31,9 +44,10 @@ //! @returns parent array //! @time O(n) //! @space a O(n) vector is allocated and returned -vi cart_k_ary_tree(const auto& a, const vi& l) { - vi p(l); - for (int i = sz(a) - 1; i >= 0; i--) +vector cart_k_ary_tree(const auto& a, + const vector& l) { + vector p(l); + for (int i = ssize(a) - 1; i >= 0; i--) for (int j = i - 1; j != l[i]; j = l[j]) if (l[j] == l[i] || a[i] == a[l[j]]) p[j] = (p[i] < i || a[i] != a[p[i]] ? i : p[i]); diff --git a/monotonic_stack/count_rectangles.hpp b/monotonic_stack/count_rectangles.hpp new file mode 100644 index 00000000..3520f270 --- /dev/null +++ b/monotonic_stack/count_rectangles.hpp @@ -0,0 +1,65 @@ +//! @code +//! vi le = mono_st(a, less()); +//! // less_equal(), greater(), greater_equal() +//! @endcode +//! when cmp == less(): +//! a[le[i]] < a[i] +//! @time O(n) +//! @space O(n) +vector mono_st(const auto& a, const auto& cmp) { + vector l(ssize(a)); + for (int i = 0; i < ssize(a); i++) + for (l[i] = i - 1; l[i] >= 0 && !cmp(a[l[i]], a[i]);) + l[i] = l[l[i]]; + return l; +} +//! @code +//! vi le = mono_st(a, less()), ri = mono_range(le); +//! // less_equal(), greater(), greater_equal() +//! @endcode +//! when cmp == less(): +//! a[le[i]] < a[i] >= a[ri[i]] +//! @time O(n) +//! @space O(n) +vector mono_range(const vector& l) { + vector r(ssize(l), ssize(l)); + for (int i = 0; i < ssize(l); i++) + for (int j = i - 1; j != l[i]; j = l[j]) r[j] = i; + return r; +} +//! @code +//! auto cnt = count_rectangles(grid); +//! @endcode +//! +//! cnt[i][j] = the number of times an i-by-j +//! sub rectangle appears in the matrix such that +//! all i*j cells in the sub rectangle are 1 +//! +//! cnt[i][0] and cnt[0][j] will contain garbage numbers. +//! @time O(n * m) +//! @space O(n * m) +vector> count_rectangles( + const vector>& grid) { + int n = ssize(grid), m = ssize(grid[0]); + vector cnt(n + 1, vector(m + 1, 0)); + vector h(m); + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) + h[j] = grid[i][j] * (h[j] + 1); + vector l(mono_st(h, less())), r(mono_range(l)); + for (int j = 0; j < m; j++) { + int cnt_l = j - l[j] - 1, cnt_r = r[j] - j - 1; + cnt[h[j]][cnt_l + cnt_r + 1]++; + cnt[h[j]][cnt_l]--; + cnt[h[j]][cnt_r]--; + } + } + for (int i = 1; i < n + 1; i++) + for (int k = 0; k < 2; k++) + for (int j = m; j > 1; j--) + cnt[i][j - 1] += cnt[i][j]; + for (int i = n; i > 1; i--) + for (int j = 1; j < m + 1; j++) + cnt[i - 1][j] += cnt[i][j]; + return cnt; +} diff --git a/monotonic_stack/max_rect_histogram.hpp b/monotonic_stack/max_rect_histogram.hpp new file mode 100644 index 00000000..5c826adc --- /dev/null +++ b/monotonic_stack/max_rect_histogram.hpp @@ -0,0 +1,41 @@ +//! @code +//! vi le = mono_st(a, less()); +//! // less_equal(), greater(), greater_equal() +//! @endcode +//! when cmp == less(): +//! a[le[i]] < a[i] +//! @time O(n) +//! @space O(n) +vector mono_st(const auto& a, const auto& cmp) { + vector l(ssize(a)); + for (int i = 0; i < ssize(a); i++) + for (l[i] = i - 1; l[i] >= 0 && !cmp(a[l[i]], a[i]);) + l[i] = l[l[i]]; + return l; +} +//! @code +//! vi le = mono_st(a, less()), ri = mono_range(le); +//! // less_equal(), greater(), greater_equal() +//! @endcode +//! when cmp == less(): +//! a[le[i]] < a[i] >= a[ri[i]] +//! @time O(n) +//! @space O(n) +vector mono_range(const vector& l) { + vector r(ssize(l), ssize(l)); + for (int i = 0; i < ssize(l); i++) + for (int j = i - 1; j != l[i]; j = l[j]) r[j] = i; + return r; +} +//! returns largest integer x such that there exists a +//! subarray a[l,r) with: (r-l) * min(a[l,r)) == x +//! @time O(n) +//! @space O(n) +int64_t max_rect_histogram(const vector& a) { + vector l(mono_st(a, less())), r(mono_range(l)); + int64_t max_area = 0; + for (int i = 0; i < ssize(a); i++) + max_area = + max(max_area, int64_t(a[i]) * (r[i] - l[i] - 1)); + return max_area; +} diff --git a/library/monotonic_stack/mono_stack_le.png b/monotonic_stack/mono_stack_le.png similarity index 100% rename from library/monotonic_stack/mono_stack_le.png rename to monotonic_stack/mono_stack_le.png diff --git a/library/monotonic_stack/mono_stack_ri.png b/monotonic_stack/mono_stack_ri.png similarity index 100% rename from library/monotonic_stack/mono_stack_ri.png rename to monotonic_stack/mono_stack_ri.png diff --git a/monotonic_stack/monotonic_range.hpp b/monotonic_stack/monotonic_range.hpp new file mode 100644 index 00000000..59c39020 --- /dev/null +++ b/monotonic_stack/monotonic_range.hpp @@ -0,0 +1,29 @@ +//! @code +//! vi le = mono_st(a, less()); +//! // less_equal(), greater(), greater_equal() +//! @endcode +//! when cmp == less(): +//! a[le[i]] < a[i] +//! @time O(n) +//! @space O(n) +vector mono_st(const auto& a, const auto& cmp) { + vector l(ssize(a)); + for (int i = 0; i < ssize(a); i++) + for (l[i] = i - 1; l[i] >= 0 && !cmp(a[l[i]], a[i]);) + l[i] = l[l[i]]; + return l; +} +//! @code +//! vi le = mono_st(a, less()), ri = mono_range(le); +//! // less_equal(), greater(), greater_equal() +//! @endcode +//! when cmp == less(): +//! a[le[i]] < a[i] >= a[ri[i]] +//! @time O(n) +//! @space O(n) +vector mono_range(const vector& l) { + vector r(ssize(l), ssize(l)); + for (int i = 0; i < ssize(l); i++) + for (int j = i - 1; j != l[i]; j = l[j]) r[j] = i; + return r; +} diff --git a/library/monotonic_stack/monotonic_stack.hpp b/monotonic_stack/monotonic_stack.hpp similarity index 50% rename from library/monotonic_stack/monotonic_stack.hpp rename to monotonic_stack/monotonic_stack.hpp index a133d804..061f7a2e 100644 --- a/library/monotonic_stack/monotonic_stack.hpp +++ b/monotonic_stack/monotonic_stack.hpp @@ -1,4 +1,3 @@ -#pragma once //! @code //! vi le = mono_st(a, less()); //! // less_equal(), greater(), greater_equal() @@ -7,9 +6,10 @@ //! a[le[i]] < a[i] //! @time O(n) //! @space O(n) -vi mono_st(const auto& a, const auto& cmp) { - vi l(sz(a)); - rep(i, 0, sz(a)) for (l[i] = i - 1; - l[i] >= 0 && !cmp(a[l[i]], a[i]);) l[i] = l[l[i]]; +vector mono_st(const auto& a, const auto& cmp) { + vector l(ssize(a)); + for (int i = 0; i < ssize(a); i++) + for (l[i] = i - 1; l[i] >= 0 && !cmp(a[l[i]], a[i]);) + l[i] = l[l[i]]; return l; } diff --git a/notebook-generator b/notebook-generator deleted file mode 160000 index ed824cd2..00000000 --- a/notebook-generator +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ed824cd2cc9982cc1f2bb185deb4a769e4bebe76 diff --git a/library/strings/kmp.hpp b/strings/kmp.hpp similarity index 55% rename from library/strings/kmp.hpp rename to strings/kmp.hpp index c691faae..087d01b3 100644 --- a/library/strings/kmp.hpp +++ b/strings/kmp.hpp @@ -1,5 +1,15 @@ -#pragma once -#include "prefix_function.hpp" +//! https://cp-algorithms.com/string/prefix-function.html#implementation +//! @time O(n) +//! @space O(n) +vector prefix_function(const auto& s) { + vector pi(ssize(s)); + for (int i = 1; i < ssize(s); i++) { + int j = pi[i - 1]; + while (j && s[i] != s[j]) j = pi[j - 1]; + pi[i] = j + (s[i] == s[j]); + } + return pi; +} //! @code //! string s,t; //! KMP kmp(t); @@ -11,18 +21,17 @@ //! if match[i] == 1 then s[i,sz(t)) == t //! @time O(|s| + |t|) //! @space O(|s| + |t|) -// NOLINTNEXTLINE(readability-identifier-naming) template struct KMP { T t; - vi pi; + vector pi; KMP(const T& t): t(t), pi(prefix_function(t)) {} vector find_str(const T& s) { - vector is_m(sz(s)); + vector is_m(ssize(s)); int j = 0; - rep(i, 0, sz(s)) { + for (int i = 0; i < ssize(s); i++) { while (j && s[i] != t[j]) j = pi[j - 1]; j += (s[i] == t[j]); - if (j == sz(t)) { + if (j == ssize(t)) { is_m[i - j + 1] = 1; j = pi[j - 1]; } diff --git a/library/strings/longest_common_subsequence/lcs_dp.hpp b/strings/longest_common_subsequence/lcs_dp.hpp similarity index 66% rename from library/strings/longest_common_subsequence/lcs_dp.hpp rename to strings/longest_common_subsequence/lcs_dp.hpp index 3fe99723..623f3c78 100644 --- a/library/strings/longest_common_subsequence/lcs_dp.hpp +++ b/strings/longest_common_subsequence/lcs_dp.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://codeforces.com/blog/entry/111625 //! Given strings s, t (s initially empty): //! -append character onto s @@ -9,11 +8,13 @@ //! @space O(|t|) template struct lcs_dp { T t; - vi dp; - lcs_dp(const T& t): t(t), dp(sz(t)) { iota(all(dp), 0); } + vector dp; + lcs_dp(const T& t): t(t), dp(ssize(t)) { + iota(begin(dp), end(dp), 0); + } void push_onto_s(int c) { int v = -1; - rep(i, 0, sz(t)) if (c == t[i] || dp[i] < v) - swap(dp[i], v); + for (int i = 0; i < ssize(t); i++) + if (c == t[i] || dp[i] < v) swap(dp[i], v); } }; diff --git a/strings/longest_common_subsequence/lcs_queries.hpp b/strings/longest_common_subsequence/lcs_queries.hpp new file mode 100644 index 00000000..72c401d6 --- /dev/null +++ b/strings/longest_common_subsequence/lcs_queries.hpp @@ -0,0 +1,94 @@ +//! @time O(n + q log n) +//! @space O(n) +struct BIT { + vector s; + BIT(int n): s(n) {} + BIT(const vector& a): s(a) { + for (int i = 0; i < ssize(a); i++) { + int j = i | (i + 1); + if (j < ssize(a)) s[j] += s[i]; + } + } + void update(int i, int64_t d) { + for (; i < ssize(s); i |= i + 1) s[i] += d; + } + int64_t query(int r) { // [0, r) + int64_t ret = 0; + for (; r > 0; r &= r - 1) ret += s[r - 1]; + return ret; + } + int64_t query(int l, int r) { // [l, r) + return query(r) - query(l); + } + //! Requires s[i] >= 0 + //! max r such that sum of [0,r) < sum, or -1 + int walk(int64_t sum) { + if (sum <= 0) return -1; + int r = 0; + for (int pw = bit_floor(size(s)); pw; pw >>= 1) + if (r + pw <= ssize(s) && s[r + pw - 1] < sum) + sum -= s[(r += pw) - 1]; + return r; + } +}; +//! https://codeforces.com/blog/entry/111625 +//! Given strings s, t (s initially empty): +//! -append character onto s +//! -given range [l,r): +//! size(LCS(s,t.substr(l,r-l))) = number +//! of indexes i in [l,r) with dp[i] < l +//! @time O(|s| * |t|) +//! @space O(|t|) +template struct lcs_dp { + T t; + vector dp; + lcs_dp(const T& t): t(t), dp(ssize(t)) { + iota(begin(dp), end(dp), 0); + } + void push_onto_s(int c) { + int v = -1; + for (int i = 0; i < ssize(t); i++) + if (c == t[i] || dp[i] < v) swap(dp[i], v); + } +}; +//! @code +//! string s,t; +//! vi lcs_len = lcs_queries(s, t, queries); +//! vi s_vec,t_vec; +//! vi lcs_len1 = lcs_queries(s_vec, t_vec, queries); +//! @endcode +//! lcs_len[i] = size(LCS( +//! s[0,queries[i][0]), +//! t[queries[i][1],queries[i][2]) +//! )) +//! @time O(n*m*log(m) + q*log(m) + q*log(q)) +//! @space O(n + m + q) +vector lcs_queries(const auto& s, const auto& t, + const vector>& queries) { + int n = ssize(s), m = ssize(t), q = ssize(queries); + vector>> qs(n); + for (int i = 0; i < q; i++) { + auto [s_r, t_le, t_ri] = queries[i]; + if (s_r == 0 || t_le == m) continue; + qs[s_r - 1].push_back({t_le, t_ri, i}); + } + lcs_dp lcs(t); + vector res(q); + for (int i = 0; i < n; i++) { + lcs.push_onto_s(s[i]); + BIT bit(m); + vector dp_inv(m, -1); + for (int j = 0; j < m; j++) + if (lcs.dp[j] == -1) bit.update(j, 1); + else dp_inv[lcs.dp[j]] = j; + ranges::sort(qs[i]); + int j = 0; + for (int t_le = 0; t_le < m; t_le++) { + while (j < ssize(qs[i]) && qs[i][j][0] == t_le) + res[qs[i][j][2]] = bit.query(t_le, qs[i][j][1]), + j++; + if (dp_inv[t_le] != -1) bit.update(dp_inv[t_le], 1); + } + } + return res; +} diff --git a/strings/manacher/is_palindrome.hpp b/strings/manacher/is_palindrome.hpp new file mode 100644 index 00000000..8c0b2f0f --- /dev/null +++ b/strings/manacher/is_palindrome.hpp @@ -0,0 +1,40 @@ +//! https://codeforces.com/blog/entry/12143#comment-324162 +//! @code +//! string s; +//! auto man = manacher(s); +//! vi s_vec; +//! auto man1 = manacher(s_vec); +//! @endcode +//! +//! man[center] = index of start of longest +//! palindrome centered at `center` +//! +//! center 0 2 4 6 8 +//! string b a a b a +//! center 1 3 5 7 +//! +//! @time O(n) +//! @space O(n) +vector manacher(const auto& s) { + int n = ssize(s), p = 0; + vector man(2 * n - 1); + for (int i = 0; i < 2 * n - 1; i++) { + int r = i <= 2 * (p - man[p]) + ? p - max(man[2 * p - i], man[p]) + : i / 2; + man[i] = i - r; + while ( + man[i] > 0 && r + 1 < n && s[man[i] - 1] == s[r + 1]) + man[i]--, r++, p = i; + } + return man; +} +//! @time O(n + q) +//! @space O(n) +struct pal_query { + vector man; + pal_query(const auto& s): man(manacher(s)) {}; + bool is_pal(int l, int r) { // [l, r] + return man[l + r] <= l; + } +}; diff --git a/strings/manacher/longest_from_index.hpp b/strings/manacher/longest_from_index.hpp new file mode 100644 index 00000000..7c918374 --- /dev/null +++ b/strings/manacher/longest_from_index.hpp @@ -0,0 +1,57 @@ +//! https://codeforces.com/blog/entry/12143#comment-324162 +//! @code +//! string s; +//! auto man = manacher(s); +//! vi s_vec; +//! auto man1 = manacher(s_vec); +//! @endcode +//! +//! man[center] = index of start of longest +//! palindrome centered at `center` +//! +//! center 0 2 4 6 8 +//! string b a a b a +//! center 1 3 5 7 +//! +//! @time O(n) +//! @space O(n) +vector manacher(const auto& s) { + int n = ssize(s), p = 0; + vector man(2 * n - 1); + for (int i = 0; i < 2 * n - 1; i++) { + int r = i <= 2 * (p - man[p]) + ? p - max(man[2 * p - i], man[p]) + : i / 2; + man[i] = i - r; + while ( + man[i] > 0 && r + 1 < n && s[man[i] - 1] == s[r + 1]) + man[i]--, r++, p = i; + } + return man; +} +//! @time O(n + q) +//! @space O(n) +struct pal_query { + vector man; + pal_query(const auto& s): man(manacher(s)) {}; + bool is_pal(int l, int r) { // [l, r] + return man[l + r] <= l; + } +}; +//! https://github.com/brunomaletta/Biblioteca/blob/master/Codigo/Strings/manacher.cpp +//! @code +//! auto r = longest_from_index(pq); +//! @endcode +//! r[i] = max index such that [i, r[i]] +//! is a palindrome +//! @time O(n) +//! @space O(n) +vector longest_from_index(pal_query& pq) { + int n = (ssize(pq.man) + 1) / 2; + vector longest(n, n - 1); + for (int i = n - 2; i >= 0; i--) { + longest[i] = min(longest[i + 1] + 1, n - 1); + while (!pq.is_pal(i, longest[i])) longest[i]--; + } + return longest; +} diff --git a/library/strings/manacher/longest_palindrome_query.hpp b/strings/manacher/longest_palindrome_query.hpp similarity index 52% rename from library/strings/manacher/longest_palindrome_query.hpp rename to strings/manacher/longest_palindrome_query.hpp index dd9c753b..a6b0db7b 100644 --- a/library/strings/manacher/longest_palindrome_query.hpp +++ b/strings/manacher/longest_palindrome_query.hpp @@ -1,17 +1,72 @@ -#pragma once -#include "../../data_structures/rmq.hpp" -#include "manacher.hpp" +//! @code +//! RMQ rmq1(a, ranges::min); +//! RMQ rmq2(a, [&](auto& x, auto& y) { +//! return min(x, y); +//! }); +//! vector>> +//! rmqs(3, {{}, NULL}); +//! rmqs[1] = {a, ranges::min}; +//! @endcode +//! @time O(nlogn + q) +//! @space O(nlogn) +template struct RMQ { + vector> dp; + F op; + RMQ(const vector& a, F op): dp(1, a), op(op) { + for (int i = 0; (2 << i) <= ssize(a); i++) { + dp.emplace_back(ssize(a) - (2 << i) + 1); + ranges::transform(dp[i], dp[i] | views::drop(1 << i), + begin(dp[i + 1]), op); + } + } + T query(int l, int r) { // [l, r) + assert(l < r); + int lg = __lg(r - l); + return op(dp[lg][l], dp[lg][r - (1 << lg)]); + } +}; +//! https://codeforces.com/blog/entry/12143#comment-324162 +//! @code +//! string s; +//! auto man = manacher(s); +//! vi s_vec; +//! auto man1 = manacher(s_vec); +//! @endcode +//! +//! man[center] = index of start of longest +//! palindrome centered at `center` +//! +//! center 0 2 4 6 8 +//! string b a a b a +//! center 1 3 5 7 +//! +//! @time O(n) +//! @space O(n) +vector manacher(const auto& s) { + int n = ssize(s), p = 0; + vector man(2 * n - 1); + for (int i = 0; i < 2 * n - 1; i++) { + int r = i <= 2 * (p - man[p]) + ? p - max(man[2 * p - i], man[p]) + : i / 2; + man[i] = i - r; + while ( + man[i] > 0 && r + 1 < n && s[man[i] - 1] == s[r + 1]) + man[i]--, r++, p = i; + } + return man; +} //! queries for longest palindromic substring of a given //! substring struct longest_pal_query { - vi man; + vector man; RMQ> rmq = {{}, NULL}; //! @param s string/vector //! @time O(n log n) //! @space O(n log n) for rmq, everything else is O(n) longest_pal_query(const auto& s): man(manacher(s)) { - vi init(sz(man)); - iota(all(init), 0); + vector init(ssize(man)); + iota(begin(init), end(init), 0); rmq = {init, [&](int i1, int i2) { return len(i1) < len(i2) ? i2 : i1; }}; @@ -43,7 +98,7 @@ struct longest_pal_query { //! returns an arbitrary start index //! @time O(log n) //! @space O(1) - pii longest_pal(int l, int r) { + pair longest_pal(int l, int r) { assert(l < r); int pal_len = *ranges::partition_point( views::iota(0, r - l), [&](int x) { diff --git a/library/strings/manacher/manacher.hpp b/strings/manacher/manacher.hpp similarity index 81% rename from library/strings/manacher/manacher.hpp rename to strings/manacher/manacher.hpp index d35d1405..f30238b2 100644 --- a/library/strings/manacher/manacher.hpp +++ b/strings/manacher/manacher.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://codeforces.com/blog/entry/12143#comment-324162 //! @code //! string s; @@ -16,10 +15,10 @@ //! //! @time O(n) //! @space O(n) -vi manacher(const auto& s) { - int n = sz(s), p = 0; - vi man(2 * n - 1); - rep(i, 0, 2 * n - 1) { +vector manacher(const auto& s) { + int n = ssize(s), p = 0; + vector man(2 * n - 1); + for (int i = 0; i < 2 * n - 1; i++) { int r = i <= 2 * (p - man[p]) ? p - max(man[2 * p - i], man[p]) : i / 2; diff --git a/library/strings/prefix_function.hpp b/strings/prefix_function.hpp similarity index 66% rename from library/strings/prefix_function.hpp rename to strings/prefix_function.hpp index 103db3b1..a42410ac 100644 --- a/library/strings/prefix_function.hpp +++ b/strings/prefix_function.hpp @@ -1,10 +1,9 @@ -#pragma once //! https://cp-algorithms.com/string/prefix-function.html#implementation //! @time O(n) //! @space O(n) -vi prefix_function(const auto& s) { - vi pi(sz(s)); - rep(i, 1, sz(s)) { +vector prefix_function(const auto& s) { + vector pi(ssize(s)); + for (int i = 1; i < ssize(s); i++) { int j = pi[i - 1]; while (j && s[i] != s[j]) j = pi[j - 1]; pi[i] = j + (s[i] == s[j]); diff --git a/library/strings/suffix_array/compare/compare_substrings.hpp b/strings/suffix_array/compare/compare_substrings.hpp similarity index 56% rename from library/strings/suffix_array/compare/compare_substrings.hpp rename to strings/suffix_array/compare/compare_substrings.hpp index b92b1007..c9093c9b 100644 --- a/library/strings/suffix_array/compare/compare_substrings.hpp +++ b/strings/suffix_array/compare/compare_substrings.hpp @@ -1,5 +1,18 @@ -#pragma once -#include "compare_suffixes.hpp" +//! @code +//! string s; +//! auto [sa, sa_inv, lcp] = get_sa(s, 256); +//! sa_query saq(s, sa, sa_inv, lcp); +//! int cmp = saq.cmp_sufs(l1,l2); +//! @endcode +//! requires l1,l2 < n +//! if cmp2<0 then s[l1,n) < s[l2,n) +//! if cmp2=0 then s[l1,n) = s[l2,n) +//! if cmp2>0 then s[l1,n) > s[l2,n) +//! @time O(1) +//! @space O(1) +int cmp_sufs(int l1, int l2) { + return sa_inv[l1] - sa_inv[l2]; +} //! @code //! string s; //! auto [sa, sa_inv, lcp] = get_sa(s, 256); diff --git a/library/strings/suffix_array/compare/compare_suffixes.hpp b/strings/suffix_array/compare/compare_suffixes.hpp similarity index 96% rename from library/strings/suffix_array/compare/compare_suffixes.hpp rename to strings/suffix_array/compare/compare_suffixes.hpp index ee4bd3cc..517b483b 100644 --- a/library/strings/suffix_array/compare/compare_suffixes.hpp +++ b/strings/suffix_array/compare/compare_suffixes.hpp @@ -1,4 +1,3 @@ -#pragma once //! @code //! string s; //! auto [sa, sa_inv, lcp] = get_sa(s, 256); diff --git a/library/strings/suffix_array/find/find_string_bs.hpp b/strings/suffix_array/find/find_string_bs.hpp similarity index 79% rename from library/strings/suffix_array/find/find_string_bs.hpp rename to strings/suffix_array/find/find_string_bs.hpp index 9bbdc231..4cb0f264 100644 --- a/library/strings/suffix_array/find/find_string_bs.hpp +++ b/strings/suffix_array/find/find_string_bs.hpp @@ -1,15 +1,15 @@ -#pragma once //! https://github.com/yosupo06/Algorithm/blob/master/src/string/suffixarray.hpp //! returns range [l,r) such that: //! - for all i in [l,r): t==s.substr(sa[i],sz(t)) //! - `r-l` is the # of matches of t in s. //! @time O(|t| * log(|s|)) //! @space O(1) -pii find_str(const T& t) { +pair find_str(const T& t) { auto [l, r] = ranges::equal_range(sa, 0, {}, [&](int i) { return bit_cast( lexicographical_compare_three_way(begin(s) + i, - begin(s) + min(i + sz(t), sz(s)), all(t))); + begin(s) + min(i + ssize(t), ssize(s)), begin(t), + end(t))); }); return {l - begin(sa), r - begin(sa)}; } diff --git a/library/strings/suffix_array/find/find_string_bs_fast.hpp b/strings/suffix_array/find/find_string_bs_fast.hpp similarity index 51% rename from library/strings/suffix_array/find/find_string_bs_fast.hpp rename to strings/suffix_array/find/find_string_bs_fast.hpp index 1f43f0f3..4cf0efd5 100644 --- a/library/strings/suffix_array/find/find_string_bs_fast.hpp +++ b/strings/suffix_array/find/find_string_bs_fast.hpp @@ -1,5 +1,13 @@ -#pragma once -#include "match.hpp" +//! for all i in [sa_le,sa_ri): +//! - t==s.substr(sa[i],sz(t)) +//! - `sa_ri-sa_le` is the # of matches of t in s. +//! +//! if sa_le==sa_ri then: +//! s[s_l,s_r) is longest substring such that: +//! s[s_l,s_r) == t[0,s_r-s_l) +struct match { + int sa_le, sa_ri, s_l, s_r; +}; //! https://stackoverflow.com/a/11374737 //! https://codeforces.com/blog/entry/133051 //! @time O(log(|s|) + |t|) @@ -10,18 +18,19 @@ match find_str_fast(const T& t) { if (int lcp_len = s_l == n ? 0 : len_lcp(s_l, i); lcp_len != s_len) return (lcp_len < s_len) ^ (cmp_sufs(s_l, i) < 0); - auto [it_s, it_t] = - mismatch(i + s_len + all(s), s_len + all(t)); + auto [it_s, it_t] = mismatch(i + s_len + begin(s), + end(s), s_len + begin(t), end(t)); s_l = i, s_len = it_t - begin(t); return lexicographical_compare(it_s, end(s), it_t, end(t)); }; - int sa_le = lower_bound(all(sa), 0, cmp) - begin(sa), + int sa_le = lower_bound(begin(sa), end(sa), 0, cmp) - + begin(sa), sa_ri = sa_le; - if (s_len == sz(t)) - sa_ri = lower_bound(sa_le + all(sa), 0, + if (s_len == ssize(t)) + sa_ri = lower_bound(sa_le + begin(sa), end(sa), 0, [&](int i, int) -> bool { - return len_lcp(s_l, i) >= sz(t); + return len_lcp(s_l, i) >= ssize(t); }) - begin(sa); return {sa_le, sa_ri, s_l, s_l + s_len}; diff --git a/library/strings/suffix_array/find/find_substring.hpp b/strings/suffix_array/find/find_substring.hpp similarity index 83% rename from library/strings/suffix_array/find/find_substring.hpp rename to strings/suffix_array/find/find_substring.hpp index 0f8d0319..10b337e8 100644 --- a/library/strings/suffix_array/find/find_substring.hpp +++ b/strings/suffix_array/find/find_substring.hpp @@ -1,4 +1,3 @@ -#pragma once //! @code //! string s; //! auto [sa, sa_inv, lcp] = get_sa(s, 256); @@ -12,14 +11,15 @@ //! s.substr(s_l, s_r - s_l) in s. //! @time O(log(|s|)) //! @space O(1) -pii find_substr(int s_l, int s_r) { +pair find_substr(int s_l, int s_r) { auto cmp = [&](int i, bool flip) -> bool { return flip ^ (len_lcp(i, s_l) < s_r - s_l); }; int l = lower_bound(begin(sa), begin(sa) + sa_inv[s_l], 0, cmp) - begin(sa); - int r = lower_bound(sa_inv[s_l] + 1 + all(sa), 1, cmp) - + int r = lower_bound(sa_inv[s_l] + 1 + begin(sa), end(sa), + 1, cmp) - begin(sa); return {l, r}; } diff --git a/library/strings/suffix_array/find/find_substrings_concatenated.hpp b/strings/suffix_array/find/find_substrings_concatenated.hpp similarity index 76% rename from library/strings/suffix_array/find/find_substrings_concatenated.hpp rename to strings/suffix_array/find/find_substrings_concatenated.hpp index dd2fa74e..d8839ae1 100644 --- a/library/strings/suffix_array/find/find_substrings_concatenated.hpp +++ b/strings/suffix_array/find/find_substrings_concatenated.hpp @@ -1,5 +1,13 @@ -#pragma once -#include "match.hpp" +//! for all i in [sa_le,sa_ri): +//! - t==s.substr(sa[i],sz(t)) +//! - `sa_ri-sa_le` is the # of matches of t in s. +//! +//! if sa_le==sa_ri then: +//! s[s_l,s_r) is longest substring such that: +//! s[s_l,s_r) == t[0,s_r-s_l) +struct match { + int sa_le, sa_ri, s_l, s_r; +}; //! @param substrs this defines query string t as: //! s.substr(substrs[0][0], substrs[0][1] - //! substrs[0][0]) + s.substr(substrs[1][0], @@ -11,7 +19,8 @@ //! @returns see match //! @time O(sz(substrs) * log(|s|)) //! @space O(1) -match find_substrs_concated(const vector& substrs) { +match find_substrs_concated( + const vector>& substrs) { using dt = array; int sa_le = 0, sa_ri = n, s_l = 0, s_r = 0, sum_len = 0; auto cmp = [&](int i, const dt& x) -> bool { diff --git a/library/strings/suffix_array/find/match.hpp b/strings/suffix_array/find/match.hpp similarity index 95% rename from library/strings/suffix_array/find/match.hpp rename to strings/suffix_array/find/match.hpp index efa9e39b..8f50278a 100644 --- a/library/strings/suffix_array/find/match.hpp +++ b/strings/suffix_array/find/match.hpp @@ -1,4 +1,3 @@ -#pragma once //! for all i in [sa_le,sa_ri): //! - t==s.substr(sa[i],sz(t)) //! - `sa_ri-sa_le` is the # of matches of t in s. diff --git a/library/strings/suffix_array/suffix_array.hpp b/strings/suffix_array/suffix_array.hpp similarity index 81% rename from library/strings/suffix_array/suffix_array.hpp rename to strings/suffix_array/suffix_array.hpp index 8ce1278f..4bf84e8f 100644 --- a/library/strings/suffix_array/suffix_array.hpp +++ b/strings/suffix_array/suffix_array.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://github.com/kth-competitive-programming/kactl/blob/main/content/strings/SuffixArray.h //! //! 0 banana 3 @@ -35,30 +34,30 @@ //! @time O(nlogn + max_num) //! @space O(n + max_num) auto get_sa(const auto& s, int max_num) { - int n = sz(s); - vi sa(n), sa_inv(all(s)), lcp(n - 1); - iota(all(sa), 0); + int n = ssize(s); + vector sa(n), sa_inv(begin(s), end(s)), lcp(n - 1); + iota(begin(sa), end(sa), 0); for (int i = 0; i < n; i = max(1, 2 * i)) { - vi y(sa_inv), freq(max_num); - iota(all(sa_inv), n - i); + vector y(sa_inv), freq(max_num); + iota(begin(sa_inv), end(sa_inv), n - i); ranges::copy_if(sa, begin(sa_inv) + i, [&](int& x) { return (x -= i) >= 0; }); for (int x : y) freq[x]++; - partial_sum(all(freq), begin(freq)); + partial_sum(begin(freq), end(freq), begin(freq)); for (int x : sa_inv | views::reverse) sa[--freq[y[x]]] = x; max_num = 1, sa_inv[sa[0]] = 0; auto prev_inv = [&](int j) { return pair(y[j], i + j < n ? y[i + j] : -1); }; - rep(j, 1, n) { + for (int j = 1; j < n; j++) { max_num += prev_inv(sa[j - 1]) != prev_inv(sa[j]); sa_inv[sa[j]] = max_num - 1; } if (max_num == n) break; } int sz = 0; - rep(i, 0, n) { + for (int i = 0; i < n; i++) { if (sz > 0) sz--; if (sa_inv[i] == 0) continue; for (int j = sa[sa_inv[i] - 1]; diff --git a/strings/suffix_array/suffix_array_query.hpp b/strings/suffix_array/suffix_array_query.hpp new file mode 100644 index 00000000..d562ee65 --- /dev/null +++ b/strings/suffix_array/suffix_array_query.hpp @@ -0,0 +1,271 @@ +//! https://github.com/kth-competitive-programming/kactl/blob/main/content/strings/SuffixArray.h +//! +//! 0 banana 3 +//! 1 anana 2 +//! 2 nana 5 +//! 3 ana 1 +//! 4 na 4 +//! 5 a 0 +//! +//! 5 a 0 +//! | +//! 3 ana 1 +//! ||| +//! 1 anana 2 +//! +//! 0 banana 3 +//! +//! 4 na 4 +//! || +//! 2 nana 5 +//! +//! sa = {5, 3, 1, 0, 4, 2} +//! sa_inv = {3, 2, 5, 1, 4, 0} +//! lcp = {1, 3, 0, 0, 2} +//! +//! @code +//! // requires 0<=s[i] sa(n), sa_inv(begin(s), end(s)), lcp(n - 1); + iota(begin(sa), end(sa), 0); + for (int i = 0; i < n; i = max(1, 2 * i)) { + vector y(sa_inv), freq(max_num); + iota(begin(sa_inv), end(sa_inv), n - i); + ranges::copy_if(sa, begin(sa_inv) + i, + [&](int& x) { return (x -= i) >= 0; }); + for (int x : y) freq[x]++; + partial_sum(begin(freq), end(freq), begin(freq)); + for (int x : sa_inv | views::reverse) + sa[--freq[y[x]]] = x; + max_num = 1, sa_inv[sa[0]] = 0; + auto prev_inv = [&](int j) { + return pair(y[j], i + j < n ? y[i + j] : -1); + }; + for (int j = 1; j < n; j++) { + max_num += prev_inv(sa[j - 1]) != prev_inv(sa[j]); + sa_inv[sa[j]] = max_num - 1; + } + if (max_num == n) break; + } + int sz = 0; + for (int i = 0; i < n; i++) { + if (sz > 0) sz--; + if (sa_inv[i] == 0) continue; + for (int j = sa[sa_inv[i] - 1]; + max(i, j) + sz < n && s[i + sz] == s[j + sz];) + sz++; + lcp[sa_inv[i] - 1] = sz; + } + return tuple{sa, sa_inv, lcp}; +} +//! @code +//! RMQ rmq1(a, ranges::min); +//! RMQ rmq2(a, [&](auto& x, auto& y) { +//! return min(x, y); +//! }); +//! vector>> +//! rmqs(3, {{}, NULL}); +//! rmqs[1] = {a, ranges::min}; +//! @endcode +//! @time O(nlogn + q) +//! @space O(nlogn) +template struct RMQ { + vector> dp; + F op; + RMQ(const vector& a, F op): dp(1, a), op(op) { + for (int i = 0; (2 << i) <= ssize(a); i++) { + dp.emplace_back(ssize(a) - (2 << i) + 1); + ranges::transform(dp[i], dp[i] | views::drop(1 << i), + begin(dp[i + 1]), op); + } + } + T query(int l, int r) { // [l, r) + assert(l < r); + int lg = __lg(r - l); + return op(dp[lg][l], dp[lg][r - (1 << lg)]); + } +}; +//! for all i in [sa_le,sa_ri): +//! - t==s.substr(sa[i],sz(t)) +//! - `sa_ri-sa_le` is the # of matches of t in s. +//! +//! if sa_le==sa_ri then: +//! s[s_l,s_r) is longest substring such that: +//! s[s_l,s_r) == t[0,s_r-s_l) +struct match { + int sa_le, sa_ri, s_l, s_r; +}; +//! @code +//! string s; +//! auto [sa, sa_inv, lcp] = get_sa(s, 256); +//! sa_query saq(s, sa, sa_inv, lcp); +//! vi s_vec; +//! auto [sa1, sa_inv1, lcp1] = sa_short(s_vec); +//! sa_query saq1(s_vec, sa1, sa_inv1, lcp1); +//! @endcode +template struct sa_query { + int n; + T s; + vector sa, sa_inv, lcp; + RMQ> rmq; + sa_query(const T& s, const vector& sa, + const vector& sa_inv, const vector& lcp): + n(ssize(s)), s(s), sa(sa), sa_inv(sa_inv), lcp(lcp), + rmq(lcp, ranges::min) {} + //! returns max integer k such that + //! s.substr(i1, k) == s.substr(i2, k) + //! @time O(1) + //! @space O(1) + int len_lcp(int i1, int i2) { + if (i1 == i2) return n - i1; + auto [l, r] = minmax(sa_inv[i1], sa_inv[i2]); + return rmq.query(l, r); + } + //! @code + //! string s; + //! auto [sa, sa_inv, lcp] = get_sa(s, 256); + //! sa_query saq(s, sa, sa_inv, lcp); + //! int cmp = saq.cmp_sufs(l1,l2); + //! @endcode + //! requires l1,l2 < n + //! if cmp2<0 then s[l1,n) < s[l2,n) + //! if cmp2=0 then s[l1,n) = s[l2,n) + //! if cmp2>0 then s[l1,n) > s[l2,n) + //! @time O(1) + //! @space O(1) + int cmp_sufs(int l1, int l2) { + return sa_inv[l1] - sa_inv[l2]; + } + //! @code + //! string s; + //! auto [sa, sa_inv, lcp] = get_sa(s, 256); + //! sa_query saq(s, sa, sa_inv, lcp); + //! int cmp = saq.cmp_substrs(l1,r1,l2,r2); + //! @endcode + //! requires l1,l2 < n + //! if cmp1<0 then s[l1,r1) < s[l2,r2) + //! if cmp1=0 then s[l1,r1) = s[l2,r2) + //! if cmp1>0 then s[l1,r1) > s[l2,r2) + //! @time O(1) + //! @space O(1) + int cmp_substrs(int l1, int r1, int l2, int r2) { + int len1 = r1 - l1, len2 = r2 - l2; + return len_lcp(l1, l2) >= min(len1, len2) + ? len1 - len2 + : cmp_sufs(l1, l2); + } + //! https://github.com/yosupo06/Algorithm/blob/master/src/string/suffixarray.hpp + //! returns range [l,r) such that: + //! - for all i in [l,r): t==s.substr(sa[i],sz(t)) + //! - `r-l` is the # of matches of t in s. + //! @time O(|t| * log(|s|)) + //! @space O(1) + pair find_str(const T& t) { + auto [l, r] = + ranges::equal_range(sa, 0, {}, [&](int i) { + return bit_cast( + lexicographical_compare_three_way(begin(s) + i, + begin(s) + min(i + ssize(t), ssize(s)), + begin(t), end(t))); + }); + return {l - begin(sa), r - begin(sa)}; + } + //! https://stackoverflow.com/a/11374737 + //! https://codeforces.com/blog/entry/133051 + //! @time O(log(|s|) + |t|) + //! @space O(1) + match find_str_fast(const T& t) { + int s_l = n, s_len = 0; + auto cmp = [&](int i, int) -> bool { + if (int lcp_len = s_l == n ? 0 : len_lcp(s_l, i); + lcp_len != s_len) + return (lcp_len < s_len) ^ (cmp_sufs(s_l, i) < 0); + auto [it_s, it_t] = mismatch(i + s_len + begin(s), + end(s), s_len + begin(t), end(t)); + s_l = i, s_len = it_t - begin(t); + return lexicographical_compare(it_s, end(s), it_t, + end(t)); + }; + int sa_le = lower_bound(begin(sa), end(sa), 0, cmp) - + begin(sa), + sa_ri = sa_le; + if (s_len == ssize(t)) + sa_ri = lower_bound(sa_le + begin(sa), end(sa), 0, + [&](int i, int) -> bool { + return len_lcp(s_l, i) >= ssize(t); + }) - + begin(sa); + return {sa_le, sa_ri, s_l, s_l + s_len}; + } + //! @code + //! string s; + //! auto [sa, sa_inv, lcp] = get_sa(s, 256); + //! sa_query saq(s, sa, sa_inv, lcp); + //! auto [sa_le,sa_ri] = saq.find_substr(s_l,s_r); + //! @endcode + //! requires s_l < n + //! for all i in [sa_le,sa_ri): s.substr(s_l,s_r-s_l) + //! == s.substr(sa[i],s_r-s_l) + //! - `r-l` is the # of matches of + //! s.substr(s_l, s_r - s_l) in s. + //! @time O(log(|s|)) + //! @space O(1) + pair find_substr(int s_l, int s_r) { + auto cmp = [&](int i, bool flip) -> bool { + return flip ^ (len_lcp(i, s_l) < s_r - s_l); + }; + int l = lower_bound(begin(sa), begin(sa) + sa_inv[s_l], + 0, cmp) - + begin(sa); + int r = lower_bound(sa_inv[s_l] + 1 + begin(sa), + end(sa), 1, cmp) - + begin(sa); + return {l, r}; + } + //! @param substrs this defines query string t as: + //! s.substr(substrs[0][0], substrs[0][1] - + //! substrs[0][0]) + s.substr(substrs[1][0], + //! substrs[1][1] - substrs[1][0]) + + //! ... + //! s.substr(substrs.back()[0], substrs.back()[1] - + //! substrs.back()[0]) + //! - doesn't work when substrs[i][0] == n + //! @returns see match + //! @time O(sz(substrs) * log(|s|)) + //! @space O(1) + match find_substrs_concated( + const vector>& substrs) { + using dt = array; + int sa_le = 0, sa_ri = n, s_l = 0, s_r = 0, + sum_len = 0; + auto cmp = [&](int i, const dt& x) -> bool { + int j = i + sum_len, + lcp_len = + j == n ? 0 : min(len_lcp(j, x[0]), x[1]); + if (lcp_len + sum_len > s_r - s_l) + s_l = i, s_r = j + lcp_len; + if (lcp_len < min(n - j, x[1])) + return sa_inv[j] - sa_inv[x[0]] < x[2]; + return x[2] ^ (n - j < x[1]); + }; + for (auto [l, r] : substrs) { + sa_le = lower_bound(begin(sa) + sa_le, + begin(sa) + sa_ri, dt{l, r - l, 0}, cmp) - + begin(sa); + sa_ri = lower_bound(begin(sa) + sa_le, + begin(sa) + sa_ri, dt{l, r - l, 1}, cmp) - + begin(sa); + sum_len += r - l; + } + return {sa_le, sa_ri, s_l, s_r}; + } +}; diff --git a/library/strings/suffix_array/suffix_array_short.hpp b/strings/suffix_array/suffix_array_short.hpp similarity index 72% rename from library/strings/suffix_array/suffix_array_short.hpp rename to strings/suffix_array/suffix_array_short.hpp index cb0a7f34..7f8b0fac 100644 --- a/library/strings/suffix_array/suffix_array_short.hpp +++ b/strings/suffix_array/suffix_array_short.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://github.com/atcoder/ac-library/blob/master/atcoder/string.hpp //! @code //! // requires s[i]>=0 @@ -11,21 +10,22 @@ //! @time O(n * log^2(n)) //! @space O(n) auto sa_short(const auto& s) { - int n = sz(s); - vi sa(n), sa_inv(all(s)), lcp(n - 1); - iota(all(sa), 0); + int n = ssize(s); + vector sa(n), sa_inv(begin(s), end(s)), lcp(n - 1); + iota(begin(sa), end(sa), 0); for (int k = 1; k <= n; k *= 2) { - vi x(sa_inv); + vector x(sa_inv); auto proj = [&](int i) { return pair(x[i], i + k < n ? x[i + k] : -1); }; ranges::sort(sa, {}, proj); sa_inv[sa[0]] = 0; - rep(i, 1, n) sa_inv[sa[i]] = - sa_inv[sa[i - 1]] + (proj(sa[i - 1]) != proj(sa[i])); + for (int i = 1; i < n; i++) + sa_inv[sa[i]] = sa_inv[sa[i - 1]] + + (proj(sa[i - 1]) != proj(sa[i])); } int sz = 0; - rep(i, 0, n) { + for (int i = 0; i < n; i++) { if (sz > 0) sz--; if (sa_inv[i] == 0) continue; for (int j = sa[sa_inv[i] - 1]; diff --git a/library/strings/trie.hpp b/strings/trie.hpp similarity index 88% rename from library/strings/trie.hpp rename to strings/trie.hpp index 3cf12e3a..a43124ff 100644 --- a/library/strings/trie.hpp +++ b/strings/trie.hpp @@ -1,11 +1,10 @@ -#pragma once //! https://cp-algorithms.com/string/aho_corasick.html#construction-of-the-trie const int mn = 'A'; struct trie { struct node { array next; bool end_of_word = 0; - node() { fill(all(next), -1); } + node() { fill(begin(next), end(next), -1); } }; deque t; trie(): t(1) {} @@ -14,7 +13,7 @@ struct trie { for (char ch : s) { int u = ch - mn; if (t[v].next[u] == -1) { - t[v].next[u] = sz(t); + t[v].next[u] = ssize(t); t.emplace_back(); } v = t[v].next[u]; diff --git a/library/strings/wildcard_pattern_matching.hpp b/strings/wildcard_pattern_matching.hpp similarity index 71% rename from library/strings/wildcard_pattern_matching.hpp rename to strings/wildcard_pattern_matching.hpp index 4bc4f31d..6741e723 100644 --- a/library/strings/wildcard_pattern_matching.hpp +++ b/strings/wildcard_pattern_matching.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://codeforces.com/blog/entry/111380 //! @code //! vl s_vec, t_vec; @@ -9,11 +8,11 @@ //! s_vec[i]=0 or t_vec[i]=0 for a wildcard //! @time O((n+m) log (n+m)) //! @space O(n+m) -using vl = vector; +using vl = vector; vector make_powers(const vl& v) { - int n = sz(v); + int n = ssize(v); vector pws(3, vl(n)); - rep(i, 0, n) { + for (int i = 0; i < n; i++) { pws[0][i] = v[i]; pws[1][i] = v[i] * v[i]; pws[2][i] = v[i] * v[i] * v[i]; @@ -22,15 +21,15 @@ vector make_powers(const vl& v) { } vector wildcard_pattern_matching(const vl& s, const vl& t, auto conv) { - int n = sz(s), m = sz(t); + int n = ssize(s), m = ssize(t); auto s_pws = make_powers(s); auto t_pws = make_powers(t); - for (auto& t_pw : t_pws) reverse(all(t_pw)); + for (auto& t_pw : t_pws) reverse(begin(t_pw), end(t_pw)); vector res(3); - rep(pw_hay, 0, 3) res[pw_hay] = - conv(s_pws[pw_hay], t_pws[2 - pw_hay]); + for (int pw_hay = 0; pw_hay < 3; pw_hay++) + res[pw_hay] = conv(s_pws[pw_hay], t_pws[2 - pw_hay]); vector mtch(n - m + 1); - rep(i, 0, n - m + 1) { + for (int i = 0; i < n - m + 1; i++) { int id = i + m - 1; auto num = res[0][id] - 2 * res[1][id] + res[2][id]; mtch[i] = num == 0; diff --git a/tests/.config/.astylerc b/tests/.config/.astylerc deleted file mode 100644 index 9924c5da..00000000 --- a/tests/.config/.astylerc +++ /dev/null @@ -1,19 +0,0 @@ -indent=tab -indent-col1-comments -keep-one-line-blocks -style=attach -attach-return-type -attach-closing-while -attach-classes -remove-braces -align-reference=type -align-pointer=type -delete-empty-lines -pad-oper -pad-header -pad-comma -unpad-paren -close-templates -suffix=none -mode=c -formatted diff --git a/tests/.config/.clang-format b/tests/.config/.clang-format deleted file mode 100644 index ed27099e..00000000 --- a/tests/.config/.clang-format +++ /dev/null @@ -1,94 +0,0 @@ ---- -Language: Cpp -BasedOnStyle: Google -AccessModifierOffset: -2 -AlignAfterOpenBracket: DontAlign -AlignConsecutiveAssignments: false -AlignConsecutiveBitFields: None -AlignConsecutiveDeclarations: None -AlignConsecutiveMacros: None -AlignOperands: DontAlign -AlignTrailingComments: false -AllowShortBlocksOnASingleLine: Always -AllowShortCaseLabelsOnASingleLine: true -AllowShortEnumsOnASingleLine: true -AllowShortFunctionsOnASingleLine: All -AllowShortIfStatementsOnASingleLine: AllIfsAndElse -AllowShortLambdasOnASingleLine: All -AllowShortLoopsOnASingleLine: true -AlwaysBreakAfterReturnType: None -# AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: MultiLine -AttributeMacros: [] -BinPackArguments: true -BinPackParameters: true -BitFieldColonSpacing: Both -BreakBeforeBinaryOperators: None -BreakBeforeBraces: Attach -BreakBeforeConceptDeclarations: false -BreakBeforeTernaryOperators: true -BreakConstructorInitializers: AfterColon -BreakInheritanceList: AfterColon -BreakStringLiterals: false -ColumnLimit: 59 -CompactNamespaces: true -ConstructorInitializerAllOnOneLineOrOnePerLine: false -ConstructorInitializerIndentWidth: 2 -ContinuationIndentWidth: 2 -Cpp11BracedListStyle: true -DerivePointerAlignment: true -EmptyLineAfterAccessModifier: Never -EmptyLineBeforeAccessModifier: Never -FixNamespaceComments: false -ForEachMacros: [] -IncludeBlocks: Preserve -IndentCaseBlocks: false -IndentCaseLabels: false -IndentGotoLabels: false -IndentWidth: 2 -IndentWrappedFunctionNames: false -InsertTrailingCommas: None -# LambdaBodyIndentation: OuterScope -KeepEmptyLinesAtTheStartOfBlocks: false -MaxEmptyLinesToKeep: 0 -NamespaceIndentation: None -PackConstructorInitializers: BinPack -PenaltyBreakAssignment: 1 -PenaltyBreakBeforeFirstCallParameter: 1 -# PenaltyBreakComment: 300 -PenaltyBreakFirstLessLess: 1 -PenaltyBreakOpenParenthesis: 1 -# PenaltyBreakString: 1000 -PenaltyExcessCharacter: 1000000 -# PenaltyIndentedWhitespace: 1000 -PenaltyReturnTypeOnItsOwnLine: 200 -PointerAlignment: Left -# QualifierAlignment: Left -# ReflowComments: false -ReferenceAlignment: Left -RemoveBracesLLVM: true -SeparateDefinitionBlocks: Never -SortIncludes: false -SortUsingDeclarations: false -SpaceAfterCStyleCast: false -SpaceAfterLogicalNot: false -SpaceAfterTemplateKeyword: false -SpaceAroundPointerQualifiers: Default -SpaceBeforeAssignmentOperators: true -SpaceBeforeCaseColon: false -SpaceBeforeCpp11BracedList: false -SpaceBeforeCtorInitializerColon: false -SpaceBeforeInheritanceColon: false -SpaceBeforeParens: ControlStatementsExceptControlMacros -SpaceBeforeRangeBasedForLoopColon: true -SpaceBeforeSquareBrackets: false -SpaceInEmptyBlock: false -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 1 -SpacesInAngles: false -SpacesInCStyleCastParentheses: false -SpacesInContainerLiterals: false -SpacesInParentheses: false -SpacesInSquareBrackets: false -Standard: c++20 -... diff --git a/tests/.config/.clang-tidy b/tests/.config/.clang-tidy deleted file mode 100644 index b1126e4b..00000000 --- a/tests/.config/.clang-tidy +++ /dev/null @@ -1,122 +0,0 @@ -Checks: > - -clang-analyzer-core.UndefinedBinaryOperatorResult, - -clang-analyzer-core.BitwiseShift, - bugprone-argument-comment, - bugprone-assert-side-effect, - bugprone-bad-signal-to-kill-thread, - bugprone-bool-pointer-implicit-conversion, - bugprone-branch-clone, - bugprone-copy-constructor-init, - bugprone-dangling-handle, - bugprone-dynamic-static-initializers, - bugprone-fold-init-type, - bugprone-forward-declaration-namespace, - bugprone-forwarding-reference-overload, - bugprone-inaccurate-erase, - bugprone-incorrect-roundings, - bugprone-infinite-loop, - bugprone-integer-division, - bugprone-lambda-function-name, - bugprone-macro-parentheses, - bugprone-macro-repeated-side-effects, - bugprone-misplaced-operator-in-strlen-in-alloc, - bugprone-misplaced-pointer-arithmetic-in-alloc, - bugprone-misplaced-widening-cast, - bugprone-move-forwarding-reference, - bugprone-multiple-statement-macro, - bugprone-no-escape, - bugprone-not-null-terminated-result, - bugprone-parent-virtual-call, - bugprone-posix-return, - bugprone-redundant-branch-condition, - bugprone-reserved-identifier, - bugprone-shared-ptr-array-mismatch, - bugprone-signal-handler, - bugprone-signed-char-misuse, - bugprone-sizeof-container, - bugprone-sizeof-expression, - bugprone-spuriously-wake-up-functions, - bugprone-string-constructor, - bugprone-string-integer-assignment, - bugprone-string-literal-with-embedded-nul, - bugprone-stringview-nullptr, - bugprone-suspicious-enum-usage, - bugprone-suspicious-include, - bugprone-suspicious-memory-comparison, - bugprone-suspicious-memset-usage, - bugprone-suspicious-missing-comma, - bugprone-suspicious-semicolon, - bugprone-suspicious-string-compare, - bugprone-swapped-arguments, - bugprone-terminating-continue, - bugprone-throw-keyword-missing, - bugprone-too-small-loop-variable, - bugprone-unchecked-optional-access, - bugprone-undefined-memory-manipulation, - bugprone-undelegated-constructor, - bugprone-unhandled-exception-at-new, - bugprone-unhandled-self-assignment, - bugprone-unused-return-value, - bugprone-use-after-move, - bugprone-virtual-near-miss, - misc-confusable-identifiers - misc-const-correctness, - misc-misleading-bidirectional, - misc-misleading-identifier, - misc-misplaced-const, - misc-new-delete-overloads, - misc-non-copyable-objects, - misc-redundant-expression, - misc-static-assert, - misc-throw-by-value-catch-by-reference, - misc-unconventional-assign-operator, - misc-uniqueptr-reset-release, - misc-unused-alias-decls, - misc-unused-parameters, - misc-unused-using-decls, - modernize-use-auto, - modernize-use-emplace, - modernize-use-using, - modernize-use-default-member-init, - cppcoreguidelines-avoid-const-or-ref-data-members, - cppcoreguidelines-avoid-goto, - cppcoreguidelines-interfaces-global-init, - performance-*, - readability-identifier-naming, - readability-container-size-empty, - readability-convert-member-functions-to-static, - readability-else-after-return, - readability-duplicate-include, - readability-function-size, - readability-misleading-indentation, - readability-misplaced-array-index, - readability-string-compare, - readability-suspicious-call-argument, - readability-use-anyofallof, - readability-redundant-*, - readability-simplify-*, - readability-container-contains -WarningsAsErrors: "*" -HeaderFilterRegex: "/library/[^.]+\\.hpp$" -UseColor: true -CheckOptions: - - key: readability-identifier-naming.StructCase - value: lower_case - - key: readability-identifier-naming.ClassCase - value: lower_case - - key: readability-identifier-naming.FunctionCase - value: lower_case - - key: readability-identifier-naming.MethodCase - value: lower_case - - key: readability-identifier-naming.VariableCase - value: lower_case - - key: readability-identifier-naming.ParameterCase - value: lower_case - - key: readability-identifier-naming.TypedefCase - value: lower_case - - key: readability-identifier-naming.TemplateParameterCase - value: UPPER_CASE - - key: readability-identifier-naming.TypeTemplateParameterIgnoredRegexp - value: expr-type - - key: clang-diagnostic-deprecated-declarations - value: false diff --git a/tests/.config/.clang_compile_flags b/tests/.config/.clang_compile_flags deleted file mode 100644 index ad873187..00000000 --- a/tests/.config/.clang_compile_flags +++ /dev/null @@ -1,15 +0,0 @@ --Wall --Wextra --Wunused --Wpedantic --Wshadow --Wformat=2 --Wfloat-equal --Wcast-qual --Wcast-align --Wno-keyword-macro --Werror --O2 --Wno-narrowing --Wno-deprecated-declarations --Wno-gnu-conditional-omitted-operand diff --git a/tests/.config/.code_snippet_excluded_file_list b/tests/.config/.code_snippet_excluded_file_list deleted file mode 100644 index 63f606e0..00000000 --- a/tests/.config/.code_snippet_excluded_file_list +++ /dev/null @@ -1,24 +0,0 @@ -dist.hpp -in_subtree.hpp -on_path.hpp -virtual_tree.hpp -prime_sieve -find_first.hpp -find_last.hpp -loops -kth_path.hpp -deque.hpp -index.hpp -compare_substrings.hpp -compare_suffixes.hpp -find_string_bs.hpp -find_string_bs_fast.hpp -find_substring.hpp -find_substrings_concatenated.hpp -pascals_identity.hpp -binary_search.hpp -walk.hpp -prev.hpp -next.hpp -wavelet_count_less.hpp -dynamic_bitset.hpp diff --git a/tests/.config/.cppcheck_suppression_list b/tests/.config/.cppcheck_suppression_list deleted file mode 100644 index 85f4f173..00000000 --- a/tests/.config/.cppcheck_suppression_list +++ /dev/null @@ -1,62 +0,0 @@ -noExplicitConstructor -missingIncludeSystem -functionConst -unknownMacro -constParameterReference -unusedStructMember:../library/flow/min_cost_max_flow.hpp -unusedStructMember:../library/flow/dinic.hpp:15 -unusedStructMember:../library/strings/suffix_array/find/match.hpp:10 -unusedScopedObject:library_checker_aizu_tests/trees/centroid_path_dist.test.cpp:29 -unusedScopedObject:library_checker_aizu_tests/trees/edge_cd_lca.test.cpp:20 -unusedScopedObject:library_checker_aizu_tests/trees/cd_jump_on_tree.test.cpp:20 -unusedScopedObject:library_checker_aizu_tests/trees/cd_jump_on_tree.test.cpp:58 -arrayIndexOutOfBoundsCond:library_checker_aizu_tests/math/linear_prime_sieve.test.cpp:17 -negativeContainerIndex:../library/strings/suffix_array/burrows_wheeler.hpp:50 -useStlAlgorithm:../kactl/content/numerical/FastFourierTransform.h:53 -useStlAlgorithm:../library/graphs/strongly_connected_components/add_edges_strongly_connected.hpp:58 -useStlAlgorithm:../library/math/matrix_related/row_reduce.hpp:28 -useStlAlgorithm:../library/math/count_paths/count_paths_triangle.hpp:24 -useStlAlgorithm:../library/math/matrix_related/xor_basis_unordered.hpp:16 -shadowFunction:../kactl/content/graph/BinaryLifting.h:17 -unknownMacro:../kactl/content/graph/BinaryLifting.h:18 -constParameter:../kactl/content/graph/BinaryLifting.h:29 -constParameter:../library/data_structures/wavelet_merge/merge_sort_tree.hpp:28 -constParameter:../library/data_structures/wavelet_merge/merge_sort_tree.hpp:41 -constParameter:../library/data_structures/wavelet_merge/merge_sort_tree_updates.hpp:50 -constParameter:../library/data_structures/wavelet_merge/merge_sort_tree_updates.hpp:55 -constParameter:../library/data_structures/wavelet_merge/merge_sort_tree_updates.hpp:59 -constParameter:../library/data_structures/wavelet_merge/wavelet_tree_updates.hpp:49 -constParameter:../library/data_structures/wavelet_merge/wavelet_tree_updates.hpp:53 -constParameter:../hackpack-cpp/content/number-theory/ModInt.h:45 -constParameter:library_checker_aizu_tests/data_structures/rmq_inc.test.cpp:11 -variableScope:../kactl/content/number-theory/Factor.h:47 -syntaxError:../library/math/n_choose_k/pascals_identity.hpp:4 -syntaxError:../library/math/prime_sieve/calc_sieve.hpp:6 -syntaxError:../library/math/prime_sieve/calc_linear_sieve.hpp:6 -syntaxError:../library/loops/chooses.hpp:7 -syntaxError:../library/loops/quotients.hpp:10 -syntaxError:../library/loops/submasks.hpp:7 -syntaxError:../library/loops/supermasks.hpp:8 -syntaxError:../library/math/prime_sieve/mobius.hpp:6 -syntaxError:../library/trees/lca_rmq/iterate_subtree.hpp:6 -knownConditionTrueFalse:../library/strings/suffix_array/suffix_array.hpp:62 -knownConditionTrueFalse:../library/strings/suffix_array/suffix_array_short.hpp:29 -knownConditionTrueFalse:../library/data_structures/dsu/kruskal_tree.hpp:15 -knownConditionTrueFalse:../library/data_structures/dsu/dsu.hpp:11 -constVariable:../kactl/content/numerical/NumberTheoreticTransform.h:30 -constVariable:../kactl/content/graph/CompressTree.h:20 -constVariableReference:../kactl/content/graph/CompressTree.h:20 -constVariableReference:../library/flow/min_cost_max_flow.hpp:43 -constVariableReference:library_checker_aizu_tests/graphs/connected_components_of_complement_graph.test.cpp:21 -constVariableReference:library_checker_aizu_tests/handmade_tests/dsu_size.test.cpp:39 -constVariableReference:../library/trees/centroid_decomp_uncommon/count_paths_per_length.hpp:34 -constVariablePointer:../kactl/content/numerical/FastFourierTransform.h:39 -cstyleCast:../kactl/content/numerical/FastFourierTransform.h:39 -derefInvalidIterator:../library/data_structures/uncommon/linear_rmq.hpp:27 -derefInvalidIterator:library_checker_aizu_tests/handmade_tests/n_choose_k.test.cpp:13 -unreadVariable:library_checker_aizu_tests/handmade_tests/permutation_tree_small.test.cpp:12 -uninitvar:library_checker_aizu_tests/handmade_tests/seg_tree_find_small.test.cpp:41 -unusedFunction:../kactl/content/data-structures/UnionFind.h:14 -unusedFunction:../kactl/content/number-theory/ModPow.h:13 -unusedFunction:../kactl/stress-tests/utilities/genTree.h:49 -containerOutOfBounds:../library/data_structures/uncommon/permutation_tree.hpp:85 diff --git a/tests/.config/.gcc_compile_flags b/tests/.config/.gcc_compile_flags deleted file mode 100644 index 5babab28..00000000 --- a/tests/.config/.gcc_compile_flags +++ /dev/null @@ -1,13 +0,0 @@ --Wall --Wextra --Wunused --Wlogical-op --Wformat=2 --Wfloat-equal --Wcast-qual --Wcast-align --Wshift-overflow=2 --Wduplicated-cond --Werror --O2 --std=c++20 diff --git a/tests/.gitignore b/tests/.gitignore deleted file mode 100644 index 8169c5d4..00000000 --- a/tests/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -*.out -html/ -latex/ -ptc.pdf -input -output -entire_library_without_main -entire_library.cpp -.verify-helper/ diff --git a/tests/Makefile b/tests/Makefile deleted file mode 100644 index 0e663fd5..00000000 --- a/tests/Makefile +++ /dev/null @@ -1,59 +0,0 @@ -help: - @echo "command | explanation" - @echo "------------------------------------ | -----------" - @echo "make compile_gcc | compile all tests with -std=c++20 for warnings" - @echo " |" - @echo "make compile_clang | compile all tests with clang, -std=c++20 for warnings" - @echo " |" - @echo "make compile_commented_snippets | compile code in @code...@endcode comments" - @echo " |" - @echo "make grep_clangformat_cppcheck | various greps to catch certain things, clang-format, cppcheck" - @echo " |" - @echo "make do_format | format with clang-format" - @echo " |" - @echo "make clangtidy | runs clang-tidy (mainly to verify snake_case)" - @echo " |" - @echo "make build_pdf | build build_pdf.pdf from .tex file" - @echo " |" - @echo "make shellcheck_shfmt | runs shellcheck and shfmt" - @echo " |" - @echo "make update_main | 1) copies included files into file" - @echo " | 2) force pushes to main branch" - @echo " |" - @echo "make find_files_without_tests | print list of all .hpp files included by *no* .test.cpp files" - @echo " | - these files are not compiled nor linted as part of ci" - @echo " |" - @echo "make print_which_tests_havent_run | mainly to check if all tests have run" - -compile_gcc: - ./scripts/compile_gcc.sh - -compile_clang: - ./scripts/compile_clang.sh - -grep_clangformat_cppcheck: - ./scripts/grep_clangformat_cppcheck.sh - -do_format: - ./scripts/do_format.sh - -clangtidy: - ./scripts/clangtidy.sh - -find_files_without_tests: - ./scripts/find_files_without_tests.sh - -build_pdf: - ./scripts/build_pdf.sh - -shellcheck_shfmt: - ./scripts/shellcheck_shfmt.sh - -update_main: - ./scripts/update_main.sh - -print_which_tests_havent_run: - ./scripts/print_which_tests_havent_run.sh - -compile_commented_snippets: - ./scripts/compile_commented_snippets.sh diff --git a/tests/README.md b/tests/README.md deleted file mode 100644 index 7c32b04b..00000000 --- a/tests/README.md +++ /dev/null @@ -1,32 +0,0 @@ -## Makefile -to see commands: -``` -make help -``` - -## Run on each commit: -command | settings | notes | see ---- | --- | --- | --- -oj-verify | [config.toml](../.verify-helper/config.toml) |
  • Run from `programming_team_code/` to enable `config.toml` settings, else disabled.
  • [Check/Delete] [timestamps.remote.json](../.verify-helper/timestamps.remote.json) to [see which tests ran/re-run all tests].
|
  • https://online-judge-tools.github.io/verification-helper/document.html
  • https://online-judge-tools.github.io/verification-helper/installer.html
  • [Library Checker](https://judge.yosupo.jp/)
  • [Aizu Online Judge](https://onlinejudge.u-aizu.ac.jp/courses/list)
-g++ | [.config/.gcc_compile_flags](.config/.gcc_compile_flags) |
  • `-Wconversion`, `-Wsign-conversion` is out of scope
  • `-Werror` treats warnings as errors to make CI fail
|
  • https://codeforces.com/blog/entry/15547
  • https://codeforces.com/blog/entry/74032
  • https://codeforces.com/blog/entry/79024
-clang-format | [.config/.clang-format](.config/.clang-format) | running `make do_format` locally will format files | https://clang.llvm.org/docs/ClangFormat.html -cppcheck | [.config/.cppcheck_suppression_list](.config/.cppcheck_suppression_list), also see flags in cppcheck command in [scripts/foramt_lint.sh](scripts/foramt_lint.sh) | | https://cppcheck.sourceforge.io/ -clang-tidy | [.config/.clang-tidy](.config/.clang-tidy) | checks variables for snake_case | https://clang.llvm.org/extra/clang-tidy/checks/list.html -notebook-generator | see flags in command in [scripts/ptc.sh](scripts/ptc.sh) | creates ptc.pdf | https://github.com/pin3da/notebook-generator -shellcheck | see flags in [scripts/shellcheck_shfmt.sh](scripts/shellcheck_shfmt.sh) | linter for bash scripts | https://www.shellcheck.net/ -shfmt | see flags in [scripts/shellcheck_shfmt.sh](scripts/shellcheck_shfmt.sh) | formatter for bash scripts | https://github.com/mvdan/sh - -## Doxygen -Let's try to minimize the # of non-doxygen comments. - -Place this at the beginning of a file. - -``` -//! https://codeforces.com/blog/entry/69247 -//! @code -//! vector arr; -//! @endcode -//! @time O(n + q * log n) -//! @space O(n * \alpha(n)) -``` - diff --git a/tests/images/south_dakota_mines_logo.png b/tests/images/south_dakota_mines_logo.png deleted file mode 100644 index 2ead0c0da9b35e7cf2d1e7776b6b7ba759c5e991..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26216 zcmeGDhf`Bu)CCMjMJdu01t|ux(L+(`ML~*6?s?u9dDJYxKfu&P4*vz6Y)J>kDf~%UnmYKQ4aL=^*s&xn!3%b3%;o4uCR6! zIxz_ifd+ct1a9@lX7An%cl9*B&`D@Y!w_qHM;*TqujX!~hI%cZ2&<(@0evk{kui+2 zq?~f?o?dld#H(T&cMw=&=eYb?>5l%&-U?b!?bUi3kovoOGPjz3d#E5BhV!!ptmrF3s>1p! z(ZK(u&O=Xv!ZFv=KN`Eq4)j+REl2v+{@G*YV7D*{7Koi0f~JD*PG*f*od7Kiyz2Nk z)pMmI7mFDi) zu;I3f&n0FLsN!#c^r-)60sdim*ReqoxAx219eJ3$*?1cCiJn@74)~9rV}n6diYwMC zLmb;V5|IKbcYE~+^qHgm<0kthi!y~wOzdD;Tn4;tYwuevCrIv1;e%TGBebPJq5{166wWJYYB?Ss$4P&CMtwnlKZa87|`nHL*zW=cCLaAYun*jm>;`Ct0W?Q7srMv54g^d#K-72K@YB2? z_Itp?x6e~qrYm8Ajv`KtPtspMHyeOH97Q!U0#qWKg-#anB*?}LVDnq}FPlL^BM5XU z6M){$_*bHf4=B+Bw5I=s^aCKn-12BuFpHir5Gei;VDcoN%B5A>j~D*sqtu?AS1 zf$&-Z|34Ccv;h*g{zKw`N}}r@32`Q%M5^Gw5?a)ne)2bj9za+@ph2J)hkg88U;h)j zO`!4EsQ(8-n+ieyABYqx#NB^12X6upui5^EYLm*M{XY;aR0x585Is~DH~+(eOl9%< zKP(QYEL8pjp-Y9J`ws**>#`;2dzM=s2SH6=AsxSC@t&4i4|~6W){}=flld_57BT0n ze*uZL$}J9miHwt0(+@HWya)=j0>DB0#!<-{zS1d3Ks-lUGE1a^@A-2T7pzW#7*&C= z_GcM8`olunCx1G~=Fd;J6Sca9sznm~+rB`DyF%5_hNgyQhPIS753UdvQPYSN z5U7LN1HN!DiJG<(+c5{Fk;%gCk3eBZKu|!x#sQ(A6RX1hy#OR`0If{(X>q@Yn%~FL zKvm2|0R3(#&@e#HmM{E$w94DD;c7DtXn`8D&rK$Xx!5&HZu#i{LEWT2I_bp#7$fl_ zQEhq_(aCUo0pNK}O{x=C@B2OGR_8a01Y$|psn4z%su;8cG%_V?WQqo4!w&>C%;$Yn zvM}I05XNT9!0?vqXGMj(%NfN!9BG5XZcs&hxh$o>a%LzfC0rA1Q5G>()mnlAL}-L+ zyJ=Cr8oD(qZygw(6abX8qW^pXG|mQ;dV$;lN#owyCUt3kE4!pLdCfZD&M z>1gg=u??hJ%X7f96R!RJl`0GHk$!{&=iSii(et3Y^3=zFb^)#-u+cTrj`nK+-1C)- zAkZo`YK~GCj^=!uOD;YAm2QlHO)Ac}IaZ5gr7~1Iq>EWJjt6#dwNmAJx6+wxGF%~rZ6Ize5INO=z4$% zlpE!%V17{k{ucZDJL~e^4^M#e6D<%n+K=eN%3D8{#KT{__3$YI154+5+3x0hH-40{O>5a@Ca}D+tgnMIr!&H2Y+l zu=^+Y*R0DxFF*lgBlx#>2K};hVh3z*StULLnK4s);dLZ15LT9-`LK;&o&P1iJ|}0n z&kW#Fb>z{y)$cq0b!z(QkYIk1Q74q>2^;gj^paj;E3PT}KYdl)Da5OgdKCm>R|nkd zfpJ=ZIj<`DPZK4Y%yhCM@n`@Fd?iuoKWVBtLR{(}iA}1S$3OU20!6KL`~TQLQXRYWA6D{Ih}-`l7^x79|A7dnLa6?O`1+X& z!TJwETn2#Xm;MJ4PlecA{Lt^g-g40bG7^XYOe8Dg$e_ErQ@}J&Xf3r`(ocz9L2QHw z%yvv4P1A$EQpcfppF50t`}lh9jbvt&c=#PR^gpkdigq%yVFJZJ1TepB@I}Blwih15 z5o9%)ga9<8ugPs0ncQ*>6sAC}LI^t3+@TLGjH%qWccyi{sc8D|Kl5Z#zsFPfYJ zq795ZZ$l&81UaxO32jMjzoz$h#TAKXyiG22N;kZSw`T!qwM|Vc)@A`jn`2Sx!5HG+UA7G`C$9u>e?W_i1xuk9z&}IeLfMjQ3L+oBs z*AeI`WptE{HpRfU5MU_&+2pwBh;(zw8gy66;_(Ahd@C;r$R%Z{w0>gf5wV)_W?c3z z&ru+3kLd8$pKD4!WG}Hb)L-m@TZ6Bkfe%rEK|XJSj|Cgz=u1+)Q9jXMOkK923B6?r z%;6KCQ`X$GoiqM~FmjA9D!%m9+Jj9q4?8YYW&n&hoRBv!fWhh8dz{w<`(}%klmk=< z);RkK%AWLTcpx^ltmDldd4lALqa$p(uVSru0s1<11x6$A=^eWm(q(k#EIZDOQQxJm zW^>;(ngUxzgZ7-6aig}pEIz?~u(%Cx14@f(@LD!0EW1o~(kb3qacZW`c=8f%Z2m|A zEjv|Nb}R1%QOp>@Xa=(^T$0RExjZj77ea@aLjp6bmnN9=JDdn+%Rd&!$AZcR`$?w-XHiT-ijylaU0D%n ztg#G0DjTg_&P>{A$#-)7gT(qgwM4l1a4kuyPIga6CY&r?l9+=g!}Wz6_5#=&dPDqy zW{_pvj*;w97=PxTS&4vJeM7t_liX&QjPdexSvy%9WYq;}*}0#&%`bsvpCIN32{ws}dJ+EyQAbpUvcNJ8a+gXyvvT75 zS_Ne=UfeA0vPM(ijtwt#9>XvG0@j_XUZQIxGJF;Cd81k-)SOi@V$<>y(t-N)NlhlP z8j7J#TSx@4TrFV>*-w5}hHyByq+(CBC|l93hho%l8(Z%6>K?x1cpe<@uH2$Q=rph2 zb#t73EARXYw*jtJ1GyC)BN&ye=5p;4hDXF}W8YO^I;uHQxp2t7*K)|-WCfYCbN~mM z3GWd+gSADN(8{R#4YRT6-r&|Z(&jMc$nawU!zd(6Ya6Y7^D865^`q8ttJ|wNR-sa% zfn%{M&@HvuC*M_MG(1^k_76fbkl`=Oa?1$2dMAV@;oVCFR=buAP1Wc8^x#V+S~Ug} z#$pb3beQRz1y#+w#oej<*zDZY#-bXxLxl%x`Cxes^$$eV-l8&`%;PlM)s+wMeAVIM z^Fh4^2@g2Tmvc7EqQ7onD@d*gu;EBynQC{J^Nv2}eXAiA%+<{z1*Ad&#lx!gpnDpr zlIkDi>c*L=XC0|-=%QF}a$?@NS5aRG;o8eol#l2aE;k`%{bpDkCGZPuqp&+;ID&^Vp!Z*5S3KB0l{_av2(tx5D^uH1R@!i2hm8waHQJBGFH zN*dvqe$Xca$A&l*TVJm$OxVV#Cm2Y7XL%wOAHw*7=W5xJ8bpONsq%7- zD_8sgBTAsBcC)r;`qJ4gabCmHz84H)NG|XaEZQlzM81WgI1y>WCl-1n#09B&!B!sqIsgjlN0z8xUKTKUx%iOuCHXw_Ib~E+Lp&4h(qO|r$4AHK)!qmw zx2_4Fts?>AEzwxG*E?geTm)TvGPCv3ntS{@!4|$&6ZqJyoFG#DtXEjsy3y<`6IDc)(;MVX1@>J zE`uHl$IcwL2X9hRj&~`fl?XGpu@qcCQ}q$D?_p=ZZrA*T^Yq(@XPjO!Q*>odjt)N; z*Tkyi?Z1d{`tAA*t@q}3t-Qr6T0gos8O@Q4 zl>LM`cixc@p^OF1my*pvfQF|`Z;2s(dR&Z(OF2HQH(M;H8XS zVNL}HPY>>_eL0pnc(iq)5c-m|K+SD$ue}K6)opd@IMG}dai^8k*FS2O!Ki@`<=yHh z|F$Uze&7ov`8kG;)}C?>@5PM#WH)5x)9>Lxhj|hH8XRp{=J?yy^}Xu1IORORFF?X$kmKlU5#~7l=;~j z>D1UN;8{;B=}R-GpU|fvmX@gqxt`(RIgun?;sc(hY=~zuqLTdv&z+B+sPz}5_ZyV;>yrLL|nVmM! zPu78r_o~&V8#tH&`xB=<{WN0VR7_DxMbXn9=4na4#4xwLT#AwrRUPt95Z#t2k|31^ zSnA-O*F3()iQB`a6TR?lrbS=NgVq9SF{;Uxvxa_Vf#9Vmj@L_)4_4!b5i^3XFdNS( z)|jq|JoHpBuny4I!O@H&Xw*pJ1G(bJ;G>ax;bqj+)f-}IkzD$nbi zG^@x4bD@`7BlEKb=d7Nv41dkP*UmT78h`tK^Fr~_a4i^Tc!+r=GAMEXV~&ziS(OC) zPlhbPwNEYiY@edjZF3v3p`pH>{u8-R{pezNZ*Zw+UXRzl49$%EQd_m=YcO#T-B|HO zZlJ{(7sr1y;_I~f)N|EN&d;=b-xZinJc*6=>7k?#`Q z`>CCGbv^@x19M|Rm+P(uq>hB zSlYod`!6ASAE*1=j6k2rSC)Xf{b=e;2VO+C2f+K$) zD_Je*G@f9@77$Og`HpW(Lvgqa6o2itA!wNG!tliD2K^Ua(KKAfD`^v(`G z_iIB$M-C+Q==RK&r_NkK&Zi_hI-T0D3c)nK#4FxcfbX0tVST{|cW`8b3Ssk{zHjL2 zDJoOgEw5Hsc~rfE<7h}(=G`l#?-P866D?z{YG3|}j z^rNxa_XnakXwIaDHz>V$e#fh6b|y4{|FDg99bXvw(;6o^FSlvs(sBFJEO$0GcPg2j zr=e8X(^y8`H)8zh_w8O<*LL)HX!LH+n8baafWhsTJp|@A+JI*HD%?#B>3B_8S$|8; zZ8y4c7Q)nV5+p_M9Vyi|R%AQvQ-Ge~K20AT!`t^bM&`>57zVjcG`ojU>RY0ONMtY0Q~jX7M*kwu~zK!(3+%ld1&9V-6d zXI@9egw{7T43)p~b`JDHqH7>5r)W}U<>?f!ePCe0fyMk16|>Uaqq&|Bg`M4Ql1lMK3( zfIJ#=q696osd(=bdJMNLoJC-LXBx-gFv*%7c0FhjE^k#S;au9 zCCnXyacG7Sn2-_+W{UA_de#7|`@#c1aku^rWau+7_#AEu|6@GOa$k}uisXhAnio%=rHhL1J-Wvq=<`vHS6A~>;TW7%hgwl*K@05+%%6-8G;SL-lvq4J|0 zfWh8G9=PC4N@2i*-C)4_c5*_m~?T*L~qC(U!|MBOX(W)d*%Nfv`A0 zbNmGYF}W7QSYVYipoDGIE|;g~0H%N8*mV1M2Ii{E@NdayzQ0&)lI53M9ejs9nuFWh zc|fT#2_1q&-Oo)%%gIBxegNF`7k>V#)$l~|5Ir&!s|z%w(i8o;0&GH<`Q{(XUpxXsqb?6SY^`de+jj`r0!Pz;2Pud@5Ot7QJmjS<>gBY9 zz|SLSrh=30^y}LACo|zVL0-hl@)F3>Uhczn0T#VSE7WlwDQG2;p}El1HWo4-wd){ljpNJ8l1uoPD?bs zjJ8EB&m&6eygoj(n`>8njXZctT6?_G37&|0u_RKGrmeLeuhiekmFUNhrg86MSu?h>eeshZR ze%M|aJYUwk7_vK9{iDzNsJCM5;X^l>t~+}|Lm9X!`|*JDM~7VPgC%koN1|gnY-guR z5C6C^KabmQ{-w2yA7<`>ExO=T;A z#4p3R2DMR)x7S*?Zx5w3DrHFD=cygkXc*btXT{xz;-=ISExnqbu^CO=lyP0qjXk}} z+#ddb{W{IGtK@Fin8*?v6Qm<`J4dS>10UX{9G@*j?twv9>@P49H^ z0c?oyd_k=?r_JG=t6#&$ZLQt_xN4m-=t|Keme0D{o-qDTp53SVl`mao#t{w5CZ&Fw za-f^a_@b>+7Hd$`3X^;UL zQb+xd*szN5d?U0#9Nw4nj$>fzkNfx80AjGet6PHsvlAfgBHVn(X^YIlgHw`=!>lL5 z*1a$5jQO4loj%nkwtYIKyrxVsb5*#`VDs~!urR82CoNo*Ya{A)A2jvMObX5P#(F=Q z;eDdV;~rq+-MsGT(WP@4mMlGo{gld-XH2!s5L0y2{ZZRvw#JhA+qCl`X0?;2nLx8k zo~eH4qNIFF!wbX?@|JVqMH+NH<|(w2ysJb$jwxv-^^nF*FDDU8)wG%w72Q{uXZ~;j z$ADbZt;$Fcc@r3#E3mZuEH}ja&e@GSA$_Vn-5SnEz0CqfsmZ8|M_id#|GeMNB&wYN z&1#CLd*G}z=EENmo_h1wo2KZw;iA$#L~r5mndAH!cwJJ{`o-5H>AHnG^+@5`wlZ<@ zNQmT$(eCZ7Q|rJQhw<3q9-uQKUs_}tZ-@n2wQSu!2~r;z(!`C_Dn4jb8VDZUc|61B ziCCp^=Np|)Y-z}F#sE=UWLAh+P)niww7AQeFfdz_HIXot%ywa3Q0tsXMuRDfon##Q zlkr0F#Z&9o0W0dNKNR19!rZ+U;hQ12%;u-V$l&v#n>1KX0;C_0f%g=7xXm6BRop&DLhIsjg zplK}p9yhQs*Sw_XA2k&b4Tq_0A;K|;rE9?fY*Dwp%@+_$3K1#bgLc=s@$iHW-u z^4-oPK$ij}cPE(!@`W}BI#Ha@{5h!3w7DPauNqaX`72rX{6CGP?P2JfiNZAzwFY=l z!EUhnrH3vBG$6)&Vo_6*RJFXRU5Dzhps+?t^TYaw`z^9VzlC7|mQ$*}k$FtkJXGC zj=KIWrDF##b;q~8ZSJXGl{zQXTsxrt!D2FJ%pZ!wzZECPIeLj=w=vEfK3mx@@{h)6 zSd^DpO%_im-!5RosQ@B9=aX`PVE3y<7512ofDM}G?tp7`Oqe~R}| z+;~p*K-gB1mxP!>hs5!(yj2?^xBH*NQNl$1IiUnK{R8>7r={~vLxFL*OBQ8J4X>Og z-|amg6z1Nx6?!AZ53<(68TjIuJ%Gx@&!T-kq_d-wKHu z=zW=~ETYA(`bX|Obo*({hTi8IkZoprZSk<`w0hR55Fubw@NFR{V?Okw!>QJE8%4Z$ z7Qd*eX4C_ER9rXIj2|wm6aFr;pG|Vui$|hP9Sn&L6gFp2?9rf}_-Xv~NVoG)iQ_WQ z*t2%oYO9Z=_oq__!x>Q!%HY$)?{(~R<_WA3t(N;CVV3|y{lh#_hGji9*tzbA?n3C$ zx{4U&iHnXy8gxGfDAGS$$&b)@%Dv5W{T#4r>}Y!OG<|Ets7F((6#Gz}$?% zmd2{+E?oM2@Aw~MYh6=d0|wn1T)y2EbUCR5tAd!OB?p{9(eXVjsw~D1YqBxs2f;3M z4v!a4X816MJUzBq0+O8qBRQmbdwvy--=dzn$PaK`t~&CrE#Jrfi3ERxC5)wIzRIs` z4sO_9+HTPbKNmpz-fV1s6xf+bS_qKVO20aha^$329$A&id$sRoeGql@T$|5r8_ONa z`zE^)N8^c4@>GN6gSlASry&C%hNSiJqI)0VFBOU01pfHX7=EL^dAmla*OcQ0!TnT4IY z;tQk+vJ!fVI;o>yB5MSYx0V#z?i^dyYn@wi0|wr%H*cSe-fn#IAdym3cXJ7}W4i*s zd?=`Ynv4-gB&j;1TLI!8?+WT1kcv95j4mcwcMR@bSNWb?bWY+s+K1kCWX|9JVgStz zV1LY-?XUsC?Rz&5Z6%J++?kHZVU#mHU)!Ji@)&{aGN)r|RC9TK;tZnC)&TRjm{yhJ7%KH>J;lFrKT=J&4c3Se=ELEQ##c?nwhIpBsO>_X=~x z_y+1=^;q!KOGvR`GQm5Wf6`cWRrks@2Y;jF^|_9>mHDQ?)DjuZzl2iac_5x%Ns5++ zWyy)zDb=re9i`Mrk8|3$V3G*$_Ob1ezfqV?`rxc%Sf4MsYDYkUaY?d=60YW7z(7b6 zM9+(L28X}{o0s-kWxWdg(hQ?ZhxOKr?<*>7cd!vn@m+^LIB*7^ksO2WkzwyMfBF9M z+~RK?(Y(=+);e2jtLRW(qN0(?tos&8;DBhal*<=LXLaL~uTw4~O=eWXQxi(nL?RX+ zwbq0_3NjkYD&*od4uH0M!8_~>mA)^iPQS@2Q}m5;{OwC0j%j$$%OpObM2l=kLDUY5 zOPbQ*o{nXx!NlTkEEiL(jx8F?=EhlB9?R88vr95{IiedvRL9DRhlKFcNip=E25Dk@ zb$Tu{XkI`i{PL2<0sXP2_=2I4%ay zlP#Io^&~n!%*@`{^bsa$*nZP0QUirBlVRH}Bs5t7|LT(QqtZ}O81{Do*8XDePT9(v zoO1!{Vrc4VR|BF#wP&4V`@vVONB)UNiS|;l#xYo&5x3&w2iC*3?bB06{Ex*?i-tQT3@)CJDa4w0$nd!BJd*PE73toqO{`ob|IVidpy}&=7XcSkTQX zc?HP?G$-*{*q#d`u|aN!!!yz#c)8Fjufus+#h6OZf&4v%z_P{bFhcEf{AZ4xc>ccNJ6+}T{c9n0+g+Oti=f~J?dFGGA0`MdEgzh_ zF5-M~YBu5`fnSi_xjAv4tSa#NkLDX?S;^tsPjprhF#Vc-SgI` zQ}F6C(cEKAN%Dn}vmevlc)MK6jk)wZ>4v7`gRD-HYZycWU1j($>Bw$&q?MsQvtw@w zD%emQfWhT9EsrFygC=ZyXBa}pGb^6f!+Ln>588Z%_V`7d2$lJCPbN66@d!$CH;-u8 zX@OCGEbfZ?>~b+A<-9h{RAwCYe45kGs{F~%Z?Bit{WE`76oY7ZA&~kP$G=Wb%PW}M z`S~Z8gURA0GF)^UVsH`$~U7>BaJQHxUYAiFZ`Oz)37>U?zn-4}qw0?GC>4U_g+778o#{xMW>@ z8-BXGg>KFf>olm4A`X-L)?-$HRZjgKKFShY^C%mbdUrFe58M|DnR`Q_0AtvasD_k_ zeZZHT*V@^Zy=|!uxw24D;>~IsU4N@1R~KNCadu8My_M-u?|PdXx{a{QM9FvRbbZ(6 zP*2L^dGB+s7hzQxI?(=sS$?HMv%A#Ezo`3$mQlTOtNX!x@x~RY;UUFf$_<5}6$db- z>vtucr&Uz!bRFl8S0J0gGuzvde3jt zfS1$D7A-O%9$fL98|C&5y-%vkCC~9u1QI=a$GW5YKhBi&Mf(A31#piAzcEd;$k!k? zp@4kVQk`+N8#G5wPjoe=BG^jnyqZ}Y!WEbM(jhZARCPya^FOJdv}0gd!Nxs zOk<^`?&*>-Gi-FN8+r9@Q-p)V>FB`aI=+&iB>k~pxv%8MPi2&o8kuVrJ#kG#r%J;-n@rI_pyxQk%;1ac^AU<#0S)~KqlRO z-!r{rWFd4KR?{rT6mneRq%ZZ@Q;dnQ<{szae9rqN``pNH2PaceWK*#o zn1!piwwWc-Aknd+)ZUp;wvs$78=|zPum~fv+JA2;S(c^vwT=TX9Dz%&;R?cp+1@*(C3V&eb(vhYU`i( zG0KO#9l}kwcoXz9GZjPimCx{o?ypD3<&ro+EqUEH;TFrSK=9FGH*Xm>gjJH2A#UUK zY6oC32slD_kk1<`j2B-b80(T=+-(X}3OQk|o5Nqbuy9rB#`4%#~pKa%J?KLoWd)plHl;@aUSw;e{awR;J<5fi)-z>=LLR)LD%yGtlk&)y}SE6C%ne5 z!t?hw;7|;TIXEuEHw$ZZf<0eKZE#Ch`RMZtP-=qN$6(x=9GO+VwytTaRTX$&XBqlS zoNT1pnf409pUL&MFyQmik7oA>?(U}XgtfIu{fMszsw-6)iFeOMrIqG6O8!v(8gaWu zRw3dOGGc4L4o*3?^ICQ1jH(=NYBtIEbS;4q#Q@AZ$>j0$t48UOp0ffImmteL>RvqP zVhwzdk;w_QdW{p}uwtq13b`pep6J<-q4`v4MrrGa3#y$&l&JEsPu}nM%MtnJ1Q*t! z$b8$I4{x5u2fg4L28r~)=Z1hh^`Ch<`ik6tQqa1-U%l<2_(cJz#S@?~ z7m;75L6~dxFAAs5eo2RJUX}E*c0C6IE$9G8iO>EjKYwWF#RMTvLQRXgh6xdY&p-Nt zK#s19OdKGy0<}at7sYOej%)>2;p4-G?Wt$6do)>!q3gqXn^_?Tw$4XAK+EBY&L41? zTXkPqVX-|wQP)s1u?1AipxafYSR?i6=uZ17AM@3g+G(Yz%!(!#jfUwmyH?zAR9_3z zbnC$?hpko2l9Y1MmVz1OW9pi}b*Ue(e9BeI!o5=3b>qYOh_@~K!9~~~OB87Iw04V% zo6NCk7EJlrw0qrIH|y{UPvWTWu~F0Zs-lhrjwgI3(Y|>+`4DaC!09&S1;%1h^N2S# z0yS#5(YXDGTku0qo^4(4CKC!lXuAnENgm_Ibnb6e{;ZMAb7Lw?2wqmwi*Ukwj!v5j zZtt*XHOX~h;eC^SEYAa#qzYfmy8q#tG@Dvo;}pdF(AjCZ2@mXEG8-n|deED=CYz6! z?<#8|qVKe>Ll-P_87<-V!{nV}&$^XEdyJ?3VDJ~L=WM3O#^91?w~Q6s>86zQ$fDw) zjX0+BezNa1h#3s^wXcU71WitPK_;4fzXc5H$xjR6AEC_ukm1Q~o`?xS@-knaPE~ETFisn+z z?RKDHxwGrE?|1fpXKM2SG&?Y8cjMCVX* z|6^Cnsq!VlQ~$Qr(!<~TBzWX#Xc3M)n5fKiG4#U3+;&jicHB=3-ofv+D~)29KBc&e z2ck-pw6(DmHD!78snn7eXNf zk1A&f#fm2Uv}o7`Jn0+WuuXGvU=;1^fa?|yANru$Oq6!~qCLFkw(Y9v*9qQt zwSETU{A7F;bhG!Cf?xqRg9&0MFDXaJ{uLzx{Tb70>k zsD-Zl(xKaFIW9&W80++3KUf`0aOg5!*}Ys_RdEPAaG!+U-_{*Q5!5k~<#ao3b$nlN zX1rr_Ty)b-6Pf%@t}d=Cfdn6jb1^X0k5cnr(&Z&aKCzD5R1i86Xg)^S^BHC)iDAN} z|LARRRH@wCA}4UD?@b=DJ^JBWZEd2};RB5>cSu_gOmm_n_Mk>9RpL`zBXq#sO8E zi;ld}p7z*7!%U(ntoIGtzX9_UiS8`cQx6(MR4Ak}6Y%JJ^&!6F)A*L!{Rt^bAvs7s zoA|$H0ZySPUIJN}Lug!W(cI%S`=N$(M#2V;eeSV0ckT1H5rLbbK8(CAjjJP5+9d`o zd%74;=?987-baZ+F4cR>0f+APs<}CXZY$eX%+ZH_lk*cyJH;bAWVGy_6UJ%tUYgB~ zAj0wLZbqD&RvFunt;w7{Ze;y{BycC{L5bxa;?&lnXDTuX} z=jH=edo|87Z+{8&P1~@^EKaCZ^25Es4$BGxz9fjwaoY)9c2R>3cEV z_?@aO-5YKGW;I(idi3a~AQwU=G3~kxOVOOOCGG13{bG+wkLeYIy}&wc-B`Wk7HFV- zU?Q#K!3BKNm-AtnQBqE_KOc?R^TR zZwp|C;}Wn${Z}iau9hxFWiQLfc`aINSL~m@M(7` z3Tvab43^(@zuXpHe(W3k)pDzx5N%e$D&W)Xa}M)F3QW4cg|?QDN-2)c?3SOX%l58+ z$obxGb-{|bN#E(wIGeCjX}0#!E3`Uewz9=GYw6xyb3ta^)}oi_l*{k^AnAkO4>Vjm zT9NZC#XZL7xLwF!fky3c8eKybf!@=X=`=Fi(SLA z!Nv{did^E$N-;)~N+q?0wXR^J-Z%RdV=NR;qPoA#h&HyHBL0Qsyy9y&H*3S4 zgw=&RU6H~rcDHcukWysrl}hU7*m@@j->WCK zRyD5fTgmP>OY!dIqx~(B%Fc4qEi~+$>D(MmNhI#F#B4QLPWe`Yh64DF#H-}*p{<3| z5B?mKk>X~fHcASuwgq^i_Zymcdl97_DS=#XDky&EUd?DUS>?PVnH={PJ8j7sgqmjr zZtd@OtOeje$M>>VMp_>2RKX*CPXqhp!X zp_s8;eJt$yoS-%Ka=u<0++W_0i`L%y#kBKNdkZ}qRk)5$;KZgWxrT?Mt8Z?t6kv%h zLwnMX6`sC3bh9k1>zsE)*7BLOQVOHDuJt}=QMdQ+nH~utIyre)MWwqa2W3gIoUkVt zY)JL?0;?WoMDCHKyb)FSi2UR5CGDrP2U7TNO$;a+d!~<7nyR-xvW^Z5VRmd#v~x}52{J!^P-g`^kE)SMWHSIp8h zvNsf!kPL%S{8jQWUIgNt({&9(U19K%`Iqb}r`cQV@xgTDubm0A-j~2`=NgVo@X)k; z*9x~4?~Wi#C#-oNFqo6-Sv-$I4EL^&)*Q(|i8yeY>AQ_mM>*-(En;&(P$l>#7@aiw zWpRL9zH1+fWap46*2?Cclz!KDkcWRN4JQ1~-kr4?_l-G{@;KlkeZbe4!Yf-s-dK4p zytJH5Af?T#Ph_VnjOMYNq2F{yuf&DI6CVxP-AH^v~XcZY)1+N1miqWjr zDX#;mF}+OZq7+#4>6dm}?UneWqQ&M!$42W(>8BIVt-iaq*EBnwDx6y6v)};U8WgK& z&}*Ve5vwCS zMvWq7C-cf!g@spft7abu>Ra2L2zZ6WVPW5;RQJBx>Q7H^SMqWpCub6gJ3PYV2&uP0iGFu_LcTeDR5B5aDMuHc{A$?ra} z?x+%C8#O6~#0Tou0}~AVZH2><@x+6lFt}p8)Sam!oZDpiw9n$j^G)wUMs2x!Rr_A? z1h+b?@!yUGwkRubE%6uW-Y}Jo6SAUDwzw3pu)x!5^1ag9v(ZmO8KJW2R#~&EKNwbu`1!NO!9UjyiaQv2(<1 z4b@Ms%V?P1*ScZk^6BK{o1Gu!q=c(Gr0$A`g9$Cp&-K)6XR{IMQ^0V^VK(GdLm2I3f?i^r zciw0Kw@UEb&+)WVj42cS=j>8Ez8o~TVyAXj4kn9~#`SooE(HzM+TOXLi_&R^yFrE$ z+wNh=65H~Ioco{9CR<--5`%f2`V^LBpso4^(j!Pp?Vj4QpY+tR$|3To+@(13Y+#Y8 z2?kk8;xxu1$QIEhFmMEXTCrN5fB2ScP^9jlBNUNs#G(Tvh}(GMKTjxLm^AAWi573O>VT7V+v*3T)ok+fSVh0d zY<|rb$}a-#6XEnE-!U<~OxKZ4!iY=x&cp|U7@V53@6@@T@Wig&Woz=PO#) zH!AfaFe_owcRISuM-ri9$O4)o{j%quP`29{vEumbL=MZxBfPLHFFakot@1Ucb9>9f zKir${*bA&#DmA0TXDmhGg9@i!nulD`ex9UHBfFj}bH70h$*||a-Dy#MKW)k{rFonMz3&UdN;wT!1&%fJs zI7zsk)+X;>`@!wCEhp=NUTkP!Op8pV;5dLA@~>8*;siHf7Yu4(CSfJZ`%U zlPo8LSb5fF#6s-cjqT%Yex|RHSuvkl)*E7FX_xlHpxepMvzRRxI-;Zs_ zHe$aQ`}<#MnAdIR_FeJE!>hKvE@Kaqw(W?p68pYO>uveIWl$Td{|y~n?pkifj(6;P ze9=&^e4nUZ*=5R=4?WDO8@n&fRcw)-*txMu?A(i;qn+&3CJD*|&TC(7_!|;k&!8x|~9iBMVul3kGeP0Rtu3pxxEuOZ6*!hv0*mrx? zsyWC4Fk+*I;hn9| zorVVx`&$fQja@%o>H}TMlGyQ!)z_QEes&3q@>Hd4oA;(6TiJDZdaT~E>3F9+*Vpc~ z9fpf{4J~8G?zr#KF1e`8w_COAR1<3pdfjs_wYGI|+3<93+Y`3_bNd~az^_}o05TK1 z7~5`h?DyJST(=!6hi!jvZ96-j*s*;vhFGE3#oB(ViM`);8)C=uz8l}#=QlK3`uhBs zjjP~|Xy|h^R@QX6#->ndy^b`P9)`sO*3Q)gVt+HY{S-S7#=hrtxjtj%#C>A>Ao+1> z2*G0e>|PD`k;}2`vK?(6 z;>Y%V*L|^e>=Mk0+$8pQlW%{+=TybYk}liP<#%Ik@~zt14LwJPeu$8RR`ryT_EVSR z9bJTJ?FYXWJJ;Km*RlN^`}_Cl9FR42q6uw?rS!avJ@nXiuH@LLjo7)F#4bH9V;94= z8y4#w7yEl{+)iM%v)IL$va-}B=!q2?y$LtPwc(W=KQEV{Du-|?WkWf3zE-Ub69P&YI?7gAOiCoI=F5A&&pRMit z1P^~>zrXf5iNyYH?DPBH{?z4v>$0R_k)CbWm58;;m)6@d#WgUbF4;;fl#11(tLo>` zr^NNjO%J)6q&i1qy*A6t;@{7nzqso00ZbMe7U|h`s)^XS)LU@*=e1Xw)h~vvdpMOR z_Os_N>dW_kS+yuZg>MRlOzg(?_Sy3nYcFo0ui=kVx01g^x+f%9k2U!=N$ z>^fK3qq1OMdv!ap^CI^B?vradFm$6Rwm(ypv03-}D(AP^u=v;0a0C7jDrRrnR<;@% z069K5tM>qWkoX#HW9a=9t7!Id&xn1_X@@8Equ%2~1^rRjjt33LKi12%i=pr3vG3G% z8{SW_cWmrj>oP=c*WX+F{Go$`o~Dl2*$CTFzkX9Jco{o(YsWZ|wQIQRJ}l3@NW1L5 z?O!|RyR>V|?-1FBU0g)!L1&RRd|hlEh8*XNCuqo4zN~w(sT^&XZtTMr=WYF={WlrZ zE0fe6!gcp;Q53(fz4_aH{Xfs1zxY&XL(DOMIFEe)(@lYPIG5_>O|K&$w+b#Bx)kqv z!p2V0vrOlu8^YKX+#D)vT~F+#2A69UrN|AX7Y$FH_A@x2bMJLMlvp{t2<6JA&z`?1 z%Y>H=-}hm-DgXNH`HMGUak5>@!B`_^3d2NmxJE~RxG-R4bCB{lg;4Q44i(g~&XG9; zms1og&kiD?R$pSD&%DI0wJEu8`|EAvQG3jX0OnKe8s7L2tzjL8#r3vK6y6W5O;8(Dzn*0W&cLwE@AKCHO=y7F&| zy;I1WkrNX(f%OKKA{HEM3RmjyeVW)@k4qN|s-xLT!y-(rr%#%ra$l4qxI!D^btD+B zI;aGgbLcb>dtebA86D20`ji9j`aYMo87dy#;Dk;i3Gdw8)*A;u{rJP)%)c`O8u@&B z9eTQvp+s{DPfqyGr&|t%EnhF^w>p|Zg*{ejcpt)ChVi$|dpci58ZSktpqCZbtNX5l z&|9sN;IqptheQ~ zybVK`tD3TvSb!Z1y0{#pWU!H1>=YvpGEg13{Oul zLIvxu8-{?CmG?G1FSFXedP+3ga)rcM3xQ)Sv@8RwvSE9^fOBZAoLuM>3$bv0$ZJGd zHGfk-#=CBRtZW@aEI^2bRqS#HkXlTStAsAj_ zS@|*2Bk)l}Skv`$>W(sAv?+FOx9Md!<#HufPV$>k%d=RoFnUp6z$HcR=^@XZwemfT zm}p(@w(LanK4s7IhOlX84U6=A)z+?zMyYx?vFpziKfie!xu+dh1MG%Hm|_8UlX?&N z#f`XF^}>Ai{Ka_~ksMnL^nBvse{7MS`neRFa$u02ruX%@jHSk1H!Sx1v5NGZ#BQXE zYDhMOv|abXQg2wXO2v@9Me4n#AL_}JjXoX_%&u}$RzAYh({I<_TwkHF`g@-vPg--_ zKlS+s_ZK*aXRMs;pgUGUGn4h7-$L zb~)Z_*W5h|x6D=;$+cPxw7%c#*V&{rEYef&!5cf52AN`_F}U0?>1M2wzO{xf%?C4I zq-X77j}$0NP+zUDYh!w;LzH6`sUgp&u|JLh4!GGRP zwt6N;rK*15_jgsW>8W8%hsoTe+aF0;>?|0jOU48XLb}i7kEKmlncBg?CAq1B2t_RH zci8m~1t#oMsO{;)+99gnp^S%8OQutx9Q>@uql#clN|N=XNDGYUUPfRGT{8uzgxRAq zm}5UQCxyu3y)Yu7Zn=S%l)Fo*^{ zu(4)wV`}}$>~4;r3>y>c0s1tlwrw6lO>)*}vGOqlxrz;3GQXh{eTGHYy|NavJNXH; z{YeWyj_Cw8wo=0U;5IVs2X^kN0Pbu@L7;A2Tl_Y%+gMpYv-Zq^Kkj0)yrm}` z%7RU#zjsYfzYdJ`Bh-waEV&kEnvf}R$=BbnN)~vSKa~X>&?1Yl{i? zt0_$+LrO2uHbG$Erf#s-BzS0?rRL)CWMHr{@UCg!z!__7G&jT5u?c#oa$I2$t8Shg2 zRAVBr*ppM1SfDgV;F2XNG2KzQz>^XhxC|%|7N}?g`@MrzLU0a0?tSq0M6$7gGr>C( zSQw$QV14|i?sFh$c~4eGCk2!QGazPCejhoWE^ty>9oEDdvJ-Wt#7i;XF##=2R@wtc zl}$t+>$WfCkvZ~BnPEcXzLNGa^kCH32{^yo8ns%O9y@6osDj*O*=CAhn!oy9;2zoi zmtxv#Y%*FR3!j?UPSd9~{+@kq$3&xS5_`P{`nVQ>?eixM?5`O&pY}c&A%U@BY}kE6 zJ^5kpgUmobv4zW6T{36CXC_~fnPX<`)|wbs=&9P*hRmqmT?0yFptjC}PGB-{nR_x@ zvWR|PcP!xVm|lDc=t~9*pq}79YWV|L(9N~&*>9sW66ol1L7C}>cXj6u(9gG1p9cnD z{m8P3ncP%TqOU)V)vq)<0Lc|GbJrJvxp>aNCDTh6sTUdphxE)zRydRAZ2ao~aNtm$ zrUhIpF~7H1uAV$a{k=|K17k5ZE@3SEPJe?f)8CKKXRBTi>SM>?*xz_RrZzBJ7)ieu zPO2 zNu@&v`}Lj#cTXJIyY+P$91FWm%j)s>0Y@YSbNseH4nDxiysRmsZvC>c$taVB!UW@Y&6HTP#-}Vb5JmAOE#juI?~4*|lCc*E)0Lua-V;$OEw%pCA)W z^ums`>Dag+HteVeJsHD2^q!0HujZ_*lkp*$Z&m!zXDldf+Tzc}a`oWY^U&CJ$8Xbd z5zy1UZd@qeJGOwGiU6ibdfpP7x&`MtL)ghgADJDduP$o zm!SfS^0gPX;16Gt0Pah)<0adc>tw>U-rZ8ct#@y%&-U&w7nlcb$uob3Ulkg2r|1{g z#vXzlN(RQFZ{vMGb<1R;0Zd;Pj$dhG8LSV7>Q}x*$um2Lcx3j@;>hlrw8I^H_Eea@ zTP#=pxc?_{h+VtP{#UT}bfm94w#+u?WG`?TP}aEy6kB1MXPm_K3KWW6-SdN&zd^Z} zRi{IIe3x0E4PGIwedn!KoD#)gcuO3GsWA_<q2)p@^!?#BdHpwC#Q{VO|Wa*SQ{1G86!;}`CIAd<9wNI$wV z;EyM!6D%9Dl`uD^EYK}+z8A) z@5sGb9(t(LXXO3!-n-#37wWT+-k37C0UK{=wWv_Tul#@@=H7Qlz&~?{;%|HBkHexw zb_>TB$jzGAYP(3ze3qz1J@oa4=vGVT2NSWa;(Lek6wQ=ZAcvAdJIVrc8=a zfHs&1(#;DfLU(H^Ggfair(%x+XFRb(D6#_?{+-CN=o$3Q>yo=Tab%1cr5(mrtV7GP zE!(d2HsyqDRcHF7fIezu*l(_{=6%UtUC`cVq_o3iaM~cdp2C=5Wnl&Z+M-M^`10cO zT~6>jqu2Wh^<=012r|k;e*&X}~nC*)W9 z<1i$TIk6Kt0&7!Q{)2UENPG&ZE>1l>^3fAgbDX)3mNVG zbl0)s*oc_%WcvH{&Gl8|OvO|<^QyNIdTodC8XdH>z#oXY2iFHleX@Ayke&jkOLv|% zRkUj>I}fy(ZKL!_G85|4WZAU`_t$2Sd?mlvStr0jyhWWYzup65i|2g|)j!M`LjV8;_DMuRRF5bj<#V!j zi<$6$MM2p$(*0TePs@W-yDo*&jU6}a+1s=wJJB=h`QUumqU3YPQK&r&D57VlU8A4F zX3=81*Bpxvp{*U3jlF(D$BFepN@qD%$0X~^hSx2{29}{`W+gSqw$LrNi6-Gpk0-Y$ z)_KAu{z4i-I-IDtIWO?&bW9C)w)gz>WtZ1udLv@+Xj!UW-G>U)9j$3j*X^z zlGV=ZJo5+T3GN-c%kFtoGLhW_I_bSEQsCL2tLh8aytb9m3+VE)Yi}Hxsk&}z znTplTsqe%8y*4)D0&PF9(2rZE4qV#>mSpofBsHvS$nnnJKXh9%9}?TfZ)>!nl}lRF zF$1?`dugw=1sk;0&XIHfo^A4krEXg$ksF8Dxnb)2DBx>n_rX2Ca#kU8mZA8S-+}DS zVDH>HM97CP63m}l>pUC0baY*)JitSnq!E;wU^TUSNg(^>+qZ9fZ;F1wM8};BJomMV z*$3Y92cI1Qx<9?Qe?Q>EouY6K;<0?`a+SnC-BJBB4BUPx>l1U@p6^WFTweuir8(dG z>NziFb&few*%-jscXioU66hENQLgb-b@SgzQq+PehVO_zJ`^c;K;LJS+s<(TeZ@t4l{RpUl< z&0@JSg0PNV?ZfxkvHvo}Li{MEe0+0#RT^Xr0fTi35kDsAdCiCS!s&tPKVzFG!5o59X z;Dw_*m`=JFLS0-1F2ztd@#^BSRYHad#>{1ig{b5=*QsvECQvk92qA#NiY#Sh5t6heq5+-1;5(J13m^uaL<=nSicEG4;&4G#Cw zwpAerrrzsfx%xLsD4coO%yrnIHfH5kB_V_mLWrqybA2_#w(U85F1Ag(j4f(oMju=n zU<*G^^Cclf6SmkMKB(ldU%q|&w)dtGU4ql}Y;A=yObwT3Wqt|K95~g-c!l@^8B^&6 zA%qY@h=$;R3tPwXMaj3H;d8~FMt+RBllAM4-LnF8XsHl_f!K@D9acY?e@%SFyo~M` e-aN1>& adj) { - vector decomp_size(sz(adj), -1); - vector naive_par_decomp(sz(adj), -1); - centroid(adj, - [&](const vector>& cd_adj, int cent, - int par_cent) -> void { - assert(naive_par_decomp[cent] == par_cent); - assert(decomp_size[cent] == -1); - auto dfs = [&](auto&& self, int u, int p) -> int { - naive_par_decomp[u] = cent; - int sub_size = 1; - for (int v : cd_adj[u]) - if (v != p) sub_size += self(self, v, u); - return sub_size; - }; - decomp_size[cent] = dfs(dfs, cent, -1); - if (par_cent != -1) - assert(1 <= decomp_size[cent] && - 2 * decomp_size[cent] <= decomp_size[par_cent]); - for (int u : cd_adj[cent]) { - int sz_subtree = dfs(dfs, u, cent); - assert(1 <= sz_subtree && - 2 * sz_subtree <= decomp_size[cent]); - } - }); - rep(i, 0, sz(adj)) assert(decomp_size[i] >= 1); -} diff --git a/tests/library_checker_aizu_tests/compress_tree_asserts.hpp b/tests/library_checker_aizu_tests/compress_tree_asserts.hpp deleted file mode 100644 index 935ade3e..00000000 --- a/tests/library_checker_aizu_tests/compress_tree_asserts.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once -#define RMQ KACTL_RMQ -#define LCA KACTL_LCA -#include "../../kactl/content/graph/CompressTree.h" -#undef RMQ -#undef LCA -#include "../../library/contest/random.hpp" -void compress_tree_asserts(vector> adj, - LCA& lc_rm) { - int n = sz(adj); - vector used(n); - KACTL_LCA kactl_lca(adj); - { - auto [parent, to_node] = lc_rm.compress_tree({}); - assert(empty(parent) && empty(to_node)); - } - for (int tests = 0; tests < 10; tests++) { - vector subset; - { - int subset_size = rnd(1, min(n, 10)); - while (subset_size--) { - int u = rnd(0, n - 1); - if (!used[u]) { - used[u] = 1; - subset.push_back(u); - } - } - } - auto kactl_res = compressTree(kactl_lca, subset); - auto [lc_rm_parent, lc_rm_to_node] = - lc_rm.compress_tree(subset); - assert(sz(lc_rm_parent) == sz(kactl_res)); - for (int i = 0; i < sz(lc_rm_parent); i++) { - assert(lc_rm_to_node[i] == kactl_res[i].second); - assert(lc_rm_parent[i] < i); - if (i > 0) - assert(lc_rm_parent[i] == kactl_res[i].first); - else assert(lc_rm_parent[i] == -1); - } - for (int u : subset) used[u] = 0; - } -} diff --git a/tests/library_checker_aizu_tests/convolution/gcd_convolution.test.cpp b/tests/library_checker_aizu_tests/convolution/gcd_convolution.test.cpp deleted file mode 100644 index ce577b11..00000000 --- a/tests/library_checker_aizu_tests/convolution/gcd_convolution.test.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/gcd_convolution" -#include "../template.hpp" -#include "../../../library/convolution/gcd_convolution.hpp" -istream& operator>>(istream& is, vector& v) { - for (int i = 1; i < sz(v); i++) is >> v[i]; - return is; -} -int main() { - cin.tie(0)->sync_with_stdio(0); - int n; - cin >> n; - vector a(n + 1), b(n + 1); - cin >> a >> b; - auto c = gcd_convolution(a, b); - for (int i = 1; i <= n; i++) cout << c[i] << ' '; - cout << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/convolution/lcm_convolution.test.cpp b/tests/library_checker_aizu_tests/convolution/lcm_convolution.test.cpp deleted file mode 100644 index ffa94340..00000000 --- a/tests/library_checker_aizu_tests/convolution/lcm_convolution.test.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/lcm_convolution" -#include "../template.hpp" -#include "../../../library/convolution/lcm_convolution.hpp" -istream& operator>>(istream& is, vector& v) { - for (int i = 1; i < sz(v); i++) is >> v[i]; - return is; -} -int main() { - cin.tie(0)->sync_with_stdio(0); - int n; - cin >> n; - vector a(n + 1), b(n + 1); - cin >> a >> b; - auto c = lcm_convolution(a, b); - for (int i = 1; i <= n; i++) cout << c[i] << ' '; - cout << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/convolution/min_plus_convolution.test.cpp b/tests/library_checker_aizu_tests/convolution/min_plus_convolution.test.cpp deleted file mode 100644 index 3212cc1f..00000000 --- a/tests/library_checker_aizu_tests/convolution/min_plus_convolution.test.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/min_plus_convolution_convex_arbitrary" -#include "../template.hpp" -#include "../../../library/convolution/min_plus_convolution_convex_and_arbitrary.hpp" -istream& operator>>(istream& is, vector& v) { - for (int& e : v) is >> e; - return is; -} -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, m; - cin >> n >> m; - vector convex(n), arbitrary(m); - cin >> convex >> arbitrary; - auto res = min_plus(convex, arbitrary); - for (int r : res) cout << r << ' '; - cout << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/binary_search_example.test.cpp b/tests/library_checker_aizu_tests/data_structures/binary_search_example.test.cpp deleted file mode 100644 index c162264e..00000000 --- a/tests/library_checker_aizu_tests/data_structures/binary_search_example.test.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/problems/DSL_3_A" -#include "../template.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - { - ll lo = -5, hi = 5; -#include "../../../library/contest/binary_search.hpp" - assert(res == 0); - } - int n, s; - cin >> n >> s; - vector a(n); - for (int i = 0; i < n; i++) cin >> a[i]; - vector pref_sum(a); - for (int i = 1; i < n; i++) - pref_sum[i] += pref_sum[i - 1]; - auto sum = [&](int l, int r) -> int { //[l,r] - int res = pref_sum[r]; - if (l) res -= pref_sum[l - 1]; - return res; - }; - if (sum(0, n - 1) < s) { - cout << 0 << '\n'; - return 0; - } - int res = n; - for (int i = 0; i < n; i++) { - if (sum(i, n - 1) < s) break; - int curr = *ranges::partition_point(views::iota(i, n), - [&](int x) -> bool { return sum(i, x) < s; }); - res = min(res, curr - i + 1); - } - cout << res << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/binary_trie.test.cpp b/tests/library_checker_aizu_tests/data_structures/binary_trie.test.cpp deleted file mode 100644 index de34b555..00000000 --- a/tests/library_checker_aizu_tests/data_structures/binary_trie.test.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/set_xor_min" -#include "../template.hpp" -#include "../../../library/data_structures/binary_trie.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int q; - cin >> q; - { - binary_trie bt; - bt.update(61238612412983LL, 5); - assert( - bt.walk(54289162783746217LL) == 61238612412983LL); - } - binary_trie bt; - bt.update(0, 0); - while (q--) { - int type, x; - cin >> type >> x; - if (type == 0) { - if ( - bt.t[bt.t[0].next[0]].siz == 0 || bt.walk(x) != x) - bt.update(x, 1); - } else if (type == 1) { - if (bt.t[bt.t[0].next[0]].siz > 0 && bt.walk(x) == x) - bt.update(x, -1); - } else { - assert(type == 2); - int val = bt.walk(x); - cout << (val ^ x) << '\n'; - } - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/bit.test.cpp b/tests/library_checker_aizu_tests/data_structures/bit.test.cpp deleted file mode 100644 index 3c328043..00000000 --- a/tests/library_checker_aizu_tests/data_structures/bit.test.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/point_add_range_sum" -#include "../template.hpp" -#include "../../../library/contest/random.hpp" -#include "../../../library/data_structures/bit_uncommon/rupq.hpp" -#include "../../../library/data_structures/bit_uncommon/rurq.hpp" -#include "../../../library/data_structures/lazy_seg_tree.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vector arr(n); - vector arr_int(n); - for (int i = 0; i < n; i++) { - cin >> arr[i]; - arr_int[i] = int(arr[i]); - } - BIT bit(arr); - seg_tree st(arr_int); - bit_rurq bit_rr(arr); - vector suf_sum(n); - partial_sum(rbegin(arr), rend(arr), rbegin(suf_sum)); - bit_rupq bit_i(suf_sum); - for (int i = 0; i < n; i++) { - assert(arr[i] == bit.query(i, i + 1)); - assert(bit_i.get_index(i) == bit.query(i, n)); - assert(bit_i.get_index(i) == suf_sum[i]); - } - while (q--) { - int type; - cin >> type; - if (type == 0) { - int p, x; - cin >> p >> x; - bit.update(p, x); - st.update(p, p + 1, x); - bit_rr.update(p, p + 1, x); - bit_i.update(0, p + 1, x); - } else { - int l, r; - cin >> l >> r; - ll res = bit.query(l, r); - { - ll bit_i_result = bit_i.get_index(l); - if (r < n) bit_i_result -= bit_i.get_index(r); - assert(res == bit_i_result); - } - assert(res == bit_rr.query(l, r)); - cout << res << '\n'; - } - auto sum = rnd(0LL, (ll)(1e12)); - auto need = sum; - auto f = [&](ll x, int tl, int tr) -> bool { - assert(tl <= tr); - if (x < need) { - need -= x; - return 0; - } - return 1; - }; - assert(bit.walk(sum) == st.find_first(0, n, f)); - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/bit_inc.test.cpp b/tests/library_checker_aizu_tests/data_structures/bit_inc.test.cpp deleted file mode 100644 index 7e5a39ab..00000000 --- a/tests/library_checker_aizu_tests/data_structures/bit_inc.test.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/point_add_range_sum" -#include "../template.hpp" -#include "../../../library/data_structures/bit_inc.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - bit_inc bit(n); - for (int i = 0; i < n; i++) { - int val; - cin >> val; - bit.update(i, val); - } - while (q--) { - int type; - cin >> type; - if (type == 0) { - int p, x; - cin >> p >> x; - bit.update(p, x); - } else { - int l, r; - cin >> l >> r; - cout << bit.query(l, r - 1) << '\n'; - } - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/bit_ordered_set.test.cpp b/tests/library_checker_aizu_tests/data_structures/bit_ordered_set.test.cpp deleted file mode 100644 index 24cbfb29..00000000 --- a/tests/library_checker_aizu_tests/data_structures/bit_ordered_set.test.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/ordered_set" -#include "../template.hpp" -#include "../../../library/data_structures/bit_inc.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vector init(n); - for (int i = 0; i < n; i++) cin >> init[i]; - vector compress(init); - vector> query(q); - for (int i = 0; i < q; i++) { - int type, x; - cin >> type >> x; - query[i] = {type, x}; - compress.push_back(x); - } - ranges::sort(compress); - compress.erase(unique(all(compress)), end(compress)); - bit_inc bit(ssize(compress)); - auto get_compressed_idx = [&](int val) -> int { - int l = 0, r = ssize(compress); - while (l + 1 < r) { - int m = (l + r) / 2; - if (compress[m] <= val) l = m; - else r = m; - } - return l; - }; - for (int i = 0; i < n; i++) { - int val = get_compressed_idx(init[i]); - bit.update(val, 1); - } - for (auto [type, x] : query) { - if (type == 0) { - x = get_compressed_idx(x); - if (bit.query(x, x) == 0) bit.update(x, 1); - } else if (type == 1) { - x = get_compressed_idx(x); - if (bit.query(x, x) == 1) bit.update(x, -1); - } else if (type == 2) { - int res = bit.walk(x); - if (res == -1 || res == ssize(compress)) - cout << -1 << '\n'; - else cout << compress[res] << '\n'; - } else if (type == 3) { - x = get_compressed_idx(x); - cout << bit.query(x) << '\n'; - } else if (type == 4) { - x = get_compressed_idx(x); - int res = bit.prev(x); - if (res == -1) cout << -1 << '\n'; - else cout << compress[res] << '\n'; - } else { - x = get_compressed_idx(x); - int res = bit.next(x); - if (res == ssize(bit.s)) cout << -1 << '\n'; - else cout << compress[res] << '\n'; - } - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/bit_rupq.test.cpp b/tests/library_checker_aizu_tests/data_structures/bit_rupq.test.cpp deleted file mode 100644 index 49b54b42..00000000 --- a/tests/library_checker_aizu_tests/data_structures/bit_rupq.test.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#define PROBLEM \ - "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_E" -#include "../template.hpp" -#include "../../../library/data_structures/bit_uncommon/rupq.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - bit_rupq bit_i_1(n); - bit_rupq bit_i_2(vector(n, 50)); - while (q--) { - int type; - cin >> type; - if (type == 0) { - int l, r, x; - cin >> l >> r >> x; - l--; - bit_i_1.update(l, r, x); - bit_i_2.update(l, r, x); - // test degenerate updates - bit_i_1.update(l, l, x); - bit_i_1.update(r, r, x); - bit_i_2.update(l, l, x); - bit_i_2.update(r, r, x); - } else { - int idx; - cin >> idx; - idx--; - ll res = bit_i_1.get_index(idx); - assert(res == bit_i_2.get_index(idx) - 50); - cout << res << '\n'; - } - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/bit_rurq.test.cpp b/tests/library_checker_aizu_tests/data_structures/bit_rurq.test.cpp deleted file mode 100644 index d561be4f..00000000 --- a/tests/library_checker_aizu_tests/data_structures/bit_rurq.test.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#define PROBLEM \ - "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_G" -#include "../template.hpp" -#include "../../../library/data_structures/bit_uncommon/rurq.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - bit_rurq bit(n); - while (q--) { - int type; - cin >> type; - if (type == 0) { - int l, r, x; - cin >> l >> r >> x; - l--; - bit.update(l, r, x); - // test degenerate update - bit.update(l, l, x); - bit.update(r, r, x); - } else { - int l, r; - cin >> l >> r; - l--; - cout << bit.query(l, r) << '\n'; - } - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/bit_walk.test.cpp b/tests/library_checker_aizu_tests/data_structures/bit_walk.test.cpp deleted file mode 100644 index 6069c731..00000000 --- a/tests/library_checker_aizu_tests/data_structures/bit_walk.test.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/predecessor_problem" -#include "../template.hpp" -#include "../../../library/data_structures/bit.hpp" -#include "../../../library/data_structures/lazy_seg_tree.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - string s; - cin >> n >> q >> s; - vector init(n); - vector init_ll(n); - for (int i = 0; i < n; i++) - init[i] = init_ll[i] = s[i] - '0'; - BIT bit(init_ll); - seg_tree st(init); - while (q--) { - int type, k; - cin >> type >> k; - if (type == 0) { - if (bit.query(k, k + 1) == 0) { - bit.update(k, 1); - st.update(k, k + 1, 1); - } - } else if (type == 1) { - if (bit.query(k, k + 1) == 1) { - bit.update(k, -1); - st.update(k, k + 1, -1); - } - } else if (type == 2) { - int res = bit.query(k, k + 1); - auto res_st = st.query(k, k + 1); - assert(res == res_st); - cout << res << '\n'; - } else if (type == 3) { - if (bit.query(k, k + 1) == 1) { - cout << k << '\n'; - continue; - } - int order = bit.query(k); - int need = order + 1; - auto f = [&](int64_t x, int tl, int tr) -> bool { - assert(tl <= tr); - if (x < need) { - need -= x; - return 0; - } - return 1; - }; - int res = bit.walk(order + 1); - assert(res == st.find_first(0, n, f)); - assert(res == - st.find_first(k, n, - [&](int64_t x, int, int) -> bool { - return x > 0; - })); - if (res == n) res = -1; - cout << res << '\n'; - } else { - if (bit.query(k, k + 1) == 1) { - cout << k << '\n'; - continue; - } - int order = bit.query(k); - int need = order; - auto f = [&](int64_t x, int tl, int tr) -> bool { - assert(tl <= tr); - if (x < need) { - need -= x; - return 0; - } - return 1; - }; - int res = bit.walk(order); - assert(max(res, 0) == st.find_first(0, n, f)); - assert(res == - st.find_last(0, k + 1, - [&](int64_t x, int, int) -> bool { - return x > 0; - })); - cout << res << '\n'; - } - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/deque.test.cpp b/tests/library_checker_aizu_tests/data_structures/deque.test.cpp deleted file mode 100644 index 30e25494..00000000 --- a/tests/library_checker_aizu_tests/data_structures/deque.test.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/courses/lesson/8/ITP2/all/ITP2_1_B" -#include "../template.hpp" -#include "../../../library/data_structures/uncommon/deque_op.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int q; - cin >> q; - deq dq(vector(), - [](int x, int y) -> int { return min(x, y); }); - while (q--) { - int type; - cin >> type; - if (type == 0) { - int d, x; - cin >> d >> x; - if (d == 0) dq.push_front(x); - else { - assert(d == 1); - dq.push_back(x); - } - } else if (type == 1) { - int p; - cin >> p; - cout << dq[p] << '\n'; - } else { - assert(type == 2); - int d; - cin >> d; - if (d == 0) dq.pop_front(); - else { - assert(d == 1); - dq.pop_back(); - } - } - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/deque_index.test.cpp b/tests/library_checker_aizu_tests/data_structures/deque_index.test.cpp deleted file mode 100644 index 52f89ffb..00000000 --- a/tests/library_checker_aizu_tests/data_structures/deque_index.test.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#define PROBLEM "https://judge.yosupo.jp/problem/deque" -#include "../template.hpp" -#include "../../../library/data_structures/uncommon/deque_op.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int q; - cin >> q; - deq dq(vector(), - [](int x, int y) -> int { return min(x, y); }); - while (q--) { - int type; - cin >> type; - if (type == 0) { - int x; - cin >> x; - dq.push_front(x); - } else if (type == 1) { - int x; - cin >> x; - dq.push_back(x); - } else if (type == 2) { - dq.pop_front(); - } else if (type == 3) { - dq.pop_back(); - } else { - int i; - cin >> i; - cout << dq[i] << '\n'; - } - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/deque_op.test.cpp b/tests/library_checker_aizu_tests/data_structures/deque_op.test.cpp deleted file mode 100644 index 91d0e21c..00000000 --- a/tests/library_checker_aizu_tests/data_structures/deque_op.test.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/deque_operate_all_composite" -#include "../template.hpp" -#include "../../../library/contest/random.hpp" -#include "../../../library/data_structures/uncommon/deque_op.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - const int mod = 998'244'353; - int q; - cin >> q; - using line = pair; - // f1 = begin, f2 = second after begin - // we want op(f1, f2) = the function f2(f1(x)) - deq dq(vector(), - [](const line& i, const line& j) -> line { - return pair(1LL * i.first * j.first % mod, - (1LL * j.first * i.second + j.second) % mod); - }); - deque stl_dq; - while (q--) { - int type; - cin >> type; - if (type == 0) { - int a, b; - cin >> a >> b; - dq.push_front(pair(a, b)); - stl_dq.emplace_front(a, b); - } else if (type == 1) { - int a, b; - cin >> a >> b; - dq.push_back(pair(a, b)); - stl_dq.emplace_back(a, b); - } else if (type == 2) { - dq.pop_front(); - stl_dq.pop_front(); - } else if (type == 3) { - dq.pop_back(); - stl_dq.pop_back(); - } else { - assert(type == 4); - int x; - cin >> x; - if (dq.siz() == 0) cout << x << '\n'; - else { - line curr = dq.query(); - cout << (1LL * curr.first * x + curr.second) % mod - << '\n'; - } - } - assert(sz(stl_dq) == dq.siz()); - if (dq.siz()) { - assert(stl_dq.front() == dq.front()); - assert(stl_dq.back() == dq.back()); - for (int index_tests = 10; index_tests--;) { - int idx = rnd(0, dq.siz() - 1); - assert(stl_dq[idx] == dq[idx]); - } - } - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/deque_sliding_window.test.cpp b/tests/library_checker_aizu_tests/data_structures/deque_sliding_window.test.cpp deleted file mode 100644 index 193d272c..00000000 --- a/tests/library_checker_aizu_tests/data_structures/deque_sliding_window.test.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/courses/library/3/DSL/all/DSL_3_D" -#include "../template.hpp" -#include "../../../library/data_structures/uncommon/deque_op.hpp" -int mn(int x, int y) { return min(x, y); } -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, l; - cin >> n >> l; - vector arr(n); - for (int i = 0; i < n; i++) cin >> arr[i]; - vector init(begin(arr), begin(arr) + l); - deq dq(init, mn); - cout << dq.query(); - for (int i = l; i < n; i++) { - dq.push_back(arr[i]); - dq.pop_front(); - cout << " " << dq.query(); - } - cout << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/disjoint_rmq_inc.test.cpp b/tests/library_checker_aizu_tests/data_structures/disjoint_rmq_inc.test.cpp deleted file mode 100644 index 970d3dff..00000000 --- a/tests/library_checker_aizu_tests/data_structures/disjoint_rmq_inc.test.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#define PROBLEM "https://judge.yosupo.jp/problem/staticrmq" -#include "../template.hpp" -#include "../../../library/data_structures/uncommon/disjoint_rmq_inc.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vi a(n); - for (int i = 0; i < n; i++) cin >> a[i]; - disjoint_rmq_inc rmq(a, - [](int x, int y) { return min(x, y); }); - while (q--) { - int l, r; - cin >> l >> r; - cout << rmq.query(l, r - 1) << '\n'; - } -} diff --git a/tests/library_checker_aizu_tests/data_structures/disjoint_rmq_inc_lines.test.cpp b/tests/library_checker_aizu_tests/data_structures/disjoint_rmq_inc_lines.test.cpp deleted file mode 100644 index 359a849c..00000000 --- a/tests/library_checker_aizu_tests/data_structures/disjoint_rmq_inc_lines.test.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/queue_operate_all_composite" -#include "../template.hpp" -#include "../../../library/data_structures/uncommon/disjoint_rmq_inc.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - const ll mod = 998'244'353; - int q; - cin >> q; - struct query { - int type; - int a, b, x; - }; - vector queries(q); - vector> lines; - for (int i = 0; i < q; i++) { - cin >> queries[i].type; - if (queries[i].type == 0) { - cin >> queries[i].a >> queries[i].b; - lines.emplace_back(queries[i].a, queries[i].b); - } else if (queries[i].type == 2) cin >> queries[i].x; - } - disjoint_rmq_inc rmq(lines, - [](const auto& a, const auto& b) { - // f1(x) = a.first * x + a.second - // f2(x) = b.first * x + b.second - // f2(f1(x)) = b.first * (a.first * x + a.second) + - // b.second - // = (a.first * b.first) * x + (b.first * - // a.second + b.second) - return pair(a.first * b.first % mod, - (b.first * a.second + b.second) % mod); - }); - int l = 0, r = 0; // range [l, r) - for (const auto& curr : queries) { - if (curr.type == 0) r++; - else if (curr.type == 1) l++; - else { - if (l == r) cout << curr.x << '\n'; - else { - auto [slope, y_int] = rmq.query(l, r - 1); - cout << (slope * curr.x + y_int) % mod << '\n'; - } - } - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/disjoint_rmq_lines.test.cpp b/tests/library_checker_aizu_tests/data_structures/disjoint_rmq_lines.test.cpp deleted file mode 100644 index ea747377..00000000 --- a/tests/library_checker_aizu_tests/data_structures/disjoint_rmq_lines.test.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/queue_operate_all_composite" -#include "../template.hpp" -#include "../../../library/data_structures/uncommon/disjoint_rmq.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - const ll mod = 998'244'353; - int q; - cin >> q; - struct query { - int type; - int a, b, x; - }; - vector queries(q); - vector> lines; - for (int i = 0; i < q; i++) { - cin >> queries[i].type; - if (queries[i].type == 0) { - cin >> queries[i].a >> queries[i].b; - lines.emplace_back(queries[i].a, queries[i].b); - } else if (queries[i].type == 2) cin >> queries[i].x; - } - disjoint_rmq rmq(lines, - [](const auto& a, const auto& b) { - // f1(x) = a.first * x + a.second - // f2(x) = b.first * x + b.second - // f2(f1(x)) = b.first * (a.first * x + a.second) + - // b.second - // = (a.first * b.first) * x + (b.first * - // a.second + b.second) - return pair(a.first * b.first % mod, - (b.first * a.second + b.second) % mod); - }); - int l = 0, r = 0; // range [l, r) - for (const auto& curr : queries) { - if (curr.type == 0) r++; - else if (curr.type == 1) l++; - else { - if (l == r) cout << curr.x << '\n'; - else { - auto [slope, y_int] = rmq.query(l, r); - cout << (slope * curr.x + y_int) % mod << '\n'; - } - } - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/disjoint_rmq_sum.test.cpp b/tests/library_checker_aizu_tests/data_structures/disjoint_rmq_sum.test.cpp deleted file mode 100644 index a812f5db..00000000 --- a/tests/library_checker_aizu_tests/data_structures/disjoint_rmq_sum.test.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/static_range_sum" -#include "../template.hpp" -#include "../../../library/data_structures/uncommon/disjoint_rmq.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vector arr(n); - for (int i = 0; i < n; i++) cin >> arr[i]; - disjoint_rmq rmq(arr, plus{}); - while (q--) { - int l, r; - cin >> l >> r; - cout << rmq.query(l, r) << '\n'; - } -} diff --git a/tests/library_checker_aizu_tests/data_structures/distinct_query.test.cpp b/tests/library_checker_aizu_tests/data_structures/distinct_query.test.cpp deleted file mode 100644 index 10e106ef..00000000 --- a/tests/library_checker_aizu_tests/data_structures/distinct_query.test.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/static_range_count_distinct" -#include "../template.hpp" -#include "../../../library/data_structures/seg_tree_uncommon/distinct_query.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vector a(n); - for (int i = 0; i < n; i++) cin >> a[i]; - distinct_query dq(a); - while (q--) { - int l, r; - cin >> l >> r; - cout << dq.query(l, r) << '\n'; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/dsu.test.cpp b/tests/library_checker_aizu_tests/data_structures/dsu.test.cpp deleted file mode 100644 index 053132dc..00000000 --- a/tests/library_checker_aizu_tests/data_structures/dsu.test.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#define PROBLEM "https://judge.yosupo.jp/problem/unionfind" -#include "../template.hpp" -#include "../../../library/data_structures/dsu/dsu.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - DSU dsu(n); - while (q--) { - int type, u, v; - cin >> type >> u >> v; - if (type == 0) dsu.join(u, v); - else cout << (dsu.go(u) == dsu.go(v)) << '\n'; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/dsu_bipartite.test.cpp b/tests/library_checker_aizu_tests/data_structures/dsu_bipartite.test.cpp deleted file mode 100644 index 2b64b760..00000000 --- a/tests/library_checker_aizu_tests/data_structures/dsu_bipartite.test.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#define PROBLEM "https://judge.yosupo.jp/problem/unionfind" -#include "../template.hpp" -#include "../../../library/data_structures/dsu/dsu_bipartite.hpp" -#include "../../../library/contest/random.hpp" -vector bipartite_check( - const vector>& adj) { - int n = sz(adj); - vector is_bi(n); - vector color(n, -1); - for (int s = 0; s < n; s++) { - if (color[s] != -1) continue; - color[s] = 0; - vector q{s}; - bool is_bipartite = 1; - for (int fr = 0; fr < sz(q); fr++) { - int u = q[fr]; - for (int v : adj[u]) - if (color[v] == -1) { - color[v] = color[u] ^ 1; - q.push_back(v); - } else is_bipartite &= color[v] != color[u]; - } - for (int u : q) is_bi[u] = is_bipartite; - } - return is_bi; -} -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - dsu_bipartite dsu(n); - vector> adj(n); - auto check = [&]() { - vector is_bi = bipartite_check(adj); - for (int s = 0; s < n; s++) - assert(dsu.is_bipartite(s) == is_bi[s]); - }; - for (int i = 0; i < q; i++) { - int t, u, v; - cin >> t >> u >> v; - if (t == 0) { - dsu.join(u, v); - adj[u].push_back(v); - adj[v].push_back(u); - } else cout << dsu.same_set(u, v) << '\n'; - if (rnd(0, 20'000) == 0) check(); - } - check(); - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/dsu_restorable.test.cpp b/tests/library_checker_aizu_tests/data_structures/dsu_restorable.test.cpp deleted file mode 100644 index 29642ff1..00000000 --- a/tests/library_checker_aizu_tests/data_structures/dsu_restorable.test.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/persistent_unionfind" -#include "../template.hpp" -#include "../../../library/data_structures/dsu/dsu_restorable.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vector> childs(q + 1), queries(q + 1); - vector query_u(q + 1), query_v(q + 1); - for (int i = 1; i <= q; i++) { - int type, k; - cin >> type >> k >> query_u[i] >> query_v[i]; - k++; - if (type == 0) childs[k].push_back(i); - else { - assert(type == 1); - queries[k].push_back(i); - } - } - vector res(q + 1, -1); - { - dsu_restorable dsu(n); - auto dfs = [&](auto&& self, int u) -> void { - for (auto idx : queries[u]) - res[idx] = - dsu.same_set(query_u[idx], query_v[idx]); - for (auto child : childs[u]) { - dsu.join(query_u[child], query_v[child]); - self(self, child); - dsu.undo(); - } - }; - dfs(dfs, 0); - } - for (int i = 1; i <= q; i++) - if (res[i] != -1) cout << res[i] << "\n"; - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/dsu_segtree_undo_trick.test.cpp b/tests/library_checker_aizu_tests/data_structures/dsu_segtree_undo_trick.test.cpp deleted file mode 100644 index 2c76e8d6..00000000 --- a/tests/library_checker_aizu_tests/data_structures/dsu_segtree_undo_trick.test.cpp +++ /dev/null @@ -1,127 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/dynamic_graph_vertex_add_component_sum" -#include "../template.hpp" -#include "../../../library/data_structures/dsu/dsu_restorable.hpp" -#include "../../../library/data_structures/lazy_seg_tree.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - dsu_restorable dsu(n); - for (int i = 0; i < n; i++) cin >> dsu.subtree[i]; - vector>> tree(2 * q); - auto add_edge = [&](auto&& self, int l, int r, - int node_u, int node_v, int tl, int tr, - int v) -> void { - if (r <= tl || tr <= l) return; - if (l <= tl && tr <= r) { - tree[v].emplace_back(node_u, node_v); - return; - } - int tm = split(tl, tr); - self(self, l, r, node_u, node_v, tl, tm, 2 * v); - self(self, l, r, node_u, node_v, tm, tr, 2 * v + 1); - }; - struct query { - int type, v, x; - }; - vector queries(q); - { - map, int> insert_time; - for (int i = 0; i < q; i++) { - int type; - cin >> type; - if (type == 0) { - int u, v; - cin >> u >> v; - if (u > v) swap(u, v); - assert(!insert_time.contains({u, v})); - insert_time[{u, v}] = i; - } else if (type == 1) { - int u, v; - cin >> u >> v; - if (u > v) swap(u, v); - assert(insert_time.contains({u, v})); - add_edge(add_edge, insert_time[{u, v}], i, u, v, 0, - q, 1); - insert_time.erase({u, v}); - } else if (type == 2) { - int v, x; - cin >> v >> x; - queries[i] = {2, v, x}; - } else { - assert(type == 3); - int v; - cin >> v; - queries[i] = {3, v, -1}; - } - } - for (auto [edge, i_time] : insert_time) - add_edge(add_edge, i_time, q, edge.first, - edge.second, 0, q, 1); - } - auto dfs = [&](auto&& self, int tl, int tr, - int v) -> void { - for (auto [node_u, node_v] : tree[v]) - dsu.join(node_u, node_v); - assert((v >= q) == ((tr - tl) == 1)); - if (v >= q) { // leaf node - const int depth_leaf = __lg(v), - max_depth = __lg(2 * q - 1); - if (tl == 0) { // left-most leaf - assert(v == (1 << max_depth)); - assert(depth_leaf == max_depth); - } - assert(q <= v && v < 2 * q); - assert(depth_leaf == max_depth || - depth_leaf == max_depth - 1); - if ((q & (q - 1)) == 0) - assert(depth_leaf == max_depth); - if (queries[tl].type == 2) - dsu.add(queries[tl].v, queries[tl].x); - else if (queries[tl].type == 3) - cout << dsu.sum(queries[tl].v) << '\n'; - } else { - assert(1 <= v && v < q); - if (((tr - tl) & (tr - tl - 1)) == 0) - assert(split(tl, tr) == (tl + tr) / 2); - { - int pow_2 = 1 << __lg(tr - tl); - if (tl + pow_2 < tr - pow_2 / 2) { - assert(pow_2 != tr - tl); - assert(pow_2 / 2 < tr - tl - pow_2 && - tr - tl - pow_2 < pow_2); - assert(pow_2 <= 2 * (tr - tl - pow_2) - 1 && - 2 * (tr - tl - pow_2) - 1 < 2 * pow_2 - 1); - assert(__lg(pow_2) == - __lg(2 * ((tr - tl) - pow_2) - 1) && - __lg(pow_2) == __lg(2 * pow_2 - 1)); - } else if (pow_2 < tr - tl) { - assert(pow_2 / 2 < tr - tl - pow_2 / 2 && - tr - tl - pow_2 / 2 <= pow_2); - assert( - pow_2 <= 2 * ((tr - tl) - pow_2 / 2) - 1 && - 2 * ((tr - tl) - pow_2 / 2) - 1 <= - 2 * pow_2 - 1); - assert(__lg(2 * (tr - tl - pow_2 / 2) - 1) == - __lg(2 * pow_2 - 1)); - assert(__lg(2 * ((tr - tl) - pow_2 / 2) - 1) == - __lg(pow_2)); - assert( - __lg(pow_2) == 1 + __lg(2 * (pow_2 / 2) - 1)); - } - } - int tm = split(tl, tr); - // in particular, this tests that split works with - // negatives - assert(split(tl - 1234, tr - 1234) == tm - 1234); - assert(split(tl - 1, tr - 1) == tm - 1); - assert(split(tl + 50, tr + 50) == tm + 50); - self(self, tl, tm, 2 * v); - self(self, tm, tr, 2 * v + 1); - } - for (int i = 0; i < sz(tree[v]); i++) dsu.undo(); - }; - dfs(dfs, 0, q, 1); - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/implicit_seg_tree.test.cpp b/tests/library_checker_aizu_tests/data_structures/implicit_seg_tree.test.cpp deleted file mode 100644 index 683af629..00000000 --- a/tests/library_checker_aizu_tests/data_structures/implicit_seg_tree.test.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/area_of_union_of_rectangles" -#include "../template.hpp" -#include "../../../library/data_structures/seg_tree_uncommon/implicit.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n; - cin >> n; - struct vertical_edge { - int x, y1, y2, add; - }; - vector edges; - for (int i = 0; i < n; i++) { - int x1, y1, x2, y2; - cin >> x1 >> y1 >> x2 >> y2; - edges.push_back({x1, y1, y2, 1}); - edges.push_back({x2, y1, y2, -1}); - } - sort(begin(edges), end(edges), - [&](const vertical_edge& a, const vertical_edge& b) - -> bool { return a.x < b.x; }); - const int mn = 0, mx = 1'000'000'001; - implicit_seg_tree<500'000 * 31 * 2 * 2 + 100> ist(mn, - mx); - int64_t area = 0; - // sweepline - for (int i = 0; i < sz(edges);) { - if (i) { - auto [curr_mn, cnt_mn] = ist.query(mn, mx); - int64_t num_pos = mx - mn; - if (curr_mn == 0) num_pos -= cnt_mn; - area += (edges[i].x - edges[i - 1].x) * num_pos; - } - int j = i; - while (j < sz(edges) && edges[i].x == edges[j].x) { - ist.update(edges[j].y1, edges[j].y2, edges[j].add); - j++; - } - i = j; - } - cout << area << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/kruskal_tree_aizu.test.cpp b/tests/library_checker_aizu_tests/data_structures/kruskal_tree_aizu.test.cpp deleted file mode 100644 index 77cac40a..00000000 --- a/tests/library_checker_aizu_tests/data_structures/kruskal_tree_aizu.test.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/problems/ALDS1_12_A" -#include "../template.hpp" -#include "../../../library/data_structures/dsu/kruskal_tree.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n; - cin >> n; - vector> w_eds; - vector> mat(n, vector(n)); - for (int i = 0; i < n; i++) { - for (int j = 0; j < n; j++) { - cin >> mat[i][j]; - if (mat[i][j] == -1) { - mat[i][j] = INT_MAX; - continue; - } - w_eds.push_back({mat[i][j], i, j}); - } - } - sort(all(w_eds)); - kr_tree kt(n); - vector weight(2 * n); - for (auto [w, u, v] : w_eds) - if (kt.join(u, v)) weight[kt.id - 1] = w; - rep(k, 0, n) rep(i, 0, n) rep(j, 0, n) { - mat[i][j] = min(mat[i][j], max(mat[i][k], mat[k][j])); - } - int mst_sum = 0; - for (int i = n; i < kt.id; i++) mst_sum += weight[i]; - vector depth(2 * n); - vector actual_par(2 * n, -1); - auto dfs = [&](auto&& self, int v) -> void { - for (int u : kt.adj[v]) { - depth[u] = 1 + depth[v]; - actual_par[u] = v; - self(self, u); - } - }; - dfs(dfs, kt.id - 1); - rep(i, 0, n) rep(j, i + 1, n) { - int u = i, v = j; - while (u != v) - if (depth[u] > depth[v]) u = actual_par[u]; - else v = actual_par[v]; - assert(weight[u] == mat[i][j]); - } - cout << mst_sum << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/kth_smallest_pst.test.cpp b/tests/library_checker_aizu_tests/data_structures/kth_smallest_pst.test.cpp deleted file mode 100644 index 3a7f1e81..00000000 --- a/tests/library_checker_aizu_tests/data_structures/kth_smallest_pst.test.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/range_kth_smallest" -#include "../template.hpp" -#include "../../../library/data_structures/seg_tree_uncommon/kth_smallest_query.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vector arr(n); - for (int i = 0; i < n; i++) cin >> arr[i]; - vector sorted(arr); - sort(begin(sorted), end(sorted)); - sorted.erase(unique(begin(sorted), end(sorted)), - end(sorted)); - for (int& val : arr) { - int start = 0, end = sz(sorted); - while (start + 1 < end) { - int mid = (start + end) / 2; - if (sorted[mid] <= val) start = mid; - else end = mid; - } - assert(sorted[start] == val); - val = start - 50; - } - kth_smallest st(arr, -50, sz(sorted) - 50); - for (int i = 0; i < n; i++) { - int mx = arr[i]; - for (int j = i + 1; j <= min(i + 5, n); j++) { - mx = max(mx, arr[j - 1]); - assert(st.query(i, j, j - i) == mx); - } - } - while (q--) { - int l, r, k; - cin >> l >> r >> k; - cout << sorted[st.query(l, r, k + 1) + 50] << '\n'; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/kth_smallest_wavelet_matrix.test.cpp b/tests/library_checker_aizu_tests/data_structures/kth_smallest_wavelet_matrix.test.cpp deleted file mode 100644 index 95ec3365..00000000 --- a/tests/library_checker_aizu_tests/data_structures/kth_smallest_wavelet_matrix.test.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/range_kth_smallest" -#include "../template.hpp" -#include "../../../library/data_structures/seg_tree_uncommon/wavelet_matrix.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vector a(n); - for (int i = 0; i < n; i++) { - cin >> a[i]; - a[i] <<= 23; - } - wavelet_matrix wm(a, 1'000'000'000LL << 23); - while (q--) { - int l, r, k; - cin >> l >> r >> k; - cout << (wm.kth(l, r, k) >> 23) << '\n'; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/lazy_segment_tree.test.cpp b/tests/library_checker_aizu_tests/data_structures/lazy_segment_tree.test.cpp deleted file mode 100644 index 45b8d80c..00000000 --- a/tests/library_checker_aizu_tests/data_structures/lazy_segment_tree.test.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/courses/library/3/DSL/all/DSL_2_G" -#include "../template.hpp" -#include "../../../library/data_structures/lazy_seg_tree.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - { - // test empty seg tree - seg_tree st(0); - st.update(0, 0, 1); - int64_t res = st.query(0, 0); - assert(res == 0); - } - int n, q; - cin >> n >> q; - seg_tree st(n); - while (q--) { - int type, l, r; - cin >> type >> l >> r; - l--; - if (type == 0) { - int64_t x; - cin >> x; - st.update(l, r, x); - st.update(l, l, 1); - st.update(r, r, 1); - } else { - assert(type == 1); - cout << st.query(l, r) << '\n'; - { - int64_t res = st.query(l, l); - assert(res == 0); - } - { - int64_t res = st.query(r, r); - assert(res == 0); - } - } - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/lazy_segment_tree_constructor.test.cpp b/tests/library_checker_aizu_tests/data_structures/lazy_segment_tree_constructor.test.cpp deleted file mode 100644 index dce7702f..00000000 --- a/tests/library_checker_aizu_tests/data_structures/lazy_segment_tree_constructor.test.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/point_add_range_sum" -#include "../template.hpp" -#include "../../../library/data_structures/lazy_seg_tree.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - { - // test empty seg tree - seg_tree st{vector()}; - st.update(0, 0, 1); - int64_t res = st.query(0, 0); - assert(res == 0); - } - int n, q; - cin >> n >> q; - vector arr(n); - for (int i = 0; i < n; i++) cin >> arr[i]; - seg_tree st(arr); - while (q--) { - int type; - cin >> type; - if (type == 0) { - int idx; - int64_t x; - cin >> idx >> x; - st.update(idx, idx + 1, x); - st.update(idx, idx, 1); - } else { - assert(type == 1); - int l, r; - cin >> l >> r; - cout << st.query(l, r) << '\n'; - { - int64_t res = st.query(l, l); - assert(res == 0); - } - { - int64_t res = st.query(r, r); - assert(res == 0); - } - } - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/lazy_segment_tree_inc.test.cpp b/tests/library_checker_aizu_tests/data_structures/lazy_segment_tree_inc.test.cpp deleted file mode 100644 index 1dec9fc3..00000000 --- a/tests/library_checker_aizu_tests/data_structures/lazy_segment_tree_inc.test.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/courses/library/3/DSL/all/DSL_2_G" -#include "../template.hpp" -#include "../../../library/data_structures/lazy_seg_tree_inc.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - seg_tree_inc st(n); - while (q--) { - int type, l, r; - cin >> type >> l >> r; - l--, r--; - if (type == 0) { - int64_t x; - cin >> x; - st.update(l, r, x); - } else { - cout << st.query(l, r) << '\n'; - } - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/lazy_segment_tree_inc_constructor.test.cpp b/tests/library_checker_aizu_tests/data_structures/lazy_segment_tree_inc_constructor.test.cpp deleted file mode 100644 index 2786e101..00000000 --- a/tests/library_checker_aizu_tests/data_structures/lazy_segment_tree_inc_constructor.test.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/point_add_range_sum" -#include "../template.hpp" -#include "../../../library/data_structures/lazy_seg_tree_inc.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vector a(n); - for (int i = 0; i < n; i++) cin >> a[i]; - seg_tree_inc st(a); - while (q--) { - int type; - cin >> type; - if (type == 0) { - int idx; - int64_t x; - cin >> idx >> x; - st.update(idx, idx, x); - } else { - assert(type == 1); - int l, r; - cin >> l >> r; - cout << st.query(l, r - 1) << '\n'; - } - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/line_tree_aizu.test.cpp b/tests/library_checker_aizu_tests/data_structures/line_tree_aizu.test.cpp deleted file mode 100644 index d9400ddf..00000000 --- a/tests/library_checker_aizu_tests/data_structures/line_tree_aizu.test.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/problems/ALDS1_12_A" -#include "../template.hpp" -#include "../../../library/data_structures/dsu/line_tree.hpp" -#include "../../../library/data_structures/rmq.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n; - cin >> n; - vector> w_eds; - vector> mat(n, vector(n)); - for (int i = 0; i < n; i++) { - for (int j = 0; j < n; j++) { - cin >> mat[i][j]; - if (mat[i][j] == -1) { - mat[i][j] = INT_MAX; - continue; - } - w_eds.push_back({mat[i][j], i, j}); - } - } - rep(k, 0, n) rep(i, 0, n) rep(j, 0, n) mat[i][j] = - min(mat[i][j], max(mat[i][k], mat[k][j])); - sort(all(w_eds)); - line_tree lt(n); - for (auto [w, u, v] : w_eds) lt.join(u, v); - assert(lt.size(0) == n); - int mst_sum = 0; - vector edge_weights; - vector to_time(n); - for (int v = lt.find(0), timer = 1; - lt.edge[v] != pii{-1, -1}; - v = lt.edge[v].first, timer++) { - edge_weights.push_back(w_eds[lt.edge[v].second][0]); - to_time[lt.edge[v].first] = timer; - mst_sum += w_eds[lt.edge[v].second][0]; - } - assert(sz(edge_weights) == n - 1); - RMQ rmq(edge_weights, - [&](int x, int y) { return max(x, y); }); - rep(i, 0, n) rep(j, i + 1, n) { - auto [i1, i2] = minmax(to_time[i], to_time[j]); - assert(rmq.query(i1, i2) == mat[i][j]); - } - cout << mst_sum << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/line_tree_lib_checker.test.cpp b/tests/library_checker_aizu_tests/data_structures/line_tree_lib_checker.test.cpp deleted file mode 100644 index 2b6acb51..00000000 --- a/tests/library_checker_aizu_tests/data_structures/line_tree_lib_checker.test.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/minimum_spanning_tree" -#include "../template.hpp" -#include "../../../library/data_structures/dsu/line_tree.hpp" -#include "../../../library/data_structures/dsu/kruskal_tree.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, m; - cin >> n >> m; - vector> w_eds(m); - vector weights(m); - for (int i = 0; i < m; i++) { - int u, v; - cin >> u >> v >> weights[i]; - w_eds[i] = {i, u, v}; - } - sort(all(w_eds), - [&](const array& x, const array& y) - -> bool { return weights[x[0]] < weights[y[0]]; }); - line_tree lt(n); - for (auto [i, u, v] : w_eds) lt.join(u, v); - assert(lt.size(0) == n); - int64_t cost = 0; - vector ids; - for (int v = lt.find(0); lt.edge[v].first != -1; - v = lt.edge[v].first) { - ids.push_back(w_eds[lt.edge[v].second][0]); - cost += weights[w_eds[lt.edge[v].second][0]]; - } - { - kr_tree kt(n); - int64_t kr_tree_cost = 0; - for (auto [e_id, u, v] : w_eds) - if (kt.join(u, v)) kr_tree_cost += weights[e_id]; - assert(kr_tree_cost == cost); - } - cout << cost << '\n'; - for (int id : ids) cout << id << ' '; - cout << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/merge_sort_tree.test.cpp b/tests/library_checker_aizu_tests/data_structures/merge_sort_tree.test.cpp deleted file mode 100644 index 4ec6e472..00000000 --- a/tests/library_checker_aizu_tests/data_structures/merge_sort_tree.test.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/static_range_frequency" -// since this causes an O(n) partition check for each call -// to `lower_bound`, causing TLE. -#undef _GLIBCXX_DEBUG -#include "../template.hpp" -#include "../../../library/data_structures/seg_tree_uncommon/merge_sort_tree.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vector arr(n); - for (int i = 0; i < n; i++) cin >> arr[i]; - merge_sort_tree mst(arr); - while (q--) { - int l, r, x; - cin >> l >> r >> x; - assert(mst.query(l, r, x, x) == 0); - cout << mst.query(l, r, x, x + 1) << '\n'; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/mode_query.test.cpp b/tests/library_checker_aizu_tests/data_structures/mode_query.test.cpp deleted file mode 100644 index 1a2ad5da..00000000 --- a/tests/library_checker_aizu_tests/data_structures/mode_query.test.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/static_range_mode_query" -#include "../template.hpp" -#include "../../../library/data_structures/uncommon/mode_query.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vector a(n); - for (int i = 0; i < n; i++) cin >> a[i]; - vector comp(a); - sort(begin(comp), end(comp)); - comp.erase(unique(begin(comp), end(comp)), end(comp)); - for (int& val : a) { - int start = 0, end = sz(comp); - while (start + 1 < end) { - int mid = (start + end) / 2; - if (comp[mid] <= val) start = mid; - else end = mid; - } - assert(0 <= start && start < sz(comp) && - comp[start] == val); - val = start; - } - mode_query mq(a); - while (q--) { - int l, r; - cin >> l >> r; - auto [mode, cnt] = mq.query(l, r); - cout << comp[mode] << " " << cnt << '\n'; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/permutation_tree.test.cpp b/tests/library_checker_aizu_tests/data_structures/permutation_tree.test.cpp deleted file mode 100644 index 0e2a55ef..00000000 --- a/tests/library_checker_aizu_tests/data_structures/permutation_tree.test.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/common_interval_decomposition_tree" -#include "../template.hpp" -#include "../perm_tree_asserts.hpp" -#include "../../../library/data_structures/uncommon/permutation_tree.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n; - cin >> n; - vector a(n); - for (int i = 0; i < n; i++) cin >> a[i]; - perm_tree pt = perm_tree_asserts(a); - auto root = pt.root; - auto ch = pt.ch; - cout << sz(ch) << '\n'; - int curr_time = 0; - vector node_to_time(sz(ch), -1); - auto dfs = [&](auto&& self, int u, int p) -> void { - node_to_time[u] = curr_time++; - cout << (p == -1 ? p : node_to_time[p]) << " " - << pt.p[u].mn_idx << " " - << pt.p[u].mn_idx + pt.p[u].len - 1 << " " - << (pt.p[u].is_join || empty(ch[u]) ? "linear" - : "prime") - << '\n'; - for (int v : ch[u]) self(self, v, u); - }; - dfs(dfs, root, -1); - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/persistent_queue_tree.test.cpp b/tests/library_checker_aizu_tests/data_structures/persistent_queue_tree.test.cpp deleted file mode 100644 index 321e58e5..00000000 --- a/tests/library_checker_aizu_tests/data_structures/persistent_queue_tree.test.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/persistent_queue" -#include "../template.hpp" -#include "../../../library/data_structures/seg_tree_uncommon/persistent.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int q; - cin >> q; - PST pst(0, q); - vector> bounds(q + 1); - // bounds[version] = [left index, right index) represents - // subarray range of queue - for (int curr_version = 1; curr_version <= q; - curr_version++) { - int type; - cin >> type; - if (type == 0) { - int version, x; - cin >> version >> x; - version++; - pst.update(bounds[version].second, x, version); - bounds[curr_version] = bounds[version]; - bounds[curr_version].second++; - } else { - assert(type == 1); - int version; - cin >> version; - version++; - int idx = bounds[version].first; - int val_removed = - int(pst.query(idx, idx + 1, version)); - cout << val_removed << '\n'; - pst.update(idx, -val_removed, version); - bounds[curr_version] = bounds[version]; - bounds[curr_version].first++; - } - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/persistent_seg_tree.test.cpp b/tests/library_checker_aizu_tests/data_structures/persistent_seg_tree.test.cpp deleted file mode 100644 index 8480b43f..00000000 --- a/tests/library_checker_aizu_tests/data_structures/persistent_seg_tree.test.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/rectangle_sum" -// since this causes an O(n) partition check for each call -// to `lower_bound`, causing TLE. -#undef _GLIBCXX_DEBUG -#include "../template.hpp" -#include "../../../library/data_structures/seg_tree_uncommon/persistent.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vector> points(n); - for (int i = 0; i < n; i++) { - int x, y, w; - cin >> x >> y >> w; - points[i] = {x, y, w}; - } - sort(begin(points), end(points)); - PST pst(-5, 1'000'000'000); - for (const auto& point : points) - pst.update(point[1], point[2], sz(pst.roots) - 1); - while (q--) { - int l, down, r, up; - cin >> l >> down >> r >> up; - l = int(lower_bound(begin(points), end(points), - array({l, -1, -1})) - - begin(points)); - r = int(lower_bound(begin(points), end(points), - array({r, -1, -1})) - - begin(points)); - cout << pst.query(down, up, r) - pst.query(down, up, l) - << '\n'; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/pq_ds_undo_sliding_window.test.cpp b/tests/library_checker_aizu_tests/data_structures/pq_ds_undo_sliding_window.test.cpp deleted file mode 100644 index b0b27a4e..00000000 --- a/tests/library_checker_aizu_tests/data_structures/pq_ds_undo_sliding_window.test.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/courses/library/3/DSL/all/DSL_3_D" -// since _GLIBCXX_DEBUG causes std::map insert/erase -// operations to be O(n) -#undef _GLIBCXX_DEBUG -#include "../template.hpp" -#include "../../../library/data_structures/uncommon/priority_queue_of_updates.hpp" -struct stack_with_get_max { - vector> st; - void join(int val) { - st.emplace_back(val, - empty(st) ? val : min(val, st.back().second)); - } - void undo() { st.pop_back(); } - int get_max() const { return st.back().second; } -}; -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, l; - cin >> n >> l; - vector arr(n); - for (int i = 0; i < n; i++) cin >> arr[i]; - stack_with_get_max stm; - pq_updates pq(stm); - int priority = (n - l) / 2; - for (int i = 0; i < l; i++) - pq.push_update(arr[i], priority--); - cout << pq.ds.get_max(); - for (int i = l; i < n; i++) { - pq.push_update(arr[i], priority--); - pq.pop_update(); - cout << " " << pq.ds.get_max(); - } - cout << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/pq_ds_undo_with_dsu.test.cpp b/tests/library_checker_aizu_tests/data_structures/pq_ds_undo_with_dsu.test.cpp deleted file mode 100644 index 16c9de9b..00000000 --- a/tests/library_checker_aizu_tests/data_structures/pq_ds_undo_with_dsu.test.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/dynamic_graph_vertex_add_component_sum" -// since _GLIBCXX_DEBUG causes std::map insert/erase -// operations to be O(n) -#undef _GLIBCXX_DEBUG -#include "../template.hpp" -#include "../../../library/data_structures/dsu/dsu_restorable.hpp" -#include "../../../library/data_structures/uncommon/priority_queue_of_updates.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vector initial_values(n); - for (int i = 0; i < n; i++) cin >> initial_values[i]; - vector time_remove(q, -1); - struct query { - int type, u, v, x; - }; - vector queries(q); - { - map, int> insert_time; - for (int i = 0; i < q; i++) { - int type; - cin >> type; - if (type == 0) { - int u, v; - cin >> u >> v; - if (u > v) swap(u, v); - assert(!insert_time.contains({u, v})); - insert_time[{u, v}] = i; - queries[i] = {type, u, v, -1}; - } else if (type == 1) { - int u, v; - cin >> u >> v; - if (u > v) swap(u, v); - assert(insert_time.contains({u, v})); - time_remove[insert_time[{u, v}]] = i; - insert_time.erase({u, v}); - queries[i] = {type, -1, -1, -1}; - } else if (type == 2) { - int v, x; - cin >> v >> x; - queries[i] = {type, -1, v, x}; - } else { - assert(type == 3); - int v; - cin >> v; - queries[i] = {type, -1, v, -1}; - } - } - } - dsu_restorable dsu_r(n); - pq_updates pq(dsu_r); - for (int i = 0; i < n; i++) - pq.ds.add(i, initial_values[i]); - int curr_priority_counter = -q; - for (int i = 0; i < q; i++) { - int type = queries[i].type; - if (type == 0) { - int u = queries[i].u, v = queries[i].v; - int curr_pri; - if (time_remove[i] == -1) - curr_pri = curr_priority_counter--; - else curr_pri = -time_remove[i]; - pq.push_update(u, v, curr_pri); - } else if (type == 1) pq.pop_update(); - else if (type == 2) { - int v = queries[i].v, x = queries[i].x; - pq.ds.add(v, x); - } else { - assert(type == 3); - int v = queries[i].v; - cout << pq.ds.sum(v) << '\n'; - } - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/range_parallel_dsu.test.cpp b/tests/library_checker_aizu_tests/data_structures/range_parallel_dsu.test.cpp deleted file mode 100644 index af7a24cd..00000000 --- a/tests/library_checker_aizu_tests/data_structures/range_parallel_dsu.test.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/range_parallel_unionfind" -#undef _GLIBCXX_DEBUG -#include "../template.hpp" -#include "../../../library/data_structures/dsu/range_parallel_dsu.hpp" -#include "../../../library/data_structures/dsu/range_parallel_equivalence_classes.hpp" -const int mod = 998244353; -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - rp_dsu dsu(n); - vi y(n); - for (int i = 0; i < n; i++) cin >> y[i]; - vi x = y; - int ans = 0; - auto f = [&](int u, int v) { - ans = (ans + 1LL * x[u] * x[v]) % mod; - x[u] = (x[u] + x[v]) % mod; - }; - vector> queries; - queries.reserve(q); - for (int qq = 0; qq < q; qq++) { - int k, a, b; - cin >> k >> a >> b; - dsu.join(a, b, k, f); - queries.push_back({a, b, k}); - cout << ans << '\n'; - if (qq == 0 || qq == 1 || qq == 10 || qq == 1000 || - qq == 100'000 || qq == q - 1) { - auto uf = get_rp_dsu(queries, n); - vi sums(n); - int offline_ans = 0; - for (int i = 0; i < n; i++) { - int id = uf.find(i); - offline_ans = - (offline_ans + 1LL * sums[id] * y[i]) % mod; - sums[id] = (sums[id] + y[i]) % mod; - } - assert(ans == offline_ans); - } - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/rmq_disjoint_sparse_table.test.cpp b/tests/library_checker_aizu_tests/data_structures/rmq_disjoint_sparse_table.test.cpp deleted file mode 100644 index 10924cc2..00000000 --- a/tests/library_checker_aizu_tests/data_structures/rmq_disjoint_sparse_table.test.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#define PROBLEM "https://judge.yosupo.jp/problem/staticrmq" -#include "../template.hpp" -#include "../../../library/data_structures/uncommon/disjoint_rmq.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vector a(n); - for (int i = 0; i < n; i++) cin >> a[i]; - disjoint_rmq dis_rmq(a, ranges::min); - while (q--) { - int l, r; - cin >> l >> r; - cout << dis_rmq.query(l, r) << '\n'; - } -} diff --git a/tests/library_checker_aizu_tests/data_structures/rmq_linear.test.cpp b/tests/library_checker_aizu_tests/data_structures/rmq_linear.test.cpp deleted file mode 100644 index fb3de419..00000000 --- a/tests/library_checker_aizu_tests/data_structures/rmq_linear.test.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#define PROBLEM "https://judge.yosupo.jp/problem/staticrmq" -#include "../template.hpp" -#include "../../../library/data_structures/uncommon/linear_rmq.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vector a(n); - for (int i = 0; i < n; i++) cin >> a[i]; - linear_rmq rmq_less(a, less()); - linear_rmq rmq_less_equal(a, less_equal()); - vector neg_a(n); - for (int i = 0; i < n; i++) neg_a[i] = -a[i]; - linear_rmq rmq_greater(neg_a, greater()); - linear_rmq rmq_greater_equal(neg_a, greater_equal()); - while (q--) { - int l, r; - cin >> l >> r; - int idx_right_min = rmq_less.idx(l, r - 1); - assert(idx_right_min + 1 == r || - rmq_less.query(idx_right_min + 1, r - 1) > - a[idx_right_min]); - assert(l <= idx_right_min && idx_right_min < r); - assert(rmq_less.query(l, r - 1) == a[idx_right_min]); - assert(idx_right_min == rmq_greater.idx(l, r - 1)); - int idx_left_min = rmq_less_equal.idx(l, r - 1); - assert(l == idx_left_min || - rmq_less_equal.query(l, idx_left_min - 1) > - a[idx_left_min]); - assert(l <= idx_left_min && idx_left_min < r); - assert( - idx_left_min == rmq_greater_equal.idx(l, r - 1)); - assert(a[idx_right_min] == a[idx_left_min]); - assert(idx_left_min <= idx_right_min); - cout << a[idx_right_min] << '\n'; - } -} diff --git a/tests/library_checker_aizu_tests/data_structures/rmq_sparse_table.test.cpp b/tests/library_checker_aizu_tests/data_structures/rmq_sparse_table.test.cpp deleted file mode 100644 index 60f27454..00000000 --- a/tests/library_checker_aizu_tests/data_structures/rmq_sparse_table.test.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#define PROBLEM "https://judge.yosupo.jp/problem/staticrmq" -#include "../template.hpp" -#include "../mono_st_asserts.hpp" -#include "../../../library/data_structures/rmq.hpp" -int mn(int x, int y) { return min(x, y); } -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vector a(n); - for (int i = 0; i < n; i++) cin >> a[i]; - mono_st_asserts(a); - RMQ rmq(a, ranges::min); - while (q--) { - int l, r; - cin >> l >> r; - cout << rmq.query(l, r) << '\n'; - } -} diff --git a/tests/library_checker_aizu_tests/data_structures/rmq_sparse_table_inc.test.cpp b/tests/library_checker_aizu_tests/data_structures/rmq_sparse_table_inc.test.cpp deleted file mode 100644 index aca314c6..00000000 --- a/tests/library_checker_aizu_tests/data_structures/rmq_sparse_table_inc.test.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#define PROBLEM "https://judge.yosupo.jp/problem/staticrmq" -#include "../template.hpp" -#include "../../../library/data_structures/rmq_inc.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vector a(n); - for (int i = 0; i < n; i++) cin >> a[i]; - rmq_inc rmq(a, ranges::min); - while (q--) { - int l, r; - cin >> l >> r; - cout << rmq.query(l, r - 1) << '\n'; - } -} diff --git a/tests/library_checker_aizu_tests/data_structures/simple_tree.test.cpp b/tests/library_checker_aizu_tests/data_structures/simple_tree.test.cpp deleted file mode 100644 index 56afe9ff..00000000 --- a/tests/library_checker_aizu_tests/data_structures/simple_tree.test.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/problems/DSL_2_A" -#include "../template.hpp" -#include "../../../library/data_structures/seg_tree.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - tree st(n, INT_MAX, ranges::min); - while (q--) { - int type; - cin >> type; - if (type == 0) { - int pos, new_val; - cin >> pos >> new_val; - st.update(pos, new_val); - } else { - int l, r; - cin >> l >> r; - r++; - cout << st.query(l, r) << '\n'; - } - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/simple_tree_inc.test.cpp b/tests/library_checker_aizu_tests/data_structures/simple_tree_inc.test.cpp deleted file mode 100644 index 69f09256..00000000 --- a/tests/library_checker_aizu_tests/data_structures/simple_tree_inc.test.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/problems/DSL_2_A" -#include "../template.hpp" -#include "../../../library/data_structures/seg_tree_inc.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - tree_inc st(n, int{}, ranges::min); - rep(i, 0, n) st.update(i, INT_MAX); - while (q--) { - int type; - cin >> type; - if (type == 0) { - int pos, new_val; - cin >> pos >> new_val; - st.update(pos, new_val); - } else { - int l, r; - cin >> l >> r; - cout << st.query(l, r) << '\n'; - } - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/simple_tree_inc_line.test.cpp b/tests/library_checker_aizu_tests/data_structures/simple_tree_inc_line.test.cpp deleted file mode 100644 index 76ff0f99..00000000 --- a/tests/library_checker_aizu_tests/data_structures/simple_tree_inc_line.test.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/point_set_range_composite" -#include "../template.hpp" -#include "../../../library/data_structures/seg_tree_inc.hpp" -const int mod = 998'244'353; -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - tree_inc st(n, array{}, - [&](const array& l, - const array& r) -> array { - return {int(1LL * l[0] * r[0] % mod), - int((1LL * r[0] * l[1] + r[1]) % mod)}; - }); - for (int i = 0; i < n; i++) { - int a, b; - cin >> a >> b; - st.update(i, array{a, b}); - } - while (q--) { - int type; - cin >> type; - if (type == 0) { - int pos, c, d; - cin >> pos >> c >> d; - st.update(pos, {c, d}); - } else { - int l, r, x; - cin >> l >> r >> x; - auto [slope, y_int] = st.query(l, r - 1); - cout << (1LL * slope * x + y_int) % mod << '\n'; - } - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/data_structures/simple_tree_line.test.cpp b/tests/library_checker_aizu_tests/data_structures/simple_tree_line.test.cpp deleted file mode 100644 index 11208946..00000000 --- a/tests/library_checker_aizu_tests/data_structures/simple_tree_line.test.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/point_set_range_composite" -#include "../template.hpp" -#include "../../../library/data_structures/seg_tree.hpp" -const int mod = 998'244'353; -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - tree st(n, array{1, 0}, - [&](const array& l, - const array& r) -> array { - return {int(1LL * l[0] * r[0] % mod), - int((1LL * r[0] * l[1] + r[1]) % mod)}; - }); - for (int i = 0; i < n; i++) { - int a, b; - cin >> a >> b; - st.update(i, {a, b}); - } - while (q--) { - int type; - cin >> type; - if (type == 0) { - int pos, c, d; - cin >> pos >> c >> d; - st.update(pos, {c, d}); - } else { - int l, r, x; - cin >> l >> r >> x; - assert(st.query(l, l) == st.unit); - assert(st.query(r, r) == st.unit); - auto [slope, y_int] = st.query(l, r); - cout << (1LL * slope * x + y_int) % mod << '\n'; - } - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/dinic_asserts.hpp b/tests/library_checker_aizu_tests/dinic_asserts.hpp deleted file mode 100644 index f00c2185..00000000 --- a/tests/library_checker_aizu_tests/dinic_asserts.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once -void dinic_asserts(dinic& d, int source, int sink, - ll total_flow) { - int n = sz(d.q); - vector in_flow(n), out_flow(n); - for (int i = 0; i < sz(d.edges); i += 2) { - dinic::edge e = d.edges[i]; - out_flow[e.v] += e.flow(); - in_flow[e.to] += e.flow(); - assert(0 <= e.flow() && e.flow() <= e.cap); - } - assert(in_flow[source] == 0); - assert(out_flow[source] == total_flow); - assert(in_flow[sink] == total_flow); - assert(out_flow[sink] == 0); - for (int i = 0; i < n; i++) { - if (i == source) continue; - if (i == sink) continue; - assert(in_flow[i] == out_flow[i]); - } - { - queue q; - q.push(source); - vector vis(n); - vis[source] = 1; - while (!empty(q)) { - int v = q.front(); - q.pop(); - for (int id : d.adj[v]) { - dinic::edge e = d.edges[id]; - if (e.flow() == e.cap) continue; - int u = e.to; - if (!vis[u]) { - vis[u] = 1; - q.push(u); - } - } - } - for (int i = 0; i < n; i++) - assert(vis[i] == d.left_of_min_cut(i)); - } -} diff --git a/tests/library_checker_aizu_tests/edge_cd_asserts.hpp b/tests/library_checker_aizu_tests/edge_cd_asserts.hpp deleted file mode 100644 index 808806a3..00000000 --- a/tests/library_checker_aizu_tests/edge_cd_asserts.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once -void edge_cd_asserts(const vector& adj, int cent, - int split) { - assert(0 < split && split < sz(adj[cent])); - auto dfs = [&](auto&& self, int u, int p) -> int { - int siz = 1; - for (int v : adj[u]) - if (v != p) siz += self(self, v, u); - return siz; - }; - int sz_all = dfs(dfs, cent, -1); - assert(sz_all >= 3); - array cnts = {0, 0}; - array max_cnt = {0, 0}; - array number_of_cnts = {0, 0}; - for (int i = 0; i < sz(adj[cent]); i++) { - int sz_subtree = dfs(dfs, adj[cent][i], cent); - assert(2 * sz_subtree <= sz_all); - cnts[i < split] += sz_subtree; - max_cnt[i < split] = - max(max_cnt[i < split], sz_subtree); - number_of_cnts[i < split]++; - } - assert(cnts[0] + cnts[1] + 1 == sz_all); - if (sz_all == 4) return; - // a is the number of edges in the smaller edge set - // b is the number of edges in the larger edge set - // so we know 1/2 <= b/(a+b) - // returns true iff b/(a+b) <= 1/phi - auto is_balanced = [&](ll a, ll b) -> bool { - assert(a <= b); - return b * b <= a * (a + b); - }; - if (cnts[0] > cnts[1]) { - swap(cnts[0], cnts[1]); - swap(max_cnt[0], max_cnt[1]); - swap(number_of_cnts[0], number_of_cnts[1]); - } - if (!is_balanced(cnts[0], cnts[1])) { - assert(number_of_cnts[1] == 2); - int a = max_cnt[1]; - int b = cnts[1] - max_cnt[1]; - assert(a > 0); - assert(b > 0); - if (a > b) swap(a, b); - assert(is_balanced(a, b)); - assert(!is_balanced(a, cnts[0] + b)); - assert(!is_balanced(b, cnts[0] + a)); - } -} diff --git a/tests/library_checker_aizu_tests/flow/dinic_aizu.test.cpp b/tests/library_checker_aizu_tests/flow/dinic_aizu.test.cpp deleted file mode 100644 index 60fc043f..00000000 --- a/tests/library_checker_aizu_tests/flow/dinic_aizu.test.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/courses/library/5/GRL/all/GRL_6_A" -#include "../template.hpp" -#include "../../../library/flow/dinic.hpp" -#include "../dinic_asserts.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, m; - cin >> n >> m; - dinic d(n); - for (int i = 0; i < m; i++) { - int u, v, cap; - cin >> u >> v >> cap; - d.add_edge(u, v, cap); - } - ll total_flow = d.calc(0, n - 1); - dinic_asserts(d, 0, n - 1, total_flow); - cout << total_flow << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/flow/hungarian.test.cpp b/tests/library_checker_aizu_tests/flow/hungarian.test.cpp deleted file mode 100644 index 64e3b3fe..00000000 --- a/tests/library_checker_aizu_tests/flow/hungarian.test.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/assignment" -#include "../template.hpp" -#include "../../../library/flow/hungarian.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n; - cin >> n; - vector> a(n + 1, vector(n + 1)); - for (int i = 1; i <= n; i++) - for (int j = 1; j <= n; j++) cin >> a[i][j]; - auto [min_weight, l_to_r] = hungarian(a); - cout << min_weight << '\n'; - for (int i = 1; i <= n; i++) - cout << l_to_r[i] - 1 << " "; - return 0; -} diff --git a/tests/library_checker_aizu_tests/flow/min_cost_max_flow.test.cpp b/tests/library_checker_aizu_tests/flow/min_cost_max_flow.test.cpp deleted file mode 100644 index 55fd5ce1..00000000 --- a/tests/library_checker_aizu_tests/flow/min_cost_max_flow.test.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/courses/library/5/GRL/all/GRL_6_B" -#include "../template.hpp" -#include "../../../library/flow/min_cost_max_flow.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, m, f; - cin >> n >> m >> f; - mcmf mf(n); - while (m--) { - int u, v, cap, cost; - cin >> u >> v >> cap >> cost; - mf.add_edge(u, v, cap, cost); - } - auto [flow, cost] = mf.get_flow(0, n - 1, f); - cout << (flow < f ? -1 : cost) << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/graphs/bcc_callback_aizu_bcc.test.cpp b/tests/library_checker_aizu_tests/graphs/bcc_callback_aizu_bcc.test.cpp deleted file mode 100644 index 02d52421..00000000 --- a/tests/library_checker_aizu_tests/graphs/bcc_callback_aizu_bcc.test.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/problems/GRL_3_A" -#include "../template.hpp" -#include "../../../library/graphs/bcc_callback.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, m; - cin >> n >> m; - vector> adj(n); - for (int i = 0; i < n; i++) adj[i].push_back(i); - for (int i = 0; i < m; i++) { - int u, v; - cin >> u >> v; - adj[u].push_back(v); - adj[v].push_back(u); - } - vi cnt(n); - bcc_callback(adj, [&](const vi& nodes) { - assert(sz(nodes) >= 2); - for (int v : nodes) cnt[v]++; - }); - rep(i, 0, n) if (cnt[i] >= 2) cout << i << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/graphs/bcc_callback_aizu_two_edge_cc.test.cpp b/tests/library_checker_aizu_tests/graphs/bcc_callback_aizu_two_edge_cc.test.cpp deleted file mode 100644 index 94e5ae3c..00000000 --- a/tests/library_checker_aizu_tests/graphs/bcc_callback_aizu_two_edge_cc.test.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/problems/GRL_3_B" -#include "../template.hpp" -#include "../../../library/graphs/bcc_callback.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, m; - cin >> n >> m; - vector adj(n); - for (int i = 0; i < n; i++) adj[i].push_back(i); - for (int i = 0; i < m; i++) { - int u, v; - cin >> u >> v; - adj[u].push_back(v); - adj[v].push_back(u); - } - vector bridges; - bcc_callback(adj, [&](const vi& nodes) { - if (sz(nodes) == 2) { - pii bridge(nodes[0], nodes[1]); - if (bridge.first > bridge.second) - swap(bridge.first, bridge.second); - bridges.push_back(bridge); - // nodes[0] <=> nodes[1] is a bridge - return; - } - }); - ranges::sort(bridges); - for (auto [u, v] : bridges) - cout << u << ' ' << v << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/graphs/bcc_callback_lib_checker_bcc.test.cpp b/tests/library_checker_aizu_tests/graphs/bcc_callback_lib_checker_bcc.test.cpp deleted file mode 100644 index 52771ee3..00000000 --- a/tests/library_checker_aizu_tests/graphs/bcc_callback_lib_checker_bcc.test.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/biconnected_components" -#include "../template.hpp" -#include "../../../library/graphs/bcc_callback.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, m; - cin >> n >> m; - vector> adj(n); - for (int i = 0; i < n; i++) adj[i].push_back(i); - for (int i = 0; i < m; i++) { - int u, v; - cin >> u >> v; - adj[u].push_back(v); - adj[v].push_back(u); - } - vector vis(n, 0); - vector> all_bccs; - bcc_callback(adj, [&](const vi& nodes) { - assert(ssize(nodes) >= 2); - for (int v : nodes) vis[v] = 1; - all_bccs.push_back(nodes); - }); - for (int i = 0; i < n; i++) - if (!vis[i]) all_bccs.push_back({i}); - cout << ssize(all_bccs) << '\n'; - for (const vector& other_nodes : all_bccs) { - cout << ssize(other_nodes) << ' '; - for (int v : other_nodes) cout << v << ' '; - cout << '\n'; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/graphs/bcc_callback_lib_checker_two_cc.test.cpp b/tests/library_checker_aizu_tests/graphs/bcc_callback_lib_checker_two_cc.test.cpp deleted file mode 100644 index b00d8557..00000000 --- a/tests/library_checker_aizu_tests/graphs/bcc_callback_lib_checker_two_cc.test.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/two_edge_connected_components" -#include "../template.hpp" -#include "../../../library/graphs/bcc_callback.hpp" -#include "../../../library/data_structures/dsu/dsu.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, m; - cin >> n >> m; - vector adj(n); - for (int i = 0; i < m; i++) { - int u, v; - cin >> u >> v; - adj[u].push_back(v); - adj[v].push_back(u); - } - DSU dsu(n); - vector seen(n); - bcc_callback(adj, [&](const vi& nodes) { - int count_edges = 0; - rep(i, 0, sz(nodes) - 1) { - seen[nodes[i]] = 1; - count_edges += ranges::count_if(adj[nodes[i]], - [&](int v) -> bool { return !seen[v]; }); - } - if (count_edges == 1) { - assert(sz(nodes) == 2); - // nodes[0] <=> nodes[1] is a bridge - return; - } - for (int v : nodes) dsu.join(v, nodes[0]); - }); - vector two_edge_ccs(n); - rep(i, 0, n) two_edge_ccs[dsu.go(i)].push_back(i); - int cnt_ccs = 0; - rep(i, 0, n) cnt_ccs += (!empty(two_edge_ccs[i])); - cout << cnt_ccs << '\n'; - rep(i, 0, n) { - if (!empty(two_edge_ccs[i])) { - cout << sz(two_edge_ccs[i]) << ' '; - for (int v : two_edge_ccs[i]) cout << v << ' '; - cout << '\n'; - } - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/graphs/biconnected_components.test.cpp b/tests/library_checker_aizu_tests/graphs/biconnected_components.test.cpp deleted file mode 100644 index bcc8d75c..00000000 --- a/tests/library_checker_aizu_tests/graphs/biconnected_components.test.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/biconnected_components" -#include "../template.hpp" -#include "../../../library/graphs/uncommon/block_vertex_tree.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, m; - cin >> n >> m; - vector>> adj(n); - vector> edges(m); - for (int i = 0; i < m; i++) { - int u, v; - cin >> u >> v; - adj[u].emplace_back(v, i); - adj[v].emplace_back(u, i); - edges[i] = make_pair(u, v); - } - auto [num_bccs, bcc_id, is_cut] = cuts(adj, m); - auto bvt = block_vertex_tree(adj, num_bccs, bcc_id); - assert( - find(begin(bcc_id), end(bcc_id), -1) == end(bcc_id)); - for (int i = 0; i < n; i++) { - // cut node if there exists a pair of adjacent edges - // belonging to different BCCs - bool curr_is_cut = 0; - for (int j = 0; j < sz(adj[i]); j++) - if (bcc_id[adj[i][0].second] != - bcc_id[adj[i][j].second]) - curr_is_cut = 1; - assert(curr_is_cut == is_cut[i]); - } - // check correctness of block vertex tree - for (int i = 0; i < n; i++) { - assert(sz(adj[i]) >= - sz(bvt[i])); // in particular, if empty(adj[i]), then - // empty(bct[i]) - assert(is_cut[i] == - (sz(bvt[i]) > - 1)); // is cut means non-leaf in block vertex tree - } - { - vector> bcc_to_nodes(num_bccs), - node_to_bccs(n); - for (int i = 0; i < m; i++) { - int bccid = bcc_id[i]; - for (auto node : {edges[i].first, edges[i].second}) { - bcc_to_nodes[bccid].insert(node); - node_to_bccs[node].insert(bccid); - } - } - // testing commented loops in block_vertex_tree - for (int u = 0; u < n; u++) { - assert(sz(node_to_bccs[u]) == sz(bvt[u])); - for (auto bccid : bvt[u]) { - bccid -= n; - assert(node_to_bccs[u].contains(bccid)); - } - } - for (int bccid = 0; bccid < num_bccs; bccid++) { - assert( - sz(bcc_to_nodes[bccid]) == sz(bvt[bccid + n])); - for (auto u : bvt[bccid + n]) - assert(bcc_to_nodes[bccid].contains(u)); - } - } - vector lone_nodes; - for (int u = 0; u < n; u++) - if (empty(bvt[u])) lone_nodes.push_back(u); - cout << num_bccs + sz(lone_nodes) << '\n'; - for (int bccid = 0; bccid < num_bccs; bccid++) { - cout << sz(bvt[bccid + n]) << " "; - for (auto u : bvt[bccid + n]) cout << u << " "; - cout << '\n'; - } - for (auto u : lone_nodes) cout << "1 " << u << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/graphs/connected_components_of_complement_graph.test.cpp b/tests/library_checker_aizu_tests/graphs/connected_components_of_complement_graph.test.cpp deleted file mode 100644 index 8a8f359b..00000000 --- a/tests/library_checker_aizu_tests/graphs/connected_components_of_complement_graph.test.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/connected_components_of_complement_graph" -#include "../template.hpp" -#include "../../../library/graphs/uncommon/complement_graph_ccs.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, m; - cin >> n >> m; - vector> adj(n); - for (int i = 0; i < m; i++) { - int u, v; - cin >> u >> v; - adj[u].push_back(v); - adj[v].push_back(u); - } - auto cc_id = get_complement_graph_ccs(adj); - int num_ccs = *max_element(begin(cc_id), end(cc_id)) + 1; - vector> ccs(num_ccs); - for (int u = 0; u < n; u++) ccs[cc_id[u]].push_back(u); - cout << num_ccs << '\n'; - for (auto& cc : ccs) { - cout << size(cc); - for (int v : cc) cout << ' ' << v; - cout << '\n'; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/graphs/dijkstra_aizu.test.cpp b/tests/library_checker_aizu_tests/graphs/dijkstra_aizu.test.cpp deleted file mode 100644 index 523d7088..00000000 --- a/tests/library_checker_aizu_tests/graphs/dijkstra_aizu.test.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/problems/GRL_1_A" -// since this causes an O(n) heap-property check for each -// call to -//`priority_queue::push`, causing TLE. -#undef _GLIBCXX_DEBUG -#include "../template.hpp" -#include "../../../library/graphs/dijkstra.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, m, s; - cin >> n >> m >> s; - vector>> adj(n); - for (int i = 0; i < m; i++) { - int u, v, w; - cin >> u >> v >> w; - adj[u].emplace_back(v, w); - } - vector len = dijkstra(adj, s); - for (int i = 0; i < n; i++) - if (len[i] == LLONG_MAX) cout << "INF\n"; - else cout << len[i] << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/graphs/dijkstra_lib_checker.test.cpp b/tests/library_checker_aizu_tests/graphs/dijkstra_lib_checker.test.cpp deleted file mode 100644 index fc76b29e..00000000 --- a/tests/library_checker_aizu_tests/graphs/dijkstra_lib_checker.test.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/shortest_path" -// since this causes an O(n) heap-property check for each -// call to -//`priority_queue::push`, causing TLE. -#undef _GLIBCXX_DEBUG -#include "../template.hpp" -#include "../../../library/graphs/dijkstra.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, m, s, t; - cin >> n >> m >> s >> t; - vector>> adj(n), adj_inv(n); - for (int i = 0; i < m; i++) { - int u, v, w; - cin >> u >> v >> w; - adj[u].emplace_back(v, w); - adj_inv[v].emplace_back(u, w); - } - vector len = dijkstra(adj, s); - if (len[t] == LLONG_MAX) { - cout << -1 << '\n'; - return 0; - } - assert(len[s] == 0); - vector vis(n); - vis[t] = 1; - vector> path; - auto dfs = [&](auto&& self, int u) -> bool { - if (u == s) return 1; - for (auto [v, w] : adj_inv[u]) { - if (!vis[v] && len[v] != LLONG_MAX && - len[v] + w == len[u]) { - vis[v] = 1; - if (self(self, v)) { - path.push_back({v, u}); - return 1; - } - } - } - return 0; - }; - assert(dfs(dfs, t)); - cout << len[t] << " " << sz(path) << '\n'; - for (auto [u, v] : path) cout << u << " " << v << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/graphs/directed_cycle.test.cpp b/tests/library_checker_aizu_tests/graphs/directed_cycle.test.cpp deleted file mode 100644 index 8e61b4b0..00000000 --- a/tests/library_checker_aizu_tests/graphs/directed_cycle.test.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/cycle_detection" -#include "../template.hpp" -#include "../scc_asserts.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, m; - cin >> n >> m; - vector> adj(n); - vector>> adj_edge_id(n); - for (int i = 0; i < m; i++) { - int u, v; - cin >> u >> v; - adj[u].push_back(v); - adj_edge_id[u].emplace_back(v, i); - } - scc_asserts(adj); - auto [num_sccs, scc_id] = sccs(adj); - if (num_sccs == n) { - cout << -1 << '\n'; - return 0; - } - vi scc_siz(num_sccs); - vi any_node(num_sccs); - rep(i, 0, n) { - any_node[scc_id[i]] = i; - scc_siz[scc_id[i]]++; - } - rep(i, 0, num_sccs) { - if (scc_siz[i] > 1) { - int v = any_node[i]; - vi vis(n); - while (!vis[v]) { - vis[v] = 1; - for (auto [next, _] : adj_edge_id[v]) { - if (scc_id[v] == scc_id[next]) { - v = next; - break; - } - } - } - vi cycle; - while (vis[v] == 1) { - vis[v] = 2; - for (auto [next, e_id] : adj_edge_id[v]) { - if (scc_id[v] == scc_id[next]) { - cycle.push_back(e_id); - v = next; - break; - } - } - } - cout << sz(cycle) << '\n'; - for (int node : cycle) cout << node << '\n'; - return 0; - } - } - assert(0); - return 0; -} diff --git a/tests/library_checker_aizu_tests/graphs/enumerate_triangles.test.cpp b/tests/library_checker_aizu_tests/graphs/enumerate_triangles.test.cpp deleted file mode 100644 index 3c0c4ae8..00000000 --- a/tests/library_checker_aizu_tests/graphs/enumerate_triangles.test.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/enumerate_triangles" -#include "../template.hpp" -#include "../../../library/graphs/uncommon/enumerate_triangles.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, m; - cin >> n >> m; - vector vals(n); - for (int i = 0; i < n; i++) cin >> vals[i]; - vector> edges(m); - for (auto& [u, v] : edges) cin >> u >> v; - const int mod = 998'244'353; - int64_t sum = 0; - auto enumerate = [&](int u, int v, int w) { - sum = - (sum + - 1LL * vals[u] * vals[v] % mod * vals[w] % mod) % - mod; - }; - enumerate_triangles(edges, n, enumerate); - cout << sum << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/graphs/hopcroft_karp_aizu.test.cpp b/tests/library_checker_aizu_tests/graphs/hopcroft_karp_aizu.test.cpp deleted file mode 100644 index 6bc117e4..00000000 --- a/tests/library_checker_aizu_tests/graphs/hopcroft_karp_aizu.test.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#define PROBLEM \ - "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_7_A" -#include "../template.hpp" -#include "../../../library/graphs/hopcroft_karp.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int l, r, m; - cin >> l >> r >> m; - vector> adj(l); - vector> edges; - while (m--) { - int u, v; - cin >> u >> v; - adj[u].push_back(v); - edges.emplace_back(u, v); - } - hopcroft_karp res(adj, r); - cout << res.m_sz << '\n'; - // asserting correctness of both to_r, and to_l - int size_l = 0; - for (int i = 0; i < l; i++) { - if (res.to_r[i] != -1) { - size_l++; - int node_r = res.to_r[i]; - assert(res.to_l[node_r] == i); - } - } - int size_r = 0; - for (int i = 0; i < r; i++) { - if (res.to_l[i] != -1) { - size_r++; - int node_l = res.to_l[i]; - assert(res.to_r[node_l] == i); - } - } - assert(size_l == res.m_sz); - assert(size_r == res.m_sz); - // asserting found min vertex cover is correct - int cnt = - accumulate(begin(res.mvc_l), end(res.mvc_l), 0) + - accumulate(begin(res.mvc_r), end(res.mvc_r), 0); - assert(cnt == res.m_sz); // size of min vertex cover - // == size of max matching - for (auto [u, v] : edges) - assert(res.mvc_l[u] || res.mvc_r[v]); - return 0; -} diff --git a/tests/library_checker_aizu_tests/graphs/hopcroft_karp_lib_checker.test.cpp b/tests/library_checker_aizu_tests/graphs/hopcroft_karp_lib_checker.test.cpp deleted file mode 100644 index a81f0fac..00000000 --- a/tests/library_checker_aizu_tests/graphs/hopcroft_karp_lib_checker.test.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/bipartitematching" -#include "../template.hpp" -#include "../../../library/graphs/hopcroft_karp.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int l, r, m; - cin >> l >> r >> m; - vector> adj(l); - vector> edges; - while (m--) { - int u, v; - cin >> u >> v; - adj[u].push_back(v); - edges.emplace_back(u, v); - } - hopcroft_karp res(adj, r); - cout << res.m_sz << '\n'; - // asserting correctness of both to_r, and to_l (as - // well as printing answer) - int size_l = 0; - for (int i = 0; i < l; i++) { - if (res.to_r[i] != -1) { - size_l++; - int node_r = res.to_r[i]; - cout << i << " " << node_r << '\n'; - assert(res.to_l[node_r] == i); - } - } - int size_r = 0; - for (int i = 0; i < r; i++) { - if (res.to_l[i] != -1) { - size_r++; - int node_l = res.to_l[i]; - assert(res.to_r[node_l] == i); - } - } - assert(size_l == res.m_sz); - assert(size_r == res.m_sz); - // asserting found min vertex cover is correct - int cnt = - accumulate(begin(res.mvc_l), end(res.mvc_l), 0) + - accumulate(begin(res.mvc_r), end(res.mvc_r), 0); - assert(cnt == res.m_sz); // size of min vertex cover - // == size of max matching - for (auto [u, v] : edges) - assert(res.mvc_l[u] || res.mvc_r[v]); - return 0; -} diff --git a/tests/library_checker_aizu_tests/graphs/mst.test.cpp b/tests/library_checker_aizu_tests/graphs/mst.test.cpp deleted file mode 100644 index cb4feccf..00000000 --- a/tests/library_checker_aizu_tests/graphs/mst.test.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/minimum_spanning_tree" -#include "../template.hpp" -#include "../../../library/graphs/mst.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, m; - cin >> n >> m; - vector> eds(m); - for (auto& [u, v, w] : eds) cin >> u >> v >> w; - auto [cost, ids] = mst(eds, n); - cout << cost << '\n'; - for (int id : ids) cout << id << ' '; - cout << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/graphs/offline_incremental_scc.test.cpp b/tests/library_checker_aizu_tests/graphs/offline_incremental_scc.test.cpp deleted file mode 100644 index 7edac3e1..00000000 --- a/tests/library_checker_aizu_tests/graphs/offline_incremental_scc.test.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/incremental_scc" -#include "../template.hpp" -#include "../../../library/graphs/strongly_connected_components/offline_incremental_scc.hpp" -#include "../../../library/data_structures/dsu/dsu.hpp" -const int mod = 998244353; -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, m; - cin >> n >> m; - vector xs(n); - for (int i = 0; i < n; i++) cin >> xs[i]; - vector> eds(m); - for (auto& [u, v] : eds) cin >> u >> v; - auto joins = offline_incremental_scc(eds, n); - // assert joins[i] == -1 for self-edges - for (int t = 0; t < m; t++) - assert((eds[t][0] == eds[t][1]) == (joins[t] == -1)); - vector order(m); - iota(all(order), 0); - ranges::sort(all(order), {}, - [&](int i) { return joins[i]; }); - DSU dsu(n); - int sum = 0; - for (int t = 0, it = 0; t < m; t++) { - while (it < m && joins[order[it]] <= t) { - auto [u, v] = eds[order[it]]; - u = dsu.go(u); - v = dsu.go(v); - if (dsu.e[u] > dsu.e[v]) swap(u, v); - if (u != v) { - sum = (sum + 1LL * xs[u] * xs[v]) % mod; - xs[u] = (xs[u] + xs[v]) % mod; - xs[v] = xs[u]; - } - dsu.join(u, v); - it++; - } - cout << sum << '\n'; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/graphs/strongly_connected_components_aizu.test.cpp b/tests/library_checker_aizu_tests/graphs/strongly_connected_components_aizu.test.cpp deleted file mode 100644 index 9da0c857..00000000 --- a/tests/library_checker_aizu_tests/graphs/strongly_connected_components_aizu.test.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#define PROBLEM \ - "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_3_C" -#include "../template.hpp" -#include "../../../library/graphs/strongly_connected_components/add_edges_strongly_connected.hpp" -#include "../scc_asserts.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, m; - cin >> n >> m; - vector> adj(n); - for (int i = 0; i < m; i++) { - int u, v; - cin >> u >> v; - adj[u].push_back(v); - } - scc_asserts(adj); - auto [num_sccs, scc_id] = sccs(adj); - int q; - cin >> q; - while (q--) { - int u, v; - cin >> u >> v; - cout << (scc_id[u] == scc_id[v]) << '\n'; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/graphs/strongly_connected_components_lib_checker.test.cpp b/tests/library_checker_aizu_tests/graphs/strongly_connected_components_lib_checker.test.cpp deleted file mode 100644 index f4d7dce3..00000000 --- a/tests/library_checker_aizu_tests/graphs/strongly_connected_components_lib_checker.test.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#define PROBLEM "https://judge.yosupo.jp/problem/scc" -#include "../template.hpp" -#include "../../../library/graphs/strongly_connected_components/add_edges_strongly_connected.hpp" -#include "../scc_asserts.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, m; - cin >> n >> m; - vector> adj(n); - for (int i = 0; i < m; i++) { - int u, v; - cin >> u >> v; - adj[u].push_back(v); - } - scc_asserts(adj); - auto [num_sccs, scc_id] = sccs(adj); - cout << num_sccs << '\n'; - vector> each_scc(num_sccs); - for (int i = 0; i < n; i++) - each_scc[scc_id[i]].push_back(i); - for (int i = num_sccs - 1; i >= 0; i--) { - cout << sz(each_scc[i]) << " "; - for (auto node : each_scc[i]) cout << node << " "; - cout << '\n'; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/graphs/two_edge_components.test.cpp b/tests/library_checker_aizu_tests/graphs/two_edge_components.test.cpp deleted file mode 100644 index f12fbcad..00000000 --- a/tests/library_checker_aizu_tests/graphs/two_edge_components.test.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/two_edge_connected_components" -#include "../template.hpp" -#include "../../../library/graphs/uncommon/bridge_tree.hpp" -#include "../../../library/data_structures/dsu/dsu_restorable.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, m; - cin >> n >> m; - vector>> adj(n); - vector> edges(m); - for (int i = 0; i < m; i++) { - int u, v; - cin >> u >> v; - adj[u].emplace_back(v, i); - adj[v].emplace_back(u, i); - edges[i] = {u, v}; - } - auto [num_ccs, br_id, is_br] = bridges(adj, m); - auto bt = bridge_tree(adj, num_ccs, br_id, is_br); - assert(find(begin(br_id), end(br_id), -1) == end(br_id)); - // check correctness of bridge tree - { - assert(sz(bt) == num_ccs); - for (int v = 0; v < num_ccs; v++) - for (auto to : bt[v]) - assert(to != v); // didn't add any non-bridge - int sum_deg = accumulate(begin(bt), end(bt), 0, - [](int sum, const auto& neighbors) -> int { - return sum + sz(neighbors); - }); - int cnt_bridges = - accumulate(begin(is_br), end(is_br), 0); - assert(sum_deg % 2 == 0 && sum_deg / 2 == cnt_bridges); - } - dsu_restorable dsu(n); - int num_sets_dsu = n; - for (int i = 0; i < m; i++) { - if (!is_br[i]) { - auto [u, v] = edges[i]; - num_sets_dsu -= dsu.join(u, v); - } - } - assert(num_sets_dsu == sz(bt)); - for (int i = 0; i < m; i++) { - if (is_br[i]) { - auto [u, v] = edges[i]; - bool same_set = dsu.same_set(u, v); - assert(!same_set); - } - } - for (int i = 0; i < n; i++) { - int par_of_cc = dsu.find(i); - assert(br_id[i] == br_id[par_of_cc]); - } - for (int i = 0; i < m; i++) { - auto [u, v] = edges[i]; - // bridge if nodes are from different 2-edge CCs - assert(is_br[i] == (br_id[u] != br_id[v])); - } - vector> ccs(num_ccs); - for (int i = 0; i < n; i++) ccs[br_id[i]].push_back(i); - cout << num_ccs << '\n'; - for (const auto& curr_cc : ccs) { - cout << sz(curr_cc) << " "; - for (auto node : curr_cc) cout << node << " "; - cout << '\n'; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/handmade_tests/count_paths.test.cpp b/tests/library_checker_aizu_tests/handmade_tests/count_paths.test.cpp deleted file mode 100644 index 73c058b6..00000000 --- a/tests/library_checker_aizu_tests/handmade_tests/count_paths.test.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#define PROBLEM \ - "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A" -#include "../template.hpp" -#include "../../../library/contest/random.hpp" -#include "../../../library/trees/uncommon/count_paths_per_node.hpp" -#include "../../../library/trees/lca_rmq.hpp" -#include "../../../library/trees/uncommon/count_paths_per_length.hpp" -#include "../cd_asserts.hpp" -vector> naive(const vector& adj) { - LCA lc(adj); - int n = sz(adj); - vector> cnts_naive(n + 1, vector(n, 0)); - for (int u = 0; u < n; u++) { - for (int v = u; v < n; v++) { - int path_length_edges = lc.dist(u, v); - for (int node = u; node != v; - node = lc.next_on_path(node, v)) - cnts_naive[path_length_edges][node]++; - cnts_naive[path_length_edges][v]++; - } - } - return cnts_naive; -} -int main() { - cin.tie(0)->sync_with_stdio(0); - for (int n = 1; n <= 100; n++) { - vector adj(n); - for (int i = 1; i < n; i++) { - int par = rnd(0, i - 1); - adj[par].push_back(i); - adj[i].push_back(par); - } - cd_asserts(adj); - vector> cnts_naive = naive(adj); - for (int k = 1; k <= n; k++) - assert( - count_paths_per_node(adj, k) == cnts_naive[k]); - vector num_paths_len = count_paths_per_length(adj); - for (int k = 1; k < n; k++) { - vector count_paths = - count_paths_per_node(adj, k); - ll total_paths = accumulate(begin(count_paths), - end(count_paths), 0LL); - assert(total_paths % (k + 1) == 0); - total_paths /= k + 1; - assert(num_paths_len[k] == total_paths); - } - } - cout << "Hello World\n"; - return 0; -} diff --git a/tests/library_checker_aizu_tests/handmade_tests/dsu.test.cpp b/tests/library_checker_aizu_tests/handmade_tests/dsu.test.cpp deleted file mode 100644 index 410c6b00..00000000 --- a/tests/library_checker_aizu_tests/handmade_tests/dsu.test.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#define PROBLEM \ - "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A" -#include "../template.hpp" -#include "../../../library/contest/random.hpp" -#include "../../../library/data_structures/dsu/dsu.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - for (int n = 0; n <= 100; n++) { - vector> adj(n); - DSU dsu(n); - for (int q = 0; q < n; q++) { - int u = rnd(0, n - 1); - int v = rnd(0, n - 1); - bool joined = dsu.join(u, v); - { - vector vis(n); - auto dfs = [&](auto&& self, int v) -> void { - for (int u : adj[v]) { - if (!vis[u]) { - vis[u] = 1; - self(self, u); - } - } - }; - vis[u] = 1; - dfs(dfs, u); - assert(vis[v] != joined); - } - adj[u].push_back(v); - adj[v].push_back(u); - for (int i = 0; i < n; i++) { - vector vis(n); - int cnt_nodes = 0; - auto dfs = [&](auto&& self, int v) -> void { - cnt_nodes++; - for (int u : adj[v]) { - if (!vis[u]) { - vis[u] = 1; - self(self, u); - } - } - }; - vis[i] = 1; - dfs(dfs, i); - assert(cnt_nodes == dsu.size(i)); - } - } - } - cout << "Hello World\n"; - return 0; -} diff --git a/tests/library_checker_aizu_tests/handmade_tests/dsu_size.test.cpp b/tests/library_checker_aizu_tests/handmade_tests/dsu_size.test.cpp deleted file mode 100644 index edc0a2a9..00000000 --- a/tests/library_checker_aizu_tests/handmade_tests/dsu_size.test.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#define PROBLEM \ - "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A" -#include "../template.hpp" -#include "../../../library/contest/random.hpp" -#include "../../../library/data_structures/dsu/dsu_restorable.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - for (int n = 1; n < 100; n++) { - dsu_restorable dsu(n); - vector> adj(n); - vector> edge_st; - for (int q = 0; q < 100; q++) { - int type = rnd(0, 2); - if (type == 0) { - int u = rnd(0, n - 1), v = rnd(0, n - 1); - dsu.join(u, v); - adj[u].push_back(v); - adj[v].push_back(u); - edge_st.emplace_back(u, v); - } else if (type == 1) { - vector> comps; - vector vis(n); - auto dfs = [&](auto&& self, int node) -> void { - comps.back().push_back(node); - for (auto next : adj[node]) - if (!vis[next]) { - vis[next] = true; - self(self, next); - } - }; - for (int i = 0; i < n; i++) { - if (!vis[i]) { - comps.emplace_back(); - vis[i] = true; - dfs(dfs, i); - } - } - assert(sz(comps) == dsu.num_sets); - for (auto& cc : comps) - for (auto node : cc) - assert(dsu.size(node) == sz(cc)); - } else if (!empty(edge_st)) { - auto [u, v] = edge_st.back(); - edge_st.pop_back(); - assert(adj[u].back() == v && adj[v].back() == u); - adj[u].pop_back(); - adj[v].pop_back(); - dsu.undo(); - } - } - } - cout << "Hello World\n"; - return 0; -} diff --git a/tests/library_checker_aizu_tests/handmade_tests/edge_cd_small_trees.test.cpp b/tests/library_checker_aizu_tests/handmade_tests/edge_cd_small_trees.test.cpp deleted file mode 100644 index e8c20167..00000000 --- a/tests/library_checker_aizu_tests/handmade_tests/edge_cd_small_trees.test.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#define PROBLEM \ - "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A" -#include "../template.hpp" -#include "../edge_cd_asserts.hpp" -#include "../../../kactl/stress-tests/utilities/genTree.h" -#include "../../../library/trees/edge_cd.hpp" -int main() { - { - vector> adj; - edge_cd(adj, - [&](const vector>&, int, int) -> void { - assert(false); - }); - } - { - vector> adj(1); - edge_cd(adj, - [&](const vector>&, int, int) -> void { - assert(false); - }); - } - for (int n = 2; n <= 7; n++) { - int num_codes = 1; - for (int k = 0; k < n - 2; k++) num_codes *= n; - // int num_codes = mpow(n, n - 2).x; - vector> pruf_codes(num_codes, - vector(n - 2)); - for (int i = 0; i < num_codes; i++) { - int val = i; - for (int j = 0; j < n - 2; j++) { - int digit = val % n; - val /= n; - pruf_codes[i][j] = digit + 1; - } - } - for (vector& code : pruf_codes) { - auto edges = pruferCodeToTree(code); - assert(sz(edges) == n - 1); - vector> adj(n); - for (auto [u, v] : edges) { - u--, v--; - adj[u].push_back(v); - adj[v].push_back(u); - } - edge_cd(adj, edge_cd_asserts); - } - } - cout << "Hello World\n"; - return 0; -} diff --git a/tests/library_checker_aizu_tests/handmade_tests/fib_matrix_expo.test.cpp b/tests/library_checker_aizu_tests/handmade_tests/fib_matrix_expo.test.cpp deleted file mode 100644 index 5aa467aa..00000000 --- a/tests/library_checker_aizu_tests/handmade_tests/fib_matrix_expo.test.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#define PROBLEM \ - "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A" -#include "../template.hpp" -#include "../../../library/contest/random.hpp" -#include "../../../library/math/fibonacci.hpp" -// NOLINTNEXTLINE(readability-identifier-naming) -const int MOD = 998'244'353; -#include "../../../kactl/content/data-structures/Matrix.h" -#include "../../../hackpack-cpp/content/number-theory/ModInt.h" -void check(int64_t n) { - using mat_2_by_2 = Matrix; - mat_2_by_2 mat; - mat.d = {{{{1, 1}}, {{1, 0}}}}; - vector vec = {1, 0}; - int64_t res = fib(n)[0]; - assert(res == int(((mat ^ n) * vec)[1])); -} -int main() { - cin.tie(0)->sync_with_stdio(0); - // n=0 -> val=0 - // n=1 -> val=1 - // n=2 -> val=1 - // n=3 -> val=2 - // n=4 -> val=3 - // n=5 -> val=5 - assert(fib(0)[0] == 0); - assert(fib(1)[0] == 1); - assert(fib(2)[0] == 1); - assert(fib(3)[0] == 2); - assert(fib(4)[0] == 3); - assert(fib(5)[0] == 5); - for (int i = 0; i < 500; i++) check(i); - for (int tests = 1000; tests--;) - check(rnd(0LL, LLONG_MAX)); - cout << "Hello World\n"; - return 0; -} diff --git a/tests/library_checker_aizu_tests/handmade_tests/functional_graph.test.cpp b/tests/library_checker_aizu_tests/handmade_tests/functional_graph.test.cpp deleted file mode 100644 index db0a2da3..00000000 --- a/tests/library_checker_aizu_tests/handmade_tests/functional_graph.test.cpp +++ /dev/null @@ -1,155 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/problems/ITP1_1_A" -#include "../template.hpp" -#include "../../../library/contest/random.hpp" -#include "../../../library/graphs/uncommon/functional_graph_processor.hpp" -// https://github.com/Aeren1564/Algorithms/blob/master/Algorithm_Implementations_Cpp/Graph_Theory/Special_Graphs/functional_graph_processor.sublime-snippet -struct functional_graph_processor { - functional_graph_processor(const vector &next) { - init(sz(next)); - build(next); - } - template - functional_graph_processor(const Graph_t &g) { - init(g.n); - build(g); - } - void init(int a_n) { - n = a_n; - cycle.clear(); - cycle_id.assign(n, -1); - cycle_pos.assign(n, -1); - cycle_prev.assign(n, -1); - component_size.assign(n, -1); - root_of.assign(n, -1); - depth.assign(n, -1); - order.clear(); - pos.assign(n, -1); - end.assign(n, -1); - size.assign(n, -1); - abr.assign(n, {}); - was.assign(n, -2); - was2.assign(n, -2); - attempt = -1; - } - int attempt; - vector was, was2; - void build(const vector &next) { - cycle.clear(); - for (int i = 0; i < n; i++) { - cycle_id[i] = -1; - cycle_pos[i] = -1; - cycle_prev[i] = -1; - } - ++attempt; - for (auto u = 0; u < n; ++u) { - if (was[u] == attempt) continue; - int v = u; - while (was[v] != attempt) { - was[v] = attempt; - v = next[v]; - } - if (was2[v] != attempt) { - int w = v; - vector c; - while (was2[w] != attempt) { - was2[w] = attempt; - cycle_id[w] = sz(cycle); - cycle_pos[w] = sz(c); - c.push_back(w); - root_of[w] = w; - depth[w] = 0; - w = next[w]; - } - cycle.push_back(c); - } - auto dfs = [&](auto self, int u2) -> void { - if (was2[u2] == attempt) return; - was2[u2] = attempt; - int v2 = next[u2]; - self(self, v2); - root_of[u2] = root_of[v2]; - depth[u2] = depth[v2] + 1; - abr[v2].push_back(u2); - }; - dfs(dfs, u); - } - for (auto u = 0; u < n; ++u) - if (~cycle_pos[u]) cycle_prev[next[u]] = u; - for (const auto &c : cycle) { - auto dfs = [&](auto self, int u) -> void { - size[u] = 1; - pos[u] = sz(order); - order.push_back(u); - for (auto v : abr[u]) { - self(self, v); - size[u] += size[v]; - } - end[u] = sz(order); - }; - int csize = 0; - for (auto u : c) { - dfs(dfs, u); - csize += size[u]; - } - for (auto u : c) - for (auto i = pos[u]; i < end[u]; ++i) { - int v = order[i]; - component_size[v] = csize; - } - } - } - int n; - vector> cycle; - vector cycle_id; // id of the cycle it belongs to, - // -1 if not part of one - vector cycle_pos; // position in its cycle, -1 if - // not part of one - vector cycle_prev; // previous vertex in its cycle, - // -1 if not part of one - vector component_size; // size of its weakly - // connected component - vector root_of; // first reachable node in a cycle - vector depth; // distance to its root - vector> - abr; // forest of arborescences of reversed edges not - // on the cycles - vector order; // dfs order of abr - vector pos; // pos in the dfs order - vector end; // [pos[u], end[u]) denotes the subtree - vector size; // size of the subtree in abr -}; -int main() { - cin.tie(0)->sync_with_stdio(0); - for (int num_tests = 100; num_tests--;) { - int n = rnd(1, 1000); - vector a(n); - for (int i = 0; i < n; i++) a[i] = rnd(0, n - 1); - auto [root_of, cycle, childs] = func_graph(a); - functional_graph_processor fgp(a); - assert(cycle == fgp.cycle); - assert(childs == fgp.abr); - for (int i = 0; i < n; i++) { - int root = - cycle[root_of[i].first][root_of[i].second]; - assert(root == fgp.root_of[i]); - assert((root == i) == (fgp.cycle_id[i] != -1)); - if (root == i) { - assert(root_of[i].first == fgp.cycle_id[i]); - assert(root_of[i].second == fgp.cycle_pos[i]); - int cyc_len = ssize(cycle[root_of[i].first]); - assert(cycle[root_of[i].first] - [(root_of[i].second + 1) % cyc_len] == - a[i]); - assert(fgp.cycle_prev[i] == - cycle[root_of[i].first] - [(root_of[i].second - 1 + cyc_len) % - cyc_len]); - } else { - assert(fgp.cycle_prev[i] == -1); - } - } - } - cout << "Hello World\n"; - return 0; -} diff --git a/tests/library_checker_aizu_tests/handmade_tests/manacher.test.cpp b/tests/library_checker_aizu_tests/handmade_tests/manacher.test.cpp deleted file mode 100644 index db955c70..00000000 --- a/tests/library_checker_aizu_tests/handmade_tests/manacher.test.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#define PROBLEM \ - "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A" -#include "../template.hpp" -#include "../../../library/contest/random.hpp" -#include "../../../library/strings/manacher/longest_from_index.hpp" -#include "../../../library/strings/manacher/longest_palindrome_query.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - for (int n = 1; n <= 50; n++) { - for (int tests = 20; tests--;) { - string s(n, 'a'); - if (n == 0 || rnd(0, 1) == 0) { - int mx_char = rnd(0, 5); - generate(begin(s), end(s), [&]() { - return char('a' + rnd(0, mx_char)); - }); - } else { - for (int i = 5; i--;) s[rnd(0, n - 1)] = 'b'; - } - pal_query pq(s); - vector> is_pal_naive(n + 1, - vector(n + 1, 1)); - for (int len = 0; len <= n; len++) { - for (int l = 0; l + len <= n; l++) { - int r = l + len; - if (len >= 2) - is_pal_naive[l][r] = (s[l] == s[r - 1] && - is_pal_naive[l + 1][r - 1]); - } - } - for (int i = 0; i < n; i++) - for (int j = i; j < n; j++) - assert( - pq.is_pal(i, j) == is_pal_naive[i][j + 1]); - vector longest(longest_from_index(pq)); - for (int l = 0; l < n; l++) { - bool seen_pal = 0; - for (int r = n; r >= l; r--) { - seen_pal |= is_pal_naive[l][r]; - assert((longest[l] + 1 >= r) == seen_pal); - } - } - vector> count_pals_naive(n + 1, - vector(n + 1, 0)); - for (int l = 0; l + 1 <= n; l++) - count_pals_naive[l][l + 1] = 1; - for (int len = 2; len <= n; len++) { - for (int l = 0; l + len <= n; l++) { - int r = l + len; - count_pals_naive[l][r] = pq.is_pal(l, r - 1) + - count_pals_naive[l + 1][r] + - count_pals_naive[l][r - 1] - - count_pals_naive[l + 1][r - 1]; - } - } - vector> longest_pal(n + 1, - vector(n + 1, 0)); - longest_pal_query lp(s); - for (int len = 1; len <= n; len++) { - for (int l = 0; l + len <= n; l++) { - int r = l + len; - if (is_pal_naive[l][r]) longest_pal[l][r] = len; - else - longest_pal[l][r] = max(longest_pal[l + 1][r], - longest_pal[l][r - 1]); - auto [curr_idx, curr_len] = lp.longest_pal(l, r); - assert(curr_len == longest_pal[l][r]); - assert( - pq.is_pal(curr_idx, curr_idx + curr_len - 1)); - assert(l <= curr_idx); - assert(curr_idx + curr_len <= r); - } - } - } - } - cout << "Hello World\n"; - return 0; -} diff --git a/tests/library_checker_aizu_tests/handmade_tests/merge_st_and_wavelet.test.cpp b/tests/library_checker_aizu_tests/handmade_tests/merge_st_and_wavelet.test.cpp deleted file mode 100644 index e4afe658..00000000 --- a/tests/library_checker_aizu_tests/handmade_tests/merge_st_and_wavelet.test.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#define PROBLEM \ - "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A" -#include "../template.hpp" -#include "../../../library/contest/random.hpp" -#include "../../../library/data_structures/seg_tree_uncommon/merge_sort_tree.hpp" -#include "../../../library/data_structures/seg_tree_uncommon/wavelet_matrix.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - // brute force small cases - for (int n = 0; n <= 25; n++) { - for (int tests = 10; tests--;) { - int minn = rnd(-1000, 1000); - int maxn = rnd(-1000, 1000); - if (minn > maxn) swap(minn, maxn); - vector arr(n); - generate(begin(arr), end(arr), - [&]() { return rnd(minn, maxn); }); - merge_sort_tree mst(arr); - vector arr_shifted(n); - rep(i, 0, n) arr_shifted[i] = arr[i] - minn; - wavelet_matrix wm(arr_shifted, maxn - minn); - for (int queries = 30; queries--;) { - int x = rnd(minn, maxn); - int y = rnd(minn, maxn); - if (x > y) swap(x, y); - for (int l = 0; l <= n; l++) { - int cnt = 0; - for (int r = l; r <= n; r++) { - assert(mst.query(l, r, x, y) == cnt); - assert(wm.count(l, r, y - minn) - - wm.count(l, r, x - minn) == - cnt); - if (r < n && x <= arr[r] && arr[r] < y) cnt++; - } - } - } - } - } - cout << "Hello World\n"; - return 0; -} diff --git a/tests/library_checker_aizu_tests/handmade_tests/mobius.test.cpp b/tests/library_checker_aizu_tests/handmade_tests/mobius.test.cpp deleted file mode 100644 index 0132e131..00000000 --- a/tests/library_checker_aizu_tests/handmade_tests/mobius.test.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#define PROBLEM \ - "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A" -#include "../template.hpp" -#include "../../../kactl/content/number-theory/Factor.h" -int main() { - cin.tie(0)->sync_with_stdio(0); -#include "../../../library/math/prime_sieve/mobius.hpp" -#include "../../../library/math/prime_sieve/is_prime.hpp" - assert(is_prime(2)); - for (int i = 1; i < sz(mobius); i++) { - int val = i; - map factors; - for (auto prime_factor : factor(val)) - factors[prime_factor]++; - { - bool found_square = 0; - for (auto [prime, exponent] : factors) { - if (exponent > 1) { - assert(mobius[i] == 0); - found_square = 1; - break; - } - } - if (found_square) continue; - } - assert(1 - 2 * (sz(factors) % 2) == mobius[i]); - } - cout << "Hello World\n"; - return 0; -} diff --git a/tests/library_checker_aizu_tests/handmade_tests/mod_division.test.cpp b/tests/library_checker_aizu_tests/handmade_tests/mod_division.test.cpp deleted file mode 100644 index b4e0b429..00000000 --- a/tests/library_checker_aizu_tests/handmade_tests/mod_division.test.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/problems/ITP1_1_A" -#include "../template.hpp" -#define const ; -#include "../../../library/math/mod_division.hpp" -#undef const -int main() { - cin.tie(0)->sync_with_stdio(0); - for (mod = 1; mod < 500; mod++) { - for (int x = 0; x < mod; x++) { - for (int y = 0; y < mod; y++) { - if (gcd(y, mod) == 1) { - int quotient = mod_div(x, y); - assert(1LL * quotient * y % mod == x); - } - } - } - } - cout << "Hello World\n"; - return 0; -} diff --git a/tests/library_checker_aizu_tests/handmade_tests/n_choose_k.test.cpp b/tests/library_checker_aizu_tests/handmade_tests/n_choose_k.test.cpp deleted file mode 100644 index 9e2f8319..00000000 --- a/tests/library_checker_aizu_tests/handmade_tests/n_choose_k.test.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#define PROBLEM \ - "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A" -#include "../template.hpp" -#include "../../../library/contest/random.hpp" -#include "../../../library/math/n_choose_k/large_n_choose_small_k.hpp" -#include "../../../library/math/n_choose_k/lucas_theorem.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); -#define mod mod_2 -#include "../../../library/math/n_choose_k/pascals_identity.hpp" -#undef mod - for (int i = 0; i < sz(ch); i++) { - assert(ch[i][0] == 1 && end(ch[i])[-1] == 1); - assert(lucas(i, -1) == 0); - assert(c_small_k(i, -1) == 0); - assert(lucas(i, i + 1) == 0); - assert(c_small_k(i, i + 1) == 0); - assert(lucas(-1, i) == 0); - assert(c_small_k(-1, i) == 0); - assert(lucas(i, i - 1) == i % mod); - if (i - 1 < mod) - assert(c_small_k(i, i - 1) == i % mod); - for (int j = 0; j < sz(ch[i]); j++) { - assert(lucas(i, j) == ch[i][j]); - if (j < mod) assert(c_small_k(i, j) == ch[i][j]); - } - } - for (int tests = 100'000; tests--;) { - auto n = rnd(int64_t(-1e18), int64_t(1e18)); - auto k = rnd(-mod, mod - 1); - assert(lucas(n, k) == c_small_k(n, k)); - } - assert(lucas(371283LL, 32981LL) == 0); - assert( - lucas(47382946300290018LL, 47382946300290014LL) == 7); - assert( - lucas(4032010405302301LL, 403201040302301LL) == 0); - assert( - lucas(4032010405302301LL, 4032010405302298LL) == 4); - cout << "Hello World\n"; - return 0; -} diff --git a/tests/library_checker_aizu_tests/handmade_tests/permutation_tree_small.test.cpp b/tests/library_checker_aizu_tests/handmade_tests/permutation_tree_small.test.cpp deleted file mode 100644 index b39e64b8..00000000 --- a/tests/library_checker_aizu_tests/handmade_tests/permutation_tree_small.test.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#define PROBLEM \ - "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A" -#include "../template.hpp" -#include "../perm_tree_asserts.hpp" -#include "../../../library/data_structures/uncommon/permutation_tree.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - for (int n = 1; n <= 8; n++) { - vector a(n); - iota(begin(a), end(a), 0); - do { - perm_tree pt = perm_tree_asserts(a); - } while (next_permutation(begin(a), end(a))); - } - cout << "Hello World\n"; - return 0; -} diff --git a/tests/library_checker_aizu_tests/handmade_tests/rmq_small_n.test.cpp b/tests/library_checker_aizu_tests/handmade_tests/rmq_small_n.test.cpp deleted file mode 100644 index 2dbec0e4..00000000 --- a/tests/library_checker_aizu_tests/handmade_tests/rmq_small_n.test.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#define PROBLEM \ - "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A" -#include "../template.hpp" -#include "../../../library/contest/random.hpp" -#include "../../../library/data_structures/rmq.hpp" -#include "../../../library/data_structures/uncommon/disjoint_rmq.hpp" -#include "../../../library/data_structures/uncommon/linear_rmq.hpp" -void test_all_subarrays(const vector& a) { - auto n = sz(a); - RMQ rmq(a, [](auto x, auto y) { return min(x, y); }); - disjoint_rmq dis_rmq(a, - [](auto x, auto y) { return min(x, y); }); - linear_rmq lin_rmq(a, less()); - for (int l = 0; l < n; l++) { - for (int r = l + 1; r <= n; r++) { - int idx_min = lin_rmq.idx(l, r - 1); - assert(l <= idx_min && idx_min < r); - assert(a[idx_min] == rmq.query(l, r)); - assert(a[idx_min] == dis_rmq.query(l, r)); - } - } -} -int main() { - cin.tie(0)->sync_with_stdio(0); - for (int n = 1; n <= 8; n++) { - vector perm(n); - iota(begin(perm), end(perm), 0); - do { - test_all_subarrays(perm); - } while (next_permutation(begin(perm), end(perm))); - } - for (int n = 1; n <= 100; n++) { - for (int times = 0; times < 40; times++) { - vector a(n); - for (int i = 0; i < n; i++) - a[i] = rnd(INT_MIN, INT_MAX); - test_all_subarrays(a); - } - } - cout << "Hello World\n"; -} diff --git a/tests/library_checker_aizu_tests/handmade_tests/sa_find_subarray.test.cpp b/tests/library_checker_aizu_tests/handmade_tests/sa_find_subarray.test.cpp deleted file mode 100644 index b0f257c5..00000000 --- a/tests/library_checker_aizu_tests/handmade_tests/sa_find_subarray.test.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#define PROBLEM \ - "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A" -#include "../template.hpp" -#include "../../../library/contest/random.hpp" -#include "../../../library/strings/suffix_array/suffix_array_query.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - for (int n = 1; n <= 30; n++) { - for (int tests = 10; tests--;) { - string s(n, 'a'); - int mx_char = rnd(0, 5); - generate(begin(s), end(s), [&]() { - return char('a' + rnd(0, mx_char)); - }); - auto [sa, sa_inv, lcp] = get_sa(s, 256); - sa_query lq(s, sa, sa_inv, lcp); - for (int i = 0; i < n; i++) { - for (int j = i; j <= n; j++) { - auto [sa_le, sa_ri, s_l, s_r] = - lq.find_substrs_concated({{i, j}}); - pair short_res = lq.find_substr(i, j); - assert(sa_le == short_res.first && - sa_ri == short_res.second); - assert(s.substr(i, j - i) == - s.substr(s_l, s_r - s_l)); - if (i == j) { - assert(sa_le == 0 && sa_ri == n); - assert(s_l == s_r); - } - if (i < n) - assert(0 <= sa_le && sa_le <= lq.sa_inv[i] && - lq.sa_inv[i] < sa_ri && sa_ri <= n); - for (int idx = sa_le; idx < sa_ri; idx++) - assert(s.substr(lq.sa[idx], j - i) == - s.substr(i, j - i)); - assert(sa_le == 0 || - s.substr(lq.sa[sa_le - 1], j - i) != - s.substr(i, j - i)); - assert(sa_ri == n || - s.substr(lq.sa[sa_ri], j - i) != - s.substr(i, j - i)); - } - } - for (int i = 0; i < n; i++) { - for (int k = 0; k < n; k++) { - for (int j = i; j <= n; j++) { - for (int l = k; l <= n; l++) { - int cmp_val = lq.cmp_substrs(i, j, k, l); - string sub1 = s.substr(i, j - i); - string sub2 = s.substr(k, l - k); - if (cmp_val < 0) assert(sub1 < sub2); - if (cmp_val == 0) assert(sub1 == sub2); - if (cmp_val > 0) assert(sub1 > sub2); - } - } - string suf1 = s.substr(i); - string suf2 = s.substr(k); - int cmp_val = lq.cmp_sufs(i, k); - if (cmp_val < 0) assert(suf1 < suf2); - if (cmp_val == 0) assert(suf1 == suf2); - if (cmp_val > 0) assert(suf1 > suf2); - } - } - } - } - cout << "Hello World\n"; - return 0; -} diff --git a/tests/library_checker_aizu_tests/handmade_tests/seg_tree_find.test.cpp b/tests/library_checker_aizu_tests/handmade_tests/seg_tree_find.test.cpp deleted file mode 100644 index 75920096..00000000 --- a/tests/library_checker_aizu_tests/handmade_tests/seg_tree_find.test.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#define PROBLEM \ - "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A" -#include "../template.hpp" -#include "../../../library/contest/random.hpp" -#include "../../../library/data_structures/bit.hpp" -#include "../../../library/data_structures/lazy_seg_tree.hpp" -const int mx_n = 100'000; -int rv(int i) { return mx_n - i - 1; } -int main() { - cin.tie(0)->sync_with_stdio(0); - BIT bit(mx_n); - seg_tree seg(mx_n), rev(mx_n); - for (int i = 0; i < mx_n; i++) - bit.update(i, 1), seg.update(i, i + 1, 1), - rev.update(i, i + 1, 1); - for (int q = 0; q < 100'000; q++) { - int i = rnd(0, mx_n - 1); - int add = rnd(0, 100'000); - bit.update(i, add); - seg.update(i, i + 1, add); - rev.update(rv(i), rv(i) + 1, add); - int l = rnd(0, mx_n - 1); - int r = rnd(l + 1, mx_n); - int64_t in_tree = seg.query(l, r); - auto sum = rnd(1, in_tree); - int64_t need; - vector> rngs; - auto reset = [&] { - need = sum; - rngs = {}; - }; - auto f = [&](int64_t x, int tl, int tr) -> bool { - if (x < need) { - rngs.push_back({tl, tr, 0}); - need -= x; - return 0; - } - rngs.push_back({tl, tr, 1}); - return 1; - }; - int pos = min(bit.walk(bit.query(l) + sum), r); - reset(); - assert(pos == seg.find_first(l, r, f)); - assert(!empty(rngs)); - assert(rngs[0][0] == l); - for (auto [tl, tr, _] : rngs) - assert(l <= tl && tl < tr && tr <= r); - for (int it = 1; it < sz(rngs); it++) { - auto [prv_le, prv_ri, prv] = rngs[it - 1]; - auto [cur_le, cur_ri, cur] = rngs[it]; - if (prv) assert(cur_le == prv_le && cur_ri < prv_ri); - else assert(cur_le == prv_ri); - } - sort(begin(rngs), end(rngs)); - assert(unique(begin(rngs), end(rngs)) == end(rngs)); - reset(); - assert( - pos == rv(rev.find_last(rv(r - 1), rv(l) + 1, f))); - assert(!empty(rngs)); - assert(rngs[0][1] == rv(l) + 1); - for (auto [tl, tr, _] : rngs) - assert( - rv(r - 1) <= tl && tl < tr && tr <= rv(l) + 1); - for (int it = 1; it < sz(rngs); it++) { - auto [prv_le, prv_ri, prv] = rngs[it - 1]; - auto [cur_le, cur_ri, cur] = rngs[it]; - if (prv) assert(cur_ri == prv_ri && cur_le > prv_le); - else assert(prv_le == cur_ri); - } - sort(begin(rngs), end(rngs)); - assert(unique(begin(rngs), end(rngs)) == end(rngs)); - } - cout << "Hello World\n"; - return 0; -} diff --git a/tests/library_checker_aizu_tests/handmade_tests/seg_tree_find_small.test.cpp b/tests/library_checker_aizu_tests/handmade_tests/seg_tree_find_small.test.cpp deleted file mode 100644 index 92d8c688..00000000 --- a/tests/library_checker_aizu_tests/handmade_tests/seg_tree_find_small.test.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#define PROBLEM \ - "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A" -#include "../template.hpp" -#include "../../../library/contest/random.hpp" -#include "../../../library/data_structures/lazy_seg_tree.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - for (int iters = 0; iters < 100; ++iters) { - int n = 1'000; - seg_tree seg(n); - vector a(n); - for (int q = 0; q < 1'000; q++) { - if (rnd(0, 1) == 0) { - int l = rnd(0, n - 1); - int r = rnd(l + 1, n); - int diff = rnd(0, 10); - seg.update(l, r, diff); - for (int i = l; i < r; i++) a[i] += diff; - } else { - int l = rnd(0, n - 1); - int r = rnd(l + 1, n); - int target_sum = rnd(0, 100); - int smallest_index_greater_sum = r; - for (int pos = l, sum = 0; pos < r; pos++) { - sum += a[pos]; - if (sum > target_sum) { - smallest_index_greater_sum = pos; - break; - } - } - int largest_index_greater_sum = l - 1; - for (int pos = r - 1, sum = 0; pos >= l; pos--) { - sum += a[pos]; - if (sum > target_sum) { - largest_index_greater_sum = pos; - break; - } - } - int st_walk_sum; - auto f = [&](int64_t x, int, int) -> bool { - if (st_walk_sum + x <= target_sum) { - st_walk_sum += x; - return 0; - } - return 1; - }; - st_walk_sum = 0; - assert(smallest_index_greater_sum == - seg.find_first(l, r, f)); - st_walk_sum = 0; - assert(largest_index_greater_sum == - seg.find_last(l, r, f)); - } - } - } - cout << "Hello World\n"; - return 0; -} diff --git a/tests/library_checker_aizu_tests/kactl_macros.hpp b/tests/library_checker_aizu_tests/kactl_macros.hpp deleted file mode 100644 index 6e053f5a..00000000 --- a/tests/library_checker_aizu_tests/kactl_macros.hpp +++ /dev/null @@ -1,6 +0,0 @@ -#define rep(i, a, b) for (int i = a; i < b; i++) -#define all(x) begin(x), end(x) -#define sz(x) ssize(x) -#define ll int64_t -#define pii pair -#define vi vector diff --git a/tests/library_checker_aizu_tests/loops/chooses.test.cpp b/tests/library_checker_aizu_tests/loops/chooses.test.cpp deleted file mode 100644 index b12f8bef..00000000 --- a/tests/library_checker_aizu_tests/loops/chooses.test.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/courses/lesson/8/ITP2/all/ITP2_11_D" -#include "../template.hpp" -#include "../../../library/loops/next_subset.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, k; - cin >> n >> k; -#include "../../../library/loops/chooses.hpp" - { - cout << mask << ':'; - for (int bit = 0; bit < n; bit++) - if ((mask >> bit) & 1) cout << ' ' << bit; - cout << '\n'; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/loops/quotients.test.cpp b/tests/library_checker_aizu_tests/loops/quotients.test.cpp deleted file mode 100644 index ddc73c79..00000000 --- a/tests/library_checker_aizu_tests/loops/quotients.test.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/enumerate_quotients" -#include "../template.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int64_t n; - cin >> n; - vector quots; - { - int64_t prev_ri = 0; -#include "../../../library/loops/quotients.hpp" - { - assert(n / l == n / r); - assert(l == 1 || n / l < n / (l - 1)); - assert(n / (r + 1) < n / r); - assert(prev_ri + 1 == l); - prev_ri = r; - quots.push_back(n / l); - } - assert(prev_ri == n); - } - cout << sz(quots) << '\n'; - for (int i = sz(quots) - 1; i >= 0; i--) - cout << quots[i] << ' '; - cout << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/loops/submasks.test.cpp b/tests/library_checker_aizu_tests/loops/submasks.test.cpp deleted file mode 100644 index f20aadee..00000000 --- a/tests/library_checker_aizu_tests/loops/submasks.test.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/courses/lesson/8/ITP2/all/ITP2_11_C" -#include "../template.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, k; - cin >> n >> k; - int mask = 0; - for (int i = 0; i < k; i++) { - int bit; - cin >> bit; - mask |= 1 << bit; - } - cout << 0 << ':' << '\n'; - vector sb_msks; - { -#include "../../../library/loops/submasks.hpp" - sb_msks.push_back(submask); - } - reverse(begin(sb_msks), end(sb_msks)); - for (auto submask : sb_msks) { - cout << submask << ':'; - for (int bit = 0; bit < n; bit++) - if ((submask >> bit) & 1) cout << ' ' << bit; - cout << '\n'; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/loops/supermasks.test.cpp b/tests/library_checker_aizu_tests/loops/supermasks.test.cpp deleted file mode 100644 index ac7f0e45..00000000 --- a/tests/library_checker_aizu_tests/loops/supermasks.test.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/courses/lesson/8/ITP2/all/ITP2_11_B" -#include "../template.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, k; - cin >> n >> k; - int mask = 0; - for (int i = 0; i < k; i++) { - int bit; - cin >> bit; - mask |= 1 << bit; - } - vector sup_msks; - { -#include "../../../library/loops/supermasks.hpp" - sup_msks.push_back(supermask); - } - for (auto supermask : sup_msks) { - cout << supermask << ':'; - for (int bit = 0; bit < n; bit++) - if ((supermask >> bit) & 1) cout << ' ' << bit; - cout << '\n'; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/math/binary_matrix_mult.test.cpp b/tests/library_checker_aizu_tests/math/binary_matrix_mult.test.cpp deleted file mode 100644 index 9259e41b..00000000 --- a/tests/library_checker_aizu_tests/math/binary_matrix_mult.test.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/matrix_product_mod_2" -#include "../template.hpp" -#include "../../../library/math/matrix_related/binary_matrix_mult.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, m, k; - cin >> n >> m >> k; - const int mx_n = 1 << 12; - array, mx_n> m1, m2; - for (int i = 0; i < n; i++) { - string row; - cin >> row; - for (int j = 0; j < m; j++) m1[i][j] = row[j] - '0'; - } - for (int i = 0; i < m; i++) { - string row; - cin >> row; - for (int j = 0; j < k; j++) m2[i][j] = row[j] - '0'; - } - auto prod = m1 * m2; - for (int i = 0; i < n; i++) { - for (int j = 0; j < k; j++) cout << prod[i][j]; - cout << '\n'; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/math/count_paths.test.cpp b/tests/library_checker_aizu_tests/math/count_paths.test.cpp deleted file mode 100644 index 7f8e5220..00000000 --- a/tests/library_checker_aizu_tests/math/count_paths.test.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/number_of_increasing_sequences_between_two_sequences" -#include "../template.hpp" -#define const ; -#define mod mod_different_name -#include "../../../library/math/n_choose_k/grow.hpp" -#undef const -#undef mod -#define mod mod_not_using -#define modpow modpow_not_using -#include "../../../kactl/content/number-theory/ModPow.h" -#undef mod -#undef modpow -ll modpow(ll b, ll e) { - ll ans = 1; - for (; e; b = b * b % 998'244'353, e /= 2) - if (e & 1) ans = ans * b % 998'244'353; - return ans; -} -#include "../../../library/math/count_paths/count_paths_triangle.hpp" -ll count_between_two_sequences(const vl& a, const vl& b) { - int n = sz(a); - vl dp(b[0] - a[0]); - dp[0] = 1; - for (int i = 0; i < n;) { - int j = i; - { - vl h(b[i] - a[i]); - for (int num = a[i]; num < b[i]; num++) { - while (j < n && a[j] <= num) j++; - h[num - a[i]] = j - i; - } - assert(sz(dp) <= sz(h)); - while (sz(dp) < sz(h)) dp.push_back(0); - dp = divide_and_conquer(h, dp); - } - { - vl h(j - i); - for (int k = i; k < j; k++) h[k - i] = b[k] - b[i]; - if (h.back() == 0) break; - dp = divide_and_conquer(h, dp); - if (j < n) - dp = vl(begin(dp) + (a[j] - b[i]), end(dp)); - } - i = j; - } - return dp.back(); -} -int main() { - cin.tie(0)->sync_with_stdio(0); - mod_different_name = 998'244'353; - int n, m; - cin >> n >> m; - vl a(n), b(n); - for (int i = 0; i < n; i++) cin >> a[i]; - for (int i = 0; i < n; i++) cin >> b[i]; - for (int i = 1; i < n; i++) a[i] = max(a[i], a[i - 1]); - for (int i = n - 2; i >= 0; i--) - b[i] = min(b[i], b[i + 1]); - for (int i = 0; i < n; i++) { - if (a[i] >= b[i]) { - cout << 0 << '\n'; - return 0; - } - } - a.insert(begin(a), a[0]); - b.push_back(b.back()); - cout << count_between_two_sequences(a, b) << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/math/derangement.test.cpp b/tests/library_checker_aizu_tests/math/derangement.test.cpp deleted file mode 100644 index d04009a3..00000000 --- a/tests/library_checker_aizu_tests/math/derangement.test.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/montmort_number_mod" -#include "../template.hpp" -#include "../../../library/math/derangements.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, mod; - cin >> n >> mod; - vector der = derangements(n + 1, mod); - for (int i = 1; i <= n; i++) cout << der[i] << " "; - cout << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/math/matrix_determinant.test.cpp b/tests/library_checker_aizu_tests/math/matrix_determinant.test.cpp deleted file mode 100644 index 4421321e..00000000 --- a/tests/library_checker_aizu_tests/math/matrix_determinant.test.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/matrix_det" -#include "../template.hpp" -#include "../../../library/math/matrix_related/row_reduce.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n; - cin >> n; - vector> matrix(n, vector(n)); - for (int i = 0; i < n; i++) - for (int j = 0; j < n; j++) cin >> matrix[i][j]; - auto [rank, det] = row_reduce(matrix, n); - cout << det << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/math/matrix_mult.test.cpp b/tests/library_checker_aizu_tests/math/matrix_mult.test.cpp deleted file mode 100644 index 38117dcd..00000000 --- a/tests/library_checker_aizu_tests/math/matrix_mult.test.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/matrix_product" -// IMO the vector checks && runtime sanitizer (which checks -// index out of bounds) suffices here. All the other stuff -// each slows down the test by 5-10 seconds, which adds up -// to a TLE. -#undef _GLIBCXX_DEBUG -#undef _GLIBCXX_DEBUG_PEDANTIC -#undef _GLIBCXX_ASSERTIONS -#include "../template.hpp" -#include "../../../library/math/matrix_related/matrix_mult.hpp" -// NOLINTNEXTLINE(readability-identifier-naming) -const int MOD = 998'244'353; -#include "../../../hackpack-cpp/content/number-theory/ModInt.h" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, m, k; - cin >> n >> m >> k; - vector> m1(n, vector(m)); - for (int i = 0; i < n; i++) - for (int j = 0; j < m; j++) cin >> m1[i][j]; - vector> m2(m, vector(k)); - for (int i = 0; i < m; i++) - for (int j = 0; j < k; j++) cin >> m2[i][j]; - auto prod = m1 * m2; - for (int i = 0; i < n; i++) { - for (int j = 0; j < k; j++) cout << prod[i][j] << " "; - cout << '\n'; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/math/n_choose_k.test.cpp b/tests/library_checker_aizu_tests/math/n_choose_k.test.cpp deleted file mode 100644 index 2c031f00..00000000 --- a/tests/library_checker_aizu_tests/math/n_choose_k.test.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/binomial_coefficient_prime_mod" -#include "../template.hpp" -// trick to remove const so I can use arbitrary prime mode -// here -#define const ; -#include "../../../library/math/n_choose_k/n_choose_k.hpp" -#undef const -int main() { - cin.tie(0)->sync_with_stdio(0); - int num_tests; - cin >> num_tests >> mod; - while (num_tests--) { - int n, k; - cin >> n >> k; - cout << C(n, k) << '\n'; - if (n > 0) { - assert(C(-n, k) == 0); - assert(C(-n, -k) == 0); - assert(C(k, -n) == 0); - assert(C(-k, -n) == 0); - } - if (k > 0) { - assert(C(n, -k) == 0); - assert(C(-k, n) == 0); - } - } - for (int i = 0; i < sz(t); i++) { - if (i) assert(i * t[i].inv % mod == 1); - assert(t[i].fact * t[i].inv_fact % mod == 1); - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/math/num_subsequences.test.cpp b/tests/library_checker_aizu_tests/math/num_subsequences.test.cpp deleted file mode 100644 index df764c62..00000000 --- a/tests/library_checker_aizu_tests/math/num_subsequences.test.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/number_of_subsequences" -#include "../template.hpp" -#include "../../../library/math/num_distinct_subsequences.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - const int mod = 998244353; - int n; - cin >> n; - vector arr(n); - for (int i = 0; i < n; i++) cin >> arr[i]; - cout << (num_subsequences(arr, mod) - 1 + mod) % mod - << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/math/partitions.test.cpp b/tests/library_checker_aizu_tests/math/partitions.test.cpp deleted file mode 100644 index a457d21d..00000000 --- a/tests/library_checker_aizu_tests/math/partitions.test.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/partition_function" -#include "../template.hpp" -#include "../../../library/math/partitions.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n; - cin >> n; - for (auto val : partitions(n + 1)) cout << val << " "; - cout << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/math/prime_sieve.test.cpp b/tests/library_checker_aizu_tests/math/prime_sieve.test.cpp deleted file mode 100644 index af82e7f7..00000000 --- a/tests/library_checker_aizu_tests/math/prime_sieve.test.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/courses/library/6/NTL/all/NTL_1_C" -#include "../template.hpp" -#include "../../../kactl/content/number-theory/MillerRabin.h" -int main() { - cin.tie(0)->sync_with_stdio(0); -#include "../../../library/math/prime_sieve/calc_sieve.hpp" -#include "../../../library/math/prime_sieve/is_prime.hpp" - for (int i = 1; i < sz(sieve); i++) - assert(isPrime(i) == is_prime(i)); - { -#define sieve linear_sieve -#include "../../../library/math/prime_sieve/calc_linear_sieve.hpp" -#undef sieve - assert(sieve == linear_sieve); - } - int n; - cin >> n; - map prime_to_max_exponent; - while (n--) { - int num; - cin >> num; - map curr; - { - int prev_prime = -1; -#include "../../../library/math/prime_sieve/get_prime_factors.hpp" - { - assert(p >= prev_prime); - prev_prime = p; - curr[p]++; - } - } - for (auto [p, e] : curr) - prime_to_max_exponent[p] = - max(prime_to_max_exponent[p], e); - } - int res = 1; - for (auto [p, e] : prime_to_max_exponent) - while (e--) res *= p; - cout << res << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/math/solve_linear_mod.test.cpp b/tests/library_checker_aizu_tests/math/solve_linear_mod.test.cpp deleted file mode 100644 index 432d531b..00000000 --- a/tests/library_checker_aizu_tests/math/solve_linear_mod.test.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/system_of_linear_equations" -#include "../template.hpp" -#include "../../../library/math/matrix_related/solve_linear_mod.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, m; - cin >> n >> m; - vector> mat(n, vector(m)); - for (int i = 0; i < n; i++) - for (int j = 0; j < m; j++) cin >> mat[i][j]; - vector b(n); - for (int i = 0; i < n; i++) cin >> b[i]; - solve_linear_mod info(mat, b); - assert(info.rank <= min(n, m)); - if (empty(info.sol)) { - cout << -1 << '\n'; - return 0; - } - cout << m - info.rank << '\n'; - for (int val : info.sol) cout << val << " "; - cout << '\n'; - vector pivot(m, -1); - for (int i = 0, j = 0; i < info.rank; i++) { - while (mat[i][j] == 0) j++; - pivot[j] = i; - } - for (int j = 0; j < m; j++) - if (pivot[j] == -1) { - vector x(m, 0); - x[j] = mod - 1; - for (int k = 0; k < j; k++) - if (pivot[k] != -1) x[k] = mat[pivot[k]][j]; - for (int k = 0; k < m; k++) cout << x[k] << " "; - cout << '\n'; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/math/tetration.test.cpp b/tests/library_checker_aizu_tests/math/tetration.test.cpp deleted file mode 100644 index 18f700b6..00000000 --- a/tests/library_checker_aizu_tests/math/tetration.test.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/tetration_mod" -#include "../template.hpp" -#include "../../../library/math/tetration_mod.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int t; - cin >> t; - while (t--) { - int a, b, mod; - cin >> a >> b >> mod; - cout << tetration(a, b, mod) << '\n'; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/math/totient.test.cpp b/tests/library_checker_aizu_tests/math/totient.test.cpp deleted file mode 100644 index 4a8875c7..00000000 --- a/tests/library_checker_aizu_tests/math/totient.test.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/courses/library/6/NTL/all/NTL_1_D" -#include "../template.hpp" -#include "../../../library/math/totient.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n; - cin >> n; - cout << totient(n) << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/math/xor_basis.test.cpp b/tests/library_checker_aizu_tests/math/xor_basis.test.cpp deleted file mode 100644 index d3c4ef70..00000000 --- a/tests/library_checker_aizu_tests/math/xor_basis.test.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#define PROBLEM \ - "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=3277" -#include "../template.hpp" -#include "../../../library/math/matrix_related/xor_basis_ordered.hpp" -#include "../../../library/math/matrix_related/xor_basis_unordered_intersection.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int k; - cin >> k; - vector> grid(k); - for (int i = 0; i < k; i++) { - int siz; - cin >> siz; - grid[i].resize(siz); - } - for (auto& row : grid) - for (auto& elem : row) cin >> elem; - vector> basises(1 << k); - for (int i = 0; i < k; i++) { - basis unordered; - basis_ordered ordered_ll; - basis_ordered> ordered_bitset; - int naive_size = 0; - for (auto elem : grid[i]) { - int64_t val1 = unordered.shrink(elem); - int64_t val2 = unordered.shrink(val1); - assert(val1 == val2); - for (int64_t v : unordered.b) - assert( - (bit_floor((unsigned long long)v) & val2) == 0); - bool inserted_unordered = unordered.insert(elem); - bool inserted_ordered_ll = ordered_ll.insert(elem); - bool inserted_ordered_bitset = - ordered_bitset.insert(bitset(elem)); - assert( - inserted_unordered == inserted_ordered_bitset); - assert(inserted_unordered == inserted_ordered_ll); - naive_size += inserted_unordered; - assert(naive_size == sz(unordered.b)); - assert(sz(unordered.b) == ordered_bitset.siz); - assert(sz(unordered.b) == ordered_ll.siz); - if (inserted_unordered) { - for (int64_t v : unordered.b) { - bitset curr_elem(v); - int idx = ordered_bitset.shrink(curr_elem); - assert(idx == -1); - idx = ordered_ll.shrink(v); - assert(idx == -1); - } - for (int j = 0; j < lg; j++) { - assert(ordered_bitset.b[j][j] == - ordered_bitset.b[j].any()); - assert(((ordered_ll.b[j] >> j) & 1) == - (!!ordered_ll.b[j])); - assert(ordered_bitset.b[j] == - bitset(ordered_ll.b[j])); - if (ordered_bitset.b[j][j]) - assert( - unordered.shrink( - ordered_bitset.b[j].to_ullong()) == 0); - } - for (int i1 = 0; i1 < sz(unordered.b); i1++) { - for (int i2 = i1 + 1; i2 < sz(unordered.b); - i2++) { - assert(__lg(unordered.b[i1]) != - __lg(unordered.b[i2])); - assert(((1LL << __lg(unordered.b[i1])) & - unordered.b[i2]) == 0); - } - } - } - } - basises[1 << i] = unordered; - } - int64_t res = 0; - for (int mask = 1; mask < (1 << k); mask++) { - if (__builtin_popcount(mask) > 1) { - basis u = basises[mask & -mask]; - basis v = basises[mask & (mask - 1)]; - basises[mask] = intersection(u, v); - basis u_v_union = u; - for (int64_t vec : v.b) u_v_union.insert(vec); - assert(sz(basises[mask].b) + sz(u_v_union.b) == - sz(u.b) + sz(v.b)); - basis v_u_union = v; - for (int64_t vec : u.b) v_u_union.insert(vec); - assert(sz(u_v_union.b) == sz(v_u_union.b)); - for (int64_t vec : basises[mask].b) { - assert(u.shrink(vec) == 0); - assert(v.shrink(vec) == 0); - } - } - if (__builtin_popcount(mask) % 2 == 1) - res += 1LL << sz(basises[mask].b); - else res -= 1LL << sz(basises[mask].b); - } - cout << res << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/math/xor_basis_intersection.test.cpp b/tests/library_checker_aizu_tests/math/xor_basis_intersection.test.cpp deleted file mode 100644 index f93d49c8..00000000 --- a/tests/library_checker_aizu_tests/math/xor_basis_intersection.test.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/intersection_of_f2_vector_spaces" -#include "../template.hpp" -#include "../../../library/math/matrix_related/xor_basis_unordered_intersection.hpp" -// checking the condition: for 0 <= i < j < sz(b): -// (bit_floor(b[i]) & b[j]) == 0 -void check_condition(const basis& b) { - int n = sz(b.b); - int or_bits = 0; - for (int i = n - 1; i >= 0; i--) { - int bit_i = bit_floor(unsigned(b.b[i])); - assert((bit_i & or_bits) == 0); - or_bits |= b.b[i]; - } -} -int main() { - cin.tie(0)->sync_with_stdio(0); - int t; - cin >> t; - while (t--) { - int n; - cin >> n; - basis basis1; - for (int i = 0; i < n; i++) { - int val; - cin >> val; - assert(basis1.insert(val)); - } - check_condition(basis1); - int m; - cin >> m; - basis basis2; - for (int j = 0; j < m; j++) { - int val; - cin >> val; - assert(basis2.insert(val)); - } - check_condition(basis2); - basis inter = intersection(basis1, basis2); - check_condition(inter); - cout << sz(inter.b) << " "; - for (int val : inter.b) cout << val << " "; - cout << '\n'; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/mono_st_asserts.hpp b/tests/library_checker_aizu_tests/mono_st_asserts.hpp deleted file mode 100644 index 06ee62a6..00000000 --- a/tests/library_checker_aizu_tests/mono_st_asserts.hpp +++ /dev/null @@ -1,89 +0,0 @@ -#pragma once -#include "../../library/monotonic_stack/monotonic_range.hpp" -#include "../../library/monotonic_stack/cartesian_binary_tree.hpp" -#include "../../library/monotonic_stack/cartesian_k_ary_tree.hpp" -#include "../../library/data_structures/uncommon/linear_rmq.hpp" -tuple>, vector> -min_cartesian_tree(const vector& a, - const vector& l, const vector& r) { - int n = sz(a); - assert(sz(l) == n && sz(r) == n); - auto is_node = [&](int i) -> bool { - return r[i] == n || a[r[i]] < a[i]; - }; - vector to_min(n); - iota(begin(to_min), end(to_min), 0); - for (int i = n - 1; i >= 0; i--) - if (!is_node(i)) to_min[i] = to_min[r[i]]; - vector> adj(n); - int root = -1; - for (int i = 0; i < n; i++) { - if (l[i] == -1 && r[i] == n) { - assert(root == -1); - root = i; - } else if (is_node(i)) { - bool le_par = - (l[i] >= 0 && (r[i] == n || a[l[i]] > a[r[i]])); - adj[to_min[le_par ? l[i] : r[i]]].push_back(i); - } - } - return {root, adj, to_min}; -} -void mono_st_asserts(const vector& a) { - vector> compares; - compares.push_back(less()); - compares.push_back(less_equal()); - compares.push_back(greater()); - compares.push_back(greater_equal()); - int n = sz(a); - for (auto cmp : compares) { - auto l = mono_st(a, cmp), r = mono_range(l), - p = cart_binary_tree(l); - { - vector old_way_ri = mono_st(vi{rbegin(a), rend(a)}, - [&](int x, int y) { return !cmp(y, x); }); - reverse(begin(old_way_ri), end(old_way_ri)); - transform(begin(old_way_ri), end(old_way_ri), - begin(old_way_ri), - [&](int i) { return sz(a) - i - 1; }); - assert(r == old_way_ri); - } - int iterations = 0; - for (int i = n - 1; i >= 0; i--) { - assert(i < r[i] && r[i] <= n); - assert(r[i] == n || !cmp(a[i], a[r[i]])); - for (int j = i + 1; j != r[i]; j = r[j]) { - // for all k in [j, r[j]): cmp(a[i], a[k]) - // these ranges are disjoint, and union to [i + 1, - // r[i]) - assert(j <= r[i]); - assert(cmp(a[i], a[j])); - assert(cmp(a[i], a[r[j] - 1])); - assert(cmp(a[i], a[j + (r[j] - j) / 2])); - iterations++; - } - } - // clear the stack - for (int j = 0; j != n; j = r[j]) iterations++; - assert(iterations == n); - } - // test cartesian tree against old method - auto l = mono_st(a, less()), r = mono_range(l), - p = cart_k_ary_tree(a, l); - assert(count(begin(p), end(p), -1) == !empty(a)); - for (int i = 0; i < n; i++) - assert(-1 <= p[i] && p[i] < n && p[i] != i); - auto [root, adj, to_min] = min_cartesian_tree(a, l, r); - vector p_old_method(n, -2); - auto set_val = [&](int i, int val) -> void { - assert(p_old_method[i] == -2); - p_old_method[i] = val; - }; - assert((root == -1) == empty(a)); - if (root != -1) set_val(root, -1); - for (int i = 0; i < n; i++) - for (int j : adj[i]) set_val(j, i); - for (int i = 0; i < n; i++) - if (to_min[i] > i) set_val(i, to_min[i]); - assert(p == p_old_method); -} diff --git a/tests/library_checker_aizu_tests/monotonic_stack_related/cartesian_binary_tree.test.cpp b/tests/library_checker_aizu_tests/monotonic_stack_related/cartesian_binary_tree.test.cpp deleted file mode 100644 index e36dd00f..00000000 --- a/tests/library_checker_aizu_tests/monotonic_stack_related/cartesian_binary_tree.test.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/cartesian_tree" -#include "../template.hpp" -#include "../../../library/monotonic_stack/cartesian_binary_tree.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n; - cin >> n; - vector a(n); - for (int i = 0; i < n; i++) cin >> a[i]; - auto l = mono_st(a, less()), p = cart_binary_tree(l); - for (int i = 0; i < n; i++) - cout << (p[i] == -1 ? i : p[i]) << " "; - return 0; -} diff --git a/tests/library_checker_aizu_tests/monotonic_stack_related/cartesian_k_ary_tree.test.cpp b/tests/library_checker_aizu_tests/monotonic_stack_related/cartesian_k_ary_tree.test.cpp deleted file mode 100644 index ab53cff0..00000000 --- a/tests/library_checker_aizu_tests/monotonic_stack_related/cartesian_k_ary_tree.test.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/cartesian_tree" -#include "../template.hpp" -#include "../mono_st_asserts.hpp" -#include "../../../library/monotonic_stack/cartesian_k_ary_tree.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n; - cin >> n; - vector a(n); - for (int i = 0; i < n; i++) cin >> a[i]; - mono_st_asserts(a); - auto l = mono_st(a, less()), r = mono_range(l), - p = cart_k_ary_tree(a, l); - assert(*min_element(begin(p), end(p)) == -1); - assert(*max_element(begin(p), end(p)) < n); - vector a_neg(n); - transform(begin(a), end(a), begin(a_neg), - [](int x) { return -x; }); - auto le_neg = mono_st(a_neg, greater()), - ri_neg = mono_range(le_neg), - p_neg = cart_k_ary_tree(a_neg, le_neg); - assert(r == ri_neg); - assert(p == p_neg); - for (int i = 0; i < n; i++) { - if (p[i] != -1) - assert(a[p[i]] < a[i]); // because distinct numbers - cout << (p[i] == -1 ? i : p[i]) << " "; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/monotonic_stack_related/count_rectangles.test.cpp b/tests/library_checker_aizu_tests/monotonic_stack_related/count_rectangles.test.cpp deleted file mode 100644 index fd88e04d..00000000 --- a/tests/library_checker_aizu_tests/monotonic_stack_related/count_rectangles.test.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/courses/library/7/DPL/all/DPL_3_B" -#include "../template.hpp" -#include "../mono_st_asserts.hpp" -#include "../../../library/contest/random.hpp" -#include "../../../library/monotonic_stack/count_rectangles.hpp" -#include "../../../kactl/content/data-structures/SubMatrix.h" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, m; - cin >> n >> m; - vector> grid(n, vector(m)); - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - bool val; - cin >> val; - grid[i][j] = !val; - } - } - { - vector h(m); - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) - h[j] = (!grid[i][j]) * (h[j] + 1); - mono_st_asserts(h); - } - } - vector> size_counts = count_rectangles(grid); - { - vector> temp_grid(n, vector(m)); - for (int i = 0; i < n; i++) - for (int j = 0; j < m; j++) - temp_grid[i][j] = grid[i][j]; - SubMatrix sm(temp_grid); - vector> tests; - { - for (int i = 1; i <= min(5, n); i++) - for (int j = 1; j <= min(5, m); j++) - tests.emplace_back(i, j); - int iter = 20; - while (iter--) - tests.emplace_back(rnd(1, n), rnd(1, m)); - } - for (auto [rows, cols] : tests) { - int cnt = 0; - for (int i = 0; i + rows <= n; i++) { - for (int j = 0; j + cols <= m; j++) - if (sm.sum(i, j, i + rows, j + cols) == - rows * cols) - cnt++; - } - assert(size_counts[rows][cols] == cnt); - } - } - int res = 0; - for (int i = 1; i <= n; i++) { - for (int j = 1; j <= m; j++) - if (size_counts[i][j]) res = max(res, i * j); - } - cout << res << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/monotonic_stack_related/max_rect_histogram.test.cpp b/tests/library_checker_aizu_tests/monotonic_stack_related/max_rect_histogram.test.cpp deleted file mode 100644 index 0575a017..00000000 --- a/tests/library_checker_aizu_tests/monotonic_stack_related/max_rect_histogram.test.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/courses/library/7/DPL/all/DPL_3_C" -#include "../template.hpp" -#include "../mono_st_asserts.hpp" -#include "../../../library/monotonic_stack/max_rect_histogram.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n; - cin >> n; - vector a(n); - for (int i = 0; i < n; i++) cin >> a[i]; - mono_st_asserts(a); - cout << max_rect_histogram(a) << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/perm_tree_asserts.hpp b/tests/library_checker_aizu_tests/perm_tree_asserts.hpp deleted file mode 100644 index b1e0e314..00000000 --- a/tests/library_checker_aizu_tests/perm_tree_asserts.hpp +++ /dev/null @@ -1,129 +0,0 @@ -#pragma once -#include "../../library/data_structures/rmq.hpp" -#include "../../library/data_structures/uncommon/permutation_tree.hpp" -perm_tree perm_tree_asserts(const vector& a) { - int n = sz(a); - perm_tree pt(a); - { - vector a_reverse(rbegin(a), rend(a)); - perm_tree pt_reverse(a_reverse); - queue> q; - q.push({pt.root, pt_reverse.root}); - while (!empty(q)) { - auto [u, u_reverse] = q.front(); - q.pop(); - assert(sz(pt.ch[u]) == sz(pt_reverse.ch[u_reverse])); - assert(pt.p[u].is_join == - pt_reverse.p[u_reverse].is_join); - assert(pt.p[u].len == pt_reverse.p[u_reverse].len); - assert( - pt.p[u].mn_num == pt_reverse.p[u_reverse].mn_num); - assert(pt.p[u].mn_idx == - n - - (pt_reverse.p[u_reverse].mn_idx + - pt_reverse.p[u_reverse].len)); - for (int i = 0; i < sz(pt.ch[u]); i++) - q.push({pt.ch[u][i], - pt_reverse - .ch[u_reverse] - [sz(pt_reverse.ch[u_reverse]) - i - 1]}); - } - } - RMQ rmq_min(a, [](int x, int y) { return min(x, y); }); - RMQ rmq_max(a, [](int x, int y) { return max(x, y); }); - auto root = pt.root; - auto ch = pt.ch; - assert(pt.p[root].mn_idx == 0 && - pt.p[root].mn_num == 0 && pt.p[root].len == n); - if (n == 1) assert(sz(ch) == 1); - else assert(n + 1 <= sz(ch) && sz(ch) < 2 * n); - for (int u = 0; u < sz(ch); u++) { - { - int mn_num_rmq = rmq_min.query(pt.p[u].mn_idx, - pt.p[u].mn_idx + pt.p[u].len); - assert(mn_num_rmq == pt.p[u].mn_num); - int mx_num_rmq = rmq_max.query(pt.p[u].mn_idx, - pt.p[u].mn_idx + pt.p[u].len); - assert(mx_num_rmq - mn_num_rmq + 1 == pt.p[u].len); - } - if (empty(ch[u])) { - assert(0 <= u && u < n); - assert(pt.p[u].len == 1); - assert(u == pt.p[u].mn_idx); - assert(a[u] == pt.p[u].mn_num); - assert(!pt.p[u].is_join); - } else { - assert(n <= u && u < sz(ch)); - if (pt.p[u].is_join) assert(pt.p[u].len >= 2); - else assert(pt.p[u].len >= 3); - assert(sz(ch[u]) >= 2); - assert(pt.p[u].mn_idx == pt.p[ch[u][0]].mn_idx); - assert(pt.p[u].mn_idx + pt.p[u].len == - pt.p[ch[u].back()].mn_idx + - pt.p[ch[u].back()].len); - assert(pt.p[u].is_join == - (pt.p[u].mn_num == pt.p[ch[u][0]].mn_num || - pt.p[u].mn_num == pt.p[ch[u].back()].mn_num)); - assert(pt.p[u].is_join == - (pt.p[u].mn_num + pt.p[u].len == - pt.p[ch[u][0]].mn_num + pt.p[ch[u][0]].len || - pt.p[u].mn_num + pt.p[u].len == - pt.p[ch[u].back()].mn_num + - pt.p[ch[u].back()].len)); - for (int i = 1; i < sz(ch[u]); i++) { - int prev = ch[u][i - 1], curr = ch[u][i]; - assert(pt.p[prev].mn_idx + pt.p[prev].len == - pt.p[curr].mn_idx); - assert(pt.p[u].is_join == pt.touches(prev, curr)); - } - if (sz(ch[u]) <= 10) { - for (int i = 0; i < sz(ch[u]); i++) { - int node_le = ch[u][i]; - int running_min = pt.p[node_le].mn_num; - int running_max = - pt.p[node_le].mn_num + pt.p[node_le].len; - int running_sum = pt.p[node_le].len; - for (int j = i + 1; j < sz(ch[u]); j++) { - int node_ri = ch[u][j]; - running_min = - min(running_min, pt.p[node_ri].mn_num); - running_max = max(running_max, - pt.p[node_ri].mn_num + pt.p[node_ri].len); - running_sum += pt.p[node_ri].len; - int mn_num_rmq = - rmq_min.query(pt.p[node_le].mn_idx, - pt.p[node_ri].mn_idx + pt.p[node_ri].len); - int mx_num_rmq = - rmq_max.query(pt.p[node_le].mn_idx, - pt.p[node_ri].mn_idx + pt.p[node_ri].len); - int curr_len = pt.p[node_ri].mn_idx + - pt.p[node_ri].len - pt.p[node_le].mn_idx; - assert(running_min == mn_num_rmq && - running_max == mx_num_rmq + 1 && - running_sum == curr_len); - assert(running_max - running_min >= curr_len); - assert(curr_len <= pt.p[u].len); - if (curr_len == pt.p[u].len) - assert( - running_max - running_min == curr_len); - else - assert(pt.p[u].is_join == - (running_max - running_min == curr_len)); - } - } - } - int mn_num_naive = n, mx_num_naive = -1, - sum_len_naive = 0; - for (int v : ch[u]) { - mn_num_naive = min(mn_num_naive, pt.p[v].mn_num); - mx_num_naive = - max(mx_num_naive, pt.p[v].mn_num + pt.p[v].len); - sum_len_naive += pt.p[v].len; - } - assert(mn_num_naive == pt.p[u].mn_num); - assert(mx_num_naive == pt.p[u].mn_num + pt.p[u].len); - assert(sum_len_naive == pt.p[u].len); - } - } - return pt; -} diff --git a/tests/library_checker_aizu_tests/scc_asserts.hpp b/tests/library_checker_aizu_tests/scc_asserts.hpp deleted file mode 100644 index 48edbaae..00000000 --- a/tests/library_checker_aizu_tests/scc_asserts.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once -#include "../../library/contest/random.hpp" -#include "../../library/graphs/strongly_connected_components/add_edges_strongly_connected.hpp" -#include "../../library/graphs/strongly_connected_components/offline_incremental_scc.hpp" -void scc_asserts(const vector>& adj) { - int n = sz(adj); - auto [num_sccs, scc_id] = sccs(adj); - { - // sanity check for reverse topo order of SCCs - for (int i = 0; i < n; i++) - for (auto j : adj[i]) assert(scc_id[i] >= scc_id[j]); - } - vector is_zero_in(num_sccs, 1), - is_zero_out(num_sccs, 1); - for (int i = 0; i < n; i++) { - for (int v : adj[i]) { - if (scc_id[i] == scc_id[v]) continue; - is_zero_in[scc_id[v]] = 0; - is_zero_out[scc_id[i]] = 0; - } - } - // since {num_sccs-1, ..., 2, 1, 0} is a topo order - assert(is_zero_in[num_sccs - 1] && is_zero_out[0]); - int num_zero_in = - int(count(begin(is_zero_in), end(is_zero_in), 1)); - int num_zero_out = - int(count(begin(is_zero_out), end(is_zero_out), 1)); - vector> edges = - extra_edges(adj, num_sccs, scc_id); - if (num_sccs == 1) assert(sz(edges) == 0); - else assert(sz(edges) == max(num_zero_in, num_zero_out)); - vector> adj_copy(adj); - for (auto [u, v] : edges) { - assert(u != v); - adj_copy[u].push_back(v); - } - assert(sccs(adj_copy).first == 1); -} diff --git a/tests/library_checker_aizu_tests/strings/kmp.test.cpp b/tests/library_checker_aizu_tests/strings/kmp.test.cpp deleted file mode 100644 index d6101e78..00000000 --- a/tests/library_checker_aizu_tests/strings/kmp.test.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/courses/lesson/1/ALDS1/all/ALDS1_14_B" -#include "../template.hpp" -#include "../../../library/strings/kmp.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - string haystack, needle; - cin >> haystack >> needle; - KMP kmp(vi(all(needle))); - vector is_m = kmp.find_str(vi(all(haystack))); - for (int i = 0; i < sz(is_m); i++) - if (is_m[i]) cout << i << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/strings/lcp_array.test.cpp b/tests/library_checker_aizu_tests/strings/lcp_array.test.cpp deleted file mode 100644 index 9e0d7ff7..00000000 --- a/tests/library_checker_aizu_tests/strings/lcp_array.test.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/number_of_substrings" -// just because with debug mode, test runs in 30s, and -// there's like 30 tests -#undef _GLIBCXX_DEBUG -#include "../template.hpp" -#include "../../../library/strings/suffix_array/suffix_array.hpp" -#include "../../../library/strings/suffix_array/suffix_array_short.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - { - // to test commented example - string s = "banana"; - auto [sa, sa_inv, lcp] = get_sa(s, 256); - assert(sa == vector({5, 3, 1, 0, 4, 2})); - assert(sa_inv == vector({3, 2, 5, 1, 4, 0})); - assert(lcp == vector({1, 3, 0, 0, 2})); - } - string s; - cin >> s; - int n = sz(s); - auto [sa, sa_inv, lcp] = get_sa(vi(all(s)), 256); - auto [sa1, sa_inv1, lcp1] = sa_short(vi(all(s))); - assert(sa == sa1); - assert(sa_inv == sa_inv1); - assert(lcp == lcp1); - assert(sz(lcp) == n - 1); - cout << 1LL * n * (n + 1) / 2 - - accumulate(begin(lcp), end(lcp), 0LL) - << '\n'; -} diff --git a/tests/library_checker_aizu_tests/strings/lcp_query_palindrome.test.cpp b/tests/library_checker_aizu_tests/strings/lcp_query_palindrome.test.cpp deleted file mode 100644 index cd8428a8..00000000 --- a/tests/library_checker_aizu_tests/strings/lcp_query_palindrome.test.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/enumerate_palindromes" -#include "../template.hpp" -#include "../../../library/strings/suffix_array/suffix_array_query.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - string s; - cin >> s; - int n = sz(s); - s = s + '$' + string(rbegin(s), rend(s)); - auto [sa, sa_inv, lcp] = get_sa(vi(all(s)), 256); - sa_query lq(vi(all(s)), sa, sa_inv, lcp); - for (int i = 0; i < n; i++) - for (int j = i; j < min(i + 2, n); j++) - cout << lq.len_lcp(j, (n - i - 1) + n + 1) * 2 - - (i == j) - << " "; - cout << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/strings/lcp_query_zfunc.test.cpp b/tests/library_checker_aizu_tests/strings/lcp_query_zfunc.test.cpp deleted file mode 100644 index 27471410..00000000 --- a/tests/library_checker_aizu_tests/strings/lcp_query_zfunc.test.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/zalgorithm" -#include "../template.hpp" -#include "../../../library/contest/random.hpp" -#include "../../../library/strings/suffix_array/suffix_array_query.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - string s; - cin >> s; - auto [sa, sa_inv, lcp] = get_sa(vi(all(s)), 256); - sa_query lq(vi(all(s)), sa, sa_inv, lcp); - // test `*_cmp` functions - { - for (int num_tests = 50; num_tests--;) { - auto l = rnd(0, int(sz(s)) - 1); - auto r = rnd(0, int(sz(s)) - 1); - int cmp_val = lq.cmp_sufs(l, r); - if (cmp_val < 0) assert(s.substr(l) < s.substr(r)); - if (cmp_val == 0) assert(s.substr(l) == s.substr(r)); - if (cmp_val > 0) assert(s.substr(l) > s.substr(r)); - } - for (int num_tests = 50; num_tests--;) { - auto l1 = rnd(0, int(sz(s))); - auto r1 = rnd(0, int(sz(s))); - if (l1 > r1) swap(l1, r1); - if (l1 == sz(s)) l1--; - int l2, r2; - if (rnd(0, 20) == 0) { - l2 = l1; - r2 = r1; - } else { - l2 = rnd(0, int(sz(s))); - r2 = rnd(0, int(sz(s))); - if (l2 > r2) swap(l2, r2); - if (l2 == sz(s)) l2--; - } - int cmp_result = lq.cmp_substrs(l1, r1, l2, r2); - string sub1 = s.substr(l1, r1 - l1); - string sub2 = s.substr(l2, r2 - l2); - if (cmp_result < 0) assert(sub1 < sub2); - else if (cmp_result == 0) assert(sub1 == sub2); - else assert(sub1 > sub2); - } - } - for (int i = 0; i < sz(s); i++) - cout << lq.len_lcp(i, 0) << " "; - cout << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/strings/lcs_dp.test.cpp b/tests/library_checker_aizu_tests/strings/lcs_dp.test.cpp deleted file mode 100644 index 943d06ac..00000000 --- a/tests/library_checker_aizu_tests/strings/lcs_dp.test.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#define PROBLEM \ - "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_10_C" -#include "../template.hpp" -#include "../../../library/strings/longest_common_subsequence/lcs_dp.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int q; - cin >> q; - for (int i = 0; i < q; i++) { - string s, t; - cin >> s >> t; - array res; - for (int j = 0; j < 2; j++) { - lcs_dp lcs(vi(all(t))); - for (char c : s) lcs.push_onto_s(c); - res[j] = int(count(begin(lcs.dp), end(lcs.dp), -1)); - swap(s, t); - } - assert(res[0] == res[1]); - cout << res[0] << '\n'; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/strings/lcs_queries.test.cpp b/tests/library_checker_aizu_tests/strings/lcs_queries.test.cpp deleted file mode 100644 index 4c17e348..00000000 --- a/tests/library_checker_aizu_tests/strings/lcs_queries.test.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/prefix_substring_lcs" -#include "../template.hpp" -#include "../../../library/strings/longest_common_subsequence/lcs_queries.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int q; - string s, t; - cin >> q >> s >> t; - vector> queries(q); - for (int i = 0; i < q; i++) { - int a, b, c; - cin >> a >> b >> c; - queries[i] = {a, b, c}; - } - vector res = - lcs_queries(vi(all(s)), vi(all(t)), queries); - for (int val : res) cout << val << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/strings/lcs_queries_merge_sort_tree.test.cpp b/tests/library_checker_aizu_tests/strings/lcs_queries_merge_sort_tree.test.cpp deleted file mode 100644 index 5190bea9..00000000 --- a/tests/library_checker_aizu_tests/strings/lcs_queries_merge_sort_tree.test.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/prefix_substring_lcs" -#include "../template.hpp" -#include "../../../library/strings/longest_common_subsequence/lcs_dp.hpp" -#include "../../../library/data_structures/seg_tree_uncommon/merge_sort_tree.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int q; - string s, t; - cin >> q >> s >> t; - vector msts; - { - lcs_dp lcs(vi(all(t))); - msts.emplace_back(lcs.dp); - for (char c : s) { - lcs.push_onto_s(c); - { - vector seen(sz(t)); - for (int i = 0; i < sz(t); i++) { - int val = lcs.dp[i]; - assert(val <= i); - if (val == -1) continue; - assert(!seen[val]); - seen[val] = 1; - } - } - msts.emplace_back(lcs.dp); - } - } - for (int i = 0; i < q; i++) { - int a, b, c; - cin >> a >> b >> c; - cout << msts[a].query(b, c, -1, b) << '\n'; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/strings/manacher.test.cpp b/tests/library_checker_aizu_tests/strings/manacher.test.cpp deleted file mode 100644 index 545b2d69..00000000 --- a/tests/library_checker_aizu_tests/strings/manacher.test.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/enumerate_palindromes" -#include "../template.hpp" -#include "../../../library/contest/random.hpp" -#include "../../../library/strings/manacher/longest_from_index.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - string s; - cin >> s; - int n = sz(s); - pal_query pq(vi(all(s))); - vector longest(longest_from_index(pq)); - { - vector> tests; - for (int i = 0; i < n; i++) - for (int j = i; j < min(n, i + 10); j++) - tests.emplace_back(i, j); - for (int i = 0; i < 30; i++) { - int l = rnd(0, n - 1), r = rnd(0, n - 1); - if (l > r) swap(l, r); - tests.emplace_back(l, r); - } - for (auto [l, r] : tests) { - string substr = s.substr(l, r - l + 1); - assert(pq.is_pal(l, r) == - (substr == string(rbegin(substr), rend(substr)))); - } - } - for (int i = 0; i < n; i++) { - assert(longest[i] < n); - assert(pq.is_pal(i, longest[i])); - if (longest[i] + 1 < n) { - assert(!pq.is_pal(i, n - 1)); - for (int tests = 10; tests--;) { - int r = rnd(longest[i] + 1, n - 1); - assert(!pq.is_pal(i, r)); - } - } - } - for (int i = 0; i < sz(pq.man); i++) { - int r = i - pq.man[i]; - assert(r + 1 == pq.man[i] || pq.is_pal(pq.man[i], r)); - assert(pq.man[i] == 0 || r == n - 1 || - !pq.is_pal(pq.man[i] - 1, r + 1)); - cout << i - 2 * pq.man[i] + 1 << " "; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/strings/multi_matching_bs.test.cpp b/tests/library_checker_aizu_tests/strings/multi_matching_bs.test.cpp deleted file mode 100644 index 8e469d7d..00000000 --- a/tests/library_checker_aizu_tests/strings/multi_matching_bs.test.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/courses/lesson/1/ALDS1/all/ALDS1_14_D" -// since this causes an O(n) partition check for each call -// to `lower_bound`, causing TLE. -#undef _GLIBCXX_DEBUG -#include "../template.hpp" -#include "../../../library/strings/suffix_array/suffix_array_query.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - string s; - cin >> s; - auto [sa, sa_inv, lcp] = get_sa(vi(all(s)), 256); - sa_query sf_a(vi(all(s)), sa, sa_inv, lcp); - { - auto [sa_le, sa_ri, s_l, s_r] = - sf_a.find_str_fast(vi()); - pair short_res = sf_a.find_str(vi()); - assert(sa_le == short_res.first && - sa_ri == short_res.second); - assert(sa_le == 0 && sa_ri == sz(s)); - assert(s_r - s_l == 0); - } - int q; - cin >> q; - while (q--) { - string t; - cin >> t; - auto [sa_le, sa_ri, s_l, s_r] = - sf_a.find_str_fast(vi(all(t))); - pair short_res = sf_a.find_str(vi(all(t))); - assert(sa_le == short_res.first && - sa_ri == short_res.second); - int str_len = s_r - s_l; - assert(str_len <= sz(t)); - assert(s.substr(s_l, str_len) == t.substr(0, str_len)); - assert(str_len == sz(t) || s_r == sz(s) || - t[str_len] != s[s_r]); - assert((sa_le < sa_ri) == (str_len == sz(t))); - cout << (!!(sa_ri - sa_le > 0)) << '\n'; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/strings/prefix_function.test.cpp b/tests/library_checker_aizu_tests/strings/prefix_function.test.cpp deleted file mode 100644 index 83990336..00000000 --- a/tests/library_checker_aizu_tests/strings/prefix_function.test.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/zalgorithm" -#include "../template.hpp" -#include "../../../library/strings/prefix_function.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - string s; - cin >> s; - int n = sz(s); - vector pi = prefix_function(vi(all(s))); - // prefix -> z func conversion - // source: - // https://codeforces.com/blog/entry/9612#comment-217621 - vector z(n, 0); - for (int i = 1; i < n; i++) - if (pi[i]) z[i - pi[i] + 1] = pi[i]; - for (int i = 1; i < n;) { - int j, v; - for (j = 1; - j < z[i] && (v = min(z[j], z[i] - j)) >= z[i + j]; - j++) - z[i + j] = v; - i += j; - } - z[0] = n; - for (int i = 0; i < n; i++) cout << z[i] << " "; - cout << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/strings/sa_cmp.test.cpp b/tests/library_checker_aizu_tests/strings/sa_cmp.test.cpp deleted file mode 100644 index 86b3e942..00000000 --- a/tests/library_checker_aizu_tests/strings/sa_cmp.test.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/courses/lesson/8/ITP2/all/ITP2_3_D" -#include "../template.hpp" -#include "../../../library/strings/suffix_array/suffix_array_query.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n; - cin >> n; - vector arr; - for (int i = 0; i < n; i++) { - int val; - cin >> val; - arr.push_back(val); - } - int m; - cin >> m; - for (int i = 0; i < m; i++) { - int val; - cin >> val; - arr.push_back(val); - } - auto [sa, sa_inv, lcp] = get_sa(arr, 1001); - sa_query lq(arr, sa, sa_inv, lcp); - cout << (lq.cmp_substrs(0, n, n, n + m) < 0) << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/strings/sa_sort_pairs.test.cpp b/tests/library_checker_aizu_tests/strings/sa_sort_pairs.test.cpp deleted file mode 100644 index 8b257c3f..00000000 --- a/tests/library_checker_aizu_tests/strings/sa_sort_pairs.test.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/courses/lesson/8/ITP2/all/ITP2_5_A" -#include "../template.hpp" -#include "../../../library/strings/suffix_array/suffix_array_query.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n; - cin >> n; - vector arr(2 * n); - for (int& x : arr) cin >> x; - vector compress(arr); - sort(begin(compress), end(compress)); - compress.erase(unique(begin(compress), end(compress)), - end(compress)); - for (int& x : arr) { - int l = -1, r = int(sz(compress)); - while (r - l > 1) { - int mi = l + (r - l) / 2; - if (compress[mi] >= x) r = mi; - else l = mi; - } - assert(0 <= r && r < sz(compress) && compress[r] == x); - x = r; - } - auto [sa, sa_inv, lcp] = get_sa(arr, int(sz(compress))); - sa_query lq(arr, sa, sa_inv, lcp); - vector idxs(n); - iota(begin(idxs), end(idxs), 0); - sort(begin(idxs), end(idxs), [&](int i, int j) -> bool { - return lq.cmp_substrs(2 * i, 2 * (i + 1), 2 * j, - 2 * (j + 1)) < 0; - }); - for (int idx : idxs) - cout << compress[arr[2 * idx]] << " " - << compress[arr[2 * idx + 1]] << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/strings/single_matching_bs.test.cpp b/tests/library_checker_aizu_tests/strings/single_matching_bs.test.cpp deleted file mode 100644 index f9eb9a84..00000000 --- a/tests/library_checker_aizu_tests/strings/single_matching_bs.test.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/courses/lesson/1/ALDS1/all/ALDS1_14_B" -// since this causes an O(n) partition check for each call -// to `lower_bound`, causing TLE. -#undef _GLIBCXX_DEBUG -#include "../template.hpp" -#include "../../../library/contest/random.hpp" -#include "../../../library/strings/suffix_array/suffix_array_query.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - string s, t; - cin >> s >> t; - auto [sa, sa_inv, lcp] = get_sa(vi(all(s)), 256); - sa_query sf_a(vi(all(s)), sa, sa_inv, lcp); - { - auto [sa_le, sa_ri, s_l, s_r] = - sf_a.find_str_fast(vi()); - assert(sa_le == 0 && sa_ri == sz(s)); - pair short_res = sf_a.find_str(vi()); - assert(sa_le == short_res.first && - sa_ri == short_res.second); - assert(s_r - s_l == 0); - } - auto [sa_le, sa_ri, s_l, s_r] = - sf_a.find_str_fast(vi(all(t))); - pair short_res = sf_a.find_str(vi(all(t))); - assert( - sa_le == short_res.first && sa_ri == short_res.second); - int str_len = s_r - s_l; - assert(s.substr(s_l, str_len) == t.substr(0, str_len)); - assert(str_len <= sz(t)); - assert(str_len == sz(t) || s_r == sz(s) || - t[str_len] != s[s_r]); - assert((sa_le < sa_ri) == (str_len == sz(t))); - vector matches(begin(sf_a.sa) + sa_le, - begin(sf_a.sa) + sa_ri); - sort(begin(matches), end(matches)); - { - // test find_substrs_concated - string both = s + '$' + t; - int t_start = sz(s) + 1; - auto [both_sa, both_sa_inv, both_lcp] = - get_sa(vi(all(both)), 256); - sa_query lq_both(vi(all(both)), both_sa, both_sa_inv, - both_lcp); - vector> tests; - if (sz(t) >= 2) - tests.push_back({{t_start, t_start + 1}, - {t_start + 1, t_start + 1}, - {t_start + 1, t_start + sz(t)}}); - for (int num_tests = 10; num_tests--;) { - vector splits = {0, int(sz(t))}; - for (int num_splits = rnd(0, 4); num_splits--;) - splits.push_back(rnd(0, int(sz(t)) - 1)); - sort(begin(splits), end(splits)); - vector> subs; - for (int i = 1; i < sz(splits); i++) - subs.emplace_back(splits[i - 1] + t_start, - splits[i] + t_start); - tests.push_back(subs); - } - for (const vector& subs : tests) { - auto [sa_le2, sa_ri2, s_le2, s_ri2] = - lq_both.find_substrs_concated(subs); - pair short_res2 = - lq_both.find_substr(t_start, sz(both)); - assert(sa_le2 == short_res2.first && - sa_ri2 == short_res2.second); - assert(both.substr(s_le2, s_ri2 - s_le2) == t); - assert(sa_ri2 - sa_le2 == 1 + sa_ri - sa_le); - vector matches_other(begin(lq_both.sa) + sa_le2, - begin(lq_both.sa) + sa_ri2); - matches_other.erase( - remove_if(begin(matches_other), end(matches_other), - [&](int val) { return val >= sz(s) + 1; }), - end(matches_other)); - sort(begin(matches_other), end(matches_other)); - assert(matches == matches_other); - } - } - for (auto match : matches) cout << match << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/strings/suffix_array.test.cpp b/tests/library_checker_aizu_tests/strings/suffix_array.test.cpp deleted file mode 100644 index c2c3e99a..00000000 --- a/tests/library_checker_aizu_tests/strings/suffix_array.test.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/suffixarray" -#include "../template.hpp" -#include "../mono_st_asserts.hpp" -#include "../../../library/strings/suffix_array/suffix_array_query.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - { - vi s(1, 'a'); - auto [_, _sa_inv, lcp] = get_sa(s, 256); - assert(empty(lcp)); - } - string s; - cin >> s; - int n = sz(s); - auto [sa, sa_inv, lcp] = get_sa(vi(all(s)), 256); - sa_query sf_a(vi(all(s)), sa, sa_inv, lcp); - mono_st_asserts(lcp); - assert(sz(sa) == n); - assert(sz(sa_inv) == n); - assert(sz(lcp) == n - 1); - { - auto [sa_le, sa_ri, s_l, s_r] = - sf_a.find_substrs_concated({}); - assert(sa_le == 0 && sa_ri == n); - assert(s_r - s_l == 0); - } - { - auto [sa_le, sa_ri, s_l, s_r] = - sf_a.find_substrs_concated({{0, 0}}); - pair short_res = sf_a.find_substr(0, 0); - assert(sa_le == short_res.first && - sa_ri == short_res.second); - assert(sa_le == 0 && sa_ri == n); - assert(s_r - s_l == 0); - } - { - auto [sa_le, sa_ri, s_l, s_r] = - sf_a.find_substrs_concated({{0, 0}, {n - 1, n - 1}}); - pair short_res = - sf_a.find_substr(n - 1, n - 1); - assert(sa_le == short_res.first && - sa_ri == short_res.second); - assert(sa_le == 0 && sa_ri == n); - assert(s_r - s_l == 0); - } - for (int i = 0; i < n; i++) { - assert(sa[sa_inv[i]] == i); - assert(sa_inv[sa[i]] == i); - } - for (auto val : sa) cout << val << " "; - cout << '\n'; -} diff --git a/tests/library_checker_aizu_tests/strings/suffix_array_short.test.cpp b/tests/library_checker_aizu_tests/strings/suffix_array_short.test.cpp deleted file mode 100644 index bb25b839..00000000 --- a/tests/library_checker_aizu_tests/strings/suffix_array_short.test.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/suffixarray" -// just because with debug mode, test runs in 30s, and -// there's like 30 tests -#undef _GLIBCXX_DEBUG -#include "../template.hpp" -#include "../../../library/strings/suffix_array/suffix_array_short.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - string s; - cin >> s; - auto [sa, sa_inv, _] = sa_short(vi(all(s))); - for (int i = 0; i < sz(s); i++) { - assert(sa[sa_inv[i]] == i); - assert(sa_inv[sa[i]] == i); - } - for (int val : sa) cout << val << " "; - cout << '\n'; -} diff --git a/tests/library_checker_aizu_tests/strings/trie.test.cpp b/tests/library_checker_aizu_tests/strings/trie.test.cpp deleted file mode 100644 index 47edbbd8..00000000 --- a/tests/library_checker_aizu_tests/strings/trie.test.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/courses/lesson/1/ALDS1/all/ALDS1_4_C" -#include "../template.hpp" -#include "../../../library/strings/trie.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n; - cin >> n; - trie tr; - for (int i = 0; i < n; i++) { - string type, s; - cin >> type >> s; - if (type == "insert") tr.insert(s); - else cout << (tr.find(s) ? "yes" : "no") << '\n'; - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/strings/wildcard_pattern_matching.test.cpp b/tests/library_checker_aizu_tests/strings/wildcard_pattern_matching.test.cpp deleted file mode 100644 index 32be6cd3..00000000 --- a/tests/library_checker_aizu_tests/strings/wildcard_pattern_matching.test.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/wildcard_pattern_matching" -#include "../template.hpp" -#include "../../../library/strings/wildcard_pattern_matching.hpp" -namespace ignore { -#include "../../../kactl/content/number-theory/ModPow.h" -} -ll modpow(ll a, ll e); -#include "../../../kactl/content/numerical/NumberTheoreticTransform.h" -ll modpow(ll a, ll e) { - if (e == 0) return 1; - ll x = modpow(a * a % mod, e >> 1); - return e & 1 ? x * a % mod : x; -} -vl to_vec(const string& s) { - int n = sz(s); - vl res(n); - for (int i = 0; i < n; i++) - if (s[i] == '*') res[i] = 0; - else res[i] = s[i] - 'a' + 1; - return res; -} -int main() { - cin.tie(0)->sync_with_stdio(0); - string haystack, needle; - cin >> haystack >> needle; - auto haystack_vec = to_vec(haystack); - auto needle_vec = to_vec(needle); - auto matches = wildcard_pattern_matching(haystack_vec, - needle_vec, conv); - for (bool b : matches) cout << b; - cout << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/template.hpp b/tests/library_checker_aizu_tests/template.hpp deleted file mode 100644 index 5924a4ab..00000000 --- a/tests/library_checker_aizu_tests/template.hpp +++ /dev/null @@ -1,37 +0,0 @@ -/////////MODIFYING THIS FILE WILL RERUN ALL TESTS///////// -// -// to avoid bits/stdc++.h include which slows down CI -// modifying this file will re-run all library checker -// tests -#include -#include -#include -#include -#include -#include //for iota -#include -#include -#include -#include -#include -// for random numbers -#include // for uint64_t -#include -#include -#include // for INT_MAX, INT_MIN -#include //for kactl's FFT -#include //for lambdas -#include -#include -#include // for std::exchange -#include -#include -using namespace std; -// https://github.com/kth-competitive-programming/kactl/blob/main/content/contest/template.cpp -// compile all tests with KACTL macros mainly to avoid -// naming collisions when combining code from both repos -// -// also defines are used here instead of typedef/using's -// (even though it's sketchier) so that they can be -// expanded before pushing to main -#include "kactl_macros.hpp" diff --git a/tests/library_checker_aizu_tests/trees/count_paths_per_length.test.cpp b/tests/library_checker_aizu_tests/trees/count_paths_per_length.test.cpp deleted file mode 100644 index bbce584a..00000000 --- a/tests/library_checker_aizu_tests/trees/count_paths_per_length.test.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/frequency_table_of_tree_distance" -#include "../template.hpp" -#include "../../../library/trees/uncommon/count_paths_per_length.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n; - cin >> n; - vector> adj(n); - for (int i = 0; i < n - 1; i++) { - int u, v; - cin >> u >> v; - adj[u].push_back(v); - adj[v].push_back(u); - } - vector cnt_len = count_paths_per_length(adj); - for (int i = 1; i < n; i++) cout << cnt_len[i] << " "; - cout << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/trees/edge_cd_contour_range_query.test.cpp b/tests/library_checker_aizu_tests/trees/edge_cd_contour_range_query.test.cpp deleted file mode 100644 index 1e4f02f9..00000000 --- a/tests/library_checker_aizu_tests/trees/edge_cd_contour_range_query.test.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/vertex_add_range_contour_sum_on_tree" -#include "../template.hpp" -#include "../edge_cd_asserts.hpp" -#include "../../../library/trees/uncommon/contour_range_query.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vector a(n); - for (int i = 0; i < n; i++) cin >> a[i]; - vector> adj(n); - for (int i = 0; i < n - 1; i++) { - int u, v; - cin >> u >> v; - adj[u].push_back(v); - adj[v].push_back(u); - } - { edge_cd(adj, edge_cd_asserts); } - contour_range_query cq(adj, a); - while (q--) { - int type; - cin >> type; - if (type == 0) { - int u; - ll delta; - cin >> u >> delta; - cq.update(u, delta); - } else { - assert(type == 1); - int u, l, r; - cin >> u >> l >> r; - ll res = cq.query(u, l, l); - assert(res == 0); - res = cq.query(u, r, r); - assert(res == 0); - cout << cq.query(u, l, r) << '\n'; - } - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/trees/edge_cd_contour_range_update.test.cpp b/tests/library_checker_aizu_tests/trees/edge_cd_contour_range_update.test.cpp deleted file mode 100644 index da3a0bc2..00000000 --- a/tests/library_checker_aizu_tests/trees/edge_cd_contour_range_update.test.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/vertex_get_range_contour_add_on_tree" -#include "../template.hpp" -#include "../edge_cd_asserts.hpp" -#include "../../../library/trees/uncommon/contour_range_update.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vector a(n); - for (int i = 0; i < n; i++) cin >> a[i]; - vector> adj(n); - for (int i = 0; i < n - 1; i++) { - int u, v; - cin >> u >> v; - adj[u].push_back(v); - adj[v].push_back(u); - } - { edge_cd(adj, edge_cd_asserts); } - contour_range_update cu(adj, a); - while (q--) { - int type; - cin >> type; - if (type == 0) { - int u, l, r, delta; - cin >> u >> l >> r >> delta; - cu.update(u, l, l, delta); - cu.update(u, l, r, delta); - cu.update(u, r, r, delta); - } else { - assert(type == 1); - int u; - cin >> u; - cout << cu.query(u) << '\n'; - } - } - return 0; -} diff --git a/tests/library_checker_aizu_tests/trees/edge_cd_count_paths_per_length.test.cpp b/tests/library_checker_aizu_tests/trees/edge_cd_count_paths_per_length.test.cpp deleted file mode 100644 index 6545d13d..00000000 --- a/tests/library_checker_aizu_tests/trees/edge_cd_count_paths_per_length.test.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/frequency_table_of_tree_distance" -#include "../template.hpp" -#include "../edge_cd_asserts.hpp" -#include "../../../library/trees/uncommon/count_paths_per_length.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n; - cin >> n; - vector> adj(n); - for (int i = 0; i < n - 1; i++) { - int u, v; - cin >> u >> v; - adj[u].push_back(v); - adj[v].push_back(u); - } - { edge_cd(adj, edge_cd_asserts); } - vector cnt_len = count_paths_per_length(adj); - for (int i = 1; i < n; i++) cout << cnt_len[i] << " "; - cout << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/trees/edge_cd_reroot_dp.test.cpp b/tests/library_checker_aizu_tests/trees/edge_cd_reroot_dp.test.cpp deleted file mode 100644 index b7548c9d..00000000 --- a/tests/library_checker_aizu_tests/trees/edge_cd_reroot_dp.test.cpp +++ /dev/null @@ -1,102 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/tree_path_composite_sum" -#include "../template.hpp" -#include "../edge_cd_asserts.hpp" -#include "../../../library/trees/edge_cd.hpp" -const int mod = 998244353; -int main() { - cin.tie(0)->sync_with_stdio(0); - int n; - cin >> n; - vector a(n); - vector res(n); - for (int i = 0; i < n; i++) { - cin >> a[i]; - res[i] = a[i]; - } - vector adj(n); - vector b(n - 1), c(n - 1); - vector> par(n, {-1, -1}); - vector> base_adj(n); - { - vector>> adj_with_id(n); - for (int i = 0; i < n - 1; i++) { - int u, v; - cin >> u >> v >> b[i] >> c[i]; - adj[u].push_back(v); - adj[v].push_back(u); - base_adj[u].push_back(v); - base_adj[v].push_back(u); - adj_with_id[u].emplace_back(v, i); - adj_with_id[v].emplace_back(u, i); - res[u] = (res[u] + 1LL * b[i] * a[v] + c[i]) % mod; - res[v] = (res[v] + 1LL * b[i] * a[u] + c[i]) % mod; - } - auto dfs = [&](auto&& self, int u) -> void { - for (auto [v, e_id] : adj_with_id[u]) - if (v != par[u].first) - par[v] = {u, e_id}, self(self, v); - }; - dfs(dfs, 0); - } - auto edge_id = [&](int u, int v) -> int { - bool u_low = (par[u].first == v); - bool v_low = (par[v].first == u); - assert(u_low ^ v_low); - return u_low ? par[u].second : par[v].second; - }; - { edge_cd(base_adj, edge_cd_asserts); } - edge_cd(adj, - [&](const vector& cd_adj, int cent, - int split) -> void { - array>, 2> all_backwards; - array sum_forward = {0, 0}; - array cnt_nodes = {0, 0}; - auto dfs = [&](auto&& self, int u, int p, - array forwards, - array backwards, - int side) -> void { - all_backwards[side].push_back( - {u, backwards[0], backwards[1]}); - sum_forward[side] = - (sum_forward[side] + 1LL * forwards[0] * a[u] + - forwards[1]) % - mod; - cnt_nodes[side]++; - for (int v : cd_adj[u]) { - if (v == p) continue; - int e_id = edge_id(u, v); - // f(x) = ax+b - // g(x) = cx+d - // f(g(x)) = a(cx+d)+b = acx+ad+b - array curr_forw = { - int(1LL * forwards[0] * b[e_id] % mod), - int( - (1LL * forwards[0] * c[e_id] + forwards[1]) % - mod)}; - array curr_backw = { - int(1LL * backwards[0] * b[e_id] % mod), - int((1LL * backwards[1] * b[e_id] + c[e_id]) % - mod)}; - self(self, v, u, curr_forw, curr_backw, side); - } - }; - for (int i = 0; i < sz(cd_adj[cent]); i++) { - int e_id = edge_id(cent, cd_adj[cent][i]); - dfs(dfs, cd_adj[cent][i], cent, {b[e_id], c[e_id]}, - {b[e_id], c[e_id]}, i < split); - } - for (int side = 0; side < 2; side++) { - for ( - auto [u, curr_b, curr_c] : all_backwards[side]) { - res[u] = - (res[u] + 1LL * curr_b * sum_forward[!side] + - 1LL * curr_c * cnt_nodes[!side]) % - mod; - } - } - }); - for (int i = 0; i < n; i++) cout << res[i] << ' '; - cout << '\n'; - return 0; -} diff --git a/tests/library_checker_aizu_tests/trees/hld_aizu1.test.cpp b/tests/library_checker_aizu_tests/trees/hld_aizu1.test.cpp deleted file mode 100644 index 00287f91..00000000 --- a/tests/library_checker_aizu_tests/trees/hld_aizu1.test.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/problems/GRL_5_D" -#include "../template.hpp" -#include "../../../library/trees/hld.hpp" -#include "../../../library/data_structures/bit.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n; - cin >> n; - vector> adj(n); - for (int i = 0; i < n; i++) { - int k; - cin >> k; - for (int j = 0; j < k; j++) { - int v; - cin >> v; - assert(v != 0); - adj[i].push_back(v); - adj[v].push_back(i); - } - } - HLD<1> hld(adj); - BIT bit(n); - int q; - cin >> q; - while (q--) { - int type; - cin >> type; - if (type == 0) { - int v, x; - cin >> v >> x; - assert(v != 0); - bit.update(hld.tin[v], x); - } else { - assert(type == 1); - int v; - cin >> v; - ll sum = 0; - hld.path(0, v, - [&](int l, int r) { sum += bit.query(l, r); }); - cout << sum << '\n'; - } - } -} diff --git a/tests/library_checker_aizu_tests/trees/hld_aizu2.test.cpp b/tests/library_checker_aizu_tests/trees/hld_aizu2.test.cpp deleted file mode 100644 index aaa4df24..00000000 --- a/tests/library_checker_aizu_tests/trees/hld_aizu2.test.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/problems/GRL_5_E" -#include "../template.hpp" -#include "../../../library/trees/hld.hpp" -#include "../../../library/data_structures/lazy_seg_tree.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n; - cin >> n; - vector> adj(n); - for (int i = 0; i < n; i++) { - int k; - cin >> k; - for (int j = 0; j < k; j++) { - int v; - cin >> v; - assert(v != 0); - adj[i].push_back(v); - adj[v].push_back(i); - } - } - HLD<1> hld(adj); - seg_tree st(n); - int q; - cin >> q; - while (q--) { - int type; - cin >> type; - if (type == 0) { - int v, x; - cin >> v >> x; - assert(v != 0); - hld.path(0, v, - [&](int l, int r) { st.update(l, r, x); }); - } else { - assert(type == 1); - int v; - cin >> v; - ll sum = 0; - hld.path(0, v, - [&](int l, int r) { sum += st.query(l, r); }); - cout << sum << '\n'; - } - } -} diff --git a/tests/library_checker_aizu_tests/trees/hld_lib_checker_path.test.cpp b/tests/library_checker_aizu_tests/trees/hld_lib_checker_path.test.cpp deleted file mode 100644 index 962c4d77..00000000 --- a/tests/library_checker_aizu_tests/trees/hld_lib_checker_path.test.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/vertex_add_path_sum" -#include "../template.hpp" -#include "../../../library/trees/hld.hpp" -#include "../../../library/data_structures/bit.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vector a(n); - for (int i = 0; i < n; i++) cin >> a[i]; - vector> adj(n); - for (int i = 0; i < n - 1; i++) { - int u, v; - cin >> u >> v; - adj[u].push_back(v); - adj[v].push_back(u); - } - HLD<0> hld(adj); - BIT bit(n); - for (int i = 0; i < n; i++) bit.update(hld.tin[i], a[i]); - while (q--) { - int type; - cin >> type; - if (type == 0) { - int v, x; - cin >> v >> x; - bit.update(hld.tin[v], x); - } else { - int u, v; - cin >> u >> v; - ll sum = 0; - hld.path(u, v, - [&](int l, int r) { sum += bit.query(l, r); }); - cout << sum << '\n'; - } - } -} diff --git a/tests/library_checker_aizu_tests/trees/hld_lib_checker_subtree_edges.test.cpp b/tests/library_checker_aizu_tests/trees/hld_lib_checker_subtree_edges.test.cpp deleted file mode 100644 index 24c2f981..00000000 --- a/tests/library_checker_aizu_tests/trees/hld_lib_checker_subtree_edges.test.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/vertex_add_subtree_sum" -#include "../template.hpp" -#include "../../../library/trees/hld.hpp" -#include "../../../library/data_structures/bit.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vector a(n); - for (int i = 0; i < n; i++) cin >> a[i]; - vector> adj(n); - for (int i = 1; i < n; i++) { - int par; - cin >> par; - adj[par].push_back(i); - adj[i].push_back(par); - } - HLD<1> hld(adj); - BIT bit(n); - for (int i = 0; i < n; i++) bit.update(hld.tin[i], a[i]); - while (q--) { - int type; - cin >> type; - if (type == 0) { - int v, x; - cin >> v >> x; - bit.update(hld.tin[v], x); - a[v] += x; - } else { - int v; - cin >> v; - auto [l, r] = hld.subtree(v); - cout << bit.query(l, r) + a[v] << '\n'; - } - } -} diff --git a/tests/library_checker_aizu_tests/trees/hld_lib_checker_subtree_nodes.test.cpp b/tests/library_checker_aizu_tests/trees/hld_lib_checker_subtree_nodes.test.cpp deleted file mode 100644 index 78146446..00000000 --- a/tests/library_checker_aizu_tests/trees/hld_lib_checker_subtree_nodes.test.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/vertex_add_subtree_sum" -#include "../template.hpp" -#include "../../../library/trees/hld.hpp" -#include "../../../library/data_structures/bit.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vector a(n); - for (int i = 0; i < n; i++) cin >> a[i]; - vector> adj(n); - for (int i = 1; i < n; i++) { - int par; - cin >> par; - adj[par].push_back(i); - adj[i].push_back(par); - } - HLD<0> hld(adj); - BIT bit(n); - for (int i = 0; i < n; i++) bit.update(hld.tin[i], a[i]); - while (q--) { - int type; - cin >> type; - if (type == 0) { - int v, x; - cin >> v >> x; - bit.update(hld.tin[v], x); - } else { - int v; - cin >> v; - auto [l, r] = hld.subtree(v); - cout << bit.query(l, r) << '\n'; - } - } -} diff --git a/tests/library_checker_aizu_tests/trees/kth_path_ladder.test.cpp b/tests/library_checker_aizu_tests/trees/kth_path_ladder.test.cpp deleted file mode 100644 index 79c41cb3..00000000 --- a/tests/library_checker_aizu_tests/trees/kth_path_ladder.test.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/jump_on_tree" -#include "../template.hpp" -#include "../../../library/trees/uncommon/ladder_decomposition.hpp" -#include "../../../library/trees/linear_kth_par.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vector> adj(n); - for (int i = 0; i < n - 1; i++) { - int u, v; - cin >> u >> v; - adj[u].push_back(v); - adj[v].push_back(u); - } - ladder ld(adj); - while (q--) { - int u, v, k; - cin >> u >> v >> k; - int lca_d = ld.d[lca(ld.jmp, ld.d, u, v)]; - int u_lca = ld.d[u] - lca_d; - int v_lca = ld.d[v] - lca_d; - if (k > u_lca + v_lca) cout << -1 << '\n'; - else if (k <= u_lca) { - int res = ld.kth_par(u, k); - assert(res == jmp(ld.jmp, u, k)); - cout << res << '\n'; - } else { - int res = ld.kth_par(v, u_lca + v_lca - k); - assert(res == jmp(ld.jmp, v, u_lca + v_lca - k)); - cout << res << '\n'; - } - } -} diff --git a/tests/library_checker_aizu_tests/trees/kth_path_linear.test.cpp b/tests/library_checker_aizu_tests/trees/kth_path_linear.test.cpp deleted file mode 100644 index 8cf83d40..00000000 --- a/tests/library_checker_aizu_tests/trees/kth_path_linear.test.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/jump_on_tree" -#include "../template.hpp" -#include "../../../library/trees/linear_lca.hpp" -#include "../../../library/trees/linear_kth_par.hpp" -#include "../../../library/trees/lca_rmq.hpp" -#include "../compress_tree_asserts.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vector> adj(n); - for (int i = 0; i < n - 1; i++) { - int u, v; - cin >> u >> v; - adj[u].push_back(v); - adj[v].push_back(u); - } - linear_lca lin_lca(adj); - linear_kth_par<1> lin_kp_1(adj); - linear_kth_par<2> lin_kp_2(adj); - linear_kth_par<3> lin_kp_3(adj); - linear_kth_par<4> lin_kp_4(adj); - LCA lc(adj); - compress_tree_asserts(adj, lc); - auto get_kth_par = [&](int v, int k) -> int { - int res = lin_kp_1.kth_par(v, k); - assert(res == lin_kp_2.kth_par(v, k)); - assert(res == lin_kp_3.kth_par(v, k)); - assert(res == lin_kp_4.kth_par(v, k)); - return res; - }; - while (q--) { - int u, v, k; - cin >> u >> v >> k; - int lca_d = lin_kp_2.d[lin_lca.lca(u, v)]; - int u_lca = lin_kp_2.d[u] - lca_d; - int v_lca = lin_kp_2.d[v] - lca_d; - if (k <= u_lca) cout << get_kth_par(u, k) << '\n'; - else if (k <= u_lca + v_lca) - cout << get_kth_par(v, u_lca + v_lca - k) << '\n'; - else cout << -1 << '\n'; - } -} diff --git a/tests/library_checker_aizu_tests/trees/kth_path_tree_lift.test.cpp b/tests/library_checker_aizu_tests/trees/kth_path_tree_lift.test.cpp deleted file mode 100644 index 098126a4..00000000 --- a/tests/library_checker_aizu_tests/trees/kth_path_tree_lift.test.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/jump_on_tree" -#include "../template.hpp" -#include "../../../library/contest/random.hpp" -#include "../../../library/trees/tree_lift.hpp" -#include "../../../library/trees/lca_rmq.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vector> adj(n); - for (int i = 0; i < n - 1; i++) { - int u, v; - cin >> u >> v; - adj[u].push_back(v); - adj[v].push_back(u); - } - tree_lift tl(adj); - LCA lc(adj); - auto kth_path = [&](int u, int v, int k) -> int { - int lca_d = lc.d[lc.lca(u, v)]; - int u_lca = lc.d[u] - lca_d; - int v_lca = lc.d[v] - lca_d; - if (k <= u_lca) return tl.kth_par(u, k); - if (k <= u_lca + v_lca) - return tl.kth_par(v, u_lca + v_lca - k); - return -1; - }; - while (q--) { - int u, v, k; - cin >> u >> v >> k; - int dist_in_edges = tl.dist(u, v); - assert(dist_in_edges == lc.dist(u, v)); - cout << kth_path(u, v, k) << '\n'; - { - int w = rnd(0, n - 1); - assert(lc.on_path(u, v, w) == - (lc.dist(u, w) + lc.dist(w, v) == lc.dist(u, v))); - } - if (u != v) { - assert(kth_path(u, v, 1) == lc.next_on_path(u, v)); - assert(kth_path(u, v, dist_in_edges - 1) == - lc.next_on_path(v, u)); - } - } -} diff --git a/tests/library_checker_aizu_tests/trees/lca_all_methods_aizu.test.cpp b/tests/library_checker_aizu_tests/trees/lca_all_methods_aizu.test.cpp deleted file mode 100644 index c2011d59..00000000 --- a/tests/library_checker_aizu_tests/trees/lca_all_methods_aizu.test.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#define PROBLEM \ - "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_5_C" -#include "../template.hpp" -#include "../../../library/trees/tree_lift.hpp" -#include "../../../library/trees/linear_lca.hpp" -#include "../../../library/trees/lca_rmq.hpp" -#include "../compress_tree_asserts.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n; - cin >> n; - vector> adj(n); - for (int i = 0; i < n; i++) { - int k; - cin >> k; - adj[i].resize(k); - for (int& child : adj[i]) cin >> child; - } - tree_lift tl(adj); - LCA lc(adj); - linear_lca lin_lca(adj); - compress_tree_asserts(adj, lc); - for (int i = 0; i < n; i++) { - assert(tl.lca(i, i) == i); - assert(lc.lca(i, i) == i); - assert(lin_lca.lca(i, i) == i); - assert(lc.tin[lc.rmq.dp[0][i]] == i && - lc.rmq.dp[0][lc.tin[i]] == i); - } - int q; - cin >> q; - while (q--) { - int u, v; - cin >> u >> v; - int lca = tl.lca(u, v); - assert(lca == lc.lca(u, v)); - assert(lca == lin_lca.lca(u, v)); - assert((lca == u) == lc.in_subtree(u, v)); - assert((lca == v) == lc.in_subtree(v, u)); - cout << lca << '\n'; - } -} diff --git a/tests/library_checker_aizu_tests/trees/lca_all_methods_lib_checker.test.cpp b/tests/library_checker_aizu_tests/trees/lca_all_methods_lib_checker.test.cpp deleted file mode 100644 index f5eea04d..00000000 --- a/tests/library_checker_aizu_tests/trees/lca_all_methods_lib_checker.test.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#define PROBLEM "https://judge.yosupo.jp/problem/lca" -#include "../template.hpp" -#include "../../../library/trees/tree_lift.hpp" -#include "../../../library/trees/linear_lca.hpp" -#include "../../../library/trees/lca_rmq.hpp" -#include "../compress_tree_asserts.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n, q; - cin >> n >> q; - vector> adj(n); - for (int i = 1; i < n; i++) { - int par; - cin >> par; - adj[par].push_back(i); - } - tree_lift tl(adj); - LCA lc(adj); - linear_lca lin_lca(adj); - compress_tree_asserts(adj, lc); - for (int i = 0; i < n; i++) { - assert(tl.lca(i, i) == i); - assert(lc.lca(i, i) == i); - assert(lc.in_subtree(i, i)); - assert(lin_lca.lca(i, i) == i); - assert(lc.tin[lc.rmq.dp[0][i]] == i && - lc.rmq.dp[0][lc.tin[i]] == i); - } - while (q--) { - int u, v; - cin >> u >> v; - int lca = tl.lca(u, v); - assert(lca == lc.lca(u, v)); - assert(lca == lin_lca.lca(u, v)); - assert((lca == u) == lc.in_subtree(u, v)); - assert((lca == v) == lc.in_subtree(v, u)); - cout << lca << '\n'; - } -} diff --git a/tests/library_checker_aizu_tests/trees/shallowest_aizu_tree_height.test.cpp b/tests/library_checker_aizu_tests/trees/shallowest_aizu_tree_height.test.cpp deleted file mode 100644 index f3823495..00000000 --- a/tests/library_checker_aizu_tests/trees/shallowest_aizu_tree_height.test.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#define PROBLEM \ - "https://onlinejudge.u-aizu.ac.jp/problems/GRL_5_B" -#include "../template.hpp" -#include "../../../library/trees/shallowest_decomp_tree.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n; - cin >> n; - vector> adj(n); - map, int> weight; - for (int i = 0; i < n - 1; i++) { - int u, v, w; - cin >> u >> v >> w; - weight[{u, v}] = w; - weight[{v, u}] = w; - adj[u].push_back(v); - adj[v].push_back(u); - } - vector res(n); - shallowest(adj, [&](int cent) { - int lowest = 0; - int curr_lowest = 0; - auto dfs = [&](auto&& self, int v, int p, - int height) -> void { - res[v] = max(res[v], height + lowest); - res[cent] = max(res[cent], height); - curr_lowest = max(curr_lowest, height); - for (int u : adj[v]) - if (u != p) - self(self, u, v, height + weight[{u, v}]); - }; - for (int v : adj[cent]) { - curr_lowest = 0; - dfs(dfs, v, cent, weight[{v, cent}]); - lowest = max(lowest, curr_lowest); - } - lowest = 0; - for (int v : adj[cent] | views::reverse) { - curr_lowest = 0; - dfs(dfs, v, cent, weight[{v, cent}]); - lowest = max(lowest, curr_lowest); - } - }); - for (int i = 0; i < n; i++) cout << res[i] << '\n'; -} diff --git a/tests/library_checker_aizu_tests/trees/shallowest_lib_checker_tree_path_composite.test.cpp b/tests/library_checker_aizu_tests/trees/shallowest_lib_checker_tree_path_composite.test.cpp deleted file mode 100644 index fbc6c7aa..00000000 --- a/tests/library_checker_aizu_tests/trees/shallowest_lib_checker_tree_path_composite.test.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/tree_path_composite_sum" -#undef _GLIBCXX_DEBUG -#include "../template.hpp" -#include "../../../library/trees/shallowest_decomp_tree.hpp" -const int mod = 998244353; -using line = array; -// returns f(g(x)) = f[0]*(g[0]*x+g[1]) + f[1] -line compose(line f, line g) { - return {int(1LL * f[0] * g[0] % mod), - int((f[1] + 1LL * f[0] * g[1]) % mod)}; -} -int main() { - cin.tie(0)->sync_with_stdio(0); - int n; - cin >> n; - vector a(n); - for (int i = 0; i < n; i++) cin >> a[i]; - vector> adj(n); - vector> weight(n); - for (int i = 0; i < n - 1; i++) { - int u, v, b, c; - cin >> u >> v >> b >> c; - adj[u].push_back(v); - adj[v].push_back(u); - weight[u].push_back({b, c}); - weight[v].push_back({b, c}); - } - vector res(a); - shallowest(adj, [&](int cent) { - assert(ssize(adj[cent]) == ssize(weight[cent])); - int total_sum_evaluated = 0; - int total_cnt_nodes = 0; - int curr_sum_evaluated = 0; - int curr_cnt_nodes = 0; - auto dfs = [&](auto&& self, int v, int p, - line downwards, line upwards, - bool forwards) -> void { - // f(x) + f(y) + f(z) = b*x+c + b*y+c + b*z+c = - // b*(x+y+z) + c*3 - res[v] = - (res[v] + 1LL * upwards[0] * total_sum_evaluated + - 1LL * upwards[1] * total_cnt_nodes) % - mod; - if (forwards) { - res[v] = (res[v] + 1LL * upwards[0] * a[cent] + - upwards[1]) % - mod; - res[cent] = - (res[cent] + 1LL * downwards[0] * a[v] + - downwards[1]) % - mod; - } - curr_cnt_nodes++; - curr_sum_evaluated = - (curr_sum_evaluated + 1LL * downwards[0] * a[v] + - downwards[1]) % - mod; - for (int i = 0; i < ssize(adj[v]); i++) { - int u = adj[v][i]; - line curr_line = weight[v][i]; - if (u != p) { - self(self, u, v, compose(downwards, curr_line), - compose(curr_line, upwards), forwards); - } - } - }; - for (int i = 0; i < ssize(adj[cent]); i++) { - curr_sum_evaluated = 0; - curr_cnt_nodes = 0; - dfs(dfs, adj[cent][i], cent, weight[cent][i], - weight[cent][i], 1); - total_sum_evaluated = - (total_sum_evaluated + curr_sum_evaluated) % mod; - total_cnt_nodes += curr_cnt_nodes; - } - total_sum_evaluated = 0; - total_cnt_nodes = 0; - for (int i = ssize(adj[cent]) - 1; i >= 0; i--) { - curr_sum_evaluated = 0; - curr_cnt_nodes = 0; - dfs(dfs, adj[cent][i], cent, weight[cent][i], - weight[cent][i], 0); - total_sum_evaluated = - (total_sum_evaluated + curr_sum_evaluated) % mod; - total_cnt_nodes += curr_cnt_nodes; - } - for (int v : adj[cent]) { - for (int i = 0; i < ssize(adj[v]); i++) { - if (adj[v][i] == cent) { - swap(weight[v][i], weight[v].back()); - weight[v].pop_back(); - break; - } - } - } - }); - for (int i = 0; i < n; i++) cout << res[i] << ' '; - cout << '\n'; -} diff --git a/tests/library_checker_aizu_tests/trees/subtree_isomorphism.test.cpp b/tests/library_checker_aizu_tests/trees/subtree_isomorphism.test.cpp deleted file mode 100644 index 28ac422f..00000000 --- a/tests/library_checker_aizu_tests/trees/subtree_isomorphism.test.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#define PROBLEM \ - "https://judge.yosupo.jp/problem/rooted_tree_isomorphism_classification" -// as std::map insert takes O(n) time in debug mode -#undef _GLIBCXX_DEBUG -#include "../template.hpp" -#include "../../../library/trees/uncommon/subtree_isomorphism.hpp" -int main() { - cin.tie(0)->sync_with_stdio(0); - int n; - cin >> n; - vector> adj(n); - for (int i = 1; i < n; i++) { - int p; - cin >> p; - adj[p].push_back(i); - adj[i].push_back(p); - } - auto [num_distinct_subtrees, iso_id] = subtree_iso(adj); - cout << num_distinct_subtrees << '\n'; - for (int i = 0; i < n; i++) cout << iso_id[i] << " "; - cout << '\n'; - return 0; -} diff --git a/tests/scripts/README.md b/tests/scripts/README.md deleted file mode 100644 index 64c4d7df..00000000 --- a/tests/scripts/README.md +++ /dev/null @@ -1,22 +0,0 @@ -https://unix.stackexchange.com/a/169765 explains how to write good bash (bash=functional; c++=procedural). In particular, I've tried to minimize the number of loops in these scripts (like [this](https://github.com/kth-competitive-programming/kactl/blob/main/doc/scripts/compile-all.sh)). - ---- -Each script should return a non-zero exit code on failure to make CI fail. - -The return code of the script is the return code of the last command. So if some intermediary command fails, I call `exit 1` to exit early, so I usually put: - -``` -command || exit 1 -``` - -Although `grep`'s return code is non-zero iff no results are found. But I usually grep the code for things I don't want: - -``` -grep "something bad" && exit 1 -``` - -When grep is the last command in the script, I use `!` to flip the return code: - -``` -! command | grep . -``` diff --git a/tests/scripts/build_pdf.sh b/tests/scripts/build_pdf.sh deleted file mode 100755 index 192f3ce7..00000000 --- a/tests/scripts/build_pdf.sh +++ /dev/null @@ -1,98 +0,0 @@ -#!/bin/bash -# ** glob now searches any number of levels -shopt -s globstar - -############################################################################# -############ DON'T PUSH ANY OF THESE CHANGES TO THE REPO!!!!!!!! ############ -############################################################################# - -echo "DON'T PUSH ANY OF THESE CHANGES TO THE REPO!!!!!!!!" -echo "if you push these changes, I'll slap your butt" - -# remove some files not suitable for PDF: -rm ../library/data_structures/bit_uncommon/rupq.hpp || exit 1 -rm ../library/data_structures/bit_uncommon/rurq.hpp || exit 1 -rm ../library/data_structures/seg_tree.png || exit 1 -rm ../library/data_structures/seg_tree_uncommon/distinct_query.hpp || exit 1 -rm ../library/data_structures/seg_tree_uncommon/implicit.hpp || exit 1 -rm ../library/data_structures/seg_tree_uncommon/kth_smallest_query.hpp || exit 1 -rm ../library/data_structures/uncommon/mode_query.hpp || exit 1 -rm ../library/data_structures/uncommon/priority_queue_of_updates.hpp || exit 1 -rm ../library/data_structures/uncommon/deque_op.hpp || exit 1 -rm ../library/graphs/strongly_connected_components/add_edges_strongly_connected.hpp || exit 1 -rm ../library/graphs/strongly_connected_components/offline_incremental_scc.hpp || exit 1 -rm ../library/graphs/uncommon/bridges.hpp || exit 1 -rm ../library/graphs/uncommon/cuts.hpp || exit 1 -rm ../library/graphs/uncommon/block_vertex_tree.hpp || exit 1 -rm ../library/graphs/uncommon/bridge_tree.hpp || exit 1 -rm ../library/math/derangements.hpp || exit 1 -rm ../library/math/num_distinct_subsequences.hpp || exit 1 -rm ../library/math/partitions.hpp || exit 1 -rm ../library/monotonic_stack/cartesian_k_ary_tree.hpp || exit 1 -rm ../library/monotonic_stack/max_rect_histogram.hpp || exit 1 -rm ../library/monotonic_stack/cartesian_binary_tree_after.png || exit 1 -rm ../library/monotonic_stack/mono_stack_ri.png || exit 1 -rm ../library/strings/manacher/longest_palindrome_query.hpp || exit 1 -rm ../library/trees/uncommon/count_paths_per_length.hpp || exit 1 -rm ../library/trees/uncommon/count_paths_per_node.hpp || exit 1 -rm ../library/trees/uncommon/contour_range_query.hpp || exit 1 -rm ../library/trees/uncommon/contour_range_update.hpp || exit 1 -rm ../library/trees/uncommon/sum_adjacent.hpp || exit 1 -rm ../library/trees/uncommon/ladder_decomposition.hpp || exit 1 - -# remove links in comments: these aren't useful in the PDF, and are usually the -# longest words which extend into the next column -echo "removing links" -sed --in-place '/\/\/! https/d' ../library/**/*.hpp - -# PDF will wrap at 68 characters. Let's check that there's no long words, as -# they won't wrap in PDF -WORD_LENGTH_THRESHOLD=61 -echo "The following words are > $WORD_LENGTH_THRESHOLD characters, and won't wrap in PDF:" -cat ../library/**/*.hpp | - tr '[:blank:]' '\n' | - awk --assign=max_len="$WORD_LENGTH_THRESHOLD" '{if(length>max_len)print$0}' | - grep . && - exit 1 - -echo "check no multiline comments. Generating hashes of file-prefixes requires this." -grep --extended-regexp "\/\*" --recursive ../library/**/*.hpp && exit 1 - -make compile_commented_snippets || exit 1 - -# remove #pragma once -sed --in-place '/^#pragma once$/d' ../library/**/*.hpp -# remove NOLINTNEXTLINE comments -sed --in-place '/^\/\/ NOLINTNEXTLINE(readability-identifier-naming)$/d' ../library/**/*.hpp - -#adds hash code comments -chmod +x ../library/contest/hash.sh -for header in ../library/**/*.hpp; do - echo "adding hash codes for $header" - for i in $(seq "$(wc --lines <"$header")" -5 1); do - hash=$(head --lines "$i" "$header" | sed '/^#include/d' | cpp -dD -P -fpreprocessed | ./../library/contest/hash.sh) - line_length=$(sed --quiet "${i}p" "$header" | wc --chars) - # PDF wraps at 68 chars, and hash comment takes 8 chars total - padding_length=$((68 - 8 - line_length)) - padding_length=$((padding_length > 0 ? padding_length : 0)) - padding=$(printf '%*s' "$padding_length" '') - sed --in-place "${i}s/$/$padding\/\/${hash}/" "$header" - done -done - -git submodule init -git submodule update - -# install dependencies listed in ../notebook-generator/package.json -npm ci --prefix ../notebook-generator/ -npm run test --prefix ../notebook-generator/ - -# underscores in file names look bad in ptc, so this -# replaces all underscores with spaces -# note, this is the perl `rename` command, not the linux util -find ../library/ -depth -execdir rename 'y/_/ /' {} + - -# regarding school branding: https://brand.sdsmt.edu/identity/our-name/ -# in particular, no initials -# logo taken from https://brand.sdsmt.edu/identity/official-logos/ -./../notebook-generator/bin/notebookgen ../library/ --author "South Dakota Mines" --output ./ptc.pdf --size 8 --columns 3 --image images/south_dakota_mines_logo.png diff --git a/tests/scripts/clangtidy.sh b/tests/scripts/clangtidy.sh deleted file mode 100755 index 9cc3d610..00000000 --- a/tests/scripts/clangtidy.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -# ** glob now searches any number of levels -shopt -s globstar - -# doesn't compile with clang -rm library_checker_aizu_tests/handmade_tests/dynamic_bitset.test.cpp - -git submodule init -git submodule update - -find library_checker_aizu_tests/ -type f -name "*.test.cpp" | - parallel clang-tidy-19 --config-file=.config/.clang-tidy {} -- -std=c++20 || - exit 1 diff --git a/tests/scripts/compile_clang.sh b/tests/scripts/compile_clang.sh deleted file mode 100755 index 029ddcb5..00000000 --- a/tests/scripts/compile_clang.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -# ** glob now searches any number of levels -shopt -s globstar - -# doesn't compile with clang -rm library_checker_aizu_tests/handmade_tests/dynamic_bitset.test.cpp - -git submodule init -git submodule update - -find library_checker_aizu_tests/ -type f -name "*.test.cpp" | - parallel clang++-19 {} "$(tr '\n' ' ' <.config/.clang_compile_flags)" -std=c++20 diff --git a/tests/scripts/compile_commented_snippets.sh b/tests/scripts/compile_commented_snippets.sh deleted file mode 100755 index 2c0cb93d..00000000 --- a/tests/scripts/compile_commented_snippets.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash -# ** glob now searches any number of levels -shopt -s globstar - -git submodule init -git submodule update - -# build cpp file with everything in the library with all code in @code ... -# @endcode comments in main - -{ - echo "#include " - echo "using namespace std;" - cat library_checker_aizu_tests/kactl_macros.hpp - echo "const ll mod = (119 << 23) + 1, root = 62;" - find ../library/ -type f -name "*.hpp" | grep --invert-match --file=.config/.code_snippet_excluded_file_list | sort | sed 's/^/#include "/; s/$/"/' | cpp -nostdinc -C -P | grep --invert-match --extended-regexp "const int mod = |const ll mod = " - echo "int main() {" - echo "vi a,b,subset;" - echo "vl left,bottom;" - echo "vector edges;" - echo "vector> eds;" - echo "vector> w_eds, queries;" - echo "vi rhs;" - echo "vector mat;" - echo "vector> grid;" - echo "int n,m,k,tl,tr,l,r,l1,r1,l2,r2,s_l,s_r,root_l,root_r,source,sink,total_flow,bccid,u,v,lsz,rsz,cols,cap,num,x,y;" -} >entire_library_without_main - -{ - cat entire_library_without_main - sed --quiet '/\/\/! @code$/,/\/\/! @endcode$/p' entire_library_without_main | sed 's/\/\/! @code/{/' | sed 's/\/\/! @endcode/}/' | sed 's/\/\/!//' - echo "return 0;" - echo "}" -} >entire_library.cpp - -echo "compiling code in @code ... @endcode comments with g++" -g++ -std=c++20 entire_library.cpp || exit 1 - -echo "compiling code in @code ... @endcode comments with clang++" -clang++-19 -std=c++20 entire_library.cpp || exit 1 diff --git a/tests/scripts/compile_gcc.sh b/tests/scripts/compile_gcc.sh deleted file mode 100755 index e38eb9f6..00000000 --- a/tests/scripts/compile_gcc.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -# ** glob now searches any number of levels -shopt -s globstar - -git submodule init -git submodule update - -find library_checker_aizu_tests/ -type f -name "*.test.cpp" | - parallel g++ {} "$(tr '\n' ' ' <.config/.gcc_compile_flags)" diff --git a/tests/scripts/do_format.sh b/tests/scripts/do_format.sh deleted file mode 100755 index 7a41729a..00000000 --- a/tests/scripts/do_format.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -# ** glob now searches any number of levels -shopt -s globstar - -clang-format-19 -i --style=file:.config/.clang-format ../**/*.hpp ../**/*.cpp diff --git a/tests/scripts/find_files_without_tests.sh b/tests/scripts/find_files_without_tests.sh deleted file mode 100755 index 6add73c6..00000000 --- a/tests/scripts/find_files_without_tests.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash -# ** glob now searches any number of levels -shopt -s globstar - -git submodule init -git submodule update - -echo ".hpp files included by no .test.cpp file:" -! comm -23 --check-order <( - basename --multiple ../library/**/*.hpp | - sort | - uniq -) <( - g++ -MM library_checker_aizu_tests/**/*.test.cpp | - xargs basename --multiple | - sort | - uniq -) | - grep . diff --git a/tests/scripts/grep_clangformat_cppcheck.sh b/tests/scripts/grep_clangformat_cppcheck.sh deleted file mode 100755 index 56c9863f..00000000 --- a/tests/scripts/grep_clangformat_cppcheck.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/bash -# ** glob now searches any number of levels -shopt -s globstar - -# miscellaneous checks - done before initializing git submodules to avoid checking stuff not in our code - -echo "check NULL instead of nullptr" -grep "nullptr" --recursive ../library/ && exit 1 - -echo "check no endl" -grep "endl" --recursive library_checker_aizu_tests/ && exit 1 - -echo "check template over template:" -grep --extended-regexp "template\s?" -grep "pair" --recursive ../library/**/*.hpp && exit 1 - -echo "check sz instead of ssize" -grep "ssize" --recursive ../library/ && exit 1 - -echo "check vi instead of vector" -grep "vector" --recursive ../library/**/*.hpp && exit 1 - -echo "check no basic_string, excluding @code example inits" -grep "[[:space:]]*//\!" --recursive --invert-match ../library/**/*.hpp library_checker_aizu_tests/**/*.test.cpp | grep "basic_string" && exit 1 - -echo "check begin(arr) instead of arr.begin(), similarly for end, rbegin, rend, empty, size:" -# TODO: remove this define filter if/when we move to -std=c++20 -grep --invert-match --fixed-strings "#define" --recursive ../library/ library_checker_aizu_tests/ | - grep --fixed-strings --regexp=".begin()" --regexp=".rbegin()" --regexp=".end()" --regexp=".rend()" --regexp=".empty()" --regexp=".size()" && exit 1 - -echo "check that there are no empty lines" -grep "^$" ../library/**/*.hpp && exit 1 - -echo "check files and directories are snake_case:" -find ../library/ library_checker_aizu_tests/ -name "*[A-Z]*" -or -name "*-*" | - grep --invert-match ".verify-helper" | - grep --invert-match "README" && - exit 1 - -clang-format-19 --dry-run --Werror --style=file:.config/.clang-format library_checker_aizu_tests/**/*.hpp library_checker_aizu_tests/**/*.test.cpp ../library/**/*.hpp ../library/**/*.cpp || exit 1 - -git submodule init -git submodule update - -cppcheck --enable=all --inconclusive --suppressions-list=.config/.cppcheck_suppression_list \ - --force --language=c++ --error-exitcode=1 --std=c++20 --max-ctu-depth=50 \ - library_checker_aizu_tests/**/*.hpp library_checker_aizu_tests/**/*.test.cpp ../library/**/*.hpp ../library/**/*.cpp || - exit 1 diff --git a/tests/scripts/print_which_tests_havent_run.sh b/tests/scripts/print_which_tests_havent_run.sh deleted file mode 100755 index b57e4516..00000000 --- a/tests/scripts/print_which_tests_havent_run.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash -# ** glob now searches any number of levels -shopt -s globstar - -# so that paths match up for comm command (otherwise you need basename) -cd .. - -echo "total number of tests:" -find tests/library_checker_aizu_tests/ -type f -name "*.test.cpp" | wc --lines - -echo "number of tests which have run:" -grep --count "test.cpp" .verify-helper/timestamps.remote.json - -echo "tests which have *not* run:" -! comm -23 --check-order <( - find tests/library_checker_aizu_tests/ -type f -name "*.test.cpp" | - sort | - uniq -) <( - grep --only-matching '".*test.cpp"' .verify-helper/timestamps.remote.json | - tr -d '"' | - sort | - uniq -) | - grep . diff --git a/tests/scripts/shellcheck_shfmt.sh b/tests/scripts/shellcheck_shfmt.sh deleted file mode 100755 index 9d5d5d5f..00000000 --- a/tests/scripts/shellcheck_shfmt.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash -# ** glob now searches any number of levels -shopt -s globstar - -echo "bash scripts missing the bash shebang:" -comm -23 --check-order <( - find scripts/ -type f -name "*.sh" | - sort | - uniq -) <( - grep --recursive --fixed-strings --files-with-matches "#!/bin/bash" scripts/ | - sort | - uniq -) | - grep . && - exit 1 - -echo "bash scripts in tests/scripts/ missing shopt -s globstar:" -comm -23 --check-order <( - find scripts/ -type f -name "*.sh" | - sort | - uniq -) <( - grep --recursive --fixed-strings --files-with-matches "shopt -s globstar" scripts/ | - sort | - uniq -) | - grep . && - exit 1 - -shellcheck --shell=bash --check-sourced --enable=check-set-e-suppressed,quote-safe-variables ./**/*.sh || exit 1 - -shfmt -ln=bash -s -d -w ./**/*.sh || exit 1 diff --git a/tests/scripts/update_main.sh b/tests/scripts/update_main.sh deleted file mode 100755 index fdaae0ba..00000000 --- a/tests/scripts/update_main.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash -# ** glob now searches any number of levels -shopt -s globstar - -git submodule init -git submodule update - -############################################################################# -############ DON'T PUSH ANY OF THESE CHANGES TO THE REPO!!!!!!!! ############ -############################################################################# - -echo "DON'T PUSH ANY OF THESE CHANGES TO THE REPO!!!!!!!!" - -# remove NOLINTNEXTLINE comments -sed --in-place '/^\/\/ NOLINTNEXTLINE(readability-identifier-naming)$/d' ../library/**/*.hpp - -# to copy files like template.cpp, *.sh, *.png, *.md to root directory; so they exist in main branch -# also to create all directories (cpp command below fails if destination path isn't created) -cp -r ../library/. ../ - -for header in ../library/**/*.hpp; do - # see https://github.com/programming-team-code/kactl_no_macros/blob/main/remove_macros.sh - cpp -nostdinc -C -P "$header" | cat library_checker_aizu_tests/kactl_macros.hpp - | cpp -nostdinc -C -P - -o "${header/\/library/}" -done - -# the cpp preprocessor sometimes leaves blank empty lines -sed --in-place '/^[[:space:]]*$/d' ../**/*.hpp -# cpp command messes up formatting -make do_format diff --git a/library/trees/edge_cd.hpp b/trees/edge_cd.hpp similarity index 81% rename from library/trees/edge_cd.hpp rename to trees/edge_cd.hpp index e3ec20cd..eeb3a002 100644 --- a/library/trees/edge_cd.hpp +++ b/trees/edge_cd.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://codeforces.com/blog/entry/104997 //! https://codeforces.com/blog/entry/120446 //! https://codeforces.com/blog/entry/142176 @@ -16,10 +15,10 @@ template struct edge_cd { vector adj; F f; - vi siz; + vector siz; edge_cd(const vector& adj, F f): - adj(adj), f(f), siz(sz(adj)) { - dfs(0, sz(adj) - 1); + adj(adj), f(f), siz(ssize(adj)) { + dfs(0, ssize(adj) - 1); } int find_cent(int v, int p, int m) { siz[v] = 1; @@ -37,10 +36,11 @@ template struct edge_cd { if (m < 2) return; v = find_cent(v, -1, m); int sum = 0; - auto it = partition(all(adj[v]), [&](int u) { - ll x = sum + siz[u]; - return x * x < m * (m - x) ? sum += siz[u], 1 : 0; - }); + auto it = + partition(begin(adj[v]), end(adj[v]), [&](int u) { + int64_t x = sum + siz[u]; + return x * x < m * (m - x) ? sum += siz[u], 1 : 0; + }); f(adj, v, it - begin(adj[v])); G oth(it, end(adj[v])); adj[v].erase(it, end(adj[v])); diff --git a/library/trees/edge_cd.png b/trees/edge_cd.png similarity index 100% rename from library/trees/edge_cd.png rename to trees/edge_cd.png diff --git a/library/trees/extra_members/dist.hpp b/trees/extra_members/dist.hpp similarity index 100% rename from library/trees/extra_members/dist.hpp rename to trees/extra_members/dist.hpp diff --git a/library/trees/extra_members/in_subtree.hpp b/trees/extra_members/in_subtree.hpp similarity index 100% rename from library/trees/extra_members/in_subtree.hpp rename to trees/extra_members/in_subtree.hpp diff --git a/library/trees/extra_members/next_on_path.hpp b/trees/extra_members/next_on_path.hpp similarity index 95% rename from library/trees/extra_members/next_on_path.hpp rename to trees/extra_members/next_on_path.hpp index 1c81a468..544a961a 100644 --- a/library/trees/extra_members/next_on_path.hpp +++ b/trees/extra_members/next_on_path.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://codeforces.com/blog/entry/71567?#comment-559285 //! returns the node vi({u,p[u],..,lca(u,v),..,p[v],v})[1] //! @time O(1) diff --git a/library/trees/extra_members/on_path.hpp b/trees/extra_members/on_path.hpp similarity index 100% rename from library/trees/extra_members/on_path.hpp rename to trees/extra_members/on_path.hpp diff --git a/library/trees/extra_members/virtual_tree.hpp b/trees/extra_members/virtual_tree.hpp similarity index 78% rename from library/trees/extra_members/virtual_tree.hpp rename to trees/extra_members/virtual_tree.hpp index 5559fa0f..05b4b410 100644 --- a/library/trees/extra_members/virtual_tree.hpp +++ b/trees/extra_members/virtual_tree.hpp @@ -9,14 +9,15 @@ //! orig_node[i] = index of node in original tree //! @time O(|subset| log |subset|) //! @space O(|subset|) -array compress_tree(vi subset) { +array, 2> compress_tree(vector subset) { auto proj = [&](int v) { return tin[v]; }; ranges::sort(subset, {}, proj); - int len = sz(subset); - rep(i, 1, len) + int len = ssize(subset); + for (int i = 1; i < len; i++) subset.push_back(lca(subset[i - 1], subset[i])); ranges::sort(subset, {}, proj); - subset.erase(unique(all(subset)), end(subset)); + subset.erase(unique(begin(subset), end(subset)), + end(subset)); return { mono_st(subset, [&](int u, int v) { return in_subtree(u, v); }), diff --git a/library/trees/hld.hpp b/trees/hld.hpp similarity index 88% rename from library/trees/hld.hpp rename to trees/hld.hpp index aaae48b6..527fe793 100644 --- a/library/trees/hld.hpp +++ b/trees/hld.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://github.com/kth-competitive-programming/kactl/blob/main/content/graph/HLD.h //! @code //! vector> adj(n); @@ -9,12 +8,11 @@ //! @endcode //! @time O(n + q log^2 n) //! @space O(n) -// NOLINTNEXTLINE(readability-identifier-naming) template struct HLD { int n; - vi p, siz, rt, tin; + vector p, siz, rt, tin; HLD(auto& adj): - n(sz(adj)), p(n), siz(n, 1), rt(n), tin(n) { + n(ssize(adj)), p(n), siz(n, 1), rt(n), tin(n) { auto dfs1 = [&](auto&& self, int v) -> void { for (int& u : adj[v]) { iter_swap(ranges::find(adj[u], v), rbegin(adj[u])); @@ -44,7 +42,7 @@ template struct HLD { } f(tin[u] + VALS_EDGES, tin[v] + 1); } - pii subtree(int v) { + pair subtree(int v) { return {tin[v] + VALS_EDGES, tin[v] + siz[v]}; } }; diff --git a/trees/lca_rmq.hpp b/trees/lca_rmq.hpp new file mode 100644 index 00000000..f39fb3fc --- /dev/null +++ b/trees/lca_rmq.hpp @@ -0,0 +1,121 @@ +//! @code +//! vi le = mono_st(a, less()); +//! // less_equal(), greater(), greater_equal() +//! @endcode +//! when cmp == less(): +//! a[le[i]] < a[i] +//! @time O(n) +//! @space O(n) +vector mono_st(const auto& a, const auto& cmp) { + vector l(ssize(a)); + for (int i = 0; i < ssize(a); i++) + for (l[i] = i - 1; l[i] >= 0 && !cmp(a[l[i]], a[i]);) + l[i] = l[l[i]]; + return l; +} +//! @code +//! RMQ rmq1(a, ranges::min); +//! RMQ rmq2(a, [&](auto& x, auto& y) { +//! return min(x, y); +//! }); +//! vector>> +//! rmqs(3, {{}, NULL}); +//! rmqs[1] = {a, ranges::min}; +//! @endcode +//! @time O(nlogn + q) +//! @space O(nlogn) +template struct RMQ { + vector> dp; + F op; + RMQ(const vector& a, F op): dp(1, a), op(op) { + for (int i = 0; (2 << i) <= ssize(a); i++) { + dp.emplace_back(ssize(a) - (2 << i) + 1); + ranges::transform(dp[i], dp[i] | views::drop(1 << i), + begin(dp[i + 1]), op); + } + } + T query(int l, int r) { // [l, r) + assert(l < r); + int lg = __lg(r - l); + return op(dp[lg][l], dp[lg][r - (1 << lg)]); + } +}; +//! https://github.com/kth-competitive-programming/kactl/blob/main/content/graph/LCA.h +//! @code +//! vector> adj(n); +//! LCA lca(adj); +//! @endcode +//! @time O(nlogn + q) +//! @space O(nlogn) +struct LCA { + int n; + vector tin, siz, d, p; + RMQ> rmq = {{}, NULL}; + LCA(const auto& adj): + n(ssize(adj)), tin(n), siz(n, 1), d(n), p(n) { + vector order; + auto dfs = [&](auto&& self, int v) -> void { + tin[v] = ssize(order), order.push_back(v); + for (int u : adj[v]) + if (u != p[v]) + d[u] = d[p[u] = v] + 1, self(self, u), + siz[v] += siz[u]; + }; + dfs(dfs, 0); + rmq = {order, + [&](int u, int v) { return d[u] < d[v] ? u : v; }}; + } + int lca(int u, int v) { + if (u == v) return u; + auto [x, y] = minmax(tin[u], tin[v]); + return p[rmq.query(x + 1, y + 1)]; + } + int dist(int u, int v) { + return d[u] + d[v] - 2 * d[lca(u, v)]; + } + //! returns 1 if v is in u's subtree + bool in_subtree(int u, int v) { + return tin[u] <= tin[v] && tin[v] < tin[u] + siz[u]; + } + //! returns 1 if w is on path from u to v + bool on_path(int u, int v, int w) { + return (in_subtree(w, u) || in_subtree(w, v)) && + in_subtree(lca(u, v), w); + } + //! https://codeforces.com/blog/entry/71567?#comment-559285 + //! returns the node + //! vi({u,p[u],..,lca(u,v),..,p[v],v})[1] + //! @time O(1) + //! @space O(1) + int next_on_path(int u, int v) { + assert(u != v); + return in_subtree(u, v) + ? rmq.query(tin[u] + 1, tin[v] + 1) + : p[u]; + } + //! https://github.com/kth-competitive-programming/kactl/blob/main/content/graph/CompressTree.h + //! @code + //! vector adj(n); + //! LCA lca(adj); + //! auto [par, orig_node] = + //! lca.compress_tree(subset); + //! @endcode + //! par[i] = parent of i in compressed tree, par[0]==-1 + //! orig_node[i] = index of node in original tree + //! @time O(|subset| log |subset|) + //! @space O(|subset|) + array, 2> compress_tree(vector subset) { + auto proj = [&](int v) { return tin[v]; }; + ranges::sort(subset, {}, proj); + int len = ssize(subset); + for (int i = 1; i < len; i++) + subset.push_back(lca(subset[i - 1], subset[i])); + ranges::sort(subset, {}, proj); + subset.erase(unique(begin(subset), end(subset)), + end(subset)); + return { + mono_st(subset, + [&](int u, int v) { return in_subtree(u, v); }), + subset}; + } +}; diff --git a/library/trees/linear_kth_par.hpp b/trees/linear_kth_par.hpp similarity index 83% rename from library/trees/linear_kth_par.hpp rename to trees/linear_kth_par.hpp index 267fc998..0c949db9 100644 --- a/library/trees/linear_kth_par.hpp +++ b/trees/linear_kth_par.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://codeforces.com/blog/entry/126580 //! @code //! vector> adj(n); @@ -10,13 +9,14 @@ //! @space O(n*max((2*KAPPA+3)/KAPPA,2*KAPPA)) template struct linear_kth_par { int n; - vi d, leaf, pos, jmp; - vector lad; + vector d, leaf, pos, jmp; + vector> lad; linear_kth_par(const auto& adj): - n(sz(adj)), d(n), leaf(n), pos(n), jmp(2 * n), lad(n) { + n(ssize(adj)), d(n), leaf(n), pos(n), jmp(2 * n), + lad(n) { static_assert(KAPPA >= 1); int t = 1; - vi st(n); + vector st(n); auto calc = [&](int s) { jmp[t] = st[max(0, s - KAPPA * (t & -t))]; t++; @@ -34,7 +34,8 @@ template struct linear_kth_par { } int s = (d[l] - d[v]) * (2 * KAPPA + 3) / KAPPA; s = min(max(s, 2 * KAPPA), d[l] + 1); - rep(i, sz(lad[l]), s) lad[l].push_back(st[d[l] - i]); + for (int i = ssize(lad[l]); i < s; i++) + lad[l].push_back(st[d[l] - i]); }; dfs(dfs, 0, 0); } diff --git a/library/trees/linear_lca.hpp b/trees/linear_lca.hpp similarity index 81% rename from library/trees/linear_lca.hpp rename to trees/linear_lca.hpp index d315c641..7f1aceef 100644 --- a/library/trees/linear_lca.hpp +++ b/trees/linear_lca.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://codeforces.com/blog/entry/125371 //! @code //! vector> adj(n); @@ -9,13 +8,13 @@ int lsb(int x) { return x & -x; } struct linear_lca { int n; - vi d, in, asc, head; + vector d, in, asc, head; linear_lca(const auto& adj): - n(sz(adj)), d(n), in(n), asc(n), head(n + 1) { - vector order; + n(ssize(adj)), d(n), in(n), asc(n), head(n + 1) { + vector> order; auto dfs = [&](auto&& self, int v, int p) -> void { order.emplace_back(v, p); - in[v] = sz(order); + in[v] = ssize(order); for (int u : adj[v]) if (u != p) { d[u] = 1 + d[v]; @@ -37,5 +36,7 @@ struct linear_lca { } return d[u] < d[v] ? u : v; } -#include "extra_members/dist.hpp" + int dist(int u, int v) { + return d[u] + d[v] - 2 * d[lca(u, v)]; + } }; diff --git a/library/trees/shallowest_decomp_tree.hpp b/trees/shallowest_decomp_tree.hpp similarity index 87% rename from library/trees/shallowest_decomp_tree.hpp rename to trees/shallowest_decomp_tree.hpp index 8256982c..37bc0ff2 100644 --- a/library/trees/shallowest_decomp_tree.hpp +++ b/trees/shallowest_decomp_tree.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://codeforces.com/blog/entry/125018 //! @code //! vector> adj(n); @@ -8,7 +7,7 @@ //! @time O(n log n) //! @space O(n) void shallowest(auto& adj, auto f) { - vector order(bit_width(size(adj))); + vector> order(bit_width(size(adj))); auto dfs = [&](auto&& self, int v, int p) -> int { int once = 0, twice = 0; for (int u : adj[v]) @@ -21,7 +20,7 @@ void shallowest(auto& adj, auto f) { return dp; }; dfs(dfs, 0, 0); - for (const vi& vec : order | views::reverse) + for (const vector& vec : order | views::reverse) for (int v : vec) { f(v); for (int u : adj[v]) diff --git a/library/trees/tree_lift.hpp b/trees/tree_lift.hpp similarity index 85% rename from library/trees/tree_lift.hpp rename to trees/tree_lift.hpp index 3a6e574b..da7edac0 100644 --- a/library/trees/tree_lift.hpp +++ b/trees/tree_lift.hpp @@ -1,4 +1,3 @@ -#pragma once //! https://github.com/ucf-programming-team/hackpack-cpp/blob/master/content/graphs/TreeLifting.h //! @code //! vector> adj(n); @@ -9,8 +8,8 @@ //! @time O(n + q log n) //! @space O(n) struct tree_lift { - vi d, p, j; - tree_lift(const auto& adj): d(sz(adj)), p(d), j(d) { + vector d, p, j; + tree_lift(const auto& adj): d(ssize(adj)), p(d), j(d) { auto dfs = [&](auto&& self, int v) -> void { int up = d[v] + d[j[j[v]]] == 2 * d[j[v]] ? j[j[v]] : v; @@ -34,5 +33,7 @@ struct tree_lift { else u = p[u], v = p[v]; return u; } -#include "extra_members/dist.hpp" + int dist(int u, int v) { + return d[u] + d[v] - 2 * d[lca(u, v)]; + } }; diff --git a/library/trees/uncommon/centroid_decomp.hpp b/trees/uncommon/centroid_decomp.hpp similarity index 93% rename from library/trees/uncommon/centroid_decomp.hpp rename to trees/uncommon/centroid_decomp.hpp index 3cd5d12d..f33d019b 100644 --- a/library/trees/uncommon/centroid_decomp.hpp +++ b/trees/uncommon/centroid_decomp.hpp @@ -1,4 +1,3 @@ -#pragma once //! @code //! vector> adj(n); //! centroid(adj, [&](const auto& adj, @@ -9,9 +8,9 @@ template struct centroid { G adj; F f; - vi siz; + vector siz; centroid(const G& adj, F f): - adj(adj), f(f), siz(sz(adj), -1) { + adj(adj), f(f), siz(ssize(adj), -1) { dfs(0, -1); } void calc_sz(int v, int p) { diff --git a/trees/uncommon/contour_range_query.hpp b/trees/uncommon/contour_range_query.hpp new file mode 100644 index 00000000..e64dd8c7 --- /dev/null +++ b/trees/uncommon/contour_range_query.hpp @@ -0,0 +1,182 @@ +//! @time O(n + q log n) +//! @space O(n) +struct BIT { + vector s; + BIT(int n): s(n) {} + BIT(const vector& a): s(a) { + for (int i = 0; i < ssize(a); i++) { + int j = i | (i + 1); + if (j < ssize(a)) s[j] += s[i]; + } + } + void update(int i, int64_t d) { + for (; i < ssize(s); i |= i + 1) s[i] += d; + } + int64_t query(int r) { // [0, r) + int64_t ret = 0; + for (; r > 0; r &= r - 1) ret += s[r - 1]; + return ret; + } + int64_t query(int l, int r) { // [l, r) + return query(r) - query(l); + } + //! Requires s[i] >= 0 + //! max r such that sum of [0,r) < sum, or -1 + int walk(int64_t sum) { + if (sum <= 0) return -1; + int r = 0; + for (int pw = bit_floor(size(s)); pw; pw >>= 1) + if (r + pw <= ssize(s) && s[r + pw - 1] < sum) + sum -= s[(r += pw) - 1]; + return r; + } +}; +//! https://codeforces.com/blog/entry/104997 +//! https://codeforces.com/blog/entry/120446 +//! https://codeforces.com/blog/entry/142176 +//! https://youtu.be/wDwaMo5xa-k +//! @code +//! vector> adj(n); +//! edge_cd(adj, [&](const auto& adj, int cent, int m) { +//! // subtrees of [0, m) of adj[cent]: 1st edge-set +//! // subtrees of [m, sz(adj[cent])): 2nd edge-set +//! }); +//! @endcode +//! handle single-edge-paths separately +//! @time O(n logφ n) +//! @space O(n) +template struct edge_cd { + vector adj; + F f; + vector siz; + edge_cd(const vector& adj, F f): + adj(adj), f(f), siz(ssize(adj)) { + dfs(0, ssize(adj) - 1); + } + int find_cent(int v, int p, int m) { + siz[v] = 1; + for (int u : adj[v]) + if (u != p) { + int cent = find_cent(u, v, m); + if (cent != -1) return cent; + siz[v] += siz[u]; + } + return 2 * siz[v] > m + ? p >= 0 && (siz[p] = m + 1 - siz[v]), + v : -1; + } + void dfs(int v, int m) { + if (m < 2) return; + v = find_cent(v, -1, m); + int sum = 0; + auto it = + partition(begin(adj[v]), end(adj[v]), [&](int u) { + int64_t x = sum + siz[u]; + return x * x < m * (m - x) ? sum += siz[u], 1 : 0; + }); + f(adj, v, it - begin(adj[v])); + G oth(it, end(adj[v])); + adj[v].erase(it, end(adj[v])); + dfs(v, sum); + swap(adj[v], oth); + dfs(v, m - sum); + } +}; +//! helper for edge CD: given tree, update node's number, +//! find sum of neighbors' numbers +struct sum_adj { + int n; + vector sum, sum_ch; + vector p; + //! @param adj undirected, unrooted tree + //! @param sum sum[v] = initial number for node v + //! @time O(n) + //! @space various O(n) vectors are allocated; recursion + //! stack for dfs is O(n) + sum_adj(const vector>& adj, + const vector& sum): + n(ssize(sum)), sum(sum), sum_ch(n), p(n, -1) { + auto dfs = [&](auto&& self, int v) -> void { + for (int u : adj[v]) + if (u != p[v]) + p[u] = v, sum_ch[v] += sum[u], self(self, u); + }; + dfs(dfs, 0); + } + //! @param v node + //! @param delta number to add + //! @time O(1) + //! @space O(1) + void update(int v, int64_t delta) { + sum[v] += delta; + if (p[v] != -1) sum_ch[p[v]] += delta; + } + //! @param v node + //! @returns sum of v's neighbors numbers + //! @time O(1) + //! @space O(1) + int64_t query(int v) { + return sum_ch[v] + (p[v] != -1 ? sum[p[v]] : 0); + } +}; +//! https://judge.yosupo.jp/problem/vertex_add_range_contour_sum_on_tree +struct contour_range_query { + int n; + sum_adj sum_a; + vector>> info; + vector> bits; + //! @param adj unrooted, undirected tree + //! @param a a[v] = initial number for node v + //! @time O(n logφ n) + //! @space O(n logφ n) for `info` and `bits` + contour_range_query(const vector>& adj, + const vector& a): + n(ssize(a)), sum_a(adj, a), info(n) { + edge_cd(adj, + [&](const vector>& cd_adj, int cent, + int split) { + vector> sum_num(2, + vector(1)); + auto dfs = [&](auto&& self, int v, int p, int d, + int side) -> void { + info[v].push_back({int(ssize(bits)), d, side}); + if (ssize(sum_num[side]) == d) + sum_num[side].push_back(0); + sum_num[side][d] += a[v]; + for (int u : cd_adj[v]) + if (u != p) self(self, u, v, 1 + d, side); + }; + for (int i = 0; i < ssize(cd_adj[cent]); i++) + dfs(dfs, cd_adj[cent][i], cent, 1, i < split); + bits.push_back({BIT(sum_num[0]), BIT(sum_num[1])}); + }); + } + //! @param v node + //! @param delta number to add to node v's number + //! @time O(logφ(n) * log2(n)) + //! @space O(1) + void update(int v, int64_t delta) { + sum_a.update(v, delta); + for (auto [decomp, d, side] : info[v]) + bits[decomp][side].update(d, delta); + } + //! @param v node + //! @param l,r defines range [l, r) + //! @returns sum of node u's number over all u such that + //! l + //! <= dist_edges(u, v) < r + //! @time O(logφ(n) * log2(n)) + //! @space O(1) + int64_t query(int v, int l, int r) { + int64_t sum = 0; + if (l <= 0 && 0 < r) sum += sum_a.sum[v]; + if (l <= 1 && 1 < r) sum += sum_a.query(v); + for (auto [decomp, d, side] : info[v]) { + auto& bit = bits[decomp][!side]; + int my_l = clamp(l - d, 1, ssize(bit.s)); + int my_r = clamp(r - d, 1, ssize(bit.s)); + sum += bit.query(my_l, my_r); + } + return sum; + } +}; diff --git a/trees/uncommon/contour_range_update.hpp b/trees/uncommon/contour_range_update.hpp new file mode 100644 index 00000000..3f1ac031 --- /dev/null +++ b/trees/uncommon/contour_range_update.hpp @@ -0,0 +1,198 @@ +//! @time O(n + q log n) +//! @space O(n) +struct BIT { + vector s; + BIT(int n): s(n) {} + BIT(const vector& a): s(a) { + for (int i = 0; i < ssize(a); i++) { + int j = i | (i + 1); + if (j < ssize(a)) s[j] += s[i]; + } + } + void update(int i, int64_t d) { + for (; i < ssize(s); i |= i + 1) s[i] += d; + } + int64_t query(int r) { // [0, r) + int64_t ret = 0; + for (; r > 0; r &= r - 1) ret += s[r - 1]; + return ret; + } + int64_t query(int l, int r) { // [l, r) + return query(r) - query(l); + } + //! Requires s[i] >= 0 + //! max r such that sum of [0,r) < sum, or -1 + int walk(int64_t sum) { + if (sum <= 0) return -1; + int r = 0; + for (int pw = bit_floor(size(s)); pw; pw >>= 1) + if (r + pw <= ssize(s) && s[r + pw - 1] < sum) + sum -= s[(r += pw) - 1]; + return r; + } +}; +struct bit_rupq { + int n; + BIT bit = {0}; + bit_rupq(int n): n(n), bit(n) {} + bit_rupq(vector a): n(ssize(a)) { + adjacent_difference(begin(a), end(a), begin(a)); + bit = {a}; + } + //! does a[l]+=d, a[l+1]+=d, .., a[r-1]+=d + //! @time O(log n) + //! @space O(1) + void update(int l, int r, int64_t d) { + if (l < n) bit.update(l, d); + if (r < n) bit.update(r, -d); + } + //! @returns a[i] + //! @time O(log n) + //! @space O(1) + int64_t get_index(int i) { return bit.query(i + 1); } +}; +//! https://codeforces.com/blog/entry/104997 +//! https://codeforces.com/blog/entry/120446 +//! https://codeforces.com/blog/entry/142176 +//! https://youtu.be/wDwaMo5xa-k +//! @code +//! vector> adj(n); +//! edge_cd(adj, [&](const auto& adj, int cent, int m) { +//! // subtrees of [0, m) of adj[cent]: 1st edge-set +//! // subtrees of [m, sz(adj[cent])): 2nd edge-set +//! }); +//! @endcode +//! handle single-edge-paths separately +//! @time O(n logφ n) +//! @space O(n) +template struct edge_cd { + vector adj; + F f; + vector siz; + edge_cd(const vector& adj, F f): + adj(adj), f(f), siz(ssize(adj)) { + dfs(0, ssize(adj) - 1); + } + int find_cent(int v, int p, int m) { + siz[v] = 1; + for (int u : adj[v]) + if (u != p) { + int cent = find_cent(u, v, m); + if (cent != -1) return cent; + siz[v] += siz[u]; + } + return 2 * siz[v] > m + ? p >= 0 && (siz[p] = m + 1 - siz[v]), + v : -1; + } + void dfs(int v, int m) { + if (m < 2) return; + v = find_cent(v, -1, m); + int sum = 0; + auto it = + partition(begin(adj[v]), end(adj[v]), [&](int u) { + int64_t x = sum + siz[u]; + return x * x < m * (m - x) ? sum += siz[u], 1 : 0; + }); + f(adj, v, it - begin(adj[v])); + G oth(it, end(adj[v])); + adj[v].erase(it, end(adj[v])); + dfs(v, sum); + swap(adj[v], oth); + dfs(v, m - sum); + } +}; +//! helper for edge CD: given tree, update node's number, +//! find sum of neighbors' numbers +struct sum_adj { + int n; + vector sum, sum_ch; + vector p; + //! @param adj undirected, unrooted tree + //! @param sum sum[v] = initial number for node v + //! @time O(n) + //! @space various O(n) vectors are allocated; recursion + //! stack for dfs is O(n) + sum_adj(const vector>& adj, + const vector& sum): + n(ssize(sum)), sum(sum), sum_ch(n), p(n, -1) { + auto dfs = [&](auto&& self, int v) -> void { + for (int u : adj[v]) + if (u != p[v]) + p[u] = v, sum_ch[v] += sum[u], self(self, u); + }; + dfs(dfs, 0); + } + //! @param v node + //! @param delta number to add + //! @time O(1) + //! @space O(1) + void update(int v, int64_t delta) { + sum[v] += delta; + if (p[v] != -1) sum_ch[p[v]] += delta; + } + //! @param v node + //! @returns sum of v's neighbors numbers + //! @time O(1) + //! @space O(1) + int64_t query(int v) { + return sum_ch[v] + (p[v] != -1 ? sum[p[v]] : 0); + } +}; +//! https://judge.yosupo.jp/problem/vertex_get_range_contour_add_on_tree +struct contour_range_update { + int n; + vector a; + sum_adj sum_a; + vector>> info; + vector> bits; + //! @param adj unrooted, undirected tree + //! @param a a[v] = initial number for node v + //! @time O(n logφ n) + //! @space O(n logφ n) for `info` and `bits` + contour_range_update(const vector>& adj, + const vector& a): + n(ssize(a)), a(a), sum_a(adj, vector(n)), + info(n) { + edge_cd(adj, + [&](const vector>& cd_adj, int cent, + int split) { + array mx_d = {0, 0}; + auto dfs = [&](auto&& self, int v, int p, int d, + int side) -> void { + mx_d[side] = max(mx_d[side], d); + info[v].push_back({int(ssize(bits)), d, side}); + for (int u : cd_adj[v]) + if (u != p) self(self, u, v, 1 + d, side); + }; + for (int i = 0; i < ssize(cd_adj[cent]); i++) + dfs(dfs, cd_adj[cent][i], cent, 1, i < split); + bits.push_back( + {bit_rupq(mx_d[0] + 1), bit_rupq(mx_d[1] + 1)}); + }); + } + //! @param v,l,r,delta add delta to all nodes u such + //! that l <= dist_edges(v, u) < r + //! @time O(logφ(n) * log2(n)) + //! @space O(1) + void update(int v, int l, int r, int64_t delta) { + if (l <= 0 && 0 < r) a[v] += delta; + if (l <= 1 && 1 < r) sum_a.update(v, delta); + for (auto [decomp_id, d, side] : info[v]) { + auto& bit = bits[decomp_id][!side]; + int my_l = clamp(l - d, 1, bit.n); + int my_r = clamp(r - d, 1, bit.n); + bit.update(my_l, my_r, delta); + } + } + //! @param v node + //! @returns number of node v + //! @time O(logφ(n) * log2(n)) + //! @space O(1) + int64_t query(int v) { + int64_t sum = a[v] + sum_a.query(v); + for (auto [decomp_id, d, side] : info[v]) + sum += bits[decomp_id][side].get_index(d); + return sum; + } +}; diff --git a/trees/uncommon/count_paths_per_length.hpp b/trees/uncommon/count_paths_per_length.hpp new file mode 100644 index 00000000..4facebd2 --- /dev/null +++ b/trees/uncommon/count_paths_per_length.hpp @@ -0,0 +1,154 @@ +/** + * Author: Ludo Pulles, chilli, Simon Lindholm + * Date: 2019-01-09 + * License: CC0 + * Source: + http://neerc.ifmo.ru/trains/toulouse/2017/fft2.pdf (do + read, it's excellent) Accuracy bound from + http://www.daemonology.net/papers/fft.pdf + * Description: fft(a) computes $\hat f(k) = \sum_x a[x] + \exp(2\pi i \cdot k x / N)$ for all $k$. N must be a power + of 2. Useful for convolution: + \texttt{conv(a, b) = c}, where $c[x] = \sum a[i]b[x-i]$. + For convolution of complex numbers or more than two + vectors: FFT, multiply pointwise, divide by n, + reverse(start+1, end), FFT back. Rounding is safe if + $(\sum a_i^2 + \sum b_i^2)\log_2{N} < 9\cdot10^{14}$ (in + practice $10^{16}$; higher for random inputs). Otherwise, + use NTT/FFTMod. + * Time: O(N \log N) with $N = |A|+|B|$ ($\tilde 1s$ for + $N=2^{22}$) + * Status: somewhat tested + * Details: An in-depth examination of precision for both + FFT and FFTMod can be found + * here + (https://github.com/simonlindholm/fft-precision/blob/master/fft-precision.md) + */ +typedef complex C; +typedef vector vd; +void fft(vector& a) { + int n = ssize(a), L = 31 - __builtin_clz(n); + static vector> R(2, 1); + static vector rt(2, 1); // (^ 10% faster if double) + for (static int k = 2; k < n; k *= 2) { + R.resize(n); + rt.resize(n); + auto x = polar(1.0L, acos(-1.0L) / k); + for (int i = k; i < 2 * k; i++) + rt[i] = R[i] = i & 1 ? R[i / 2] * x : R[i / 2]; + } + vector rev(n); + for (int i = 0; i < n; i++) + rev[i] = (rev[i / 2] | (i & 1) << L) / 2; + for (int i = 0; i < n; i++) + if (i < rev[i]) swap(a[i], a[rev[i]]); + for (int k = 1; k < n; k *= 2) + for (int i = 0; i < n; i += 2 * k) + for (int j = 0; j < k; j++) { + // C z = rt[j+k] * a[i+j+k]; // (25% faster if + // hand-rolled) /// include-line + auto x = (double*)&rt[j + k], + y = (double*)&a[i + j + k]; /// exclude-line + C z(x[0] * y[0] - x[1] * y[1], + x[0] * y[1] + x[1] * y[0]); /// exclude-line + a[i + j + k] = a[i + j] - z; + a[i + j] += z; + } +} +vd conv(const vd& a, const vd& b) { + if (a.empty() || b.empty()) return {}; + vd res(ssize(a) + ssize(b) - 1); + int L = 32 - __builtin_clz(ssize(res)), n = 1 << L; + vector in(n), out(n); + copy(begin(a), end(a), begin(in)); + for (int i = 0; i < ssize(b); i++) in[i].imag(b[i]); + fft(in); + for (C& x : in) x *= x; + for (int i = 0; i < n; i++) + out[i] = in[-i & (n - 1)] - conj(in[i]); + fft(out); + for (int i = 0; i < ssize(res); i++) + res[i] = imag(out[i]) / (4 * n); + return res; +} +//! https://codeforces.com/blog/entry/104997 +//! https://codeforces.com/blog/entry/120446 +//! https://codeforces.com/blog/entry/142176 +//! https://youtu.be/wDwaMo5xa-k +//! @code +//! vector> adj(n); +//! edge_cd(adj, [&](const auto& adj, int cent, int m) { +//! // subtrees of [0, m) of adj[cent]: 1st edge-set +//! // subtrees of [m, sz(adj[cent])): 2nd edge-set +//! }); +//! @endcode +//! handle single-edge-paths separately +//! @time O(n logφ n) +//! @space O(n) +template struct edge_cd { + vector adj; + F f; + vector siz; + edge_cd(const vector& adj, F f): + adj(adj), f(f), siz(ssize(adj)) { + dfs(0, ssize(adj) - 1); + } + int find_cent(int v, int p, int m) { + siz[v] = 1; + for (int u : adj[v]) + if (u != p) { + int cent = find_cent(u, v, m); + if (cent != -1) return cent; + siz[v] += siz[u]; + } + return 2 * siz[v] > m + ? p >= 0 && (siz[p] = m + 1 - siz[v]), + v : -1; + } + void dfs(int v, int m) { + if (m < 2) return; + v = find_cent(v, -1, m); + int sum = 0; + auto it = + partition(begin(adj[v]), end(adj[v]), [&](int u) { + int64_t x = sum + siz[u]; + return x * x < m * (m - x) ? sum += siz[u], 1 : 0; + }); + f(adj, v, it - begin(adj[v])); + G oth(it, end(adj[v])); + adj[v].erase(it, end(adj[v])); + dfs(v, sum); + swap(adj[v], oth); + dfs(v, m - sum); + } +}; +//! @param adj unrooted, connected tree +//! @returns array `num_paths` where `num_paths[i]` = # of +//! paths in tree with `i` edges. `num_paths[1]` = # edges +//! @time O(n * logφ(n) * log2(n)) +//! @space this function allocates/returns various vectors +//! which are each O(n) +vector count_paths_per_length( + const vector>& adj) { + vector num_paths(ssize(adj)); + if (ssize(adj) >= 2) num_paths[1] = ssize(adj) - 1; + edge_cd(adj, + [&](const vector>& cd_adj, int cent, + int split) { + vector> cnt(2, vector(1)); + auto dfs = [&](auto&& self, int v, int p, int d, + int side) -> void { + if (ssize(cnt[side]) == d) + cnt[side].push_back(0.0); + cnt[side][d]++; + for (int u : cd_adj[v]) + if (u != p) self(self, u, v, 1 + d, side); + }; + for (int i = 0; i < ssize(cd_adj[cent]); i++) + dfs(dfs, cd_adj[cent][i], cent, 1, i < split); + vector prod = conv(cnt[0], cnt[1]); + for (int i = 0; i < ssize(prod); i++) + num_paths[i] += llround(prod[i]); + }); + return num_paths; +} diff --git a/trees/uncommon/count_paths_per_node.hpp b/trees/uncommon/count_paths_per_node.hpp new file mode 100644 index 00000000..ed741e40 --- /dev/null +++ b/trees/uncommon/count_paths_per_node.hpp @@ -0,0 +1,78 @@ +//! @code +//! vector> adj(n); +//! centroid(adj, [&](const auto& adj, +//! int cent, int par_cent) {}); +//! @endcode +//! @time O(n log n) +//! @space O(n) +template struct centroid { + G adj; + F f; + vector siz; + centroid(const G& adj, F f): + adj(adj), f(f), siz(ssize(adj), -1) { + dfs(0, -1); + } + void calc_sz(int v, int p) { + siz[v] = 1; + for (int u : adj[v]) + if (u != p) calc_sz(u, v), siz[v] += siz[u]; + } + void dfs(int v, int p) { + calc_sz(v, -1); + for (int w = -1, sz_root = siz[v];;) { + auto big_ch = ranges::find_if(adj[v], [&](int u) { + return u != w && 2 * siz[u] > sz_root; + }); + if (big_ch == end(adj[v])) break; + w = v, v = *big_ch; + } + f(adj, v, p); + for (int u : adj[v]) { + iter_swap(ranges::find(adj[u], v), rbegin(adj[u])); + adj[u].pop_back(); + dfs(u, v); + } + } +}; +//! @param adj unrooted, connected forest +//! @param k number of edges +//! @returns array `num_paths` where `num_paths[i]` = +//! number of paths with k edges where node `i` is on the +//! path. 0-based nodes. +//! @time O(n log n) +//! @space this function allocates/returns various vectors +//! which are all O(n) +vector count_paths_per_node( + const vector>& adj, int k) { + vector num_paths(ssize(adj)); + centroid(adj, + [&](const vector>& cd_adj, int cent, int) { + vector pre_d{1}, cur_d{0}; + auto dfs = [&](auto&& self, int v, int p, + int d) -> int64_t { + if (d > k) return 0LL; + if (ssize(cur_d) <= d) cur_d.push_back(0); + cur_d[d]++; + int64_t cnt = 0; + if (k - d < ssize(pre_d)) cnt += pre_d[k - d]; + for (int u : cd_adj[v]) + if (u != p) cnt += self(self, u, v, d + 1); + num_paths[v] += cnt; + return cnt; + }; + auto dfs_child = [&](int child) -> int64_t { + int64_t cnt = dfs(dfs, child, cent, 1); + pre_d.resize(ssize(cur_d)); + for (int i = 1; i < ssize(cur_d) && cur_d[i]; i++) + pre_d[i] += cur_d[i], cur_d[i] = 0; + return cnt; + }; + for (int child : cd_adj[cent]) + num_paths[cent] += dfs_child(child); + pre_d = cur_d = {0}; + for (int child : cd_adj[cent] | views::reverse) + dfs_child(child); + }); + return num_paths; +} diff --git a/trees/uncommon/ladder_decomposition.hpp b/trees/uncommon/ladder_decomposition.hpp new file mode 100644 index 00000000..d663ce49 --- /dev/null +++ b/trees/uncommon/ladder_decomposition.hpp @@ -0,0 +1,93 @@ +/** + * Author: Johan Sannemo + * Date: 2015-02-06 + * License: CC0 + * Source: Folklore + * Description: Calculate power of two jumps in a tree, + * to support fast upward jumps and LCAs. + * Assumes the root node points to itself. + * Time: construction $O(N \log N)$, queries $O(\log N)$ + * Status: Tested at Petrozavodsk, also stress-tested via + * LCA.cpp + */ +vector> treeJump(vector& P) { + int on = 1, d = 1; + while (on < ssize(P)) on *= 2, d++; + vector> jmp(d, P); + for (int i = 1; i < d; i++) + for (int j = 0; j < ssize(P); j++) + jmp[i][j] = jmp[i - 1][jmp[i - 1][j]]; + return jmp; +} +int jmp(vector>& tbl, int nod, int steps) { + for (int i = 0; i < ssize(tbl); i++) + if (steps & (1 << i)) nod = tbl[i][nod]; + return nod; +} +int lca(vector>& tbl, vector& depth, + int a, int b) { + if (depth[a] < depth[b]) swap(a, b); + a = jmp(tbl, a, depth[a] - depth[b]); + if (a == b) return a; + for (int i = ssize(tbl); i--;) { + int c = tbl[i][a], d = tbl[i][b]; + if (c != d) a = c, b = d; + } + return tbl[0][a]; +} +//! https://codeforces.com/blog/entry/71567#comment-559299 +//! https://youtu.be/0rCFkuQS968 +//! @code +//! ladder ld(adj); +//! // KACTL functions +//! int kth_par = jmp(ld.jmp, v, k); +//! int curr_lca = lca(ld.jmp, ld.d, u, v); +//! @endcode +struct ladder { + int n; + vector d, p, leaf, idx, lad; + vector> jmp; + //! @param adj forest (rooted or unrooted) + //! @time O(n log n) + //! @space O(n log n) for jmp. Everything else is O(n) + ladder(const auto& adj): + n(ssize(adj)), d(n), p(n), leaf(n), idx(n), + lad(2 * n) { + auto dfs = [&](auto&& self, int v) -> void { + leaf[v] = v; + for (int u : adj[v]) + if (u != p[v]) { + d[u] = d[p[u] = v] + 1; + self(self, u); + if (d[leaf[v]] < d[leaf[u]]) leaf[v] = leaf[u]; + } + }; + dfs(dfs, 0); + int pos = 0; + for (int i = 0; i < n; i++) + if (p[i] == i || leaf[p[i]] != leaf[i]) { + int l = leaf[i]; + int len = min((d[l] - d[i]) * 2, d[l] + 1); + idx[l] = pos; + for (; len--; l = p[l]) lad[pos++] = l; + } + jmp = treeJump(p); + } + //! @param v query node + //! @param k number of edges + //! @returns a node k edges up from v. With k=1, this + //! returns v's parent. + //! @time O(1) + //! @space O(1) + int kth_par(int v, int k) { + assert(0 <= k && k <= d[v]); + if (k == 0) return v; + int bit = __lg(k); + v = jmp[bit][v], k -= (1 << bit); + int l = idx[leaf[v]] + d[leaf[v]] - d[v]; + assert(lad[l] == v); + // subarray [l, l+k] of lad corresponds to the rest + // of the jump + return lad[l + k]; + } +}; diff --git a/library/trees/uncommon/subtree_isomorphism.hpp b/trees/uncommon/subtree_isomorphism.hpp similarity index 75% rename from library/trees/uncommon/subtree_isomorphism.hpp rename to trees/uncommon/subtree_isomorphism.hpp index 784421f3..b5c8be33 100644 --- a/library/trees/uncommon/subtree_isomorphism.hpp +++ b/trees/uncommon/subtree_isomorphism.hpp @@ -1,4 +1,3 @@ -#pragma once //! @code //! vector> adj(n); //! auto [num_distinct_subtrees, iso_id] = @@ -10,17 +9,17 @@ //! @time O(n log n) //! @space O(n) auto subtree_iso(const auto& adj) { - vi iso_id(sz(adj), -1); - map hashes; + vector iso_id(ssize(adj), -1); + map, int> hashes; auto dfs = [&](auto&& self, int v, int p) -> int { - vi ch_ids; + vector ch_ids; for (int u : adj[v]) if (u != p) ch_ids.push_back(self(self, u, v)); ranges::sort(ch_ids); return iso_id[v] = - hashes.try_emplace(ch_ids, sz(hashes)) + hashes.try_emplace(ch_ids, ssize(hashes)) .first->second; }; dfs(dfs, 0, 0); - return pair{sz(hashes), iso_id}; + return pair{ssize(hashes), iso_id}; } diff --git a/library/trees/uncommon/sum_adjacent.hpp b/trees/uncommon/sum_adjacent.hpp similarity index 77% rename from library/trees/uncommon/sum_adjacent.hpp rename to trees/uncommon/sum_adjacent.hpp index f54c3d00..c1d1f3ad 100644 --- a/library/trees/uncommon/sum_adjacent.hpp +++ b/trees/uncommon/sum_adjacent.hpp @@ -1,17 +1,17 @@ -#pragma once //! helper for edge CD: given tree, update node's number, //! find sum of neighbors' numbers struct sum_adj { int n; - vector sum, sum_ch; - vi p; + vector sum, sum_ch; + vector p; //! @param adj undirected, unrooted tree //! @param sum sum[v] = initial number for node v //! @time O(n) //! @space various O(n) vectors are allocated; recursion //! stack for dfs is O(n) - sum_adj(const vector& adj, const vector& sum): - n(sz(sum)), sum(sum), sum_ch(n), p(n, -1) { + sum_adj(const vector>& adj, + const vector& sum): + n(ssize(sum)), sum(sum), sum_ch(n), p(n, -1) { auto dfs = [&](auto&& self, int v) -> void { for (int u : adj[v]) if (u != p[v]) @@ -23,7 +23,7 @@ struct sum_adj { //! @param delta number to add //! @time O(1) //! @space O(1) - void update(int v, ll delta) { + void update(int v, int64_t delta) { sum[v] += delta; if (p[v] != -1) sum_ch[p[v]] += delta; } @@ -31,7 +31,7 @@ struct sum_adj { //! @returns sum of v's neighbors numbers //! @time O(1) //! @space O(1) - ll query(int v) { + int64_t query(int v) { return sum_ch[v] + (p[v] != -1 ? sum[p[v]] : 0); } };