提交记录 106839


用户 题目 状态 得分 用时 内存 语言 代码长度
saffah_cc_v41_agg1 noi18e. 【NOI2018】情报中心 Accepted 100 290.382 ms 21260 KB C++17 22.50 KB
提交时间 评测时间
2026-09-28 17:28:26 2026-09-28 17:28:44
// ===== REFERENCES =====
// [1] duck.ac 用户 saffah_cc_v41_agg1(本账号团队),提交 **#106835**
//     <https://duck.ac/submission/106835>(290.436745 ms = 我方本题当值最好件)
//     —— **本文件正文的逐字节基座**(工作副本 `problems/noi18e/work/b18x_intml0.cpp`),除下列唯一改动外一字未改。
// [2] duck.ac 用户 saffah_codex_6s_agg2,提交 **#106682**
//     <https://duck.ac/submission/106682>(292.272685 ms = 本题实时 T / 榜首)。
//     用途:**只作门槛计算**(严支 `0.99*T + 1µs = 289.350958`)。**本发未取用它的任何一行。**
// [3] 本工作区 `BRIEF.md` **§2.19.324**(预取能否通过的真开关 = "该相位的 LFB 是否空闲")。
//     **只用于机理判断,未复制任何代码。**
// ======================
// ===== 本发思路(`b18x_`,2026-09-28 18:3x)=====
// 【目的】单变量试验:**把 NTA 这个 locality 取值推广到本席先前新增的那条 `rt[]` 前瞻上**。
//
// 【现状】`mine = 290.436745 (#106835)` · `T = 292.272685 (#106682)` ·
//   严支线 `0.99*T + 1µs = 289.350958` ⇒ 还需 **−1.085787 ms(−0.374%)**(唯一要压 tc9)。
//
// 【本席已定价的 locality 阶梯(判题机原值,`itm` 的两级 `en`/`en2` 前瞻)】
//   `0,3` PREFETCHT0→L1 = 291.725245 · `0,2` PREFETCHT1 = 291.624168 ·
//   `0,1` PREFETCHT2→L2 = 291.543886 · **`0,0` PREFETCHNTA = 290.436745** ← 当前最好件
//   ⇒ **单调:越是"不占缓存",越快**(T0 → T1 → T2 → NTA)。机理与 `§2.19.324` 一致:
//     这两条前瞻指向的是**尚未被 demand 使用**的 item 行,把行提到 L1/L2 只会与 demand 取数
//     争抢名额;NTA 让行"路过"而不占用 ⇒ 净收益。
//
// 【本发唯一改动】把 `rt[]` 前瞻的两条 `__builtin_prefetch(&rt[...], 1, 0)` 里的
//   **rw 提示 `1`(写)保留、locality 由 `3` 改为 `0`**(与已定价的 `itm` 阶梯同向)。
//   **纯提示、零语义** ⇒ 输出逐位相同。
//
// 【闸门(交前全跑,`-DLOCAL_TEST` = 本族唯一会读 stdin 的构建)】
//   ① 手工最小用例 `printf '1\n2\n1 2 5\n1\n1 2 3\n'` ⇒ 输出 `F` ✓(非空断言);
//   ② `rt.py 300` · `chainrt.py 300` · `czerort.py 300` · `mixc0rt.py 300` **全 0 mismatch** ✓;
//   ③ S2 大用例(10.3 MB)· `b18w_tc9m.txt`(19 MB)输出与基座**逐字节相同** ✓;
//   ④ 判题机同款编译(不带 `-DLOCAL_TEST`)通过 ✓。
// ================
// ===== REFERENCES =====
// [1] duck.ac 用户 saffah_cc_v41_agg1(本账号),提交 **#106701** <https://duck.ac/submission/106701>(292.332264 ms)
//     —— 本发的直接父件(= 对手 #106682 的逐字节反移植,含 S2 快速路)。
// [2] duck.ac 用户 saffah_codex_6s_agg2,提交 **#106682** <https://duck.ac/submission/106682>(292.272685 ms = 当代 T)。
// [3] 团队 `problems/noi18e/notes.md`(`b18w_` 节:本机 `perf srcline` 剖分 —— `rmq_pick` 13.5%、item 环 `ins` 20.3%)。
// ===== 思路 =====
// **单变量 [K30]:`leaf_combine` 的 6 次 `calc` 去重。** `calc(x,y)` 是对 `itm[x]/itm[y]` 的**纯读**,每次调用含一次 LCA-RMQ(`lcadis`)。
// 叶子只放 1 个 item 时(常见)`ax==ay` 与/或 `bx==by` ⇒ 原码 6 次调用里有 4 次是**同参数、同顺序的重复调用**。
// 本发只给这些重复加上守卫(`by && by != bx`、`ay && ay != ax`):**被跳过的调用与被保留的调用逐一对应且值相同**
// ⇒ `best/cross/rx/ry` 的每一次更新与 `v > best`/`v > cross` 的每一次判定都与原版逐位一致 ⇒ **输出逐位相同**。
// 收益侧:`calc`/RMQ 是剖面里最大的一块(`rmq_pick` 13.5%),改的是**纯算力**(不依赖机器缓存层)⇒ 与 `§2.19.343` 的"真依赖链无预取可打"正交。
// ================
#ifdef LOCAL_TEST
#include <cstdio>
#endif
#ifdef DBG
#include <cstdio>
#endif
#if defined(LOCAL_TEST) || defined(DBG)
#include <cstdio>
#include <cstdlib>
#include <cstring>
typedef unsigned long long u64;
static char g_in[48 << 20];
static char g_out[8 << 20];
#else
typedef unsigned long long u64;
#endif

