提交记录 123898


用户 题目 状态 得分 用时 内存 语言 代码长度
saffah_cc_v41_260924 noi18a. 【NOI2018】归程 Accepted 100 210.197 ms 35184 KB C++17 27.65 KB
提交时间 评测时间
2026-10-03 15:56:54 2026-10-03 15:57:07
// noi18a 【NOI2018】归程 -- v4
// Kruskal tree -> DFS leaf order -> boundary array A0[b] = merge altitude at the boundary
// between DFS-adjacent leaves b,b+1.
// component(v,p) = maximal leaf interval around x=pos[v] whose internal boundaries all have
//                  A0 > p  (a boundary with A0 <= p blocks: its merging edge is flooded).
//   L = prevLE(x-1,p)+1,  R = nextLE(x,p),  answer = min dPos[L..R]
// Searches / range-min use SIMD scans over a 3-level 64-ary block structure.
#pragma GCC target("bmi2,lzcnt,popcnt")
#pragma GCC optimize("O2","align-functions=144","align-jumps=8","no-tree-loop-optimize","no-caller-saves","no-ssa-phiopt")
#ifdef LOCAL_TEST
#include <cstdio>
#include <cstdlib>
typedef unsigned long long u64;
typedef unsigned int u32;
typedef long long i64;
static char g_in[80 << 20];
static char g_out[80 << 20];
#else
typedef unsigned long long u64;
typedef unsigned int u32;
typedef long long i64;
#endif
#include <immintrin.h>
#define PHASE_TIMING 1

/* ---- RIG-ONLY INSTRUMENT.  `LOCAL_TEST` is defined ONLY by this lane's rig; the judge build
   does not define it, so every macro below compiles to nothing and the board artifact is the
   pristine kernel.  This is what makes `arm/*.cpp` both the measured and the posted file. ---- */
#ifdef LOCAL_TEST
static unsigned long long g_qf, g_qc, g_qn, g_pc[4];
#define RQN()    (g_qn++)
#define RQF()    (g_qf++)
#define RQC()    (g_qc++)
#define RPC(i,v) (g_pc[i] += (unsigned long long)(v))
#else
#define RQN()    ((void)0)
#define RQF()    ((void)0)
#define RQC()    ((void)0)
#define RPC(i,v) ((void)0)
#endif

#define MAXN 200005
#define MAXM 400005
#define MAXARC 800005
#define MAXND 400010
#define RBITS 10
#define RSIZE (1u << RBITS)
#define RMASK (RSIZE - 1)
#define SH1 6
#define MSK1 63
#define MAXB1 (MAXN / 64 + 128)   /* U1: a 64-aligned span read needs nb2*64 = 3136 entries */
#define MAXB2 128                 /* U1: the far L2A span reads 64 entries from base 0 */
static_assert(MAXB1 >= 3136, "U1: L1A/L1D span padding");
static_assert(MAXB2 >= 64, "U1: L2A/L2D span padding");

/* eln[] REMOVED: w is packed into the high 14 bits of krs[0][i].u (u<2^18, w<2^14). */
static u32 rka[MAXM], rkb[MAXM];
static u32 beg[MAXN + 2], curs[MAXN + 2], cnt[RSIZE + 1];
static u32 adj[MAXARC];
/* sz[] REMOVED: lo(c2) == Rr[c1]+1 in DFS leaf order; the descent carries lo. */
static u32 dist_[MAXN + 2];
static u64 heapp[MAXARC + 8];
// ---- MONOTONE RADIX HEAP (replaces the 4-ary binary heap above) ----
// Key = (u64)dist << 32 | vertex.  Keys are extracted in non-decreasing order, so a radix heap
// is exact.  33 buckets (0..32); bucket k holds keys sharing the top (32-k) bits with `rhs_last`.
// The node pool is APPEND-ONLY (never freed), so every push writes and every pop reads a slot in
// the most recently touched region -> no dependent-load chain and no random heap access at all.
/* ---- H1: CIRCULAR DIAL BUCKET QUEUE.  Width C = 2^14 (the kernel's own edge-weight format),
   occupancy bitmap for O(1)-amortised skipping, ZERO redistributions, NO key stored in the pool. */
