提交记录 110390


用户 题目 状态 得分 用时 内存 语言 代码长度
saffah_cc_v41_260924 noi17b. 【NOI2017】蚯蚓排队 Accepted 100 252.976 ms 161724 KB C++17 20.10 KB
提交时间 评测时间
2026-09-29 08:22:28 2026-09-29 08:22:37
#pragma GCC optimize("O3")
#pragma GCC target("bmi,bmi2,popcnt,lzcnt")
// NOI2017 Day1 T2 -- 蚯蚓排队 (Earthworm queue)
// Counts of backwards strings of each length 1..50 kept in open-addressing tables.
//   merge : for x within last 49 of A, add strings (suffix of A at x)+(prefix of B), lengths d+1..min(50,d+|B|)
//   split : same computation, decrement
//   query : multiply counts of every length-k substring of s
// Optimisations:  (a) pre-scan finds which k values occur -> only those levels are maintained,
//                (b) per-level tables are sized to 2*(n-l+1) slots, packed in one pool,
//                (c) entry generation is batched and prefetched before the (latency bound) updates.
typedef unsigned char u8;
typedef unsigned int u32;
typedef unsigned long long u64;

static const u32 MOD = 998244353;
static const u64 HB = 0x9E3779B97F4A7C15ULL | 1ULL;
// hash must be mixed before splitting into index/key: key = hash>>18 alone would
// make strings differing in the last character (e.g. "12321" vs "12322") collide.
static const u64 HMM = 0x9E3779B97F4A7C15ULL;

#define MAXN 300005
#define MAXK 50
#define TMAXBITS 19
#define TMAXSIZE (1u << TMAXBITS)

static const u8 *gip;
static const u8 *gEND;
static u8 *gob;

static u64 POW[MAXK + 2];
// ---- CL1: PACKED NODE LINKS ----
// NV[x] = (NXT[x] << 3) | VAL[x] ;  PV[x] = (PRV[x] << 3) | VAL[x] ;  0 == no link.
// A chase step costs ONE random line instead of TWO (pointer + separate 300 KB VAL[]),
// and the A-side hash pass no longer re-reads VAL[xs[d-1]] at all.
static u32 NV[MAXN], PV[MAXN];
#define VALX(x) ((u32)((x) & 7u))

static u64 *TBL[MAXK + 1];
static u32 TMSK[MAXK + 1];
static u64 POOL[51ULL * TMAXSIZE];

// bits: bit s of SMASK[d] set iff level (d+s) is needed; SMAXD[d] = highest such s
static u64 SMASK[MAXK + 2];
static u32 SMAXD[MAXK + 2];
static u32 DMAXX;   // deepest worm distance that can still produce a needed entry
static u8 NEEDED[MAXK + 1];
static u32 KMIN;   // CL1: smallest queried level

// ---- input ----
static const u64 MASKV[9] = {0ULL, 0xFFULL, 0xFFFFULL, 0xFFFFFFULL, 0xFFFFFFFFULL,
                             0xFFFFFFFFFFULL, 0xFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFULL,
                             0xFFFFFFFFFFFFFFFFULL};
static const u64 INV5[9] = {1ULL,
                            0xCCCCCCCCCCCCCCCDULL, 0x8F5C28F5C28F5C29ULL, 0x1CAC083126E978D5ULL,
                            0xD288CE703AFB7E91ULL, 0x5D4E8FB00BCBE61DULL, 0x790FB65668C26139ULL,
                            0xE5032477AE8D46A5ULL, 0xC767074B22E90E21ULL};

static inline u32 rd() {
  // RIGHT-ALIGN the k digits by shifting t LEFT 8*(8-k) bits: the separator byte (t's
  // byte k) and everything after it shifts out of the 64-bit word, so the three-level
  // SWAR fusion then yields the value DIRECTLY -- no MASKV[]/INV5[] table loads, no >>j,
  // no in-table magic multiply.  Ported verbatim from work/noip17f_lane4/PF2.cpp rd()
  // (lines 43-62), where it is the shipped, row-minimum form.
  for (;;) {
    u64 x;
    __builtin_memcpy(&x, gip, 8);
    u64 t = x ^ 0x3030303030303030ULL;
    u64 mm = ((t + 0x7676767676767676ULL) | t) & 0x8080808080808080ULL;
    u32 k = mm ? (u32)(__builtin_ctzll(mm) >> 3) : 8u;
    if (k == 0) { gip++; continue; }
    u64 d = t << ((8u - k) << 3);
    u64 c1 = (d * 10 + (d >> 8)) & 0x00FF00FF00FF00FFULL;
    u64 c2 = (c1 * 100 + (c1 >> 16)) & 0x0000FFFF0000FFFFULL;
    u64 c3 = (c2 * 10000 + (c2 >> 32));
    gip += k + 1;
    return (u32)c3;
  }
}