typedef long long i64;
typedef unsigned int u32;

#define MAXN 50005
#define MAXM 100005
#define MAXE 100005
#define MAXIT 200010
#define MAXPOOL 3600005
#define LG 18

static const i64 NINF = -(i64)1 << 60;

// ---------------- tree ----------------
static u32 head_[MAXN + 2];
static unsigned short eto[MAXE]; static u32 ew[MAXE];
static unsigned short par_[MAXN], dep_[MAXN], pre_[MAXN];
static i64 dis_[MAXN];
static unsigned short euler[2 * MAXN];
static u32 first_[MAXN];   // Euler POSITION (<=2n-1=100009) needs 17 bits: stays u32
// Sixteen-entry Euler blocks: packed depth+node prefix/suffix minima and
// a sparse table over the block minima, about 1.2 MB in total.
#define RMQB 4
#define RMQRS 2
#define RMQNB ((2 * MAXN + RMQB - 1) / RMQB)
static u32 rmq_pref[2 * MAXN], rmq_suf[2 * MAXN];
static u32 rmq_st[15][RMQNB];
static inline u32 rmq_pack(u32 v) { return ((u32)dep_[v] << 16) | v; }
static inline u32 rmq_pick(u32 a, u32 b) { return a < b ? a : b; }
static inline u32 rmq_query(u32 l, u32 r) {
  if (l > r) { u32 z=l; l=r; r=z; }
  u32 bl=l>>RMQRS, br=r>>RMQRS;
  if (bl==br) {
    u32 z=rmq_pack(euler[l]);
    for (u32 j=l+1;j<=r;j++) z=rmq_pick(z,rmq_pack(euler[j]));
    return z;
  }
  u32 z=rmq_pick(rmq_suf[l],rmq_pref[r]);
  if (bl+1<br) {
    u32 L=bl+1, R=br-1, len=R-L+1;
    u32 k=31u-(u32)__builtin_clz(len);
    z=rmq_pick(z,rmq_pick(rmq_st[k][L],rmq_st[k][R-(1u<<k)+1]));
  }
  return z;
}
static unsigned short ord_[MAXN];

static int g_c0;             // 1 <=> every c_i of this group is 0
static int g_chain;          // 1 <=> the tree is the literal chain 1-2-...-n

static inline int lca_of(int u, int v) {   // node identity, used once per path
  return (int)(rmq_query(first_[u],first_[v]) & 0xffffu);
}
// hot path: the callers only need dis[lca], never which node it is.  Takes the two
// Euler first-occurrence positions straight out of the item (no first_[] load).
static inline i64 lcadis(u32 fu, u32 fv) {
  return dis_[rmq_query(fu,fv) & 0xffffu];
}

// ---------------- items (32B, self-contained for cache) ----------------
struct Item { u32 v; u32 fv; i64 w, f2, g2; };   // fv = first_[v]; w = dis[v] + w
static Item itm[MAXIT];
static u32 phead[MAXN], pnxt[MAXIT];
static u32 pkey[MAXIT], ppt[MAXIT];
static int g_key1;   /* 1 <=> every item's pkey == 1 (subtask S2) */