#define RHNIL 0xFFFFFFFFu
#define DCBITS 14
#define DC (1u << DCBITS)
#define DCMASK (DC - 1u)
#define DNW (DC >> 6)
static u32 dl_head[DC];                     /* 64 KB: bucket -> pool index */
static u64 dl_bit[DNW];                     /* 2 KB: occupancy bitmap */
static u32 dl_pool[2 * MAXM + 8];           /* node -> vertex */
static u32 dl_nx[2 * MAXM + 8];             /* node -> next */
static u32 dl_np;
static u32 dl_cnt;                          /* nodes still IN the buckets */
static i64 dl_curd;                         /* the current minimum distance (exact) */
__attribute__((always_inline)) static inline void dl_reset(void) {
  dl_np = 0; dl_cnt = 0; dl_curd = 0;
  for (u32 k = 0; k < DC; k++) dl_head[k] = RHNIL;
  for (u32 k = 0; k < DNW; k++) dl_bit[k] = 0;
}
__attribute__((always_inline)) static inline void dl_push(u32 v, u32 d) {
  u32 b = d & DCMASK;                       /* ONE link write, no move, no bucket search */
  u32 ni = dl_np++;
  dl_pool[ni] = v; dl_nx[ni] = dl_head[b]; dl_head[b] = ni;
  dl_bit[b >> 6] |= (u64)1 << (b & 63u);
  dl_cnt++;
}
/* advance dl_curd to the smallest distance >= it that owns a non-empty bucket */
__attribute__((always_inline)) static inline void dl_advance(void) {
  u32 b = (u32)dl_curd & DCMASK;
  u32 w = b >> 6, off = b & 63u;
  u64 m = dl_bit[w] & (~0ull << off);
  /* ⛔ `ctz(m)` IS AN ABSOLUTE BIT POSITION, NOT A DELTA.  The bit at position `off + k`
     is the bucket `k` steps AHEAD of the current one, so the distance added is `ctz(m) - off`.
     Writing `ctz(m)` alone makes the pointer jump `off` buckets too far, it lands on an empty
     bucket, and the pop reads an `RHNIL` head.  (Caught by a runtime head check, not by the eye.) */
  if (m) { dl_curd += (i64)__builtin_ctzll(m) - (i64)off; return; }
  i64 add = (i64)(64u - off);
  for (u32 w2 = (w + 1u) & (DNW - 1u); ; w2 = (w2 + 1u) & (DNW - 1u)) {
    u64 m2 = dl_bit[w2];
    if (m2) { dl_curd += add + (i64)__builtin_ctzll(m2); return; }
    add += 64;
  }
}
__attribute__((always_inline)) static inline u32 dl_pop(u32 *dv) {
  u32 b = (u32)dl_curd & DCMASK;
  u32 n = dl_head[b];
  dl_head[b] = dl_nx[n];
  if (dl_head[b] == RHNIL) dl_bit[b >> 6] &= ~((u64)1 << (b & 63u));
  dl_cnt--;
  *dv = (u32)dl_curd;
  return dl_pool[n];
}
static u32 dsu[MAXND], alt_[MAXND], ch1[MAXND], ch2[MAXND], Rr[MAXND];
static u32 stk[MAXND];
/* posOf[] REMOVED: pos1 is captured during the DFS leaf enumeration. */
static u32 leafOf[MAXN];      /* DFS position -> vertex (posOf's inverse) */
/* (pos, zeroAlt[pos]) PACKED per VERTEX: the query's serial dependency chain becomes ONE load,
   and zeroAlt[] disappears entirely.  vinfo[v] lo32 = posOf[v], hi32 = zeroAlt[posOf[v]]. */
static u64 vinfo[MAXN + 2];
static u32 dPos[MAXN];
static u32 preD[MAXN], sufD[MAXN];
static u32 A0[MAXN];
static u32 L1A[MAXB1], L2A[MAXB2];
static u32 L1D[MAXB1], L2D[MAXB2];
/* S5: the skip structure.  PS[i] packs  hi32 = min A0[blkstart(i)..i] (prefix, for prevLE)
   and lo32 = min A0[i..blkend(i)] (suffix, for nextLE) -- ONE 8-byte load serves both. */
static u32 preAB[MAXB1], preLA[MAXB1], sufLA[MAXB1];
static u32 preSUP[MAXB2], sufSUP[MAXB2];
#define STK 12
static u32 st1[STK][MAXB1];
static u32 MB, nb1, nb2, nn;
struct KRRec { u32 key; u32 u; u32 v; };            /* key = ~eal : descending altitude */
static KRRec krs[2][MAXM];

#ifdef PHASE_TIMING
#include <cstdio>
static u64 ph[16];
static inline u64 rd() { return __builtin_ia32_rdtsc(); }
#define PH_START() u64 _t = rd()
#define PH_MARK(i) do { u64 _n = rd(); ph[i] += _n - _t; _t = _n; } while (0)
#define PH_DUMP() do { for (int _i = 0; _i < 16; _i++) if (ph[_i]) fprintf(stderr, "phase %d: %llu cycles\n", _i, (unsigned long long)ph[_i]); } while (0)
#else
#define PH_START()
#define PH_MARK(i)
#define PH_DUMP()
#endif

#ifdef LOCAL_TEST
static const unsigned char *ip_, *ie_;
static char *op_;
#else
struct DI {
  u64 abi;
  const char *s; u64 sn;
  char *o; u64 ol; u64 os;
  char *e; u64 el; u64 es;
  const char *IB; u64 IBl;
  char *OB; u64 OBl;
  u64 tsc;
} __attribute__((packed));
static DI *D;
static const unsigned char *ip_, *ie_;
static char *op_;
#endif