static inline u32 swar_len(const u8 *p) {  // length of digit run
  u32 L = 0;
  for (;;) {
    u64 x;
    __builtin_memcpy(&x, p, 8);
    u64 m = (x - 0x3030303030303030ULL) & ~x & 0x8080808080808080ULL;
    if (m) return L + ((u32)__builtin_ctzll(m) >> 3);
    L += 8;
    p += 8;
  }
}

// ---- output ----
static const char HEXD[201] =
    "00010203040506070809101112131415161718192021222324252627282930313233343536373839"
    "40414243444546474849505152535455565758596061626364656667686970717273747576777879"
    "8081828384858687888990919293949596979899";

static inline void wr(u32 v) {
  u32 len;
  if (v < 10) len = 1;
  else if (v < 100) len = 2;
  else if (v < 1000) len = 3;
  else if (v < 10000) len = 4;
  else if (v < 100000) len = 5;
  else if (v < 1000000) len = 6;
  else if (v < 10000000) len = 7;
  else if (v < 100000000) len = 8;
  else len = 9;
  u8 *o = gob + len;
  u32 t = v;
  while (t >= 100) {
    u32 q = t / 100;
    u32 r = t - q * 100;
    o -= 2;
    __builtin_memcpy(o, HEXD + r * 2, 2);
    t = q;
  }
  if (t < 10) *--o = (u8)('0' + t);
  else { o -= 2; __builtin_memcpy(o, HEXD + t * 2, 2); }
  gob += len;
  *gob++ = '\n';
}

// ---- hash table ----
#ifdef CHECKING
static u64 LEVELSUM[MAXK + 1];
static u32 GOP;
static void verify(u32 n);
#endif

// CL1 PFUSE: `slot` is the address the EMIT already computed; `hh` is the already-
// multiplied key.  TBL[]/TMSK[] are needed only to wrap on a collision.
static inline void tupd(u64 *slot, u64 hh, u32 ell, long sgn) {
  u64 kk = hh >> 18;
  if (!kk) kk = 1;
  u64 e = *slot;
#if defined(CHECKING)
  if ((e >> 18) == kk) { LEVELSUM[ell] += sgn; *slot = e + sgn; return; }
  if (e == 0) { LEVELSUM[ell] += sgn; *slot = (kk << 18) + (u64)(sgn > 0 ? sgn : 1); return; }
#else
  if ((e >> 18) == kk) { *slot = e + sgn; return; }
  if (e == 0) { *slot = (kk << 18) + (u64)(sgn > 0 ? sgn : 1); return; }
#endif
  // CS1-17b PFHOIST: only reached on a COLLISION (load factor <= 0.5, so ~38 % of
  // calls).  TBL[ell] and TMSK[ell] are LOOP-INVARIANT, but the shipped loop
  // re-loads BOTH on every probe step -- two extra dependent loads sitting ON the
  // probe chain (`slot - T` cannot start until T has arrived).  Hoist them once and
  // the probe step becomes  idx=(idx+1)&msk;  slot=T+idx;  load *slot :  ONE load on
  // the chain instead of three.  The visited slot sequence is IDENTICAL.
  {
    u64 *T = TBL[ell];
    u32 idx = (u32)(slot - T);
    u32 msk = TMSK[ell];
    for (;;) {
      idx = (idx + 1) & msk;
      slot = T + idx;
      e = *slot;
#if defined(CHECKING)
      if ((e >> 18) == kk) { LEVELSUM[ell] += sgn; *slot = e + sgn; return; }
      if (e == 0) { LEVELSUM[ell] += sgn; *slot = (kk << 18) + (u64)(sgn > 0 ? sgn : 1); return; }
#else
      if ((e >> 18) == kk) { *slot = e + sgn; return; }
      if (e == 0) { *slot = (kk << 18) + (u64)(sgn > 0 ? sgn : 1); return; }
#endif
    }
  }
}

