結果
問題 | No.1951 消えたAGCT(2) |
ユーザー | suisen |
提出日時 | 2022-05-20 23:14:47 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 753 ms / 3,000 ms |
コード長 | 23,805 bytes |
コンパイル時間 | 2,722 ms |
コンパイル使用メモリ | 228,628 KB |
実行使用メモリ | 331,904 KB |
最終ジャッジ日時 | 2024-09-20 09:37:57 |
合計ジャッジ時間 | 14,894 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 225 ms
331,304 KB |
testcase_01 | AC | 229 ms
331,308 KB |
testcase_02 | AC | 231 ms
331,320 KB |
testcase_03 | AC | 231 ms
331,372 KB |
testcase_04 | AC | 228 ms
331,308 KB |
testcase_05 | AC | 226 ms
331,352 KB |
testcase_06 | AC | 229 ms
331,320 KB |
testcase_07 | AC | 230 ms
331,336 KB |
testcase_08 | AC | 242 ms
331,680 KB |
testcase_09 | AC | 246 ms
331,720 KB |
testcase_10 | AC | 241 ms
331,904 KB |
testcase_11 | AC | 243 ms
331,904 KB |
testcase_12 | AC | 239 ms
331,636 KB |
testcase_13 | AC | 241 ms
331,496 KB |
testcase_14 | AC | 707 ms
331,828 KB |
testcase_15 | AC | 614 ms
331,776 KB |
testcase_16 | AC | 656 ms
331,776 KB |
testcase_17 | AC | 753 ms
331,800 KB |
testcase_18 | AC | 736 ms
331,744 KB |
testcase_19 | AC | 733 ms
331,816 KB |
testcase_20 | AC | 736 ms
331,852 KB |
testcase_21 | AC | 238 ms
331,876 KB |
testcase_22 | AC | 238 ms
331,744 KB |
testcase_23 | AC | 242 ms
331,888 KB |
testcase_24 | AC | 242 ms
331,892 KB |
testcase_25 | AC | 242 ms
331,776 KB |
testcase_26 | AC | 747 ms
331,848 KB |
testcase_27 | AC | 742 ms
331,840 KB |
ソースコード
#include <bits/stdc++.h> #include <limits> #include <type_traits> namespace suisen { // ! utility template <typename ...Types> using constraints_t = std::enable_if_t<std::conjunction_v<Types...>, std::nullptr_t>; template <bool cond_v, typename Then, typename OrElse> constexpr decltype(auto) constexpr_if(Then&& then, OrElse&& or_else) { if constexpr (cond_v) { return std::forward<Then>(then); } else { return std::forward<OrElse>(or_else); } } // ! function template <typename ReturnType, typename Callable, typename ...Args> using is_same_as_invoke_result = std::is_same<std::invoke_result_t<Callable, Args...>, ReturnType>; template <typename F, typename T> using is_uni_op = is_same_as_invoke_result<T, F, T>; template <typename F, typename T> using is_bin_op = is_same_as_invoke_result<T, F, T, T>; template <typename Comparator, typename T> using is_comparator = std::is_same<std::invoke_result_t<Comparator, T, T>, bool>; // ! integral template <typename T, typename = constraints_t<std::is_integral<T>>> constexpr int bit_num = std::numeric_limits<std::make_unsigned_t<T>>::digits; template <typename T, unsigned int n> struct is_nbit { static constexpr bool value = bit_num<T> == n; }; template <typename T, unsigned int n> static constexpr bool is_nbit_v = is_nbit<T, n>::value; // ? template <typename T> struct safely_multipliable {}; template <> struct safely_multipliable<int> { using type = long long; }; template <> struct safely_multipliable<long long> { using type = __int128_t; }; template <> struct safely_multipliable<unsigned int> { using type = unsigned long long; }; template <> struct safely_multipliable<unsigned long int> { using type = __uint128_t; }; template <> struct safely_multipliable<unsigned long long> { using type = __uint128_t; }; template <> struct safely_multipliable<float> { using type = float; }; template <> struct safely_multipliable<double> { using type = double; }; template <> struct safely_multipliable<long double> { using type = long double; }; template <typename T> using safely_multipliable_t = typename safely_multipliable<T>::type; } // namespace suisen // ! type aliases using i128 = __int128_t; using u128 = __uint128_t; template <typename T> using pq_greater = std::priority_queue<T, std::vector<T>, std::greater<T>>; template <typename T, typename U> using umap = std::unordered_map<T, U>; // ! macros (capital: internal macro) #define OVERLOAD2(_1,_2,name,...) name #define OVERLOAD3(_1,_2,_3,name,...) name #define OVERLOAD4(_1,_2,_3,_4,name,...) name #define REP4(i,l,r,s) for(std::remove_reference_t<std::remove_const_t<decltype(r)>>i=(l);i<(r);i+=(s)) #define REP3(i,l,r) REP4(i,l,r,1) #define REP2(i,n) REP3(i,0,n) #define REPINF3(i,l,s) for(std::remove_reference_t<std::remove_const_t<decltype(l)>>i=(l);;i+=(s)) #define REPINF2(i,l) REPINF3(i,l,1) #define REPINF1(i) REPINF2(i,0) #define RREP4(i,l,r,s) for(std::remove_reference_t<std::remove_const_t<decltype(r)>>i=(l)+fld((r)-(l)-1,s)*(s);i>=(l);i-=(s)) #define RREP3(i,l,r) RREP4(i,l,r,1) #define RREP2(i,n) RREP3(i,0,n) #define rep(...) OVERLOAD4(__VA_ARGS__, REP4 , REP3 , REP2 )(__VA_ARGS__) #define rrep(...) OVERLOAD4(__VA_ARGS__, RREP4 , RREP3 , RREP2 )(__VA_ARGS__) #define repinf(...) OVERLOAD3(__VA_ARGS__, REPINF3, REPINF2, REPINF1)(__VA_ARGS__) #define CAT_I(a, b) a##b #define CAT(a, b) CAT_I(a, b) #define UNIQVAR(tag) CAT(tag, __LINE__) #define loop(n) for (std::remove_reference_t<std::remove_const_t<decltype(n)>> UNIQVAR(loop_variable) = n; UNIQVAR(loop_variable) --> 0;) #define all(iterable) std::begin(iterable), std::end(iterable) #define input(type, ...) type __VA_ARGS__; read(__VA_ARGS__) #ifdef LOCAL # define debug(...) debug_internal(#__VA_ARGS__, __VA_ARGS__) template <class T, class... Args> void debug_internal(const char* s, T&& first, Args&&... args) { constexpr const char* prefix = "[\033[32mDEBUG\033[m] "; constexpr const char* open_brakets = sizeof...(args) == 0 ? "" : "("; constexpr const char* close_brakets = sizeof...(args) == 0 ? "" : ")"; std::cerr << prefix << open_brakets << s << close_brakets << ": " << open_brakets << std::forward<T>(first); ((std::cerr << ", " << std::forward<Args>(args)), ...); std::cerr << close_brakets << "\n"; } #else # define debug(...) void(0) #endif // ! I/O utilities // pair template <typename T, typename U> std::ostream& operator<<(std::ostream& out, const std::pair<T, U> &a) { return out << a.first << ' ' << a.second; } // tuple template <unsigned int N = 0, typename ...Args> std::ostream& operator<<(std::ostream& out, const std::tuple<Args...> &a) { if constexpr (N >= std::tuple_size_v<std::tuple<Args...>>) { return out; } else { out << std::get<N>(a); if constexpr (N + 1 < std::tuple_size_v<std::tuple<Args...>>) { out << ' '; } return operator<<<N + 1>(out, a); } } // vector template <typename T> std::ostream& operator<<(std::ostream& out, const std::vector<T> &a) { for (auto it = a.begin(); it != a.end();) { out << *it; if (++it != a.end()) out << ' '; } return out; } // array template <typename T, size_t N> std::ostream& operator<<(std::ostream& out, const std::array<T, N> &a) { for (auto it = a.begin(); it != a.end();) { out << *it; if (++it != a.end()) out << ' '; } return out; } inline void print() { std::cout << '\n'; } template <typename Head, typename... Tail> inline void print(const Head &head, const Tail &...tails) { std::cout << head; if (sizeof...(tails)) std::cout << ' '; print(tails...); } template <typename Iterable> auto print_all(const Iterable& v, std::string sep = " ", std::string end = "\n") -> decltype(std::cout << *v.begin(), void()) { for (auto it = v.begin(); it != v.end();) { std::cout << *it; if (++it != v.end()) std::cout << sep; } std::cout << end; } // pair template <typename T, typename U> std::istream& operator>>(std::istream& in, std::pair<T, U> &a) { return in >> a.first >> a.second; } // tuple template <unsigned int N = 0, typename ...Args> std::istream& operator>>(std::istream& in, std::tuple<Args...> &a) { if constexpr (N >= std::tuple_size_v<std::tuple<Args...>>) { return in; } else { return operator>><N + 1>(in >> std::get<N>(a), a); } } // vector template <typename T> std::istream& operator>>(std::istream& in, std::vector<T> &a) { for (auto it = a.begin(); it != a.end(); ++it) in >> *it; return in; } // array template <typename T, size_t N> std::istream& operator>>(std::istream& in, std::array<T, N> &a) { for (auto it = a.begin(); it != a.end(); ++it) in >> *it; return in; } template <typename ...Args> void read(Args &...args) { ( std::cin >> ... >> args ); } // ! integral utilities // Returns pow(-1, n) template <typename T> constexpr inline int pow_m1(T n) { return -(n & 1) | 1; } // Returns pow(-1, n) template <> constexpr inline int pow_m1<bool>(bool n) { return -int(n) | 1; } // Returns floor(x / y) template <typename T> constexpr inline T fld(const T x, const T y) { return (x ^ y) >= 0 ? x / y : (x - (y + pow_m1(y >= 0))) / y; } template <typename T> constexpr inline T cld(const T x, const T y) { return (x ^ y) <= 0 ? x / y : (x + (y + pow_m1(y >= 0))) / y; } template <typename T, suisen::constraints_t<suisen::is_nbit<T, 16>> = nullptr> constexpr inline int popcount(const T x) { return __builtin_popcount(x); } template <typename T, suisen::constraints_t<suisen::is_nbit<T, 32>> = nullptr> constexpr inline int popcount(const T x) { return __builtin_popcount(x); } template <typename T, suisen::constraints_t<suisen::is_nbit<T, 64>> = nullptr> constexpr inline int popcount(const T x) { return __builtin_popcountll(x); } template <typename T, suisen::constraints_t<suisen::is_nbit<T, 16>> = nullptr> constexpr inline int count_lz(const T x) { return x ? __builtin_clz(x) : suisen::bit_num<T>; } template <typename T, suisen::constraints_t<suisen::is_nbit<T, 32>> = nullptr> constexpr inline int count_lz(const T x) { return x ? __builtin_clz(x) : suisen::bit_num<T>; } template <typename T, suisen::constraints_t<suisen::is_nbit<T, 64>> = nullptr> constexpr inline int count_lz(const T x) { return x ? __builtin_clzll(x) : suisen::bit_num<T>; } template <typename T, suisen::constraints_t<suisen::is_nbit<T, 16>> = nullptr> constexpr inline int count_tz(const T x) { return x ? __builtin_ctz(x) : suisen::bit_num<T>; } template <typename T, suisen::constraints_t<suisen::is_nbit<T, 32>> = nullptr> constexpr inline int count_tz(const T x) { return x ? __builtin_ctz(x) : suisen::bit_num<T>; } template <typename T, suisen::constraints_t<suisen::is_nbit<T, 64>> = nullptr> constexpr inline int count_tz(const T x) { return x ? __builtin_ctzll(x) : suisen::bit_num<T>; } template <typename T> constexpr inline int floor_log2(const T x) { return suisen::bit_num<T> - 1 - count_lz(x); } template <typename T> constexpr inline int ceil_log2(const T x) { return floor_log2(x) + ((x & -x) != x); } template <typename T> constexpr inline int kth_bit(const T x, const unsigned int k) { return (x >> k) & 1; } template <typename T> constexpr inline int parity(const T x) { return popcount(x) & 1; } struct all_subset { struct all_subset_iter { const int s; int t; constexpr all_subset_iter(int s) : s(s), t(s + 1) {} constexpr auto operator*() const { return t; } constexpr auto operator++() {} constexpr auto operator!=(std::nullptr_t) { return t ? (--t &= s, true) : false; } }; int s; constexpr all_subset(int s) : s(s) {} constexpr auto begin() { return all_subset_iter(s); } constexpr auto end() { return nullptr; } }; // ! container template <typename T, typename Comparator, suisen::constraints_t<suisen::is_comparator<Comparator, T>> = nullptr> auto priqueue_comp(const Comparator comparator) { return std::priority_queue<T, std::vector<T>, Comparator>(comparator); } template <typename Iterable> auto isize(const Iterable &iterable) -> decltype(int(iterable.size())) { return iterable.size(); } template <typename T, typename Gen, suisen::constraints_t<suisen::is_same_as_invoke_result<T, Gen, int>> = nullptr> auto generate_vector(int n, Gen generator) { std::vector<T> v(n); for (int i = 0; i < n; ++i) v[i] = generator(i); return v; } template <typename T> auto generate_range_vector(T l, T r) { return generate_vector(r - l, [l](int i) { return l + i; }); } template <typename T> auto generate_range_vector(T n) { return generate_range_vector(0, n); } template <typename T> void sort_unique_erase(std::vector<T> &a) { std::sort(a.begin(), a.end()); a.erase(std::unique(a.begin(), a.end()), a.end()); } template <typename InputIterator, typename BiConsumer> auto foreach_adjacent_values(InputIterator first, InputIterator last, BiConsumer f) -> decltype(f(*first++, *last), void()) { if (first != last) for (auto itr = first, itl = itr++; itr != last; itl = itr++) f(*itl, *itr); } template <typename Container, typename BiConsumer> auto foreach_adjacent_values(Container c, BiConsumer f) -> decltype(c.begin(), c.end(), void()){ foreach_adjacent_values(c.begin(), c.end(), f); } // ! other utilities // x <- min(x, y). returns true iff `x` has chenged. template <typename T> inline bool chmin(T &x, const T &y) { if (y >= x) return false; x = y; return true; } // x <- max(x, y). returns true iff `x` has chenged. template <typename T> inline bool chmax(T &x, const T &y) { if (y <= x) return false; x = y; return true; } namespace suisen {} using namespace suisen; using namespace std; struct io_setup { io_setup(int precision = 20) { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cout << std::fixed << std::setprecision(precision); } } io_setup_ {}; // ! code from here #include <cassert> #include <sstream> #include <string> #include <tuple> #include <deque> #include <vector> namespace suisen { template <typename T, bool auto_extend = false> struct ObjectPool { using value_type = T; using value_pointer_type = T*; template <typename U> using container_type = std::conditional_t<auto_extend, std::deque<U>, std::vector<U>>; container_type<value_type> pool; container_type<value_pointer_type> stock; decltype(stock.begin()) it; ObjectPool() : ObjectPool(0) {} ObjectPool(int siz) : pool(siz), stock(siz) { clear(); } int capacity() const { return pool.size(); } int size() const { return it - stock.begin(); } value_pointer_type alloc() { if constexpr (auto_extend) ensure(); return *it++; } void free(value_pointer_type t) { *--it = t; } void clear() { int siz = pool.size(); it = stock.begin(); for (int i = 0; i < siz; i++) stock[i] = &pool[i]; } void ensure() { if (it != stock.end()) return; int siz = stock.size(); for (int i = siz; i <= siz * 2; ++i) { stock.push_back(&pool.emplace_back()); } it = stock.begin() + siz; } }; } // namespace suisen namespace suisen::bbst::internal { template <typename T, typename Derived> struct RedBlackTreeNodeBase { enum RedBlackTreeNodeColor { RED, BLACK }; using base_type = void; using size_type = int; using value_type = T; using node_type = Derived; using tree_type = node_type*; using color_type = RedBlackTreeNodeColor; RedBlackTreeNodeBase() = default; static inline ObjectPool<node_type> pool{}; static void init_pool(int siz) { pool = ObjectPool<node_type>(siz); } static int node_num() { return pool.size(); } static tree_type empty_tree() { return nullptr; } static size_type size(tree_type node) { return node ? node->_siz : 0; } static bool empty(tree_type node) { return not node; } template <bool force_black_root = true> static tree_type merge(tree_type l, tree_type r) { if (not l) return r; if (not r) return l; tree_type res = nullptr; if (size_type hl = height(l), hr = height(r); hl > hr) { l = node_type::push(l); tree_type c = l->_ch[1] = merge<false>(l->_ch[1], r); if (l->_col == BLACK and c->_col == RED and color(c->_ch[1]) == RED) { std::swap(l->_col, c->_col); if (std::exchange(l->_ch[0]->_col, BLACK) == BLACK) return rotate(l, 1); } res = node_type::update(l); } else if (hr > hl) { r = node_type::push(r); tree_type c = r->_ch[0] = merge<false>(l, r->_ch[0]); if (r->_col == BLACK and c->_col == RED and color(c->_ch[0]) == RED) { std::swap(r->_col, c->_col); if (std::exchange(r->_ch[1]->_col, BLACK) == BLACK) return rotate(r, 0); } res = node_type::update(r); } else { res = create_branch(l, r); } if constexpr (force_black_root) res->_col = BLACK; return res; } static std::pair<tree_type, tree_type> split(tree_type node, size_type k) { if (not node) return { nullptr, nullptr }; node = node_type::push(node); if (k == 0) return { nullptr, node }; if (k == size(node)) return { node, nullptr }; tree_type l = std::exchange(node->_ch[0], nullptr); tree_type r = std::exchange(node->_ch[1], nullptr); free_node(node); if (color(l) == RED) l->_col = BLACK; if (color(r) == RED) r->_col = BLACK; size_type szl = size(l); tree_type m; if (k < szl) { std::tie(l, m) = split(l, k); return { l, merge(m, r) }; } if (k > szl) { std::tie(m, r) = split(r, k - szl); return { merge(l, m), r }; } return { l, r }; } static std::tuple<tree_type, tree_type, tree_type> split_range(tree_type node, size_type l, size_type r) { auto [tlm, tr] = split(node, r); auto [tl, tm] = split(tlm, l); return { tl, tm, tr }; } static tree_type insert(tree_type node, size_type k, const value_type& val) { auto [tl, tr] = split(node, k); return merge(merge(tl, create_leaf(val)), tr); } static tree_type push_front(tree_type node, const value_type &val) { return insert(node, 0, val); } static tree_type push_back(tree_type node, const value_type &val) { return insert(node, size(node), val); } static std::pair<tree_type, value_type> erase(tree_type node, size_type k) { auto [tl, tm, tr] = split_range(node, k, k + 1); value_type erased_value = tm->_val; free_node(tm); return { merge(tl, tr) , erased_value }; } static std::pair<tree_type, value_type> pop_front(tree_type node) { return erase(node, 0); } static std::pair<tree_type, value_type> pop_back(tree_type node) { return erase(node, size(node) - 1); } template <typename U> static tree_type build(const std::vector<U>& a, int l, int r) { if (r - l == 1) return create_leaf(a[l]); int m = (l + r) >> 1; return merge(build(a, l, m), build(a, m, r)); } template <typename U> static tree_type build(const std::vector<U>& a) { return a.empty() ? empty_tree() : build(a, 0, a.size()); } template <typename OutputIterator> static void dump(tree_type node, OutputIterator it) { if (empty(node)) return; auto dfs = [&](auto dfs, tree_type cur) -> void { if (cur->is_leaf()) { *it++ = cur->_val; return; } dfs(dfs, cur->_ch[0]); dfs(dfs, cur->_ch[1]); }; dfs(dfs, node); } // Don't use on persistent tree. static void free(tree_type node) { auto dfs = [&](auto dfs, tree_type cur) -> void { if (not cur) return; dfs(dfs, cur->_ch[0]); dfs(dfs, cur->_ch[1]); free_node(cur); }; dfs(dfs, node); } template <typename ToStr> static std::string to_string(tree_type node, ToStr f) { std::vector<value_type> dat; node_type::dump(node, std::back_inserter(dat)); std::ostringstream res; int siz = dat.size(); res << '['; for (int i = 0; i < siz; ++i) { res << f(dat[i]); if (i != siz - 1) res << ", "; } res << ']'; return res.str(); } static std::string to_string(tree_type node) { return to_string(node, [](const auto &e) { return e; }); } static void check_rbtree_properties(tree_type node) { assert(color(node) == BLACK); auto dfs = [&](auto dfs, tree_type cur) -> int { if (not cur) return 0; if (cur->_col == RED) { assert(color(cur->_ch[0]) == BLACK); assert(color(cur->_ch[1]) == BLACK); } int bl = dfs(dfs, cur->_ch[0]); int br = dfs(dfs, cur->_ch[1]); assert(bl == br); return bl + (cur->_col == BLACK); }; dfs(dfs, node); } protected: color_type _col; tree_type _ch[2]{ nullptr, nullptr }; value_type _val; size_type _siz, _lev; RedBlackTreeNodeBase(const value_type& val) : _col(BLACK), _val(val), _siz(1), _lev(0) {} RedBlackTreeNodeBase(tree_type l, tree_type r) : _col(RED), _ch{ l, r }, _siz(l->_siz + r->_siz), _lev(l->_lev + (l->_col == BLACK)) {} static void clear_pool() { pool.clear(); } static int pool_capacity() { return pool.capacity(); } static color_type color(tree_type node) { return node ? node->_col : BLACK; } static size_type height(tree_type node) { return node ? node->_lev : 0; } bool is_leaf() const { return not (_ch[0] or _ch[1]); } static tree_type clone(tree_type node) { return node; } static tree_type update(tree_type node) { node->_siz = node->is_leaf() ? 1 : size(node->_ch[0]) + size(node->_ch[1]); node->_lev = node->_ch[0] ? height(node->_ch[0]) + (node->_ch[0]->_col == BLACK) : 0; return node; } static tree_type push(tree_type node) { return node; } static tree_type rotate(tree_type node, int index) { node = node_type::push(node); tree_type ch_node = node_type::push(node->_ch[index]); node->_ch[index] = std::exchange(ch_node->_ch[index ^ 1], node); return node_type::update(node), node_type::update(ch_node); } static tree_type create_leaf(const value_type& val = value_type{}) { return &(*pool.alloc() = node_type(val)); } static tree_type create_branch(tree_type l, tree_type r) { return node_type::update(&(*pool.alloc() = node_type(l, r))); } static void free_node(tree_type node) { if (node) pool.free(node); } }; } // namespace suisen namespace suisen::bbst { template <typename T, template <typename, typename> typename BaseNode = internal::RedBlackTreeNodeBase> struct RedBlackTreeNode : public BaseNode<T, RedBlackTreeNode<T, BaseNode>> { using base_type = BaseNode<T, RedBlackTreeNode<T, BaseNode>>; using node_type = typename base_type::node_type; using tree_type = typename base_type::tree_type; using size_type = typename base_type::size_type; using value_type = typename base_type::value_type; friend base_type; friend typename base_type::base_type; RedBlackTreeNode() = default; private: RedBlackTreeNode(const value_type& val) : base_type(val) {} RedBlackTreeNode(tree_type l, tree_type r) : base_type(l, r) {} }; } using Node = bbst::RedBlackTreeNode<char>; using Tree = Node::tree_type; constexpr int A = 'A' - 'A'; constexpr int G = 'G' - 'A'; constexpr int C = 'C' - 'A'; constexpr int T = 'T' - 'A'; int main() { Node::init_pool(7000000); input(int, n); vector<char> s(n); read(s); auto seq = Node::build(s); array<int, 26> cnt{}; for (char c : s) { ++cnt[c - 'A']; } int offset = 0; auto get_index = [&](int ch) { int x = (ch - offset) % 26; if (x < 0) x += 26; return x; }; int ans = 0; for (;; ++ans) { int num = cnt[get_index(A)] + cnt[get_index(G)] + cnt[get_index(C)] + cnt[get_index(T)]; if (num == 0) break; char c; tie(seq, c) = Node::erase(seq, num - 1); int ch = (offset + (c - 'A')) % 26; int c2 = --cnt[get_index(ch)]; offset += c2; offset %= 26; } print(ans); return 0; }