static inline u32 ni() {
  const unsigned char *p = ip_;
  u32 v = (u32)(*p++ - '0');
  while (p[0] > ' ' && p[1] > ' ') { v = v * 100u + (u32)((p[0]-'0')*10u + (p[1]-'0')); p += 2; }
  if (*p > ' ') v = v * 10 + (u32)(*p++ - '0');
  ip_ = p + 1;
  return v;
}

static const char D2[] =
  "00010203040506070809"
  "10111213141516171819"
  "20212223242526272829"
  "30313233343536373839"
  "40414243444546474849"
  "50515253545556575859"
  "60616263646566676869"
  "70717273747576777879"
  "80818283848586878889"
  "90919293949596979899";

static inline void pu32(u32 v) {
  char *o = op_;
  u32 k;
  if (v < 10u) k = 1; else if (v < 100u) k = 2; else if (v < 1000u) k = 3;
  else if (v < 10000u) k = 4; else if (v < 100000u) k = 5; else if (v < 1000000u) k = 6;
  else if (v < 10000000u) k = 7; else if (v < 100000000u) k = 8; else if (v < 1000000000u) k = 9;
  else k = 10;
  char *e = o + k;
  if (k & 1u) { e -= 1; *e = (char)('0' + (v % 10u)); v /= 10u; }
  while (v >= 100u) {
    u32 d = v / 100u, r = (v - d * 100u) * 2u;
    v = d; e -= 2;
    *(unsigned short *)e = *(const unsigned short *)(D2 + r);
  }
  if (v >= 10u) { u32 r = v * 2u; e -= 2; *(unsigned short *)e = *(const unsigned short *)(D2 + r); }
  else if (v) { e -= 1; *e = (char)('0' + v); }
  op_ = o + k;
}

// ---- SIMD scans (AVX2; see mk_qavx.py for why each shape was chosen) ----
#pragma GCC push_options
#pragma GCC target("avx2")
/* ---- U1: ONE branchless 64-bit predicate mask per scan (no loop, no exit branch) ---- */
__attribute__((always_inline)) static inline u64 lomask64(int n) {
  return (n >= 64) ? ~0ull : ((1ull << n) - 1ull);
}
/* 64 predicate bits for arr[base .. base+63]: bit k set iff arr[base+k] <= p.
   Signed compare, EXACTLY the semantics scanLeftLE/scanRightLE used. */
__attribute__((always_inline)) static inline u64 span64(const u32 *base, u32 p) {
  __m256i vp = _mm256_set1_epi32((int)p);
#define U1C(k) ((u32)~((u32)_mm256_movemask_ps(_mm256_castsi256_ps( \
        _mm256_cmpgt_epi32(_mm256_loadu_si256((const __m256i *)(base + (k))), vp)))) & 0xFFu)
  u64 m0 = (u64)U1C(0),  m1 = (u64)U1C(8),  m2 = (u64)U1C(16), m3 = (u64)U1C(24);
  u64 m4 = (u64)U1C(32), m5 = (u64)U1C(40), m6 = (u64)U1C(48), m7 = (u64)U1C(56);
#undef U1C
  return m0 | (m1 << 8) | (m2 << 16) | (m3 << 24) | (m4 << 32) | (m5 << 40) | (m6 << 48) | (m7 << 56);
}
/* rightmost j in [lo,hi] with arr[j] <= p  (base = lo & ~63, so the span is one aligned block) */
__attribute__((always_inline)) static inline int sqL(const u32 *arr, int lo, int hi, u32 p) {
  int base = lo & ~MSK1;
  u64 m = span64(arr + base, p) & lomask64(hi - base + 1) & ~lomask64(lo - base);
  return m ? (base + 63 - (int)__builtin_clzll(m)) : -1;
}
/* leftmost j in [lo,hi] with arr[j] <= p; hi+1 if none */
__attribute__((always_inline)) static inline int sqR(const u32 *arr, int lo, int hi, u32 p) {
  int base = lo & ~MSK1;
  u64 m = span64(arr + base, p) & lomask64(hi - base + 1) & ~lomask64(lo - base);
  return m ? (base + (int)__builtin_ctzll(m)) : hi + 1;
}
// ONE horizontal reduction for the whole block, not one per 8 elements.
static inline u32 scanMin(const u32 *arr, int lo, int hi) {
  __m256i vmin = _mm256_set1_epi32(0x7FFFFFFF);
  int j = lo;
  while (j + 7 <= hi) {
    vmin = _mm256_min_epi32(vmin, _mm256_loadu_si256((const __m256i *)(arr + j)));
    j += 8;
  }
  __m128i mn = _mm_min_epi32(_mm256_castsi256_si128(vmin), _mm256_extracti128_si256(vmin, 1));
  mn = _mm_min_epi32(mn, _mm_shuffle_epi32(mn, 0x4E));
  mn = _mm_min_epi32(mn, _mm_shuffle_epi32(mn, 0xB1));
  u32 m = (u32)_mm_cvtsi128_si32(mn);
  for (; j <= hi; j++) if (arr[j] < m) m = arr[j];
  return m;
}
/* ONE horizontal reduction for the WHOLE rangeMin, not one per block.
   The original reduced every partial/middle block separately: up to 4 reduce
   chains (~12 cycles each, fully serial) per scanning query.  Here the vector
   minima accumulate into a single vmin and the short scalar tails accumulate
   into `sm`; the two are combined once at the end.  Semantics are unchanged
   (the vector part still uses the signed min the original used; the tail
   accumulator is the same unsigned min; the final combine is `u32 <`). */