#ifndef QCH
#define QCH 128
#endif
static inline u32 tgetK(const u64 *T, u32 msk, u64 key) {
  u32 idx = (u32)key & msk; u64 kk = key >> 18; if (!kk) kk = 1;
  for (;;) { u64 e = T[idx]; if ((e >> 18) == kk) return (u32)(e & 0x3FFFF);
             if (!e) return 0; idx = (idx + 1) & msk; } }
static inline u32 tget(u32 ell, u64 key) {
  const u64 *T = TBL[ell];
  key *= HMM;
  u32 idx = (u32)key & TMSK[ell];
  u64 kk = key >> 18;
  if (!kk) kk = 1;
  for (;;) {
    u64 e = T[idx];
    if ((e >> 18) == kk) return (u32)(e & 0x3FFFF);
    if (e == 0) return 0;
    idx = (idx + 1) & TMSK[ell];
  }
}

// ---- merge / split update ----
#define MAXENT 1300
static u64 EKEY[MAXENT];
static u8 ELVL[MAXENT];
static u64 *EPF[MAXENT];

#ifdef PROF
static u64 T_UPD, T_QRY, T_PRE, T_PARSE, T_BUF;
static u32 N_UPD, N_QRY, N_ENT;
static inline u64 rdtp(){ unsigned a,d; __asm__ volatile("rdtsc":"=a"(a),"=d"(d)); return ((u64)d<<32)|a; }
#else
#define rdtp() 0
#endif

// Tail-suffix-hash cache: after a merge whose B side is a single worm the new tail
// is that worm, and TCH[q] caches the hash of the string of length q+1 ending at it.
// This removes the dependent PRV pointer walk for the very common "append one worm"
// pattern.  Invalidated by any split or by any multi-worm merge.
static u64 TCH[MAXK + 1];
static u32 TCT, TCN;

