結果

問題 No.3794 Super Chat
ユーザー kemuniku
提出日時 2026-11-13 23:51:43
言語 Nim
(2.2.12 + ACL)
コンパイル:
nim --nimcache=~ --hints:off -o:a.out -d:release cpp _filename_
実行:
./a.out
結果
AC  
実行時間 1 ms / 2,000 ms
+ 709µs
コード長 57,697 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 5,857 ms
コンパイル使用メモリ 203,148 KB
実行使用メモリ 6,400 KB
最終ジャッジ日時 2026-11-13 23:51:51
合計ジャッジ時間 7,478 ms
ジャッジサーバーID
(参考情報)
judge4_0 / judge5_0
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 35
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

template originalSource() =
 include cplib/tmpl/sheep
 
 var N,M = ii()
 var ans = 0
 
 var SP = initTable[string,int]()
 
 for _ in range(N):
     var s = si()
     var p = ii()
     SP[s] = p
 
 for i in range(M):
     var T = si()
     ans += SP[T]
 
 print(ans)



# source: https://github.com/kemuniku/cplib/blob/d5d0fb671ed854ea197cb2e8f69df5702d31bae4/src/cplib/tmpl/sheep.nim
when not declared CPLIB_TMPL_SHEEP:
    const CPLIB_TMPL_SHEEP* = 1
    {.warning[UnusedImport]: off.}
    {.hint[XDeclaredButNotUsed]: off.}
    import algorithm
    import sequtils
    import tables
    import macros
    import math
    import sets
    import strutils
    import strformat
    import sugar
    import heapqueue
    import streams
    import deques
    import bitops
    import std/lenientops
    import options
    # source: https://github.com/kemuniku/cplib/blob/d5d0fb671ed854ea197cb2e8f69df5702d31bae4/src/cplib/tmpl/fastio.nim
    when not declared CPLIB_TMPL_FASTIO:
        const CPLIB_TMPL_FASTIO* = 1
        {.passC: "-mavx2".}
        # 対話モードは先頭の {.define: fastioInteractive.} または -d:fastioInteractive で有効化する。
        when defined(fastioInteractive):
            {.passC: "-DCPLIB_FASTIO_INTERACTIVE".}
        # mmapは明示指定時のみ使用し、対話モードと旧来の無効化指定を優先する。
        when not defined(fastioMmap) or defined(fastioNoMmap) or defined(fastioInteractive):
            {.passC: "-DCPLIB_FASTIO_NO_MMAP".}
        import macros
    
        # 入力系(C/C++共通。GCC/ClangとAVX2対応CPU向け)
        {.emit: """
    #include <stdio.h>
    #include <stddef.h>
    #include <stdint.h>
    #include <string.h>
    #include <immintrin.h>
    #include <stdlib.h>
    #include <stdbool.h>
    #include <sys/mman.h>
    #include <sys/stat.h>
    
    #define cplib_fio_buffer_size (1U << 20)
    #define cplib_fio_safe_integer_bytes 32
    
    typedef struct {
      char buffer[cplib_fio_buffer_size] __attribute__((aligned(64)));
      size_t cursor;
      size_t length;
      const char* mapped;
      bool initialized;
    } cplib_fio_InputState;
    
    static inline cplib_fio_InputState* cplib_fio_input_state(void) {
      static cplib_fio_InputState state = {0};
      return &state;
    }
    
    // バッファ境界をまたぐトークンだけ、一時領域へ連結します。
    static char* cplib_fio_token_storage;
    static size_t cplib_fio_token_capacity;
    static void cplib_fio_append_token(size_t* length, const char* source, size_t count) {
      // 必要なら領域を拡張してトークンを連結します。償却O(count)。
      if (count > SIZE_MAX - *length) abort();
      const size_t needed = *length + count;
      if (needed > cplib_fio_token_capacity) {
        size_t capacity = needed <= SIZE_MAX / 2 ? needed * 2 : needed;
        char* storage = (char*)realloc(cplib_fio_token_storage, capacity);
        if (storage == NULL) abort();
        cplib_fio_token_storage = storage;
        cplib_fio_token_capacity = capacity;
      }
      if (count != 0) memcpy(cplib_fio_token_storage + *length, source, count);
      *length = needed;
    }
    
    #if defined(__GNUC__) || defined(__clang__)
    #define CPLIB_FASTIO_ALWAYS_INLINE static inline __attribute__((always_inline))
    #define CPLIB_FASTIO_NIM_ALWAYS_INLINE \
        static inline __attribute__((always_inline))
    #define CPLIB_FASTIO_UNLIKELY(condition) (__builtin_expect(!!(condition), 0))
    #elif defined(_MSC_VER)
    #define CPLIB_FASTIO_ALWAYS_INLINE static __forceinline
    #define CPLIB_FASTIO_NIM_ALWAYS_INLINE static __forceinline
    #define CPLIB_FASTIO_UNLIKELY(condition) (condition)
    #else
    #define CPLIB_FASTIO_ALWAYS_INLINE static inline
    #define CPLIB_FASTIO_NIM_ALWAYS_INLINE static inline
    #define CPLIB_FASTIO_UNLIKELY(condition) (condition)
    #endif
    
    static inline void cplib_fio_initialize(cplib_fio_InputState* state) {
      if (state->initialized) return;
      state->initialized = true;
    
    #ifndef CPLIB_FASTIO_NO_MMAP
      struct stat st;
      const int fd = fileno(stdin);
      if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) && st.st_size > 0) {
        void* p = mmap(NULL, (size_t)(st.st_size),
                       PROT_READ, MAP_PRIVATE, fd, 0);
        if (p != MAP_FAILED) {
          state->mapped = (const char*)p;
          state->length = (size_t)(st.st_size);
          madvise((char*)(state->mapped), state->length,
                  MADV_SEQUENTIAL);
        }
      }
    #endif
    }
    
    static inline bool cplib_fio_refill(cplib_fio_InputState* state) {
      // 対話モードでは1文字だけ要求し、相手の次の応答を先読みして待たない。
    #ifdef CPLIB_FASTIO_INTERACTIVE
      const int value = getchar_unlocked();
      state->length = value == EOF ? 0 : 1;
      if (value != EOF) state->buffer[0] = (char)value;
    #else
      state->length =
          fread_unlocked(state->buffer, 1, cplib_fio_buffer_size, stdin);
    #endif
      state->cursor = 0;
      return state->length != 0;
    }
    
    static inline int cplib_fio_get_char(void) {
      cplib_fio_InputState* state = cplib_fio_input_state();
      if (CPLIB_FASTIO_UNLIKELY(!state->initialized)) cplib_fio_initialize(state);
      if (state->mapped != NULL) {
        if (state->cursor == state->length) return -1;
        return (unsigned char)(state->mapped[state->cursor++]);
      }
      if (state->cursor == state->length && !cplib_fio_refill(state)) return -1;
      return (unsigned char)(state->buffer[state->cursor++]);
    }
    
    static inline bool cplib_fio_has_eight_digits(const char* source) {
      // 正しい整数入力では、数字・符号・空白を上位4bitだけで判別できる。
      uint64_t bytes;
      memcpy(&bytes, source, sizeof(bytes));
      return ((bytes ^ 0x3030303030303030ULL) &
              0xf0f0f0f0f0f0f0f0ULL) == 0;
    }
    
    static inline unsigned cplib_fio_parse_eight_digits(const char* source) {
      uint64_t digits;
      memcpy(&digits, source, sizeof(digits));
      digits ^= 0x3030303030303030ULL;
      digits = (digits * ((10ULL << 8) + 1) >> 8) &
          0x00ff00ff00ff00ffULL;
      digits = (digits * ((100ULL << 16) + 1) >> 16) &
          0x0000ffff0000ffffULL;
      return (unsigned)(
          digits * ((10000ULL << 32) + 1) >> 32);
    }
    
    static inline unsigned cplib_fio_digit_at(const char* source) {
      return (unsigned)((unsigned char)*source) -
             '0';
    }
    
    // 型と符号を実体化し、桁ごとの符号判定をコンパイル時に除去します。
    #define CPLIB_FASTIO_DIGITS(suffix, Value, negative) \
    CPLIB_FASTIO_ALWAYS_INLINE bool cplib_fio_try_digits_##suffix( \
            const char** source, Value* output) { \
      Value value = 0; \
      if (cplib_fio_has_eight_digits(*source)) { \
        const Value digits = \
            (Value)(cplib_fio_parse_eight_digits(*source)); \
        value = negative ? value * 100000000LL - digits \
                         : value * 100000000LL + digits; \
        *source += 8; \
        if (cplib_fio_has_eight_digits(*source)) { \
          const Value next_digits = \
              (Value)(cplib_fio_parse_eight_digits(*source)); \
          value = negative ? value * 100000000LL - next_digits \
                           : value * 100000000LL + next_digits; \
          *source += 8; \
          for (int pair = 0; pair < 2; ++pair) { \
            const unsigned first = cplib_fio_digit_at(*source); \
            if (first >= 10U) { \
              *output = value; \
              return true; \
            } \
            const unsigned second = cplib_fio_digit_at(*source + 1); \
            if (second >= 10U) { \
              ++*source; \
              *output = negative \
                  ? value * 10 - (Value)first \
                  : value * 10 + (Value)first; \
              return true; \
            } \
            value = negative \
                ? value * 100 - (Value)(first * 10U + second) \
                : value * 100 + (Value)(first * 10U + second); \
            *source += 2; \
          } \
          if (cplib_fio_digit_at(*source) < 10U) return false; \
          *output = value; \
          return true; \
        } \
      } \
      for (;;) { \
        const unsigned first = cplib_fio_digit_at(*source); \
        if (first >= 10U) { \
          *output = value; \
          return true; \
        } \
        const unsigned second = cplib_fio_digit_at(*source + 1); \
        if (second >= 10U) { \
          ++*source; \
          *output = negative ? value * 10 - (Value)first \
                            : value * 10 + (Value)first; \
          return true; \
        } \
        value = negative \
            ? value * 100 - (Value)(first * 10U + second) \
            : value * 100 + (Value)(first * 10U + second); \
        *source += 2; \
      } \
    } \
    static __attribute__((noinline)) Value cplib_fio_bounded_##suffix(const char** source, \
                                          const char* end) { \
      Value value = 0; \
      while (end - *source >= 8 && cplib_fio_has_eight_digits(*source)) { \
        const Value digits = \
            (Value)(cplib_fio_parse_eight_digits(*source)); \
        value = negative ? value * 100000000LL - digits \
                         : value * 100000000LL + digits; \
        *source += 8; \
      } \
      while (end - *source >= 2) { \
        const unsigned first = cplib_fio_digit_at(*source); \
        const unsigned second = cplib_fio_digit_at(*source + 1); \
        if (first >= 10U) return value; \
        if (second >= 10U) { \
          ++*source; \
          return negative ? value * 10 - (Value)first \
                          : value * 10 + (Value)first; \
        } \
        value = negative \
            ? value * 100 - (Value)(first * 10U + second) \
            : value * 100 + (Value)(first * 10U + second); \
        *source += 2; \
      } \
      if (*source != end) { \
        const unsigned digit = cplib_fio_digit_at(*source); \
        if (digit < 10U) { \
          value = negative ? value * 10 - (Value)digit \
                           : value * 10 + (Value)digit; \
          ++*source; \
        } \
      } \
      return value; \
    }
    CPLIB_FASTIO_DIGITS(positive, long long, false)
    CPLIB_FASTIO_DIGITS(negative, long long, true)
    CPLIB_FASTIO_DIGITS(unsigned, unsigned long long, false)
    #undef CPLIB_FASTIO_DIGITS
    
    static inline unsigned long long cplib_fio_read_uint_stream_slow(cplib_fio_InputState* state) {
      const bool negative = state->buffer[state->cursor] == '-';
      if (negative || state->buffer[state->cursor] == '+') {
        ++state->cursor;
        if (state->cursor == state->length && !cplib_fio_refill(state)) return 0;
      }
      unsigned long long value = 0;
      for (;;) {
        while (state->cursor != state->length) {
          const unsigned digit = cplib_fio_digit_at(state->buffer + state->cursor);
          if (digit >= 10U) return negative ? 0ULL - value : value;
          value = value * 10ULL + digit;
          ++state->cursor;
        }
        if (!cplib_fio_refill(state)) return negative ? 0ULL - value : value;
      }
    }
    
    CPLIB_FASTIO_ALWAYS_INLINE bool cplib_fio_try_int(const char** source, long long* value, bool negative) {
      // 符号別に解析します。
      return negative ? cplib_fio_try_digits_negative(source, value)
                      : cplib_fio_try_digits_positive(source, value);
    }
    CPLIB_FASTIO_ALWAYS_INLINE bool cplib_fio_try_uint(const char** source, unsigned long long* value, bool negative) {
      // 解析後に符号を適用します。
      bool complete = cplib_fio_try_digits_unsigned(source, value);
      if (complete && negative) *value = 0ULL - *value;
      return complete;
    }
    static inline long long cplib_fio_bounded_int(const char** source, const char* end, bool negative) {
      // 終端までの符号付き整数を読み取ります。
      return negative ? cplib_fio_bounded_negative(source, end)
                      : cplib_fio_bounded_positive(source, end);
    }
    static inline unsigned long long cplib_fio_bounded_uint(const char** source, const char* end, bool negative) {
      // 終端までの符号なし整数を読み取ります。
      unsigned long long value = cplib_fio_bounded_unsigned(source, end);
      return negative ? 0ULL - value : value;
    }
    
    #define CPLIB_FASTIO_READ(suffix, Value, try_digits, bounded) \
    CPLIB_FASTIO_ALWAYS_INLINE Value cplib_fio_read_##suffix##_mapped_at( \
            const char** source, const char* end) { \
      while (*source != end && \
             (unsigned char)(**source) <= \
                 ' ') { \
        ++*source; \
      } \
      if (*source == end) return 0; \
      const bool negative = **source == '-'; \
      if (negative || **source == '+') ++*source; \
      if (end - *source >= (ptrdiff_t)cplib_fio_safe_integer_bytes) { \
        const char* parsed = *source; \
        Value value; \
        if (try_digits(&parsed, &value, negative)) { \
          *source = parsed; \
          return value; \
        } \
      } \
      const Value value = \
          bounded(source, end, negative); \
      return value; \
    } \
    CPLIB_FASTIO_ALWAYS_INLINE Value cplib_fio_read_##suffix##_stream( \
            cplib_fio_InputState* state) { \
      for (;;) { \
        if (state->cursor == state->length && !cplib_fio_refill(state)) return 0; \
        while (state->cursor != state->length && \
               (unsigned char)(state->buffer[state->cursor]) <= \
                   ' ') { \
          ++state->cursor; \
        } \
        if (state->cursor != state->length) break; \
      } \
      if (state->length - state->cursor < cplib_fio_safe_integer_bytes) { \
        return (Value)cplib_fio_read_uint_stream_slow(state); \
      } \
      const char* source = state->buffer + state->cursor; \
      const bool negative = *source == '-'; \
      if (negative || *source == '+') ++source; \
      Value value; \
      if (!try_digits(&source, &value, negative)) { \
        return (Value)cplib_fio_read_uint_stream_slow(state); \
      } \
      state->cursor = (size_t)(source - state->buffer); \
      return value; \
    } \
    CPLIB_FASTIO_ALWAYS_INLINE Value cplib_fio_read_##suffix(void) { \
      cplib_fio_InputState* state = cplib_fio_input_state(); \
      if (CPLIB_FASTIO_UNLIKELY(!state->initialized)) cplib_fio_initialize(state); \
      if (state->mapped == NULL) return cplib_fio_read_##suffix##_stream(state); \
      const char* source = state->mapped + state->cursor; \
      const Value value = \
          cplib_fio_read_##suffix##_mapped_at(&source, state->mapped + state->length); \
      state->cursor = (size_t)(source - state->mapped); \
      return value; \
    }
    CPLIB_FASTIO_READ(int, long long, cplib_fio_try_int, cplib_fio_bounded_int)
    CPLIB_FASTIO_READ(uint, unsigned long long, cplib_fio_try_uint, cplib_fio_bounded_uint)
    #undef CPLIB_FASTIO_READ
    
    static inline bool cplib_fio_is_space(char value) {
      return (unsigned char)value <=
             ' ';
    }
    
    static inline void cplib_fio_skip_spaces(const char** source, const char* end) {
      while (*source != end && cplib_fio_is_space(**source)) ++*source;
    }
    
    static inline void cplib_fio_consume_separator(const char** source, const char* end) {
      if (*source != end) {
        ++*source;
        cplib_fio_skip_spaces(source, end);
      }
    }
    
    static inline unsigned cplib_fio_parse_eight_digits_simd(const char* source) {
      const __m128i bytes = _mm_loadl_epi64(
          (const __m128i*)source);
      const __m128i digits = _mm_sub_epi8(bytes, _mm_set1_epi8('0'));
      const __m128i pairs = _mm_maddubs_epi16(
          digits, _mm_setr_epi8(10, 1, 10, 1, 10, 1, 10, 1,
                                0, 0, 0, 0, 0, 0, 0, 0));
      const __m128i quads = _mm_madd_epi16(
          pairs, _mm_setr_epi16(100, 1, 100, 1, 0, 0, 0, 0));
      return (unsigned)(_mm_cvtsi128_si32(quads)) * 10000U +
          (unsigned)(_mm_cvtsi128_si32(_mm_srli_si128(quads, 4)));
    }
    
    // 呼び出し元で空白を除去済み。長い先頭ゼロと末尾は境界付き処理へ戻す。
    static inline uint32_t cplib_fio_read_u32_digits(const char** source, const char* end) {
      if (*source == end) return 0;
      const bool negative = **source == '-';
      if (negative || **source == '+') ++*source;
      unsigned long long value = 0;
      if (end - *source >= 16) {
        if (cplib_fio_has_eight_digits(*source)) {
          value = cplib_fio_parse_eight_digits_simd(*source);
          const unsigned ninth = cplib_fio_digit_at(*source + 8);
          const unsigned tenth = cplib_fio_digit_at(*source + 9);
          if (ninth >= 10U) {
            *source += 8;
          } else if (tenth >= 10U) {
            value = value * 10ULL + ninth;
            *source += 9;
          } else if (cplib_fio_digit_at(*source + 10) >= 10U) {
            value = value * 100ULL + ninth * 10U + tenth;
            *source += 10;
          } else {
            value = cplib_fio_bounded_unsigned(source, end);
          }
        } else {
          for (;;) {
            const unsigned first = cplib_fio_digit_at(*source);
            if (first >= 10U) break;
            const unsigned second = cplib_fio_digit_at(*source + 1);
            if (second >= 10U) {
              value = value * 10ULL + first;
              ++*source;
              break;
            }
            value = value * 100ULL + first * 10U + second;
            *source += 2;
          }
        }
      } else {
        value = cplib_fio_bounded_unsigned(source, end);
      }
      return (uint32_t)(negative ? 0ULL - value : value);
    }
    
    CPLIB_FASTIO_ALWAYS_INLINE uint32_t cplib_fio_read_u32() {
      cplib_fio_InputState* state = cplib_fio_input_state();
      if (CPLIB_FASTIO_UNLIKELY(!state->initialized)) cplib_fio_initialize(state);
      if (state->mapped != NULL) {
        const char* source = state->mapped + state->cursor;
        const char* const end = state->mapped + state->length;
        cplib_fio_skip_spaces(&source, end);
        const uint32_t value = cplib_fio_read_u32_digits(&source, end);
        cplib_fio_consume_separator(&source, end);
        state->cursor = (size_t)(source - state->mapped);
        return value;
      }
      const char* source = state->buffer + state->cursor;
      const char* const end = state->buffer + state->length;
      cplib_fio_skip_spaces(&source, end);
      if (CPLIB_FASTIO_UNLIKELY(end - source <
                               (ptrdiff_t)cplib_fio_safe_integer_bytes)) {
        return (uint32_t)(cplib_fio_read_uint_stream(state));
      }
      const uint32_t value = cplib_fio_read_u32_digits(&source, end);
      // 長い先頭ゼロがrefill境界をまたぐ場合は、元の位置から読み直す。
      if (CPLIB_FASTIO_UNLIKELY(source == end)) {
        return (uint32_t)(cplib_fio_read_uint_stream(state));
      }
      cplib_fio_consume_separator(&source, end);
      state->cursor = (size_t)(source - state->buffer);
      return value;
    }
    
    static inline bool cplib_fio_try_read_four_nine_digit_u32(
            const char** source, const char* end, uint32_t* output) {
      if (end - *source < 40) return false;
      if (!cplib_fio_is_space((*source)[9]) || !cplib_fio_is_space((*source)[19]) ||
          !cplib_fio_is_space((*source)[29]) || !cplib_fio_is_space((*source)[39])) {
        return false;
      }
      const __m128i first_two = _mm_unpacklo_epi64(
          _mm_loadl_epi64((const __m128i*)*source),
          _mm_loadl_epi64((const __m128i*)(*source + 10)));
      const __m128i last_two = _mm_unpacklo_epi64(
          _mm_loadl_epi64((const __m128i*)(*source + 20)),
          _mm_loadl_epi64((const __m128i*)(*source + 30)));
      const __m256i bytes = _mm256_set_m128i(last_two, first_two);
      const __m256i is_digit = _mm256_and_si256(
          _mm256_cmpgt_epi8(bytes, _mm256_set1_epi8('/')),
          _mm256_cmpgt_epi8(_mm256_set1_epi8(':'), bytes));
      if ((unsigned)(_mm256_movemask_epi8(is_digit)) !=
          0xffffffffU) {
        return false;
      }
    
      const unsigned digit0 = cplib_fio_digit_at(*source + 8);
      const unsigned digit1 = cplib_fio_digit_at(*source + 18);
      const unsigned digit2 = cplib_fio_digit_at(*source + 28);
      const unsigned digit3 = cplib_fio_digit_at(*source + 38);
      const bool ninth_digits = (digit0 < 10U) & (digit1 < 10U) &
                                (digit2 < 10U) & (digit3 < 10U);
      if (!ninth_digits) return false;
    
      const __m256i digits =
          _mm256_sub_epi8(bytes, _mm256_set1_epi8('0'));
      const __m256i pairs = _mm256_maddubs_epi16(
          digits, _mm256_setr_epi8(
              10, 1, 10, 1, 10, 1, 10, 1,
              10, 1, 10, 1, 10, 1, 10, 1,
              10, 1, 10, 1, 10, 1, 10, 1,
              10, 1, 10, 1, 10, 1, 10, 1));
      const __m256i quads = _mm256_madd_epi16(
          pairs, _mm256_setr_epi16(
              100, 1, 100, 1, 100, 1, 100, 1,
              100, 1, 100, 1, 100, 1, 100, 1));
      const __m256i weighted = _mm256_mullo_epi32(
          quads, _mm256_setr_epi32(
              10000, 1, 10000, 1, 10000, 1, 10000, 1));
      const __m256i sums =
          _mm256_hadd_epi32(weighted, _mm256_setzero_si256());
      const __m128i first_eight = _mm_unpacklo_epi64(
          _mm256_castsi256_si128(sums),
          _mm256_extracti128_si256(sums, 1));
      const __m128i values = _mm_add_epi32(
          _mm_mullo_epi32(first_eight, _mm_set1_epi32(10)),
          _mm_setr_epi32((int)digit0,
                         (int)digit1,
                         (int)digit2,
                         (int)digit3));
      _mm_storeu_si128((__m128i*)output, values);
      *source += 40;
      return true;
    }
    
    static inline void cplib_fio_read_u32_array(uint32_t* output, size_t count) {
      cplib_fio_InputState* state = cplib_fio_input_state();
      if (CPLIB_FASTIO_UNLIKELY(!state->initialized)) cplib_fio_initialize(state);
      if (state->mapped != NULL) {
        const char* source = state->mapped + state->cursor;
        const char* const end = state->mapped + state->length;
        cplib_fio_skip_spaces(&source, end);
        size_t i = 0;
        unsigned nine_digit_count = 0;
        // 最初の16要素を読みながら分布を確認し、短い整数ではAVX判定を省く。
        if (count >= 64) {
          for (; i < 16; ++i) {
            nine_digit_count += end - source >= 10 &&
                cplib_fio_is_space(source[9]) && cplib_fio_has_eight_digits(source) &&
                cplib_fio_digit_at(source + 8) < 10U;
            output[i] = cplib_fio_read_u32_digits(&source, end);
            cplib_fio_consume_separator(&source, end);
          }
        }
        if (nine_digit_count >= 12) {
          while (i < count) {
            if (count - i >= 4 && cplib_fio_try_read_four_nine_digit_u32(&source, end, output + i)) {
              i += 4;
              cplib_fio_skip_spaces(&source, end);
            } else {
              output[i++] = cplib_fio_read_u32_digits(&source, end);
              if (i != count) cplib_fio_consume_separator(&source, end);
            }
          }
        } else {
          while (i < count) {
            output[i++] = cplib_fio_read_u32_digits(&source, end);
            if (i != count) cplib_fio_consume_separator(&source, end);
          }
        }
        state->cursor = (size_t)(source - state->mapped);
      } else {
        size_t i = 0;
        unsigned nine_digit_count = 0;
        if (count >= 64) {
          for (; i < 16; ++i) {
            output[i] = (uint32_t)(cplib_fio_read_uint_stream(state));
            nine_digit_count += output[i] >= 100000000U &&
                                output[i] < 1000000000U;
          }
        }
        if (nine_digit_count >= 12) {
          while (count - i >= 4) {
            const char* source = state->buffer + state->cursor;
            const char* const end = state->buffer + state->length;
            cplib_fio_skip_spaces(&source, end);
            if (cplib_fio_try_read_four_nine_digit_u32(&source, end, output + i)) {
              state->cursor = (size_t)(source - state->buffer);
              i += 4;
            } else {
              state->cursor = (size_t)(source - state->buffer);
              // refillをまたぐ整数は既存のストリーム処理で最後まで読む。
              output[i++] = (uint32_t)(cplib_fio_read_uint_stream(state));
            }
          }
        }
        for (; i < count; ++i) {
          output[i] = (uint32_t)(cplib_fio_read_uint_stream(state));
        }
      }
    }
    
    static inline const char* cplib_fio_read_token(size_t* output_length) {
      cplib_fio_InputState* state = cplib_fio_input_state();
      if (CPLIB_FASTIO_UNLIKELY(!state->initialized)) cplib_fio_initialize(state);
      if (state->mapped != NULL) {
        const char* source = state->mapped + state->cursor;
        const char* const end = state->mapped + state->length;
        while (source != end &&
               (unsigned char)*source <=
                   ' ') {
          ++source;
        }
        const char* const token = source;
        while (source != end &&
               (unsigned char)*source >
                   ' ') {
          ++source;
        }
        state->cursor = (size_t)(source - state->mapped);
        *output_length = (size_t)(source - token);
        return token;
      }
    
      for (;;) {
        if (state->cursor == state->length && !cplib_fio_refill(state)) {
          *output_length = 0;
          return "";
        }
        while (state->cursor != state->length &&
               (unsigned char)(state->buffer[state->cursor]) <=
                   ' ') {
          ++state->cursor;
        }
        if (state->cursor != state->length) break;
      }
    
      const size_t token_begin = state->cursor;
      while (state->cursor != state->length &&
             (unsigned char)(state->buffer[state->cursor]) >
                 ' ') {
        ++state->cursor;
      }
      if (state->cursor != state->length) {
        *output_length = state->cursor - token_begin;
        return state->buffer + token_begin;
      }
    
      size_t length = 0;
      cplib_fio_append_token(&length, state->buffer + token_begin, state->length - token_begin);
      while (cplib_fio_refill(state)) {
        while (state->cursor != state->length &&
               (unsigned char)(state->buffer[state->cursor]) >
                   ' ') {
          ++state->cursor;
        }
        cplib_fio_append_token(&length, state->buffer, state->cursor);
        if (state->cursor != state->length) break;
      }
      *output_length = length;
      return cplib_fio_token_storage;
    }
    
    #define CPLIB_FASTIO_READ_ARRAY(name, T, mapped_reader, stream_reader) \
    static inline void name(void* destination, size_t count) { \
      T* output = (T*)destination; \
      cplib_fio_InputState* state = cplib_fio_input_state(); \
      if (CPLIB_FASTIO_UNLIKELY(!state->initialized)) cplib_fio_initialize(state); \
      if (state->mapped != NULL) { \
        const char* source = state->mapped + state->cursor; \
        const char* end = state->mapped + state->length; \
        for (size_t i = 0; i < count; ++i) output[i] = (T)mapped_reader(&source, end); \
        state->cursor = (size_t)(source - state->mapped); \
      } else { \
        for (size_t i = 0; i < count; ++i) output[i] = (T)stream_reader(state); \
      } \
    }
    CPLIB_FASTIO_READ_ARRAY(cplib_fio_read_i8_array, int8_t, cplib_fio_read_int_mapped_at, cplib_fio_read_int_stream)
    CPLIB_FASTIO_READ_ARRAY(cplib_fio_read_i16_array, int16_t, cplib_fio_read_int_mapped_at, cplib_fio_read_int_stream)
    CPLIB_FASTIO_READ_ARRAY(cplib_fio_read_i32_array, int32_t, cplib_fio_read_int_mapped_at, cplib_fio_read_int_stream)
    CPLIB_FASTIO_READ_ARRAY(cplib_fio_read_i64_array, int64_t, cplib_fio_read_int_mapped_at, cplib_fio_read_int_stream)
    CPLIB_FASTIO_READ_ARRAY(cplib_fio_read_u8_array, uint8_t, cplib_fio_read_uint_mapped_at, cplib_fio_read_uint_stream)
    CPLIB_FASTIO_READ_ARRAY(cplib_fio_read_u16_array, uint16_t, cplib_fio_read_uint_mapped_at, cplib_fio_read_uint_stream)
    CPLIB_FASTIO_READ_ARRAY(cplib_fio_read_u64_array, uint64_t, cplib_fio_read_uint_mapped_at, cplib_fio_read_uint_stream)
    #undef CPLIB_FASTIO_READ_ARRAY
    
    #undef CPLIB_FASTIO_UNLIKELY
    #undef CPLIB_FASTIO_ALWAYS_INLINE
    
    """.}
    
        proc fastioGetChar(): cint {.importc: "cplib_fio_get_char", nodecl, inline.}
        proc fastioReadInt(): clonglong {.importc: "cplib_fio_read_int", nodecl, inline.}
        proc fastioReadUInt(): culonglong {.importc: "cplib_fio_read_uint", nodecl, inline.}
        proc fastioReadUInt32(): uint32 {.importc: "cplib_fio_read_u32", nodecl, inline.}
        type FastioTokenPointer {.importc: "const char*", nodecl.} = pointer
        proc fastioReadToken(length: ptr csize_t): FastioTokenPointer
            {.importc: "cplib_fio_read_token", nodecl, inline.}
        proc fastioCopyToken(destination: pointer, source: FastioTokenPointer, length: csize_t)
                {.importc: "memcpy", nodecl, inline.}
    
        proc fastioReadArray(values: ptr int8, count: csize_t) {.importc: "cplib_fio_read_i8_array", nodecl, inline.}
        proc fastioReadArray(values: ptr int16, count: csize_t) {.importc: "cplib_fio_read_i16_array", nodecl, inline.}
        proc fastioReadArray(values: ptr int32, count: csize_t) {.importc: "cplib_fio_read_i32_array", nodecl, inline.}
        proc fastioReadArray(values: ptr int64, count: csize_t) {.importc: "cplib_fio_read_i64_array", nodecl, inline.}
        proc fastioReadArray(values: ptr uint8, count: csize_t) {.importc: "cplib_fio_read_u8_array", nodecl, inline.}
        proc fastioReadArray(values: ptr uint16, count: csize_t) {.importc: "cplib_fio_read_u16_array", nodecl, inline.}
        proc fastioReadArray(values: ptr uint32, count: csize_t) {.importc: "cplib_fio_read_u32_array", nodecl, inline.}
        proc fastioReadArray(values: ptr uint64, count: csize_t) {.importc: "cplib_fio_read_u64_array", nodecl, inline.}
    
        template fastioReadIntegerArray(T: typedesc, values, count: untyped) =
            when T is SomeSignedInt:
                when sizeof(T) == 8: fastioReadArray(cast[ptr int64](values), count)
                elif sizeof(T) == 4: fastioReadArray(cast[ptr int32](values), count)
                else: fastioReadArray(values, count)
            else:
                when sizeof(T) == 8: fastioReadArray(cast[ptr uint64](values), count)
                elif sizeof(T) == 4: fastioReadArray(cast[ptr uint32](values), count)
                else: fastioReadArray(values, count)
    
        type FastioInteger = int | int8 | int16 | int32 | int64 |
            uint | uint8 | uint16 | uint32 | uint64
    
        when declared(newSeqUninit):
            template fastioNewSeqUninit(T: typedesc, length: int): untyped =
                newSeqUninit[T](length)
        else:
            template fastioNewSeqUninit(T: typedesc, length: int): untyped =
                newSeqUninitialized[T](length)
    
        when declared(newStringUninit):
            template fastioNewStringUninit(length: int): untyped =
                newStringUninit(length)
        else:
            template fastioNewStringUninit(length: int): untyped =
                newString(length)
    
        proc ii(): int {.inline,
                codegenDecl: "CPLIB_FASTIO_NIM_ALWAYS_INLINE $# $#$#".} =
            fastioReadInt().int
        proc lii(N: int): seq[int] {.inline.} =
            result = fastioNewSeqUninit(int, N)
            if N > 0:
                fastioReadIntegerArray(int, addr result[0], N.csize_t)
    
        # 型だけなら1要素、長さと型ならseqとして読み込む。
        proc input[T: FastioInteger](valueType: typedesc[T]): T {.inline,
                codegenDecl: "CPLIB_FASTIO_NIM_ALWAYS_INLINE $# $#$#".} =
            when T is range:
                {.error: "input supports only primitive integer types".}
            elif T is SomeSignedInt:
                T(fastioReadInt())
            elif T is uint32:
                fastioReadUInt32()
            else:
                T(fastioReadUInt())
    
        proc input[T: FastioInteger](N: int, valueType: typedesc[T]): seq[T] {.inline.} =
            when T is range:
                {.error: "input supports only primitive integer types".}
            else:
                result = fastioNewSeqUninit(T, N)
                if N > 0:
                    fastioReadIntegerArray(T, addr result[0], N.csize_t)
    
        proc si(): string {.inline.} =
            var length: csize_t
            let source = fastioReadToken(addr length)
            result = fastioNewStringUninit(length.int)
            if length != 0:
                fastioCopyToken(addr result[0], source, length)
    
        proc input(valueType: typedesc[char]): char {.inline.} =
            var c = fastioGetChar()
            while c >= 0 and c <= ord(' '):
                c = fastioGetChar()
            if c < 0:
                return '\0'
            return char(c)
    
        proc input(valueType: typedesc[string]): string {.inline.} =
            si()
    
        proc input(N: int, valueType: typedesc[string]): seq[string] {.inline.} =
            result = newSeq[string](N)
            for i in 0 ..< N:
                result[i] = input(string)
    
        # 出力系
        {.emit: """
    #include <stdio.h>
    #include <stddef.h>
    #include <stdint.h>
    #include <string.h>
    #include <stdbool.h>
    
    // stdioのバッファを共有し、echo/write/flushFileとの出力順を保ちます。
    static char cplib_fio_stdout_buffer[1U << 16] __attribute__((aligned(64)));
    static void __attribute__((constructor)) cplib_fio_init_stdout(void) {
      // 標準出力のバッファを初期化します。O(1)。
      setvbuf(stdout, cplib_fio_stdout_buffer, _IOFBF, sizeof(cplib_fio_stdout_buffer));
    }
    
    typedef struct { char data[10000][4]; } cplib_fio_FourDigits;
    // 4桁テーブルをC/C++共通の定数式で構築します。
    #define CPLIB_FASTIO_D4(a,b,c,d) {'0'+a, '0'+b, '0'+c, '0'+d}
    #define CPLIB_FASTIO_D3(a,b,c) CPLIB_FASTIO_D4(a,b,c,0), CPLIB_FASTIO_D4(a,b,c,1), CPLIB_FASTIO_D4(a,b,c,2), CPLIB_FASTIO_D4(a,b,c,3), CPLIB_FASTIO_D4(a,b,c,4), CPLIB_FASTIO_D4(a,b,c,5), CPLIB_FASTIO_D4(a,b,c,6), CPLIB_FASTIO_D4(a,b,c,7), CPLIB_FASTIO_D4(a,b,c,8), CPLIB_FASTIO_D4(a,b,c,9)
    #define CPLIB_FASTIO_D2(a,b) CPLIB_FASTIO_D3(a,b,0), CPLIB_FASTIO_D3(a,b,1), CPLIB_FASTIO_D3(a,b,2), CPLIB_FASTIO_D3(a,b,3), CPLIB_FASTIO_D3(a,b,4), CPLIB_FASTIO_D3(a,b,5), CPLIB_FASTIO_D3(a,b,6), CPLIB_FASTIO_D3(a,b,7), CPLIB_FASTIO_D3(a,b,8), CPLIB_FASTIO_D3(a,b,9)
    #define CPLIB_FASTIO_D1(a) CPLIB_FASTIO_D2(a,0), CPLIB_FASTIO_D2(a,1), CPLIB_FASTIO_D2(a,2), CPLIB_FASTIO_D2(a,3), CPLIB_FASTIO_D2(a,4), CPLIB_FASTIO_D2(a,5), CPLIB_FASTIO_D2(a,6), CPLIB_FASTIO_D2(a,7), CPLIB_FASTIO_D2(a,8), CPLIB_FASTIO_D2(a,9)
    static const cplib_fio_FourDigits cplib_fio_four_digit_table = {{
      CPLIB_FASTIO_D1(0), CPLIB_FASTIO_D1(1), CPLIB_FASTIO_D1(2), CPLIB_FASTIO_D1(3), CPLIB_FASTIO_D1(4), CPLIB_FASTIO_D1(5), CPLIB_FASTIO_D1(6), CPLIB_FASTIO_D1(7), CPLIB_FASTIO_D1(8), CPLIB_FASTIO_D1(9)
    }};
    #undef CPLIB_FASTIO_D1
    #undef CPLIB_FASTIO_D2
    #undef CPLIB_FASTIO_D3
    #undef CPLIB_FASTIO_D4
    
    static inline char* cplib_fio_reserve_bytes(FILE* output, size_t size) {
    #if defined(__GLIBC__)
      // stdio自身のバッファを使い、echo/write/flushFileとの出力順を保つ。
      if (output->_IO_write_ptr != NULL &&
          output->_IO_write_end != NULL &&
          (size_t)(output->_IO_write_end -
                                   output->_IO_write_ptr) >= size) {
        return output->_IO_write_ptr;
      }
    #endif
      return NULL;
    }
    
    static inline void cplib_fio_commit_bytes(FILE* output, char* end) {
    #if defined(__GLIBC__)
      output->_IO_write_ptr = end;
    #else
      (void)output;
      (void)end;
    #endif
    }
    
    static inline char* cplib_fio_write_small(char* output, unsigned value,
                             const cplib_fio_FourDigits* table) {
      if (value >= 1000) {
        memcpy(output, table->data[value], 4);
        return output + 4;
      }
      if (value >= 100) {
        memcpy(output, table->data[value] + 1, 3);
        return output + 3;
      }
      if (value >= 10) {
        memcpy(output, table->data[value] + 2, 2);
        return output + 2;
      }
      *output++ = ((char)('0' + value));
      return output;
    }
    
    static inline char* cplib_fio_write_four(char* output, unsigned value,
                            const cplib_fio_FourDigits* table) {
      memcpy(output, table->data[value], 4);
      return output + 4;
    }
    
    static inline char* cplib_fio_write_unsigned_32(char* output, uint32_t value,
                                   const cplib_fio_FourDigits* table) {
      if (value < 10000U) return cplib_fio_write_small(output, value, table);
      const uint32_t quotient = value / 10000U;
      const unsigned low = (unsigned)(value - quotient * 10000U);
      if (quotient < 10000U) {
        output = cplib_fio_write_small(output, quotient, table);
        return cplib_fio_write_four(output, low, table);
      }
      const unsigned high = quotient / 10000U;
      const unsigned middle = quotient - high * 10000U;
      output = cplib_fio_write_small(output, high, table);
      output = cplib_fio_write_four(output, middle, table);
      return cplib_fio_write_four(output, low, table);
    }
    
    static inline char* cplib_fio_write_unsigned_64(char* output, uint64_t value,
                                   const cplib_fio_FourDigits* table) {
      if (value < 10000ULL) {
        return cplib_fio_write_small(output, (unsigned)value, table);
      }
      const uint64_t quotient1 = value / 10000ULL;
      const unsigned chunk1 = (unsigned)(value - quotient1 * 10000ULL);
      if (quotient1 < 10000ULL) {
        output = cplib_fio_write_small(output, (unsigned)quotient1, table);
        return cplib_fio_write_four(output, chunk1, table);
      }
      const uint64_t quotient2 = quotient1 / 10000ULL;
      const unsigned chunk2 = (unsigned)(quotient1 - quotient2 * 10000ULL);
      if (quotient2 < 10000ULL) {
        output = cplib_fio_write_small(output, (unsigned)quotient2, table);
        output = cplib_fio_write_four(output, chunk2, table);
        return cplib_fio_write_four(output, chunk1, table);
      }
      const uint64_t quotient3 = quotient2 / 10000ULL;
      const unsigned chunk3 = (unsigned)(quotient2 - quotient3 * 10000ULL);
      if (quotient3 < 10000ULL) {
        output = cplib_fio_write_small(output, (unsigned)quotient3, table);
        output = cplib_fio_write_four(output, chunk3, table);
        output = cplib_fio_write_four(output, chunk2, table);
        return cplib_fio_write_four(output, chunk1, table);
      }
      const uint64_t quotient4 = quotient3 / 10000ULL;
      const unsigned chunk4 = (unsigned)(quotient3 - quotient4 * 10000ULL);
      output = cplib_fio_write_small(output, (unsigned)quotient4, table);
      output = cplib_fio_write_four(output, chunk4, table);
      output = cplib_fio_write_four(output, chunk3, table);
      output = cplib_fio_write_four(output, chunk2, table);
      return cplib_fio_write_four(output, chunk1, table);
    }
    
    typedef struct {
      char data[1U << 16];
      size_t length;
      FILE* output;
    } cplib_fio_BufferedWriter;
    
    static inline void cplib_fio_writer_flush(cplib_fio_BufferedWriter* writer) {
      // 保留中のバイト列を出力します。O(length)。
      if (writer->length != 0) {
        fwrite_unlocked(writer->data, 1, writer->length, writer->output);
        writer->length = 0;
      }
    }
    
    static inline void cplib_fio_writer_append(cplib_fio_BufferedWriter* writer, const char* source, size_t size) {
      // 必要に応じてフラッシュし、バイト列を追記します。O(size)。
      if (size <= sizeof(writer->data) - writer->length) {
        memcpy(writer->data + writer->length, source, size);
        writer->length += size;
        return;
      }
      cplib_fio_writer_flush(writer);
      if (size >= sizeof(writer->data)) {
        fwrite_unlocked(source, 1, size, writer->output);
      } else {
        memcpy(writer->data, source, size);
        writer->length = size;
      }
    }
    
    // 型・符号・桁数の分岐をコンパイル時に確定させます。
    #define CPLIB_FASTIO_OUTPUT(suffix, Integer, Unsigned, is_signed, write_unsigned) \
    static inline char* cplib_fio_format_##suffix(char* cursor, Integer value) { \
      Unsigned magnitude = (Unsigned)value; \
      if (is_signed && value < 0) { \
        *cursor++ = '-'; \
        magnitude = (Unsigned)0 - magnitude; \
      } \
      return write_unsigned(cursor, magnitude, &cplib_fio_four_digit_table); \
    } \
    static inline size_t cplib_fio_join_##suffix(const void* source, size_t count, char* output, \
                                       const char* separator, size_t separator_length) { \
      const Integer* values = (const Integer*)source; \
      char* cursor = output; \
      for (size_t i = 0; i < count; ++i) { \
        cursor = cplib_fio_format_##suffix(cursor, values[i]); \
        if (i + 1 != count) { \
          memcpy(cursor, separator, separator_length); \
          cursor += separator_length; \
        } \
      } \
      return (size_t)(cursor - output); \
    } \
    static inline void cplib_fio_print_array_##suffix(FILE* output, const void* source, size_t count, \
                                            const char* separator, size_t separator_length) { \
      const Integer* values = (const Integer*)source; \
      cplib_fio_BufferedWriter writer; \
      writer.length = 0; \
      writer.output = output; \
      for (size_t i = 0; i < count; ++i) { \
        if (sizeof(writer.data) - writer.length < 21) cplib_fio_writer_flush(&writer); \
        char* cursor = cplib_fio_format_##suffix(writer.data + writer.length, values[i]); \
        writer.length = (size_t)(cursor - writer.data); \
        if (i + 1 != count) cplib_fio_writer_append(&writer, separator, separator_length); \
      } \
      cplib_fio_writer_append(&writer, "\n", 1); \
      cplib_fio_writer_flush(&writer); \
    } \
    static inline void cplib_fio_print_one_##suffix(FILE* output, Integer value) { \
      char buffer[22]; \
      char* reserved = cplib_fio_reserve_bytes(output, sizeof(buffer)); \
      char* begin = reserved == NULL ? buffer : reserved; \
      char* cursor = cplib_fio_format_##suffix(begin, value); \
      *cursor++ = '\n'; \
      if (reserved != NULL) cplib_fio_commit_bytes(output, cursor); \
      else fwrite_unlocked(buffer, 1, (size_t)(cursor - buffer), output); \
    }
    CPLIB_FASTIO_OUTPUT(i32, int32_t, uint32_t, true, cplib_fio_write_unsigned_32)
    CPLIB_FASTIO_OUTPUT(i64, int64_t, uint64_t, true, cplib_fio_write_unsigned_64)
    CPLIB_FASTIO_OUTPUT(u32, uint32_t, uint32_t, false, cplib_fio_write_unsigned_32)
    CPLIB_FASTIO_OUTPUT(u64, uint64_t, uint64_t, false, cplib_fio_write_unsigned_64)
    #undef CPLIB_FASTIO_OUTPUT
    """.}
    
        template fastioOutputBindings(T: typedesc, suffix: static[string]) =
            proc fastioJoinInts(values: ptr T, count: csize_t, output: ptr char,
                    separator: cstring, separatorLen: csize_t): csize_t
                {.importc: "cplib_fio_join_" & suffix, nodecl, inject.}
            proc fastioPrintInts(output: File, values: ptr T, count: csize_t,
                    separator: cstring, separatorLen: csize_t)
                {.importc: "cplib_fio_print_array_" & suffix, nodecl, inject.}
            proc fastioPrintInt(output: File, value: T)
                {.importc: "cplib_fio_print_one_" & suffix, nodecl, inject.}
        fastioOutputBindings(int32, "i32")
        fastioOutputBindings(int64, "i64")
        fastioOutputBindings(uint32, "u32")
        fastioOutputBindings(uint64, "u64")
    
        template fastioOutputType(T: typedesc): typedesc =
            when T is SomeSignedInt:
                when sizeof(T) <= 4: int32
                else: int64
            else:
                when sizeof(T) <= 4: uint32
                else: uint64
    
        proc print_internal(prop: tuple[f: File, sepc: string, endc: string,
                flush: bool], args: openArray[string]) =
            for i in 0 ..< args.len:
                prop.f.write(args[i])
                if i != args.len - 1:
                    prop.f.write(prop.sepc)
                else:
                    prop.f.write(prop.endc)
            if prop.flush:
                prop.f.flushFile()
    
        proc print*(prop: tuple[f: File, sepc: string, endc: string, flush: bool],
                args: varargs[string, `$`]) =
            print_internal(prop, args)
    
        proc fastioPrintWithSeparator(sep: string, args: varargs[string, `$`]) =
            print_internal((f: stdout, sepc: sep, endc: "\n", flush: false), args)
    
        proc fastioAppendInteger[T: SomeInteger](destination: var string, value: T) =
            var magnitude: uint64
            when T is SomeSignedInt:
                let signedValue = value.int64
                if signedValue < 0:
                    destination.add('-')
                    magnitude = uint64(-(signedValue + 1)) + 1'u64
                else:
                    magnitude = signedValue.uint64
            else:
                magnitude = value.uint64
    
            if magnitude == 0:
                destination.add('0')
                return
            var digits: array[20, char]
            var count = 0
            while magnitude != 0:
                digits[count] = char(ord('0') + int(magnitude mod 10))
                magnitude = magnitude div 10
                inc count
            while count != 0:
                dec count
                destination.add(digits[count])
    
        # 整数は4桁テーブルを使うC/C++共通フォーマッタへまとめて渡す。
        proc fastioJoinImpl[T](a: openArray[T], sep: string): string =
            when nimvm:
                result = newStringOfCap(a.len * 4)
                for i, value in a:
                    if i != 0:
                        result.add(sep)
                    when T is SomeInteger:
                        fastioAppendInteger(result, value)
                    else:
                        result.add($value)
            else:
                if a.len == 0:
                    return ""
                when T is SomeInteger and sizeof(T) in [4, 8]:
                    const digits = when sizeof(T) == 8: 20
                                   elif T is SomeSignedInt: 11
                                   else: 10
                    result = fastioNewStringUninit(
                        a.len * digits + (a.len - 1) * sep.len)
                    let written = fastioJoinInts(cast[ptr fastioOutputType(T)](unsafeAddr a[0]),
                        a.len.csize_t, addr result[0], sep.cstring, sep.len.csize_t)
                    result.setLen(written.int)
                elif compiles(T.umod()) and compiles(a[0].val()):
                    # Montgomery表現を含め、公開値へ正規化してから一括変換する。
                    var canonical = fastioNewSeqUninit(uint32, a.len)
                    for i, value in a:
                        canonical[i] = value.val.uint32
                    result = fastioJoinImpl(canonical, sep)
                else:
                    result = newStringOfCap(a.len * 4)
                    for i, value in a:
                        if i != 0:
                            result.add(sep)
                        when T is SomeInteger:
                            fastioAppendInteger(result, value)
                        else:
                            result.add($value)
    
        proc join*[T: not string](a: openArray[T], sep: string = ""): string {.inline.} =
            fastioJoinImpl(a, sep)
    
        proc fastioPrintArrayImpl[T](a: openArray[T], sep: string) =
            if a.len == 0:
                stdout.write('\n')
                return
            when T is SomeInteger and sizeof(T) in [4, 8]:
                fastioPrintInts(stdout, cast[ptr fastioOutputType(T)](unsafeAddr a[0]), a.len.csize_t,
                    sep.cstring, sep.len.csize_t)
            elif compiles(T.umod()) and compiles(a[0].val()):
                var canonical = fastioNewSeqUninit(uint32, a.len)
                for i, value in a:
                    canonical[i] = value.val.uint32
                fastioPrintArrayImpl(canonical, sep)
            else:
                stdout.write(fastioJoinImpl(a, sep))
                stdout.write('\n')
    
        proc fastioPrintOneImpl[T](value: T, sep: string) =
            when T is SomeInteger and sizeof(T) in [4, 8]:
                fastioPrintInt(stdout, fastioOutputType(T)(value))
            elif compiles(T.umod()) and compiles(value.val()):
                fastioPrintInt(stdout, value.val.uint32)
            else:
                fastioPrintWithSeparator(sep, value)
    
        proc fastioPrintIntegerMany[T: SomeInteger](sep: string,
                values: varargs[T]) =
            fastioPrintArrayImpl(values, sep)
    
        # Python風に print(*X) と書くと、Xを空白区切りで1行に出力する。
        template `*`*[T](values: openArray[T]): string =
            fastioJoinImpl(values, " ")
    
        proc fastioSeparatorString(sep: string | char): string {.inline.} =
            $sep
    
        # 最後の文字列引数をsepと誤認しないよう、名前付きsepはマクロで処理する。
        macro print*(args: varargs[untyped]): untyped =
            var sep = newLit(" ")
            var hasSep = false
            var values: seq[NimNode]
            for arg in args:
                if arg.kind == nnkExprEqExpr and arg[0].eqIdent("sep"):
                    if hasSep:
                        error("sep can only be specified once", arg)
                    sep = newCall(bindSym"fastioSeparatorString", arg[1])
                    hasSep = true
                else:
                    values.add(arg)
            var splatValues: NimNode
            if values.len == 1:
                if values[0].kind == nnkPrefix and values[0][0].eqIdent("*"):
                    splatValues = values[0][1]
                elif values[0].kind in nnkCallKinds and values[0].len == 3 and
                        values[0][0].eqIdent("fastioJoinImpl"):
                    # オーバーロード解決時に *values が先に展開された場合。
                    splatValues = values[0][1]
            if not splatValues.isNil:
                result = newCall(bindSym"fastioPrintArrayImpl", splatValues, sep)
            elif values.len == 1:
                result = newCall(bindSym"fastioPrintOneImpl", values[0], sep)
            else:
                let integerCall = newCall(bindSym"fastioPrintIntegerMany", sep)
                let fallbackCall = newCall(bindSym"fastioPrintWithSeparator", sep)
                for value in values:
                    integerCall.add(value)
                    fallbackCall.add(value)
                result = quote do:
                    when compiles(`integerCall`):
                        `integerCall`
                    else:
                        `fallbackCall`
            when defined(fastioInteractive):
                let output = result
                result = quote do:
                    `output`
                    flushFile(stdout)
    
    macro getSymbolName(x: untyped): string =
        x.toStrLit
    macro debug*(args: varargs[untyped]): untyped =
        when defined(debug):
            result = newNimNode(nnkStmtList, args)
            template prop(e: string = ""): untyped = (f: stderr, sepc: "", endc: e, flush: true)
            for i, arg in args:
                if arg.kind == nnkStrLit:
                    result.add(quote do: print(prop(), "\"", `arg`, "\""))
                else:
                    result.add(quote do: print(prop(": "), getSymbolName(`arg`)))
                    result.add(quote do: print(prop(), `arg`))
                if i != args.len - 1: result.add(quote do: print(prop(), ", "))
                else: result.add(quote do: print(prop(), "\n"))
        else:
            return (quote do: discard)
    #chmin,chmax
    template `max=`(x, y) =
        let yVal = y # yが計算式の場合に評価を1回にするため
        if x < yVal:
            x = yVal

    template `min=`(x, y) =
        let yVal = y
        if x > yVal:
            x = yVal
    proc chmin[T](x: var T, y: T):bool=
        if x > y:
            x = y
            return true
        return false
    proc chmax[T](x: var T, y: T):bool=
        if x < y:
            x = y
            return true
        return false
    #bit演算
    proc `%`*(x: int, y: int): int =
        result = x mod y
        if y > 0 and result < 0: result += y
        if y < 0 and result > 0: result += y
    proc `//`*(x: int, y: int): int{.inline.} =
        result = x div y
        if y > 0 and result * y > x: result -= 1
        if y < 0 and result * y < x: result -= 1
    proc `%=`(x: var int, y: int): void = x = x%y
    proc `//=`(x: var int, y: int): void = x = x//y
    proc `**`(x: int, y: int): int = x^y
    proc `**=`(x: var int, y: int): void = x = x^y
    proc `^`(x: int, y: int): int = x xor y
    proc `|`(x: int, y: int): int = x or y
    proc `&`(x: int, y: int): int = x and y
    proc `>>`(x: int, y: int): int = x shr y
    proc `<<`(x: int, y: int): int = x shl y
    proc `~`(x: int): int = not x
    proc `^=`(x: var int, y: int): void = x = x ^ y
    proc `&=`(x: var int, y: int): void = x = x & y
    proc `|=`(x: var int, y: int): void = x = x | y
    proc `>>=`(x: var int, y: int): void = x = x >> y
    proc `<<=`(x: var int, y: int): void = x = x << y
    proc `[]`(x: int, n: int): bool = (x and (1 shl n)) != 0
    #便利な変換
    proc `!`(x: char, a = '0'): int = int(x)-int(a)
    #定数
    # source: https://github.com/kemuniku/cplib/blob/d5d0fb671ed854ea197cb2e8f69df5702d31bae4/src/cplib/utils/constants.nim
    when not declared CPLIB_UTILS_CONSTANTS:
        const CPLIB_UTILS_CONSTANTS* = 1
        const INF32*: int32 = 1001000027.int32
        const INF64*: int = int(3300300300300300491)
    
    const INF = INF64
    #converter

    #range
    template mapIt*[T](s: Slice[T], op: untyped): untyped =
        block:
            let bounds = s
            type OutType = typeof((block:
                var it {.inject.}: T
                op), typeOfProc)
            var mapped: seq[OutType] = @[]
            when OutType is (proc):
                proc transform(value: T): OutType =
                    let it {.inject.} = value
                    op
                for value in bounds:
                    mapped.add(transform(value))
            else:
                for it {.inject.} in bounds:
                    mapped.add(op)
            mapped

    template filterIt*[T](s: Slice[T], pred: untyped): untyped =
        block:
            let bounds = s
            var filtered: seq[T] = @[]
            for it {.inject.} in bounds:
                if pred:
                    filtered.add(it)
            filtered

    iterator range(start: int, ends: int, step: int): int =
        var i = start
        if step < 0:
            while i > ends:
                yield i
                i += step
        elif step > 0:
            while i < ends:
                yield i
                i += step
    iterator range(ends: int): int = (for i in 0..<ends: yield i)
    iterator range(start: int, ends: int): int = (for i in
            start..<ends: yield i)

    proc dump[T](arr:seq[seq[T]])=
        for i in 0..<len(arr):
            echo arr[i]

    proc sum(slice:HSlice[int,int]):int=
        return (slice.a+slice.b)*len(slice)//2
    
    proc `<`[T](l,r:seq[T]):bool=
        for i in 0..<min(len(l),len(r)):
            if l[i] > r[i]:
                return false
            elif l[i] < r[i]:
                return true
        return len(l) < len(r)
    
    proc `<=`[T](l,r:seq[T]):bool=
        for i in 0..<min(len(l),len(r)):
            if l[i] > r[i]:
                return false
            elif l[i] < r[i]:
                return true
        return len(l) <= len(r)
    
    # char
    proc `+`(a:char,b:int):char=
        return char(int(a)+b)

    proc `-`(a,b:char):int=
        return int(a) - int(b)
    
    # Yes/No
    proc yes*(b: bool = true): void = print(if b: "Yes" else: "No")

    template dblock(body: untyped) =
        when defined(debug):
            block:
                body


var N,M = ii()
var ans = 0

var SP = initTable[string,int]()

for _ in range(N):
    var s = si()
    var p = ii()
    SP[s] = p

for i in range(M):
    var T = si()
    ans += SP[T]

print(ans)
0