static const int MSKT[8][8] = {
 {0,0,0,0,0,0,0,0},{-1,0,0,0,0,0,0,0},{-1,-1,0,0,0,0,0,0},{-1,-1,-1,0,0,0,0,0},
 {-1,-1,-1,-1,0,0,0,0},{-1,-1,-1,-1,-1,0,0,0},{-1,-1,-1,-1,-1,-1,0,0},{-1,-1,-1,-1,-1,-1,-1,0}};
#define VINF _mm256_set1_epi32(0x7FFFFFFF)
/* The scalar tail (`for (; j <= hi; j++) if (arr[j] < *sm)`) is a SERIAL load+cmov
   chain of up to 7 steps per block, and rangeMin calls this up to four times per
   scanning query.  `_mm256_maskload_epi32` does NOT fault on masked-off lanes, so
   the tail can be absorbed into the vector min with no bounds risk at all. */
__attribute__((always_inline)) static inline __m256i vmin_upto(__m256i V, const u32 *arr, int lo, int hi) {
  int j = lo;
  while (j + 7 <= hi) { V = _mm256_min_epi32(V, _mm256_loadu_si256((const __m256i *)(arr + j))); j += 8; }
  int rem = hi - j + 1;
  if (rem > 0) {
    __m256i mk = _mm256_loadu_si256((const __m256i *)MSKT[rem]);
    __m256i x = _mm256_maskload_epi32((const int *)(arr + j), mk);
    V = _mm256_min_epi32(V, _mm256_blendv_epi8(VINF, x, mk));
  }
  return V;
}
static inline int min2(int a, int b) { return a < b ? a : b; }
__attribute__((always_inline)) static inline int prevLE(u32 i, u32 p) {
  int i0 = (int)i;
  int mb = (int)MB - 1;
  int b = i0 >> SH1;
  /* SOUND: PS[i].hi = min A0[blkstart(i) .. i].  If it exceeds p, NO index in
     [blkstart(i), i] qualifies, and [blkstart(i), i] ENDS at i -- so the in-block scan
     cannot win and is skipped.  (The unsound mirror of this test is F1's.) */
  /* U3: `L1A[b]` is min A0 over the WHOLE block b, which contains [blkstart(i0), i0]; if it
     exceeds p there is no in-block hit (SOUND).  L1A is 12.5 KB (L1); PS was 1.6 MB (L3). */
  if (L1A[b] <= p) { int r = sqL(A0, b << SH1, i0, p); if (r >= 0) return r; }
  if (b == 0 || preAB[b - 1] > p) return -1;   /* nothing anywhere in [0, i] */
  {
    int j = b - 1;
    int s = j >> SH1;
    if (preSUP[s] > p) return -1;
    if (preLA[j] <= p) {                        /* a L1A hit exists in [s<<6, j] */
      int r = sqL(L1A, s << SH1, j, p);
      if (r >= 0) return sqL(A0, r << SH1, min2((r << SH1) + MSK1, mb), p);
    }
    {
      int g = s - 1;
      if (g < 0) return -1;
      if (preSUP[g] > p) return -1;
      int r = sqL(L2A, 0, g, p);
      if (r < 0) return -1;
      int r1 = sqL(L1A, r << SH1, min2((r << SH1) + MSK1, (int)nb1 - 1), p);
      if (r1 < 0) return -1;
      return sqL(A0, r1 << SH1, min2((r1 << SH1) + MSK1, mb), p);
    }
  }
}
__attribute__((always_inline)) static inline int nextLE(u32 i, u32 p) {
  int i0 = (int)i;
  int mb = (int)MB - 1;
  int b = i0 >> SH1;
  int hi = min2((b << SH1) + MSK1, mb);
  /* U3 mirror: see prevLE. */
  if (L1A[b] <= p) { int r = sqR(A0, i0, hi, p); if (r <= hi) return r; }
  if (b + 1 >= (int)nb1) return (int)MB;
  {
    int j = b + 1;
    int s = j >> SH1;
    int hh = min2((s << SH1) + MSK1, (int)nb1 - 1);
    if (sufSUP[s] > p) return (int)MB;
    if (sufLA[j] <= p) {
      int r = sqR(L1A, j, hh, p);
      if (r <= hh) return sqR(A0, r << SH1, min2((r << SH1) + MSK1, mb), p);
    }
    {
      int g = s + 1;
      if (g >= (int)nb2) return (int)MB;
      if (sufSUP[g] > p) return (int)MB;
      int r = sqR(L2A, g, (int)nb2 - 1, p);
      if (r > (int)nb2 - 1) return (int)MB;
      int r1 = sqR(L1A, r << SH1, min2((r << SH1) + MSK1, (int)nb1 - 1), p);
      if (r1 > (int)nb1 - 1) return (int)MB;
      return sqR(A0, r1 << SH1, min2((r1 << SH1) + MSK1, mb), p);
    }
  }
}
__attribute__((always_inline)) static inline u32 rangeMin(u32 l, u32 r) {
  if (l == r) return dPos[l];                       // single-leaf component: no scan at all
  int bl = (int)(l >> SH1), br = (int)(r >> SH1);
  if (bl == br) return scanMin(dPos, (int)l, (int)r);
  /* ARM R2: partial dPos blocks via preD/sufD (1 load each, was up to 128 elements);
     the full-block middle via an O(1) sparse table over L1D (was up to 391 AVX2 steps). */
  u32 m = sufD[l]; { u32 b2 = preD[r]; if (b2 < m) m = b2; }
  if (bl + 1 <= br - 1) {
    u32 a = (u32)bl + 1u, b = (u32)br - 1u, len = b - a + 1u;
    int k = 31 - __builtin_clz(len);
    u32 x1 = st1[k][a], x2 = st1[k][b - (1u << k) + 1u];
    if (x1 < m) m = x1;
    if (x2 < m) m = x2;
  }
  return m;
}