static inline void update(u32 i, u32 j, long sgn) {
#ifdef PROF
  u64 _t0 = rdtp(); N_UPD++;
#endif
  if (!DMAXX) return;  // only level 1 is queried: merges/splits change nothing
  u32 bv[MAXK + 1];
  u32 tb = 0;
  u8 av[MAXK + 2];   // CL1: A-chain VALUES (xs was used only as VAL[xs[d-1]])
  u32 D = 0;
  // ---- BX3: the B-side successor chain and the A-side predecessor chain are
  // INDEPENDENT, and the A-side index sequence does not depend on `tb` (only the
  // per-depth work below does).  Walk them CONCURRENTLY so both chains' misses are
  // in flight together instead of back to back.  Bit-identical output: `D` is the
  // original `d` at loop exit and xs[] is the same visit order.
  {
    u32 y = j, x = i;
    while ((y && tb < MAXK) || (x && D < DMAXX)) {
      if (y && tb < MAXK) { u32 _e = NV[y]; bv[tb++] = VALX(_e); y = _e >> 3; }
      if (x && D < DMAXX) { u32 _e = PV[x]; av[D++] = (u8)VALX(_e); x = _e >> 3; }
    }
  }
  u32 nent = 0;
  if (sgn > 0 && tb == 1 && TCN && i == TCT) {
    // fast path: append single worm j after i using the cached suffix hashes
    u32 vj = bv[0];   // CL1: == VAL[j] when tb == 1 (the walk stored it)
    u32 lim = TCN < MAXK ? TCN : MAXK - 1;
    for (u32 q = lim; q-- > 0;) {
      u64 hh = TCH[q] * HB + vj;
      TCH[q + 1] = hh;
      u32 lv = q + 2;
      if (NEEDED[lv]) {
        { u64 _h2 = hh * HMM; EPF[nent] = &TBL[lv][(u32)_h2 & TMSK[lv]]; EKEY[nent] = _h2; } ELVL[nent] = (u8)lv; nent++;
        ;
      }
    }
    TCH[0] = vj;
    TCN = (TCN < MAXK) ? TCN + 1 : MAXK;
    TCT = j;
#ifdef PROF
    T_BUF += rdtp() - _t0; N_ENT += nent; _t0 = rdtp();
#endif
    // CS1-17b PFW: the slot line is about to be READ-MODIFY-WRITTEN.  gcc-9 without
    // -march lowers `__builtin_prefetch(p,1)` to prefetcht0, not prefetchw, so the
    // write intent is expressed in inline asm (GOAL.md explicitly allows inline asm).
    { u32 _hl = nent < 34 ? nent : 34; for (u32 _h = 0; _h < _hl; _h++) __builtin_prefetch(EPF[_h]); for (u32 t = 0; t < nent; t++) { if (t + 34 < nent) { u64 *_w = EPF[t + 34]; __asm__ volatile("prefetchw %0" :: "m"(*_w)); } tupd(EPF[t], EKEY[t], ELVL[t], sgn); } }
#ifdef PROF
    T_UPD += rdtp() - _t0;
#endif
    return;
  }
  TCT = 0;                 // general path invalidates the cache
  if (D + tb < KMIN) return;   // CL1: no length d+s with d<=D, s<=tb can be a queried level
  u64 chbuf[MAXK + 1];     // suffix hashes of the walked region (for cache rebuild)
  // CS1-17b BSUF.  key(d,s) = h_d*HB^s + sum_{t<s} bv[t]*HB^{s-1-t} by construction, so the
  // shipped inner loop's running `key = key*HB + bv[s-1]` -- a SERIAL imul chain of length
  // s_hi, restarted from s = 1 for EVERY d -- is just re-deriving the same quantity.  Two
  // exact consequences:
  //   (1) level (d+s) is needed only for d+s >= KMIN, and NEEDED[] is zero below KMIN, so
  //       every s < KMIN-d iteration computed a partial key that `(need>>s)&1` DISCARDED.
  //       The loop now starts at s0 = max(1, KMIN-d); when s0 > s_hi the whole d is skipped.
  //   (2) the B-side prefix hashes BS[s] are built ONCE per update, so the loop body has no
  //       serial chain at all: key = h*POW[s] + BS[s].
  u64 BS[MAXK + 2];
  {
    u64 a = 0;
    BS[0] = 0;
    u32 sl = tb < MAXK ? tb : MAXK;
    for (u32 t = 0; t < sl; t++) { a = a * HB + bv[t]; BS[t + 1] = a; }
  }
  u64 h = 0;
  for (u32 d = 1; d <= D; d++) {   // deeper worms can never produce a needed level
    h = (u64)av[d - 1] * POW[d - 1] + h;  // prepend char x in front of the suffix string
    if (tb == 1) chbuf[d - 1] = h;
    u32 s_hi = SMAXD[d];
    if (s_hi) {
      if (s_hi > tb) s_hi = tb;
      u32 s0 = (KMIN > d) ? (KMIN - d) : 1u;
      if (s0 > s_hi) continue;   // no d+s with s in range can be a queried level
      u64 need = SMASK[d];
      for (u32 s = s0; s <= s_hi; s++) {
        u64 key = h * POW[s] + BS[s];
        if ((need >> s) & 1) {
          { u64 _h2 = key * HMM; EPF[nent] = &TBL[d + s][(u32)_h2 & TMSK[d + s]]; EKEY[nent] = _h2; }   // CL1 PFUSE
          ELVL[nent] = (u8)(d + s);
          nent++;
        }
      }
    }
  }
  if (sgn > 0 && tb == 1) {  // single-worm append: the new tail is j, rebuild the cache
    u32 vj = bv[0];   // CL1: == VAL[j] when tb == 1
    u32 lim = D < MAXK ? D : MAXK - 1;
    TCH[0] = vj;
    for (u32 q = 0; q < lim; q++) TCH[q + 1] = chbuf[q] * HB + vj;
    TCN = lim + 1;
    TCT = j;
  }
#ifdef PROF
  T_BUF += rdtp() - _t0; N_ENT += nent; _t0 = rdtp();
#endif
  // CS1-17b PFW: the slot line is about to be READ-MODIFY-WRITTEN.  gcc-9 without
    // -march lowers `__builtin_prefetch(p,1)` to prefetcht0, not prefetchw, so the
    // write intent is expressed in inline asm (GOAL.md explicitly allows inline asm).
    { u32 _hl = nent < 34 ? nent : 34; for (u32 _h = 0; _h < _hl; _h++) __builtin_prefetch(EPF[_h]); for (u32 t = 0; t < nent; t++) { if (t + 34 < nent) { u64 *_w = EPF[t + 34]; __asm__ volatile("prefetchw %0" :: "m"(*_w)); } tupd(EPF[t], EKEY[t], ELVL[t], sgn); } }
#ifdef PROF
  T_UPD += rdtp() - _t0;
#endif
}