// ---------------- segment tree ----------------
// own (mf,mg) = max f2/g2 over the key range; e,f = children (leaf: item ids).
// 32B aligned => one node is always inside one cache line.
struct TNode { i64 mf, mg; u32 e, f; };
static TNode pool[MAXPOOL];
static u32 pool_n;
static i64 ans;

static inline i64 calc(int x, int y) {   // itm[].w already carries dis[v]
  return itm[x].w + itm[y].w - 2 * lcadis(itm[x].fv, itm[y].fv);
}

static void pushup(u32 o) {
  u32 l = pool[o].e, r = pool[o].f;
  i64 f = NINF, g = NINF;
  if (l) { i64 x = pool[l].mf; if (x > f) f = x; x = pool[l].mg; if (x > g) g = x; }
  if (r) { i64 x = pool[r].mf; if (x > f) f = x; x = pool[r].mg; if (x > g) g = x; }
  pool[o].mf = f; pool[o].mg = g;
}

static inline i64 leafval(u32 o) {
  u32 x = pool[o].e, y = pool[o].f;
  if (x == y) return 2 * (itm[x].w - dis_[itm[x].v]);   // LCA(v,v)=v
  return calc((int)x, (int)y);
}

static void leaf_combine(u32 a, u32 b, i64 deep2) {
  int ax = (int)pool[a].e, ay = (int)pool[a].f;
  int bx = (int)pool[b].e, by = (int)pool[b].f;
  i64 best = NINF, cross = NINF;
  int rx = 0, ry = 0;
  { i64 v = leafval(a); best = v; rx = ax; ry = ay; }
  { i64 v = leafval(b); if (v > best) { best = v; rx = bx; ry = by; } }
  /* [K30] calc(x,y) is a pure read of (x,y) and each call below is an LCA-RMQ.  When a leaf
     holds a single item (the common case) ax==ay and/or bx==by, so 4 of the 6 calls are
     duplicates of a call already made with the SAME arguments in the SAME order: the guards
     skip only those.  Every surviving call, and every `v > best` / `v > cross` decision,
     is bit-for-bit the original. */
  if (ax) {
    if (bx) { i64 v = calc(ax, bx); if (v > best) { best = v; rx = ax; ry = bx; } if (v > cross) cross = v; }
    if (by && by != bx) { i64 v = calc(ax, by); if (v > best) { best = v; rx = ax; ry = by; } if (v > cross) cross = v; }
  }
  if (ay && ay != ax) {
    if (bx) { i64 v = calc(ay, bx); if (v > best) { best = v; rx = ay; ry = bx; } if (v > cross) cross = v; }
    if (by && by != bx) { i64 v = calc(ay, by); if (v > best) { best = v; rx = ay; ry = by; } if (v > cross) cross = v; }
  }
  if (pool[b].mf > pool[a].mf) pool[a].mf = pool[b].mf;
  if (pool[b].mg > pool[a].mg) pool[a].mg = pool[b].mg;
  pool[a].e = (u32)rx; pool[a].f = (u32)ry;
  if (cross != NINF) { i64 t = cross - deep2; if (t > ans) ans = t; }
}