/* ONE call instead of three.  prevLE/nextLE/rangeMin were separately `noinline`,
   so every scanning query paid three call/return pairs plus three independent
   register-allocation decisions; merged, the whole component search is one
   inlined region with the `x` value available from the start. */
__attribute__((noinline)) static u32 compMin(u32 x, u32 p, u32 MB_v, u32 n_v) {
  u32 Lb = (x == 0) ? 0 : (u32)(prevLE(x - 1, p) + 1);
  u32 Rb = (x >= MB_v) ? (n_v - 1) : (u32)nextLE(x, p);
  return rangeMin(Lb, Rb);
}
#pragma GCC pop_options

// radix sort of FUSED edge records: every access is sequential.  The old form
// sorted indices and then chased eal[src[i]] / eu[e] / ev[e] at random, which a
// paired ablation priced at 404M of this phase's 567M cycles (71%).
static u32 HST3[3][RSIZE];
static const KRRec *kruskal_sort(u32 m) {
  KRRec *src = krs[0], *dst = krs[1];
  for (int p = 0; p < 3; p++) for (u32 j = 0; j < RSIZE; j++) HST3[p][j] = 0;
  for (u32 i = 0; i < m; i++) {
    u32 k = src[i].key;
    HST3[0][k & RMASK]++; HST3[1][(k >> RBITS) & RMASK]++; HST3[2][(k >> (2 * RBITS)) & RMASK]++;
  }
  u32 nz[3];
  for (int p = 0; p < 3; p++) { u32 z = 0; for (u32 j = 0; j < RSIZE; j++) if (HST3[p][j]) z++; nz[p] = z; }
  for (int p = 0; p < 3; p++) { if (nz[p] < 2) continue; u32 a = 0; for (u32 j = 0; j < RSIZE; j++) { u32 c = HST3[p][j]; HST3[p][j] = a; a += c; } }
  for (int pass = 0; pass < 3; pass++) {
    if (nz[pass] < 2) continue;
    u32 shift = (u32)pass * RBITS;
    u32 *cur = HST3[pass];
    for (u32 i = 0; i < m; i++) { KRRec r = src[i]; dst[cur[(r.key >> shift) & RMASK]++] = r; }
    KRRec *t = src; src = dst; dst = t;
  }
  return src;
}

static u32 find_(u32 x) {
  while (dsu[x] != x) { dsu[x] = dsu[dsu[x]]; x = dsu[x]; }
  return x;
}
// The KRT union loop calls find_ TWICE per edge on two INDEPENDENT chains, and dsu[] is a
// 1.6 MB array walked at RANDOM.  Two serial chains expose one random-load latency at a
// time; running them in lockstep exposes two.  Path-halving semantics are byte-identical.
static inline void find2_(u32 x, u32 y, u32 *rx, u32 *ry) {
  for (;;) {
    u32 px = dsu[x], py = dsu[y];
    int fx = (px == x), fy = (py == y);
    if (fx) *rx = x; else { dsu[x] = px = dsu[px]; x = px; }
    if (fy) *ry = y; else { dsu[y] = py = dsu[py]; y = py; }
    if (fx & fy) return;
  }
}