// ---- query ----
static void solve() {
  POW[0] = 1;
  for (u32 i = 1; i <= MAXK; i++) POW[i] = POW[i - 1] * HB;
  u32 n = rd(), m = rd();
#ifdef CHECKING
  GOP = 0;
#endif
  for (u32 i = 1; i <= n; i++) { u32 _v = rd(); NV[i] = _v; PV[i] = _v; }

  // (a) pre-scan: which k values appear in queries
  for (u32 i = 0; i <= MAXK; i++) NEEDED[i] = 0;
#ifdef PROF
  u64 _p0 = rdtp();
#endif
  {
    const u8 *p = gip;
    while (p < gEND) {
      const u8 *ls = p;
      for (;;) {  // find end of line (SWAR)
        u64 x;
        __builtin_memcpy(&x, p, 8);
        u64 y = x ^ 0x0A0A0A0A0A0A0A0AULL;
        u64 mm = (y - 0x0101010101010101ULL) & ~y & 0x8080808080808080ULL;
        if (mm) { p += ((u32)__builtin_ctzll(mm) >> 3); break; }
        p += 8;
        if (p >= gEND) { p = gEND; break; }
      }
      if (*ls == '3') {
        const u8 *q = p - 1;
        if (q >= ls && *q == '\r') q--;
        u32 k = 0, mul = 1;
        while (q >= ls && *q >= '0' && *q <= '9') { k += (u32)(*q - '0') * mul; mul *= 10; q--; }
        if (k >= 1 && k <= MAXK) NEEDED[k] = 1;
      }
      p++;
    }
  }
#ifdef PROF
  T_PRE = rdtp() - _p0;
#endif
  // build level masks + sized tables
  for (u32 d = 0; d <= MAXK; d++) SMASK[d] = 0;
  for (u32 d = 1; d <= MAXK; d++) {
    u64 msk = 0;
    for (u32 s = 1; s + d <= MAXK; s++) if (NEEDED[s + d]) msk |= 1ULL << s;
    SMASK[d] = msk;
    SMAXD[d] = msk ? (u32)(63 - __builtin_clzll(msk)) : 0;
  }
  DMAXX = 0;
  for (u32 d = 1; d <= MAXK; d++) if (SMAXD[d]) DMAXX = d;
  KMIN = MAXK + 1;
  for (u32 l = 1; l <= MAXK; l++) if (NEEDED[l]) { KMIN = l; break; }   // CL1
  {
    // at level l there are at most min(n-l+1, 6^l) distinct strings, so the table
    // only needs twice that many slots (level 1 -> 32 slots, stays in L1)
    u64 *pool = POOL;
    u64 p6 = 6;
    for (u32 l = 1; l <= MAXK; l++) {
      u32 want = 5;
      u64 avail = (n + 1 > l) ? (u64)(n - l + 1) : 0;
      if (p6 < avail) avail = p6;
      if (avail) {
        u64 need = 2ULL * avail + 16;
        while ((1ULL << want) < need && want < TMAXBITS) want++;
      }
      TBL[l] = pool;
      TMSK[l] = (1u << want) - 1;
      pool += (1u << want);
      if (p6 < (1ULL << 40)) p6 *= 6;
    }
  }
  if (NEEDED[1]) {
    u32 c6[7] = {0, 0, 0, 0, 0, 0, 0};
    for (u32 i = 1; i <= n; i++) c6[VALX(NV[i])]++;
    for (u32 v = 1; v <= 6; v++) if (c6[v]) { u64 _h1 = (u64)v * HMM; tupd(&TBL[1][(u32)_h1 & TMSK[1]], _h1, 1, (long)c6[v]); }
  }
  for (u32 op = 0; op < m; op++) {
    u32 t = rd();
    if (t == 1) {
      u32 i = rd(), j = rd();
      update(i, j, 1);
      NV[i] = (j << 3) | VALX(NV[i]);   // CL1
      PV[j] = (i << 3) | VALX(PV[j]);
    } else if (t == 2) {
      u32 i = rd();
      u32 j = NV[i] >> 3;   // CL1
      if (j) update(i, j, -1);
      NV[i] &= 7u;
      if (j) PV[j] &= 7u;
    } else {
#ifdef PROF
      N_QRY++; u64 _q0 = rdtp();
#endif
      while (*gip <= 32) gip++;  // skip separator before s
      const u8 *ps = gip;
      u32 L = swar_len(ps);
      gip = ps + L;
      u32 k = rd();
      u64 res;
      if (k > MAXK) {
        res = 0;  // no worm has a string longer than 50
      } else {
        u64 pk = POW[k];
        u32 nw = L - k + 1;
        u64 acc = 1;
        // all length-k windows coincide iff every character of s is the same
        // (holds for the "all ones" test points) -> single lookup + power
        u32 same = 1;
        {
          const u8 c0 = ps[0];
          u64 pat = 0x0101010101010101ULL * (u64)c0;
          const u8 *a = ps;
          u32 rem = L;
          while (rem >= 8) {
            u64 x;
            __builtin_memcpy(&x, a, 8);
            if (x != pat) { same = 0; break; }
            a += 8; rem -= 8;
          }
          if (same) for (; rem; rem--) { if (*a++ != c0) { same = 0; break; } }
        }
        if (same) {
          u64 h = 0;
          for (u32 i = 0; i < k; i++) h = h * HB + (u64)(ps[i] - '0');
          u64 base = tget(k, h) % MOD;
          u64 r = 1, e = nw;
          while (e) { if (e & 1) r = r * base % MOD; base = base * base % MOD; e >>= 1; }
          acc = r;
        } else {
          const u8 *p = ps;
          u64 h1 = 0;
          for (u32 i = 0; i < k; i++) h1 = h1 * HB + (u64)(p[i] - '0');
          u32 i = 0;
          const u32 D = (TMSK[k] < (1u << 13)) ? 0 : 8;  // pipeline only for big tables
                    i = 0;
          { const u64 *_T = TBL[k]; const u32 _msk = TMSK[k];
            u32 _rem = nw, _stop = 0;
            while (_rem && !_stop) {
              u32 _e = _rem > QCH ? QCH : _rem;
              u64 _kk[QCH]; u64 _h = h1;
              for (u32 _j = 0; _j < _e; _j++) { _kk[_j] = _h * HMM; _h = _h * HB + (u64)(p[i + _j + k] - '0') - (u64)(p[i + _j] - '0') * pk; }
              for (u32 _j = 0; _j < _e; _j++) __builtin_prefetch(&_T[(u32)_kk[_j] & _msk]);
              for (u32 _j = 0; _j < _e; _j++) {
                u32 c = tgetK(_T, _msk, _kk[_j]);
                if (!c) { acc = 0; _stop = 1; break; }
                acc *= c;
                if (acc >= (1ULL << 45)) acc %= MOD;
              }
              h1 = _h; i += _e; _rem -= _e;
            } }
if (acc >= MOD) acc %= MOD;
        }
        res = acc;
      }
      wr((u32)res);
#ifdef PROF
      T_QRY += rdtp() - _q0;
#endif
    }
#ifdef CHECKING
    GOP++;
#ifdef CHECKALL
    verify(n);
#else
    if (op + 1 == m) verify(n);
#endif
#endif
  }
}