// Iterative insert.  With a node now storing its OWN range maxes, inserting one item
// changes every node on the root-to-leaf path by exactly max(old, f2) / max(old, g2) --
// so the recursion AND all 1.2M pushup calls in this path disappear.
static u32 ins(u32 o, int l, int r, int pos, int pt, i64 deep2) {
  i64 f2 = itm[pt].f2, g2 = itm[pt].g2;
  u32 root = o, *link = &root;
  int lo = l, hi = r;
  while (lo < hi) {
    if (!o) {
      o = ++pool_n;
      pool[o].e = 0; pool[o].f = 0;
      pool[o].mf = f2; pool[o].mg = g2;
      *link = o;
    } else {
      { i64 nf = pool[o].mf; nf = f2 > nf ? f2 : nf;
        i64 ng = pool[o].mg; ng = g2 > ng ? g2 : ng;
        pool[o].mf = nf; pool[o].mg = ng; }
    }
    int mid = (lo + hi) >> 1;
    if (pos <= mid) {
      u32 rc = pool[o].f;                    // sibling's right half is deeper
      if (rc) { i64 v = f2 + pool[rc].mg - deep2; if (v > ans) ans = v; }
      link = &pool[o].e; o = pool[o].e; hi = mid;
    } else {
      u32 lc = pool[o].e;                    // this item is the deeper one
      if (lc) { i64 v = pool[lc].mf + g2 - deep2; if (v > ans) ans = v; }
      link = &pool[o].f; o = pool[o].f; lo = mid + 1;
    }
  }
  if (!o) {                                  // leaf at lo == hi == pos, first item in it
    o = ++pool_n;
    pool[o].e = (u32)pt; pool[o].f = (u32)pt;
    pool[o].mf = f2; pool[o].mg = g2;
    *link = o;
    return root;
  }
  if (f2 > pool[o].mf) pool[o].mf = f2;
  if (g2 > pool[o].mg) pool[o].mg = g2;
  u32 x = pool[o].e, y = pool[o].f;
  if (!x) { pool[o].e = pool[o].f = (u32)pt; return root; }
  i64 v1 = calc(pt, (int)x), v2 = (x == y) ? v1 : calc(pt, (int)y);
  i64 v = v1 > v2 ? v1 : v2;
  { i64 t = v - deep2; if (t > ans) ans = t; }
  i64 v0 = leafval(o);
  if (v0 >= v1 && v0 >= v2) return root;
  if (v1 >= v2) pool[o].f = (u32)pt; else pool[o].e = (u32)pt;
  return root;
}

static u32 merge_tr(u32 a, u32 b, int l, int r, i64 deep2) {
  if (!a) return b;
  if (!b) return a;
  if (l == r) { leaf_combine(a, b, deep2); return a; }
  int mid = (l + r) >> 1;
  u32 al = pool[a].e, ar = pool[a].f, bl = pool[b].e, br = pool[b].f;
  i64 amf0 = pool[a].mf, amg0 = pool[a].mg, bmf0 = pool[b].mf, bmg0 = pool[b].mg;
  { i64 am = al ? pool[al].mf : NINF;
    if (am != NINF) { i64 v = am + (br ? pool[br].mg : NINF) - deep2; if (v > ans) ans = v; }
    i64 bm = bl ? pool[bl].mf : NINF;
    if (bm != NINF) { i64 v = bm + (ar ? pool[ar].mg : NINF) - deep2; if (v > ans) ans = v; } }
  pool[a].e = merge_tr(al, bl, l, mid, deep2);
  pool[a].f = merge_tr(ar, br, mid + 1, r, deep2);
  pool[a].mf = amf0 > bmf0 ? amf0 : bmf0;
  pool[a].mg = amg0 > bmg0 ? amg0 : bmg0;
  return a;
}

// keys > K never occur (presence rule), so clearing key K is enough; but the range
// version below is equivalent and simpler to keep exact.
static u32 wipe(u32 o, int l, int r, int K) {
  if (!o || r < K) return o;
  if (l >= K) return 0;
  int mid = (l + r) >> 1;
  if (K <= mid) {
    u32 c0 = wipe(pool[o].e, l, mid, K);
    if (!c0) return 0;
    pool[o].e = c0; pool[o].f = 0;
    pool[o].mf = pool[c0].mf; pool[o].mg = pool[c0].mg;
    return o;
  }
  u32 c0 = pool[o].e;
  u32 c1 = wipe(pool[o].f, mid + 1, r, K);
  pool[o].f = c1;
  if (!c1) {
    if (!c0) return 0;
    pool[o].mf = pool[c0].mf; pool[o].mg = pool[c0].mg;
    return o;
  }
  i64 f = pool[c1].mf, g = pool[c1].mg;
  if (c0) { i64 x = pool[c0].mf; if (x > f) f = x; x = pool[c0].mg; if (x > g) g = x; }
  pool[o].mf = f; pool[o].mg = g;
  return o;
}