// --- ARM fastmod: the query decode did two 64-bit `%` with RUNTIME divisors per query, which a
// timing-only ablation priced at 30-45 cycles of the 106-117-cycle decode (~35 % of it, ~3 % of the
// row).  Both divisors are loop-invariant, so Lemire's fastmod (one 128-bit multiply) replaces each
// division.  Exact for every x < 2^64 and d < 2^63; one conditional correction.
static u64 g_Mn, g_Ms;
__attribute__((always_inline)) static inline u64 fastmod(u64 x, u64 d, u64 M) {
  u64 q = (u64)(((__uint128_t)M * x) >> 64);
  u64 r = x - q * d;
  return r < d ? r : r - d;
}
static void solve() {
  u32 T = ni();
  while (T--) {
    PH_START();
    u32 n = ni(), m = ni();
    // PARSE STRAIGHT INTO THE FUSED RECORD.  krs[0] is built from eu/ev/eal one pass later
    // anyway, so writing them into a separate trio of arrays first is pure duplication:
    // it costs a full 12 B/record WRITE plus a 12 B/record READ of arrays that exist for
    // nothing else.  The fused record is 12 B, so the write volume is IDENTICAL -- what
    // goes away is eu/ev/eal entirely (4.7 MB of touched .bss) and one whole pass.
    // ORDER MATTERS: the CSR below reads krs[0], and the radix sort destroys it, so CSR
    // must run first -- it already does.
    for (u32 i = 1; i <= n; i++) beg[i] = 0;
    for (u32 i = 0; i < m; i++) {
      u32 _u = ni(), _v = ni(), _w = ni();
      beg[_u]++; beg[_v]++;
      krs[0][i].u = _u | (_w << 18); krs[0][i].v = _v; krs[0][i].key = ~ni();
    }
    u32 Q = ni(), K = ni(), S = ni();
    PH_MARK(0);

    // ---- CSR ----
    {
      u32 s = 0;
      for (u32 i = 1; i <= n; i++) { u32 c = beg[i]; beg[i] = s; curs[i] = s; s += c; }
      beg[n + 1] = s; curs[n + 1] = s;
      for (u32 i = 0; i < m; i++) {
        u32 a = krs[0][i].u & 262143u, b = krs[0][i].v, w = krs[0][i].u >> 18;
        u32 pi = curs[a]++; adj[pi] = b | (w << 18);
        u32 pj = curs[b]++; adj[pj] = a | (w << 18);
      }
    }
    PH_MARK(1);

    // ---- Dijkstra from 1 ----
    const u32 INF = 3000000000u;
    for (u32 i = 1; i <= n; i++) dist_[i] = INF;
    dist_[1] = 0;
    {
      dl_reset();
      dl_push(1u, 0u);
      while (dl_cnt) {
        dl_advance();
        u32 d; u32 u = dl_pop(&d);
        if (dist_[u] != d) continue;      /* stale: H1's exact test (see the invariant above) */
        u32 e = beg[u], e2 = beg[u + 1];
        /* G1: the `e + 8 < e2` prefetch guard was tested on EVERY edge of the row's
           hottest loop while protecting only the last 8.  Split it. */
        u32 e8 = (e2 >= 8u) ? e2 - 8u : e;
        for (; e < e8; e++) {
          u32 a = adj[e];
          u32 v = a & 262143u;
          u32 nd = d + (a >> 18);
          _mm_prefetch((const char *)(dist_ + (adj[e + 8] & 262143u)), _MM_HINT_T0);
          if (nd < dist_[v]) {
            dist_[v] = nd;
            dl_push(v, nd);
          }
        }
        for (; e < e2; e++) {
          u32 a = adj[e];
          u32 v = a & 262143u;
          u32 nd = d + (a >> 18);
          if (nd < dist_[v]) {
            dist_[v] = nd;
            dl_push(v, nd);
          }
        }
      }
    }
    PH_MARK(2);

    // ---- KRT ----
    for (u32 i = 1; i <= n; i++) { dsu[i] = i; alt_[i] = 0xFFFFFFFFu; }
    u32 N = n;
    if (m) {
      const KRRec *rs = kruskal_sort(m);
      /* G2: guard split, same as G1. */
      u32 i = 0, im = (m >= 8u) ? m - 8u : 0u;
      for (; i < im; i++) {
        u32 a, b; find2_(rs[i].u & 262143u, rs[i].v, &a, &b);
        if (a != b) {
          u32 w = ++N;
          ch1[w] = a; ch2[w] = b;
          alt_[w] = ~rs[i].key;
          dsu[a] = w; dsu[b] = w; dsu[w] = w;
        }
      }
      for (; i < m; i++) {
        u32 a, b; find2_(rs[i].u & 262143u, rs[i].v, &a, &b);
        if (a != b) {
          u32 w = ++N;
          ch1[w] = a; ch2[w] = b;
          alt_[w] = ~rs[i].key;
          dsu[a] = w; dsu[b] = w; dsu[w] = w;
        }
      }
    }
    PH_MARK(3);

    // ---- DFS leaf order + boundary array ----
    u32 pos1 = 0;
    {
      u32 sp = 0;
      stk[sp++] = N;
      u32 c = 0;
      while (sp) {
        u32 u = stk[--sp];
        if (u <= n) {
          if (u == 1) pos1 = c;
          leafOf[c] = u;
          dPos[c] = dist_[u];
          Rr[u] = c;
          c++;
        } else {
          stk[sp++] = ch2[u]; stk[sp++] = ch1[u];
        }
      }
    }
    for (u32 u = n + 1; u <= N; u++) {
      Rr[u] = Rr[ch2[u]];
      A0[Rr[ch1[u]]] = alt_[u];
    }
    // zeroAlt[pos] = altitude of LCA(leaf at pos, leaf of vertex 1); +inf if pos == pos1
    {
      /* The ranges below cover EVERY position except pos1, whose only vertex is v=1 (leafOf[pos1]==1).
         So one store seeds it and no full-array init pass is needed.  posOf[leafOf[i]] == i, so the
         packed word is built with no extra load and no read-modify-write. */
      vinfo[1] = (0xFFFFFFFFull << 32) | (u64)pos1;
      u32 u = N; u32 lo = 0;
      while (u > n) {
        u32 c1 = ch1[u], c2 = ch2[u];
        u32 mid = Rr[c1];                 /* last leaf of c1; c2's leaves start at mid+1 */
        if (pos1 <= mid) {
          u32 hi = Rr[c2];
          for (u32 i = mid + 1; i <= hi; i++) { u32 v = leafOf[i]; vinfo[v] = ((u64)alt_[u] << 32) | (u64)i; }
          u = c1;
        } else {
          for (u32 i = lo; i <= mid; i++) { u32 v = leafOf[i]; vinfo[v] = ((u64)alt_[u] << 32) | (u64)i; }
          lo = mid + 1; u = c2;
        }
      }
    }
    PH_MARK(4);

    // ---- block minima ----
    nn = n; MB = n - 1;
    nb1 = (MB + MSK1) >> SH1;
    nb2 = (nb1 + MSK1) >> SH1;
    {
      for (u32 j = 0; j < nb1; j++) {
        u32 lo = j << SH1, hi = lo + MSK1; if (hi >= nn) hi = nn - 1;
        u32 m1 = 0xFFFFFFFFu, m2 = 0xFFFFFFFFu;
        for (u32 i = lo; i <= hi; i++) { u32 d = dPos[i]; if (d < m1) m1 = d; preD[i] = m1; }
        for (u32 i = hi + 1; i > lo; ) { i--; u32 d = dPos[i]; if (d < m2) m2 = d; sufD[i] = m2; }
      }
      /* ---- S5 skip structure (EXACT) ---- */
      {
        u32 runp = 0xFFFFFFFFu;
        for (u32 j = 0; j < nb1; j++) {
          u32 lo = j << SH1, hi = lo + MSK1;
          u32 hiA = hi; if (hiA >= MB) hiA = MB - 1;
          u32 pre = 0xFFFFFFFFu;                     /* U3: PS's two halves are both gone */
          for (u32 i = lo; i <= hiA; i++) { u32 d = A0[i]; if (d < pre) pre = d; }
          if (pre < runp) runp = pre;
          preAB[j] = runp;
        }
      }
      for (u32 j = 0; j < nb1; j++) {
        u32 lo = j << SH1, hi = lo + MSK1;
        u32 hiA = hi; if (hiA >= MB) hiA = MB - 1;
        L1A[j] = scanMin(A0, (int)lo, (int)hiA);
        u32 loD = lo; if (loD >= n) loD = n - 1;
        u32 hiD = hi; if (hiD >= n) hiD = n - 1;
        L1D[j] = scanMin(dPos, (int)loD, (int)hiD);
      }
      for (u32 j = 0; j < nb2; j++) {
        u32 lo = j << SH1, hi = lo + MSK1;
        if (hi >= nb1) hi = nb1 - 1;
        L2A[j] = scanMin(L1A, (int)lo, (int)hi);
        L2D[j] = scanMin(L1D, (int)lo, (int)hi);
      }
      /* preLA/sufLA are the WITHIN-SUPERBLOCK prefix/suffix minima of L1A, and
         preSUP/sufSUP the ACROSS-superblock ones.  All four are exact tests. */
      for (u32 s = 0; s < nb2; s++) {
        u32 lo = s << SH1, hi = lo + MSK1; if (hi >= nb1) hi = nb1 - 1;
        u32 pre = 0xFFFFFFFFu, suf = 0xFFFFFFFFu;
        if (lo <= hi) {
          for (u32 i = lo; i <= hi; i++) { u32 d = L1A[i]; if (d < pre) pre = d; preLA[i] = pre; }
          for (u32 i = hi + 1; i > lo; ) { i--; u32 d = L1A[i]; if (d < suf) suf = d; sufLA[i] = suf; }
        }
      }
      {
        u32 runp = 0xFFFFFFFFu;
        for (u32 s = 0; s < nb2; s++) { if (L2A[s] < runp) runp = L2A[s]; preSUP[s] = runp; }
        u32 runs = 0xFFFFFFFFu;
        for (u32 s = nb2; s > 0; ) { s--; if (L2A[s] < runs) runs = L2A[s]; sufSUP[s] = runs; }
      }
      for (u32 i = 0; i < nb1; i++) st1[0][i] = L1D[i];
      for (int k = 1; k < STK; k++) {
        u32 half = 1u << (k - 1);
        for (u32 i = 0; i < nb1; i++) {
          u32 a2 = st1[k - 1][i];
          u32 j2 = i + half;
          u32 b2 = (j2 < nb1) ? st1[k - 1][j2] : 0xFFFFFFFFu;
          st1[k][i] = a2 < b2 ? a2 : b2;
        }
      }
    }
    PH_MARK(5);

    g_Mn = (u64)(~0ull / (u64)n) + 1; g_Ms = (u64)(~0ull / ((u64)S + 1)) + 1;
    // ---- queries ----
    i64 lastans = 0;
    /* C_PF: software-pipeline the PARSE and issue a VALUE-SPECULATED prefetch of the next
       query's `vinfo` index.  With K = 1 the index is `v = (v0-1 + la) mod n + 1`; when the
       answer is 0 (measured 31.2 % of queries on br=2, 60.1 % on br=0) `la` IS 0, so the next
       index is exactly `v0next` and the prefetch is exact.  The prefetch is issued before
       `compMin` (~220 cycles of cover).  Cost when the speculation is wrong: one useless line
       in a 1.6 MB array.  The parse work is UNCHANGED -- only its position moves. */
    u32 v0 = 0, p0 = 0;
    if (Q) { v0 = ni(); p0 = ni(); }
    for (u32 qi = 0; qi < Q; qi++) {
      u32 v0n = 0, p0n = 0;
      if (qi + 1u < Q) { v0n = ni(); p0n = ni(); }
      _mm_prefetch((const char *)(vinfo + v0n), _MM_HINT_T0);
      u64 la = (u64)lastans;
      u32 v = (u32)fastmod((u64)(v0 - 1) + (u64)K * la, (u64)n, g_Mn) + 1;
      u32 p = (u32)fastmod((u64)p0 + (u64)K * la, (u64)S + 1, g_Ms);
      u64 vi = vinfo[v];
      RQN();
      u32 x = (u32)vi;
      u32 ans;
      if ((u32)(vi >> 32) > p) {
        ans = 0; RQF();
      } else {
        RQC(); ans = compMin(x, p, MB, n);
      }
      lastans = (i64)ans;
      pu32(ans); *op_++ = '\n';
      v0 = v0n; p0 = p0n;
    }
    PH_MARK(6);
  }
}