#ifdef CHECKING
#include <map>
#include <string>
#include <cstdio>
#include <cstdlib>
static void verify(u32 n) {
  static std::map<std::string, u32> cnt[MAXK + 1];
  for (u32 l = 1; l <= MAXK; l++) cnt[l].clear();
  for (u32 x = 1; x <= n; x++) {
    std::string s; u32 y = x;
    for (u32 l = 1; l <= MAXK; l++) {
      if (!y) break;
      s += (char)('0' + VALX(NV[y])); y = NV[y] >> 3;
      cnt[l][s]++;
    }
  }
  int bad = 0;
  for (u32 l = 1; l <= MAXK; l++) {
    if (!NEEDED[l]) continue;
    u64 tot = 0;
    {
      std::map<u64, std::string> seen;
      for (std::map<std::string, u32>::iterator it = cnt[l].begin(); it != cnt[l].end(); ++it) {
        u64 h = 0;
        for (size_t i = 0; i < it->first.size(); i++) h = h * HB + (u64)(it->first[i] - '0');
        std::map<u64, std::string>::iterator s2 = seen.find(h);
        if (s2 != seen.end()) {
          printf("  OP%u HASHCOLLISION level %u: %s vs %s\n", GOP, l,
                 it->first.c_str(), s2->second.c_str());
          bad = 1;
        } else seen[h] = it->first;
      }
    }
    for (std::map<std::string, u32>::iterator it = cnt[l].begin(); it != cnt[l].end(); ++it) {
      u64 h = 0;
      for (size_t i = 0; i < it->first.size(); i++) h = h * HB + (u64)(it->first[i] - '0');
      u32 got = tget(l, h);
      if ((u64)got != it->second) {
        printf("  OP%u level %u str %s table=%u true=%u\n", GOP, l, it->first.c_str(), got, it->second);
        bad = 1;
      }
      tot += it->second;
    }
    if (tot != LEVELSUM[l]) { printf("  OP%u level %u SUM table=%llu true=%llu\n", GOP, l,
                                     (unsigned long long)LEVELSUM[l], (unsigned long long)tot); bad = 1; }
  }
  if (bad) { printf("^^^ after op %u\n", GOP); exit(1); }
}
#endif