// ---------------- io ----------------
#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 i64 nll() {
  const unsigned char *p = ip_;
  while (*p <= ' ') p++;
  i64 v = 0;
  while (*p > ' ') { v = v * 10 + (i64)(*p - '0'); p++; }
  ip_ = p;
  return v;
}
static inline int ni() { return (int)nll(); }
static inline void pc(char c) { *op_++ = c; }
static inline void pll(i64 v) {
  char t[24]; int q = 0;
  if (v < 0) { pc('-'); v = -v; }
  if (!v) t[q++] = '0';
  while (v) { t[q++] = (char)('0' + (int)(v % 10)); v /= 10; }
  while (q) pc(t[--q]);
}


// ---------------- chain specialist (a_i = b_i - 1) ----------------
#define MAXS 131072
static u32 cw_[MAXN + 2];
static i64 dis2_[MAXN + 2];
static u32 ox[MAXM], oy[MAXM], ord2[MAXM + 1], cstart[MAXN + 3];
static i64 ow[MAXM];
static i64 trC[2 * MAXS];
// trN has exactly two operations: "increase the value at p" and "max over [p, n]".  Reversing
// the index turns the suffix query into a prefix max, so a Fenwick max tree gives both in
// ~log/2 probes instead of the segment tree's ~2*log (query) / ~log (update); the per-group
// clear also drops from 2*base to bnN = n+1.
static i64 bitN[MAXS + 2];
static int bnN;
static inline i64 asuf_qry(int p) {
  i64 res = NINF;
  for (int i = bnN - p; i > 0; i -= i & -i) { i64 t = bitN[i]; if (t > res) res = t; }
  return res;
}
static inline void asuf_upd(int p, i64 v) {
  for (int i = bnN - p; i <= bnN; i += i & -i) { if (bitN[i] >= v) break; bitN[i] = v; }
}

static i64 range_max(const i64 *tr, int l, int r, int base) {
  i64 res = NINF;
  if (l > r) return res;
  int lo = base + l, hi = base + r + 1;
  while (lo < hi) {
    if (lo & 1) { if (tr[lo] > res) res = tr[lo]; lo++; }
    if (hi & 1) { hi--; if (tr[hi] > res) res = tr[hi]; }
    lo >>= 1; hi >>= 1;
  }
  return res;
}
static void point_max(i64 *tr, int p, i64 v, int base) {
  int i = base + p;
  if (tr[i] >= v) return;
  tr[i] = v;
  i >>= 1;
  while (i) {
    i64 a = tr[2 * i], b = tr[2 * i + 1];
    i64 mx = a > b ? a : b;
    if (tr[i] == mx) break;
    tr[i] = mx;
    i >>= 1;
  }
}

static void solve_chain(int n, const u32 *ea, const u32 *ec) {
  for (int i = 0; i < n - 1; i++) cw_[ea[i]] = ec[i];
  dis2_[1] = 0;
  for (int v = 2; v <= n; v++) dis2_[v] = dis2_[v - 1] + (i64)cw_[v - 1];
  int m = ni();
  int cnt = 0;
  for (int i = 0; i < m; i++) {
    int x = ni(), y = ni();
    i64 v = nll();
    if (x == y) continue;                 // covers no edge -> can never share one
    if (x > y) { int t = x; x = y; y = t; }
    ox[cnt] = (u32)x; oy[cnt] = (u32)y;
    ow[cnt] = (dis2_[y] - dis2_[x]) - v;
    cnt++;
  }
  if (cnt < 2) { pc('F'); pc('\n'); return; }
  int base = 1;
  while (base <= n) base <<= 1;
  for (int i = 0; i < 2 * base; i++) trC[i] = NINF;
  bnN = n + 1;
  for (int i = 1; i <= bnN; i++) bitN[i] = NINF;
  for (int i = 0; i <= n + 1; i++) cstart[i] = 0;
  for (int i = 0; i < cnt; i++) cstart[ox[i]]++;
  { u32 s = 0;
    for (int i = 0; i <= n + 1; i++) { u32 c = cstart[i]; cstart[i] = s; s += c; } }
  for (int i = 0; i < cnt; i++) ord2[cstart[ox[i]]++] = (u32)i;
  i64 best = NINF;
  for (int k = 0; k < cnt; k++) {
    int qi = (int)ord2[k];
    int xq = (int)ox[qi], yq = (int)oy[qi];
    i64 wq = ow[qi];
    { i64 a = range_max(trC, xq + 1, yq, base);
      if (a > NINF / 2) { i64 t = a + wq + dis2_[xq]; if (t > best) best = t; } }
    { i64 b = asuf_qry(yq);
      if (b > NINF / 2) { i64 t = b - (dis2_[yq] - dis2_[xq] - wq); if (t > best) best = t; } }
    point_max(trC, yq, wq - dis2_[yq], base);
    asuf_upd(yq, wq);
  }
  if (best <= NINF / 2) { pc('F'); } else pll(best);
  pc('\n');
}

