結果
問題 | No.945 YKC饅頭 |
ユーザー | btk |
提出日時 | 2019-12-08 00:35:18 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 419 ms / 2,000 ms |
コード長 | 15,892 bytes |
コンパイル時間 | 2,636 ms |
コンパイル使用メモリ | 222,212 KB |
実行使用メモリ | 9,392 KB |
最終ジャッジ日時 | 2024-06-08 03:24:40 |
合計ジャッジ時間 | 12,501 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
6,816 KB |
testcase_01 | AC | 2 ms
6,940 KB |
testcase_02 | AC | 2 ms
6,944 KB |
testcase_03 | AC | 3 ms
6,940 KB |
testcase_04 | AC | 2 ms
6,940 KB |
testcase_05 | AC | 2 ms
6,940 KB |
testcase_06 | AC | 2 ms
6,944 KB |
testcase_07 | AC | 2 ms
6,940 KB |
testcase_08 | AC | 2 ms
6,940 KB |
testcase_09 | AC | 3 ms
6,944 KB |
testcase_10 | AC | 3 ms
6,940 KB |
testcase_11 | AC | 3 ms
6,944 KB |
testcase_12 | AC | 3 ms
6,940 KB |
testcase_13 | AC | 3 ms
6,940 KB |
testcase_14 | AC | 3 ms
6,940 KB |
testcase_15 | AC | 2 ms
6,940 KB |
testcase_16 | AC | 2 ms
6,944 KB |
testcase_17 | AC | 3 ms
6,940 KB |
testcase_18 | AC | 3 ms
6,940 KB |
testcase_19 | AC | 2 ms
6,944 KB |
testcase_20 | AC | 2 ms
6,940 KB |
testcase_21 | AC | 2 ms
6,940 KB |
testcase_22 | AC | 3 ms
6,940 KB |
testcase_23 | AC | 3 ms
6,940 KB |
testcase_24 | AC | 3 ms
6,940 KB |
testcase_25 | AC | 3 ms
6,944 KB |
testcase_26 | AC | 3 ms
6,940 KB |
testcase_27 | AC | 2 ms
6,944 KB |
testcase_28 | AC | 2 ms
6,940 KB |
testcase_29 | AC | 2 ms
6,940 KB |
testcase_30 | AC | 2 ms
6,940 KB |
testcase_31 | AC | 18 ms
6,940 KB |
testcase_32 | AC | 7 ms
6,944 KB |
testcase_33 | AC | 82 ms
8,324 KB |
testcase_34 | AC | 206 ms
6,944 KB |
testcase_35 | AC | 343 ms
8,128 KB |
testcase_36 | AC | 238 ms
6,944 KB |
testcase_37 | AC | 223 ms
6,940 KB |
testcase_38 | AC | 210 ms
6,944 KB |
testcase_39 | AC | 46 ms
6,940 KB |
testcase_40 | AC | 42 ms
8,020 KB |
testcase_41 | AC | 16 ms
6,948 KB |
testcase_42 | AC | 308 ms
6,944 KB |
testcase_43 | AC | 199 ms
6,944 KB |
testcase_44 | AC | 259 ms
7,672 KB |
testcase_45 | AC | 340 ms
6,944 KB |
testcase_46 | AC | 7 ms
6,944 KB |
testcase_47 | AC | 201 ms
6,944 KB |
testcase_48 | AC | 42 ms
6,940 KB |
testcase_49 | AC | 82 ms
6,944 KB |
testcase_50 | AC | 362 ms
6,940 KB |
testcase_51 | AC | 412 ms
7,896 KB |
testcase_52 | AC | 419 ms
7,660 KB |
testcase_53 | AC | 413 ms
9,368 KB |
testcase_54 | AC | 413 ms
8,012 KB |
testcase_55 | AC | 413 ms
7,880 KB |
testcase_56 | AC | 9 ms
8,020 KB |
testcase_57 | AC | 9 ms
8,516 KB |
testcase_58 | AC | 193 ms
8,428 KB |
testcase_59 | AC | 228 ms
8,480 KB |
testcase_60 | AC | 84 ms
9,024 KB |
testcase_61 | AC | 201 ms
9,392 KB |
testcase_62 | AC | 191 ms
8,300 KB |
testcase_63 | AC | 10 ms
8,164 KB |
testcase_64 | AC | 93 ms
8,036 KB |
testcase_65 | AC | 73 ms
7,928 KB |
testcase_66 | AC | 68 ms
7,560 KB |
testcase_67 | AC | 140 ms
7,804 KB |
testcase_68 | AC | 85 ms
8,112 KB |
testcase_69 | AC | 32 ms
8,380 KB |
testcase_70 | AC | 38 ms
8,104 KB |
testcase_71 | AC | 40 ms
8,972 KB |
testcase_72 | AC | 113 ms
8,044 KB |
testcase_73 | AC | 215 ms
8,636 KB |
ソースコード
// https://yukicoder.me/problems/no/945 #define CIN_ONLY #define DECIMAL_DIGITS 10 #define STATIC_MOD 1e9 + 7 #ifdef BTK /*<head>*/ # include "Template.hpp" /*</head>*/ #else /*<body>*/ /* #region auto includes */ /* #region stl */ /*<stl>*/ # include <bits/stdc++.h> # include <sys/types.h> # include <unistd.h> using namespace std; /*</stl>*/ /* #endregion */ /* #region template/IncludeSTL.hpp*/ /** * @file IncludeSTL.hpp * @author btk * @brief 標準ライブラリをincludeするだけ * @version 0.1 * @date 2019-07-21 * @todo 何故か2回includeされる(展開scriptに * @copyright Copyright (c) 2019 * */ /* #endregion */ /* #region template/Macro.hpp*/ /** * @file Macro.hpp * @author btk * @brief マクロとか,LLとか * @version 0.1 * @date 2019-07-13 * * @copyright Copyright (c) 2019 * */ //! LL using LL = long long; /** * @def DEBUG * @brief デバッグ用のif文 提出時はif(0)で実行されない */ /*</head>*/ # ifdef BTK # define DEBUG if (1) # else # ifdef CIN_ONLY # define FAST_IO # endif # define DEBUG if (0) # endif /** * @def ALL(v) * @brief * ALLマクロ */ # define ALL(v) (v).begin(), (v).end() /** * @def REC(ret, ...) * @brief * 再帰ラムダをするためのマクロ */ # define REC(ret, ...) std::function<ret(__VA_ARGS__)> /** * @def VAR_NAME(var) * @brief 変数名を取得する */ # define VAR_NAME(var) # var /** * @brief * rangeで生まれる使わない変数を消す用(警告消し) */ template <typename T> inline T &unused_var(T &v) { return v; } /* #endregion */ /* #region template/IO.hpp*/ /** * @file IO.hpp * @author btk * @brief cin高速化とか,出力の小数桁固定とか * @version 0.1 * @date 2019-07-13 * * @copyright Copyright (c) 2019 */ /** * @brief 入出力の設定を行うための構造体 */ struct cww { /** * @brief Construct a new cww::cww object * @details * CIN_ONLYを定義すると,submit時にcinとscanfの同期を切る設定が走る * DECIMAL_DIGITSを定義すると,doubleの出力時指定した桁数分小数部を吐くようになる */ cww() { # ifdef FAST_IO ios::sync_with_stdio(false); cin.tie(0); # endif # ifdef DECIMAL_DIGITS cout << fixed; cout << setprecision(DECIMAL_DIGITS); # endif } }; //! 入出力設定構造体を実体化 cww star; /** * @brief * vectorに直接cin流すためのやつ * @tparam T * @param is * @param v * @return istream& */ template <typename T> std::istream &operator>>(std::istream &is, std::vector<T> &v) { for (auto &it : v) is >> it; return is; } /* #endregion */ /* #region template/Loop.hpp*/ /** * @file Loop.hpp * @author btk * @brief rangeとかループ系のクラス * @version 0.1 * @date 2019-07-13 * * @copyright Copyright (c) 2019 * */ /** * @brief * rangeを逆向きに操作したいとき用 * @details * ループの範囲は[bg,ed)なので注意 * @see range */ class reverse_range { private: struct I { int x; int operator*() { return x - 1; } bool operator!=(I &lhs) { return x > lhs.x; } void operator++() { --x; } }; I i, n; public: /** * @brief Construct a new reverse range object * * @param n */ reverse_range(int n) : i({0}), n({n}) {} /** * @brief Construct a new reverse range object * * @param i * @param n */ reverse_range(int i, int n) : i({i}), n({n}) {} /** * @brief * begin iterator * @return I& */ I &begin() { return n; } /** * @brief * end iterator * @return I& */ I &end() { return i; } }; /** * @brief * python みたいな range-based for を実現 * @details * ループの範囲は[bg,ed)なので注意 * !つけると逆向きにループが回る (reverse_range) * 空間計算量はO(1) * 使わない変数ができて警告が出がちなので,unused_varとかを使って警告消しするとよい */ class range { private: struct I { int x; int operator*() { return x; } bool operator!=(I &lhs) { return x < lhs.x; } void operator++() { ++x; } }; I i, n; public: /** * @brief Construct a new range object * * @param n */ range(int n) : i({0}), n({n}) {} /** * @brief Construct a new range object * * @param i * @param n */ range(int i, int n) : i({i}), n({n}) {} /** * @brief * begin iterator * @return I& */ I &begin() { return i; } /** * @brief * end iterator * @return I& */ I &end() { return n; } /** * @brief * 逆向きに参照するrange(reverse_rangeを取得できるs) * @return reverse_range */ reverse_range operator!() { return reverse_range(*i, *n); } }; /* #endregion */ /* #region template/MinMaxOperation.hpp*/ /** * @file MinMaxOperation.hpp * @author btk * @brief 最大値とか最小値を求める * @version 0.1 * @date 2019-07-04 * * @copyright Copyright (c) 2019 * */ /** * @brief 2項の最小値求める * * @tparam T */ template <typename T> struct min_op { /** * @brief 本体 * * @param l * @param r * @return T */ static T exec(const T l, const T r) { return l < r ? l : r; } }; /** * @brief 2項の最大値求める * * @tparam T */ template <typename T> struct max_op { /** * @brief 本体 * * @param l * @param r * @return T */ static T exec(const T l, const T r) { return l > r ? l : r; } }; /** * @brief テンプレート再帰の末尾 * * @tparam F 二項演算 * @tparam T * @param v * @return T */ template <typename F, typename T> inline T multi_op(T &&v) { return v; } /** * @brief 複数項における演算の結果を返す * * @tparam F * @tparam T * @tparam Ts * @param head * @param tail * @return T */ template <typename F, typename T, typename... Ts> inline T multi_op(const T head, Ts &&... tail) { return F::exec(head, multi_op<F>(tail...)); } /** * @brief 複数項の最小値 * @see multi_op * @tparam T * @tparam Ts * @param head * @param tail * @return T */ template <typename T, typename... Ts> inline T multi_min(T &&head, Ts &&... tail) { return multi_op<min_op<T>>(head, tail...); } /** * @brief 複数項の最大値 * @see multi_op * @tparam T * @tparam Ts * @param head * @param tail * @return T */ template <typename T, typename... Ts> inline T multi_max(T &&head, Ts &&... tail) { return multi_op<max_op<T>>(head, tail...); } /** * @brief * 先頭の値をFで参照する関数に基づいて変更できたらする * @tparam F * @tparam T * @tparam Ts * @param target * @param candidates * @return true * @return false */ template <typename F, typename T, typename... Ts> inline bool ch_op(T &target, Ts &&... candidates) { const T old = target; target = multi_op<F>(target, candidates...); return old != target; } /** * @brief change min * @tparam T 型 * @param target 変更する値 * @param candidates * @return 更新があればtrue */ template <typename T, typename... Ts> inline bool chmin(T &target, Ts &&... candidates) { return ch_op<min_op<T>>(target, candidates...); } /** * @brief chminのmax版 * @see chmin * @tparam T 型 * @param target 変更する値 * @param candidates * @return 更新があればtrue */ template <typename T, typename... Ts> inline bool chmax(T &target, Ts &&... candidates) { return ch_op<max_op<T>>(target, candidates...); } /* #endregion */ /* #region template/Random.hpp*/ /** * @file Random.hpp * @author btk * @brief 乱数生成系 * @version 0.1 * @date 2019-07-13 * @copyright Copyright (c) 2019 */ //! 乱数のシード値をプロセスIDとして取得 const pid_t pid = getpid(); /** * @brief XorShift32の実装 */ class XorShift32 { private: //! XorShiftの現在の値 unsigned value; /** * @brief XorShift32のアルゴリズムに基づいて value を更新 */ inline void update() { value = value ^ (value << 13); value = value ^ (value >> 17); value = value ^ (value << 5); } /** * @brief 値を更新し,更新前の値を返却 * @return unsigned 呼び出し時の value を用いる */ inline unsigned get() { unsigned v = value; update(); return v; } public: /** * @brief [0, 2^bit) の範囲の乱数値を取り出す * @tparam デフォルトは31 * @return int */ template <int bit = 31> inline int next_int() { return (int)(get() >> (32 - bit)); } /** * @brief [-2^bit,2^bit)の範囲の乱数値を取り出す * @tparam デフォルトは31 * @return int */ template <int bit = 31> inline int next_signed() { unsigned v = get(); return (int)((v >> (31 - bit)) - (1 << (bit))); } /** * @brief next_int呼び出し時の最大値を取得 * @tparam 31 * @return int */ template <int bit = 31> inline int range_max() { return (int)((1u << bit) - 1); }; /** * @brief Construct a new XorShift32 object * @param seed * @details 初期シードをvalueとするXorShift32のインスタンスを生成 */ XorShift32(const unsigned seed) { value = seed; update(); } /** * @brief Construct a new XorShift 32 object * @details 初期シードをプロセスIDとするXorShift32のインスタンスを生成 */ XorShift32() : XorShift32(pid) {} }; /* #endregion */ /* #region Template.hpp*/ /** * @file Template.hpp * @brief 競技プログラミング用テンプレート * @author btk15049 * @date 2019/05/02 */ /* #endregion */ /* #endregion */ /*</body>*/ #endif /* default:: range minimum query - update(element) : chmin (weak update), set (force update) - get (segment) : min(l,r) */ constexpr int INF = 1e7; template <typename SEG> using SetInitialLeaf = function<void(SEG &, int)>; template <typename SEG> using SetInitialSegment = function<void(SEG &, const int, const int)>; template <typename RET, typename SEG> using GetSingleSegment = function<RET(SEG &, const int, const int)>; template <typename RET> using GetMergedSegment = function<RET(RET, RET)>; template <typename SEG, typename Q> using UpdateSingleSegment = function<void(SEG &, Q)>; template <typename SEG> using LazyUpdate = function<void(SEG &, SEG &, SEG &)>; struct node { int ret; bool all; }; SetInitialLeaf<node> set_leaf = [](node &v, const int id) { v.ret = 0; v.all = false; }; SetInitialSegment<node> set_segment = [](node &v, const int l, const int r) { v.all = false; }; GetSingleSegment<int, node> segment_sum = [](node &v, const int l, const int r) { if (v.all) { return r - l; } else { return v.ret; } }; GetMergedSegment<int> merge_segment = [](int l, int r) { return l + r; }; UpdateSingleSegment<node, int> update = [](node &v, int l) { v.all = true; }; LazyUpdate<node> lazy = [](node &v, node &l, node &r) { l.all |= v.all; r.all |= v.all; }; #ifndef NDBUF # define NDBUF template <typename T> struct BufferManager { T *mem; int ptr; BufferManager(T *mem) { ptr = 0; this->mem = mem; } T *get(int m) { ptr += m; return mem + ptr - m; } void reset() { ptr = 0; } }; namespace NodeBuffer { constexpr int BufferSize = 812345; using NodeType = node; NodeType mem[BufferSize]; BufferManager<NodeType> buffer(mem); } // namespace NodeBuffer #endif template <typename Node, typename RET> struct SegmentTree { int size; Node *seg; GetSingleSegment<RET, Node> get_single_segment; GetMergedSegment<RET> get_merged_segment; LazyUpdate<Node> lazy_update; void init(int l, int r, SetInitialSegment<Node> &init_segment, SetInitialLeaf<Node> &init_leaf, int k = 0) { auto &v = seg[k]; init_segment(v, l, r); if (r - l == 1) { //葉の時の処理 init_leaf(v, l); } else if (r - l > 1) { int m = (l + r) / 2; init(l, m, init_segment, init_leaf, k * 2 + 1); init(m, r, init_segment, init_leaf, k * 2 + 2); v.ret = get_merged_segment(get_single_segment(seg[k * 2 + 1], l, m), get_single_segment(seg[k * 2 + 2], m, r)); } } SegmentTree(int n, GetSingleSegment<RET, Node> gss, GetMergedSegment<RET> gms, SetInitialSegment<Node> sis, SetInitialLeaf<Node> sil, LazyUpdate<Node> lu = [](Node &v, Node &l, Node &r) {}, BufferManager<Node> &buf = NodeBuffer::buffer) : get_single_segment(gss), get_merged_segment(gms), lazy_update(lu) { size = 1; while (size < n) size *= 2; seg = buf.get(size * 2 + 10); init(0, size, sis, sil); } #define LQ a, b, k * 2 + 1, l, m #define RQ a, b, k * 2 + 2, m, r RET get(int a, int b, int k, int l, int r) { if (a <= l && r <= b) return get_single_segment(seg[k], l, r); if (r - l > 1) lazy_update(seg[k], seg[2 * k + 1], seg[2 * k + 2]); int m = (l + r) / 2; bool ll = !(m <= a || b <= l); bool rr = !(r <= a || b <= m); RET ret; if (ll && rr) ret = get_merged_segment(get(LQ), get(RQ)); else if (ll) ret = get(LQ); else ret = get(RQ); seg[k].ret = get_merged_segment(get_single_segment(seg[k * 2 + 1], l, m), get_single_segment(seg[k * 2 + 2], m, r)); return ret; } RET get(int a, int b) { return get(a, b, 0, 0, size); } template <typename Q> void update(int a, int b, int k, int l, int r, UpdateSingleSegment<Node, Q> &update_segment, Q value) { if (r <= a || b <= l) return; if (a <= l && r <= b) { update_segment(seg[k], value); } else { if (r - l > 1) lazy_update(seg[k], seg[2 * k + 1], seg[2 * k + 2]); int m = (l + r) / 2; update(LQ, update_segment, value); update(RQ, update_segment, value); seg[k].ret = get_merged_segment(get_single_segment(seg[k * 2 + 1], l, m), get_single_segment(seg[k * 2 + 2], m, r)); } } template <typename Q> void update_segment(int a, int b, UpdateSingleSegment<Node, Q> &update_segment, Q value) { update(a, b, 0, 0, size, update_segment, value); } template <typename Q> void update_element(int a, UpdateSingleSegment<Node, Q> &update_segment, Q value) { update(a, a + 1, 0, 0, size, update_segment, value); } }; int main() { /* write here */ int N, M; cin >> N >> M; map<string, int> ret; SegmentTree<node, int> tree(N + 10, segment_sum, merge_segment, set_segment, set_leaf, lazy); for (int i : range(M)) { int l, r; string s; cin >> l >> r >> s; l--; int add_val = (r - l) - tree.get(l, r); ret[s] += add_val; //cerr << add_val << endl; tree.update_segment(l, r, update, 1); } cout << ret["Y"] << " "; cout << ret["K"] << " "; cout << ret["C"] << endl; return 0; }