struct DUCKDI{unsigned long abi;const char*sp;unsigned long sn;char*op;unsigned long ol,os;char*ep;unsigned long el,es;const char*IB;unsigned long IBl;char*OB;unsigned long OBl;unsigned long tsc;}__attribute__((packed));
extern "C" void __libc_start_main(void*m,int argc,char**argv){
 unsigned long*p=(unsigned long*)(argv+argc+1);while(*p)p++;p++;
 DUCKDI*d=0;for(;p[0];p+=2)if(p[0]==0x6b637564UL){d=(DUCKDI*)p[1];break;}
 gip=(const u8*)d->sp; gob=(u8*)d->op; gEND=gip+d->sn;
 solve();
 d->os=(unsigned long)(gob-(u8*)d->op);
 __asm__ volatile("syscall"::"a"(60),"D"(0):"rcx","r11","memory");
 for(;;);
}
int main(){return 0;}

CompilationN/AN/ACompile OKScore: N/A

Testcase #132.09 us24 KBAcceptedScore: 4

Testcase #215.74 us40 KBAcceptedScore: 4

Testcase #32.718 ms64 KBAcceptedScore: 4

Testcase #477.33 us112 KBAcceptedScore: 4

Testcase #51.431 ms168 KBAcceptedScore: 4

Testcase #65.045 ms600 KBAcceptedScore: 4

Testcase #78.178 ms528 KBAcceptedScore: 4

Testcase #818.813 ms23 MB + 448 KBAcceptedScore: 4

Testcase #929.277 ms25 MB + 448 KBAcceptedScore: 4

Testcase #1041.641 ms32 MB + 528 KBAcceptedScore: 4

Testcase #1171.097 ms33 MB + 528 KBAcceptedScore: 4

Testcase #1211.254 ms1 MB + 888 KBAcceptedScore: 4

Testcase #1318.563 ms936 KBAcceptedScore: 4

Testcase #1446.425 ms54 MB + 840 KBAcceptedScore: 4

Testcase #1554.54 ms54 MB + 844 KBAcceptedScore: 4

Testcase #1697.26 ms68 MB + 1020 KBAcceptedScore: 4

Testcase #17129.946 ms68 MB + 1020 KBAcceptedScore: 4

Testcase #1868.506 ms3 MB + 440 KBAcceptedScore: 4

Testcase #1969.027 ms3 MB + 440 KBAcceptedScore: 4

Testcase #2021.913 ms5 MB + 608 KBAcceptedScore: 4

Testcase #2139.49 ms1 MB + 712 KBAcceptedScore: 4

Testcase #22105.511 ms113 MB + 600 KBAcceptedScore: 4

Testcase #23120.42 ms125 MB + 604 KBAcceptedScore: 4

Testcase #24228.415 ms157 MB + 956 KBAcceptedScore: 4

Testcase #25252.976 ms141 MB + 1008 KBAcceptedScore: 4


Judge Duck Online | 评测鸭在线
Server Time: 2026-10-01 07:17:44 | Loaded in 2 ms | Server Status
个人娱乐项目,仅供学习交流使用 | 捐赠