#ifdef LOCAL_TEST
int main() {
  size_t sn = fread(g_in, 1, sizeof(g_in), stdin);
  ip_ = (const unsigned char *)g_in; ie_ = ip_ + sn;
  op_ = g_out;
  solve();
  fwrite(g_out, 1, (size_t)(op_ - g_out), stdout);
  PH_DUMP();
  return 0;
}
#else
int main() { return 0; }
extern "C" void __libc_start_main(void *mmm, int argc, char **argv) {
  (void)mmm;
  unsigned long *p = (unsigned long *)(argv + argc + 1);
  while (*p) p++;
  p++;
  for (; p[0]; p += 2) if (p[0] == 0x6b637564UL) { D = (DI *)p[1]; break; }
  if (D) {
    ip_ = (const unsigned char *)D->s; ie_ = ip_ + D->sn; op_ = D->o;
    solve();
    D->os = (u64)(op_ - D->o);
  }
  __asm__ volatile("syscall" ::"a"(60), "D"(0) : "rcx", "r11", "memory");
  for (;;);
}
#endif

CompilationN/AN/ACompile OKScore: N/A

Testcase #139.15 us132 KBAcceptedScore: 5

Testcase #260.08 us240 KBAcceptedScore: 5

Testcase #391.04 us244 KBAcceptedScore: 5