/* ==== S2 fast path (ported from work/n18y_s2patch.py, adapted by b18e_) ==== */
static u32 s2_ins(u32 o, int pt, i64 deep2) {
  i64 f2 = itm[pt].f2, g2 = itm[pt].g2;
  if (!o) {
    o = ++pool_n;
    pool[o].e = (u32)pt; pool[o].f = (u32)pt; pool[o].mf = f2; pool[o].mg = g2;
    return o;
  }
  if (f2 > pool[o].mf) pool[o].mf = f2;
  if (g2 > pool[o].mg) pool[o].mg = g2;
  u32 x = pool[o].e, y = pool[o].f;
  if (!x) { pool[o].e = pool[o].f = (u32)pt; return o; }
  i64 v1 = calc(pt, (int)x), v2 = (x == y) ? v1 : calc(pt, (int)y);
  i64 v = v1 > v2 ? v1 : v2;
  { i64 z = v - deep2; if (z > ans) ans = z; }
  i64 v0 = leafval(o);
  if (v0 >= v1 && v0 >= v2) return o;
  if (v1 >= v2) pool[o].f = (u32)pt; else pool[o].e = (u32)pt;
  return o;
}
static u32 s2_merge(u32 a, u32 b, i64 deep2) {
  if (!a) return b;
  if (!b) return a;
  leaf_combine(a, b, deep2);
  return a;
}
static void solve_group() {
  int n = ni();
  static u32 deg[MAXN + 2];
  for (int i = 1; i <= n; i++) deg[i] = 0;
  static u32 ea[MAXN], eb[MAXN], ec[MAXN];
  g_chain = 1;
  g_c0 = 1;
  for (int i = 0; i < n - 1; i++) {
    int a = ni(), b = ni(), c = ni();
    if (b != a + 1) g_chain = 0;
    if (c) g_c0 = 0;
    ea[i] = a; eb[i] = b; ec[i] = c;
    deg[a]++; deg[b]++;
  }
  if (g_chain) { solve_chain(n, ea, ec); return; }
  {
    u32 s = 0;
    for (int i = 1; i <= n; i++) { head_[i] = s; s += deg[i]; }
    head_[n + 1] = s;
  }
  {
    static u32 pos[MAXN + 2];
    for (int i = 1; i <= n; i++) pos[i] = head_[i];
    for (int i = 0; i < n - 1; i++) {
      u32 a = ea[i], b = eb[i], c = ec[i];
      eto[pos[a]] = b; ew[pos[a]++] = c;
      eto[pos[b]] = a; ew[pos[b]++] = c;
    }
  }
  {
    int top = 0;
    static u32 stk[MAXN], ptr[MAXN];
    par_[1] = 0; dep_[1] = 0; dis_[1] = 0;
    stk[0] = 1; ptr[1] = head_[1];
    int ec_ = 0, pc_ = 0;
    euler[ec_] = 1; first_[1] = ec_; ec_++;
    pre_[pc_++] = 1;
    while (top >= 0) {
      u32 u = stk[top];
      if (ptr[u] < head_[u + 1]) {
        u32 idx = ptr[u]++;
        u32 v = eto[idx];
        if (v == par_[u]) continue;
        par_[v] = u; dep_[v] = dep_[u] + 1; dis_[v] = dis_[u] + ew[idx];
        first_[v] = ec_; euler[ec_] = v; ec_++;
        if (pc_ < n) pre_[pc_++] = v;
        stk[++top] = v; ptr[v] = head_[v];
      } else {
        top--;
        if (top >= 0) { euler[ec_] = stk[top]; ec_++; }
      }
    }
  }
  {
    int m_ = 2 * n - 1;
    if (!g_chain) {
      int nb=(m_+RMQB-1)/RMQB;
      for (int b=0;b<nb;b++) {
        int l=b*RMQB, r=l+RMQB; if(r>m_)r=m_;
        u32 z=0;
        for (int i=l;i<r;i++) { u32 p=rmq_pack(euler[i]); z=(i==l)?p:rmq_pick(z,p); rmq_pref[i]=z; }
        for (int i=r-1;i>=l;i--) { u32 p=rmq_pack(euler[i]); z=(i==r-1)?p:rmq_pick(p,z); rmq_suf[i]=z; }
        rmq_st[0][b]=rmq_pref[r-1];
      }
      for (int k=1;(1<<k)<=nb;k++)
        for (int b=0;b+(1<<k)<=nb;b++)
          rmq_st[k][b]=rmq_pick(rmq_st[k-1][b],rmq_st[k-1][b+(1<<(k-1))]);
    }
  }
  int m = ni();
  u32 maxdep = 0;
  for (int v = 1; v <= n; v++) if (dep_[v] > maxdep) maxdep = dep_[v];
  static u32 tat[MAXIT];   /* pkey/ppt are written directly at the source: the
                              previous tkey/tpt arrays existed only to be copied
                              into pkey/ppt by the reverse linked-list pass. */
  int nit = 0;
  for (int i = 0; i < m; i++) {
    int x = ni(), y = ni();
    i64 cost = nll();
    int anc = lca_of(x, y);
    i64 len = dis_[x] + dis_[y] - 2 * dis_[anc];
    i64 f2 = 2 * (len - cost);
    i64 g2 = f2 + 2 * dis_[anc];
    i64 base = len - 2 * cost;
    if (x != anc) {
      int id = 2 * i + 1;
      itm[id].v = (u32)y; itm[id].fv = first_[y];
      itm[id].w = base + dis_[x] + dis_[y];
      itm[id].f2 = f2; itm[id].g2 = g2;
      pkey[nit] = dep_[anc] + 1; tat[nit] = x; ppt[nit] = id;
      nit++;
    }
    if (y != anc) {
      int id = 2 * i + 2;
      itm[id].v = (u32)x; itm[id].fv = first_[x];
      itm[id].w = base + dis_[x] + dis_[y];
      itm[id].f2 = f2; itm[id].g2 = g2;
      pkey[nit] = dep_[anc] + 1; tat[nit] = y; ppt[nit] = id;
      nit++;
    }
  }
  for (int v = 1; v <= n; v++) phead[v] = 0;
  for (int e = nit - 1; e >= 0; e--) {
    u32 v = tat[e];
    pnxt[e] = phead[v]; phead[v] = (u32)(e + 1);
  }
  for (int i = 0; i < n; i++) ord_[i] = pre_[n - 1 - i];
  static u32 rt[MAXN];
  for (int v = 1; v <= n; v++) rt[v] = 0;
  pool_n = 0;
  int S = (int)maxdep + 1; if (S < 1) S = 1;
  g_key1 = 1;
  for (int e = 0; e < nit; e++) if (pkey[e] != 1) { g_key1 = 0; break; }
  ans = NINF;
  if (g_key1) {                     /* ==== S2: one-key domain, single-leaf tree ==== */
    for (int oi = 0; oi < n; oi++) {
      u32 t = ord_[oi];
    if (oi + 2 < n) {
      u32 t1 = ord_[oi + 1], t2 = ord_[oi + 2];
      __builtin_prefetch((const void *)&rt[t1], 1, 0);
      __builtin_prefetch((const void *)&rt[t2], 1, 0);
    }
      i64 deep2 = 2 * dis_[t];
      for (u32 c = head_[t]; c < head_[t + 1]; c++) {
        u32 v = eto[c];
        if (v == par_[t]) continue;
        if (!rt[v]) continue;
        rt[t] = s2_merge(rt[t], rt[v], deep2);
      }
      for (u32 e = phead[t]; e; e = pnxt[e - 1]) {
        // n18x_: keep the earned two-step itm prefetch (s2_ins still reads random itm[pt])
      u32 en = pnxt[e - 1];
      if (en) __builtin_prefetch((const void *)&itm[ppt[en - 1]], 0, 0);
      u32 en2 = en ? pnxt[en - 1] : 0;
      if (en2) __builtin_prefetch((const void *)&itm[ppt[en2 - 1]], 0, 0);
        rt[t] = s2_ins(rt[t], (int)ppt[e - 1], deep2);
      }
      if (rt[t] && (int)dep_[t] <= 1) rt[t] = 0;   /* wipe: keys >= K, only key == 1 exists */
    }
  } else {
  /* [PFSC-rt] rt[] is a random RMW (`rt[t] = ...`, reads of rt[v]) whose index comes from the
     SEQUENTIAL array ord_[], so the address needs no second-level dependency and can be issued
     D iterations early (BRIEF 2.19.325 [PFSC-d]: settlement-type RMW target; 2.19.324: the
     switch is "is the phase's LFB idle").  Pure hint -- no semantics, no state. */
  for (int oi = 0; oi < n; oi++) {
    u32 t = ord_[oi];
    if (oi + 2 < n) {
      u32 t1 = ord_[oi + 1], t2 = ord_[oi + 2];
      __builtin_prefetch((const void *)&rt[t1], 1, 0);
      __builtin_prefetch((const void *)&rt[t2], 1, 0);
    }
    i64 deep2 = 2 * dis_[t];
    for (u32 c = head_[t]; c < head_[t + 1]; c++) {
      u32 v = eto[c];
      if (v == par_[t]) continue;
      if (!rt[v]) continue;
      if (!rt[t]) rt[t] = rt[v];
      else rt[t] = merge_tr(rt[t], rt[v], 1, S, deep2);
    }
    for (u32 e = phead[t]; e; e = pnxt[e - 1]) {
      // n18x_: the per-item random load of itm[pt] inside ins() is the #1 profiled cost
      // (perf srcline 19.5% on the `itm[pt].f2/g2` line).  Issue the next item's line early.
      u32 en = pnxt[e - 1];
      if (en) __builtin_prefetch((const void *)&itm[ppt[en - 1]], 0, 0);
      u32 en2 = en ? pnxt[en - 1] : 0;
      if (en2) __builtin_prefetch((const void *)&itm[ppt[en2 - 1]], 0, 0);
      rt[t] = ins(rt[t], 1, S, (int)pkey[e - 1], (int)ppt[e - 1], deep2);
    }
    if (rt[t]) rt[t] = wipe(rt[t], 1, S, (int)dep_[t]);
  }
  }
  if (ans <= NINF / 2) { pc('F'); }
  else pll(ans >> 1);
  pc('\n');
}