Testcase #4123.97 us252 KBAcceptedScore: 5

Testcase #5913.42 us464 KBAcceptedScore: 5

Testcase #6142.282 ms26 MB + 596 KBAcceptedScore: 5

Testcase #7713.23 us440 KBAcceptedScore: 5

Testcase #8707.16 us444 KBAcceptedScore: 5

Testcase #9704.15 us440 KBAcceptedScore: 5

Testcase #10114.82 ms24 MB + 296 KBAcceptedScore: 5

Testcase #11116.488 ms24 MB + 300 KBAcceptedScore: 5

Testcase #12150.878 ms30 MB + 904 KBAcceptedScore: 5

Testcase #13151.029 ms30 MB + 892 KBAcceptedScore: 5

Testcase #14151.044 ms30 MB + 908 KBAcceptedScore: 5

Testcase #151.048 ms508 KBAcceptedScore: 5

Testcase #161.044 ms508 KBAcceptedScore: 5

Testcase #17152.121 ms30 MB + 904 KBAcceptedScore: 5

Testcase #18151.855 ms30 MB + 904 KBAcceptedScore: 5

Testcase #19210.197 ms34 MB + 324 KBAcceptedScore: 5

Testcase #20209.735 ms34 MB + 368 KBAcceptedScore: 5


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