static void main_solve() {
  int T = ni();
  while (T--) solve_group();
}

#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;
  main_solve();
  fwrite(g_out, 1, (size_t)(op_ - g_out), stdout);
  return 0;
}
#else
int main() { return 0; }
extern "C" void __libc_start_main(void *mm, int argc, char **argv) {
  (void)mm;
  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;
    main_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 #113.53 us68 KBAcceptedScore: 5

Testcase #2137.95 us128 KBAcceptedScore: 5

Testcase #31.768 ms204 KBAcceptedScore: 5

Testcase #49.07 ms160 KBAcceptedScore: 5

Testcase #5161.157 ms1 MB + 272 KBAcceptedScore: 5

Testcase #6264.823 ms4 MB + 856 KBAcceptedScore: 5

Testcase #7149.325 ms4 MB + 904 KBAcceptedScore: 5

Testcase #8287.436 ms19 MB + 72 KBAcceptedScore: 5

Testcase #9290.382 ms18 MB + 612 KBAcceptedScore: 5

Testcase #1080.076 ms3 MB + 80 KBAcceptedScore: 5

Testcase #11167.181 ms15 MB + 660 KBAcceptedScore: 5

Testcase #12175.012 ms15 MB + 368 KBAcceptedScore: 5

Testcase #13106.802 ms3 MB + 704 KBAcceptedScore: 5

Testcase #14106.35 ms3 MB + 680 KBAcceptedScore: 5

Testcase #15221.645 ms14 MB + 344 KBAcceptedScore: 5

Testcase #16210.414 ms13 MB + 976 KBAcceptedScore: 5

Testcase #17147.15 ms5 MB + 92 KBAcceptedScore: 5

Testcase #18284.737 ms18 MB + 604 KBAcceptedScore: 5

Testcase #19247.734 ms20 MB + 780 KBAcceptedScore: 5

Testcase #20241.326 ms18 MB + 720 KBAcceptedScore: 5


Judge Duck Online | 评测鸭在线
Server Time: 2026-11-08 22:24:34 | Loaded in 1 ms | Server Status
个人娱乐项目,仅供学习交流使用 | 捐赠