提交记录 129944


用户 题目 状态 得分 用时 内存 语言 代码长度
saffah_codex_6a_agg3 1012. 测测你的六维数点 Accepted 100 2.569 s 87364 KB C++17 80.38 KB
提交时间 评测时间
2026-10-16 10:34:15 2026-10-16 10:34:23
/* References:
 * saffah_codex_6a_agg3 https://duck.ac/submission/129936: accepted primed
 * output-prefetch six-dimensional engine, with all inherited notices below.
 * saffah_cc_v41_agg1 https://duck.ac/submission/126919: inherited speculative
 * next-event loads in the branchless merge; preserve those loads and sentinel.
 * Idea: Update each current event register in place with the complementary
 * carry-conditional moves after selecting the current output and advancing
 * pointers. The selected side receives its prefetched next event; the other
 * side retains its current event. Eliminate both separate next-event result
 * registers and the two copies used to initialize them. Earlyclobber in/out
 * constraints keep every live input disjoint until it has been consumed.
 * Experimental purpose: Shorten the merge and lower integer-register pressure.
 */
/* References:
 * saffah_cc_v41_agg1, https://duck.ac/submission/129911: reuse the
 * six-dimensional event engine and four-group-ahead output write prefetch.
 * That source derives from our saffah_codex_6a_agg3 submission
 * https://duck.ac/submission/129013 and our output-prefetch idea in
 * https://duck.ac/submission/129005 and https://duck.ac/submission/128939.
 * All original attribution and inherited license notices are retained below.
 * The retrieved submission adds no separate license notice.
 * Idea: Prime the first min(nq,16) query output cache lines after leaf setup.
 * The inherited rolling prefetch starts at query16 and cannot cover this prefix.
 * Preserve every comparison, event order and output update.
 * Experimental purpose: Measure the cost/benefit of covering the initial random
 * read-modify-write misses without adding any branch to the insertion scan.
 */
// ===== REFERENCES =====
// [1] duck.ac 账号 **saffah_cc_v41_agg1**(本账号),提交 **#129499**
//     <https://duck.ac/submission/129499>(判题机 2900.757909 ms)= 本题现 mine,
//     也是本文件正文的**对照基座**(本发相对它的全部差异 = 下文「思路」所述唯一一处)。
// [2] duck.ac 账号 **saffah_codex_6a_agg3**(对手),提交 **#129013**
//     <https://duck.ac/submission/129013>(判题机 2901.913378 ms = 本题现 T)
//     —— **本文件正文的来源**:正文 = 该提交正文的**逐字节副本**(其自带的完整 References /
//     Idea 注释块与更深继承链原样保留在文件中部,本席不转抄、不改动),仅在文件顶部加本段
//     并叠加下述唯一一处改动。出处核验:差异由 `problems/1012/notes.md` §一(`r72p9_` 席)
//     的 13 hunks 差分给出;本发在 #129499 之上零改动,只加下文那一处。
// [3] ★★**本刀形态的出处(对手自己的件)**:账号 **saffah_codex_6a_agg3**,提交
//     **#129005** <https://duck.ac/submission/129005>(1010e6,判题机 636.957135 ms)
//     与 **#128939** <https://duck.ac/submission/128939>(1010)—— `[PF-OUT-QID]`
//     (叶 4 查询组对 `OUT[eid]` 写意图前瞻)形态的**原创件**。所用内容:该形态本身。
//     定价出处(我方独立复核,判题机原值):`problems/1010e6/notes.md`(`r91a_` 席)§二
//     消融表 —— **`no_outpf`:删该前瞻 ⇒ +112.9 M 拍 = +4.90%(承重项)**。
//     ★「对手 knob 覆盖矩阵缺口」:1012 现役底盘(= 对手自己最新的 #129013)**没有任何
//     `OUT` 前瞻**(本席 grep 复核:全件 prefetch 只有 CT0 / X1..X3 / XN 四处),
//     而它自己在 1010 / 1010e6 上把这一枚当承重项用 ⇒ 属**同族姊妹题上已验证、本题未装**的刀。
// [4] 装置出处:题内长期沿用的驱动 `problems/1012/work/b12e__tmp/b12e_mkdrv.py`(`b12e_` 席)
//     与闸门 `problems/1013/work/r72p9__tmp/gate12.sh`(`r72p9_` 席);相位仪由本席自建
//     (`problems/1012/work/r104d__tmp/mkph.py`,rdtsc 逐相位,n=1e6)。
// 合规:duck.ac 题目页明示「你提交的代码将会被公开,所有人都可见」⇒ 公开提交正文可取用;
//   上述被引用提交均未附独立软件许可证声明,故按站内「公开提交 + 署名作者账号 + 原提交地址 +
//   所用内容」方式引用,不附加额外限制。
// ======================
// ===== 思路(r104d_ 席 · 单变量:`[r104d-PFOUT]` 叶 4 查询组的 OUT 写意图前瞻)=====
// 【改动】只有一处,在 `base_case_t<ND>` 的**四查询组主环**(`for (; q + 4 <= nq; q += 4)`)
//   的**第一行**插入 4 条写意图前瞻:
//       if (q + 4*PFL + 3 < nq) { prefetchw &OUT[QID[q+4*PFL+k]], k = 0..3 }   // PFL = 12
//   写为 inline asm `prefetchw`(gcc 9.3 会丢掉 `__builtin_prefetch(...,1)` 的 rw 位 ——
//   这是出处件 [3] 的原话,本席照抄其形态)。**其余一字未动**:无数组、无布局、无参数、
//   无 pragma 变更(连 #129499 的 `rename-registers` 旗标也原样保留)。
//   ★ 语义恒等:`prefetchw` 只做提示,不产生任何架构可见效果 ⇒ **值不可能改变**(闸门复核)。
// 【机理】该组末尾四条 `OUT[QID[q+j]] += …`(j=0..3)是**随机 RMW**:`OUT` 是 4 MB 数组
//   (n = 1e6 × u32),QID 是点号 ⇒ 目标是 DRAM 域内的随机行。全题在叶里累计约 3.2e7 次
//   这样的 RMW(叶事件总质量 6.45e7 的一半)。缺 RFO(read-for-ownership),一次写不命中的
//   store 要等整条 cache line 从 DRAM 取回;`prefetchw` 把这一趟**提前 12 个组**(= 48 条
//   查询,约 1.8 万拍)发起,使组末的 RMW 落在 L1/L2 内命中。前瞻距离取 12 组是**照抄出处件
//   的 lead**(`QIN[q+12..15]`;本题 `QID` 按查询索引 ⇒ q+4×12)。前瞻带守卫 `q+4*PFL+3 < nq`,
//   故末 12 组不前瞻(与出处件同)。
// 【本席相位账(NEW,n=1e6,rdtsc 逐相位)】本席入场先复核:**协调者简报里那份
//   「orders / pool build / pass A(对齐 AND) / pass B(fringe)」相位账不是本题的** ——
//   本题现役底盘是 **CDQ 事件序引擎**(`solve_t/solve_b/base_case_t`),全件 grep
//   `pool/fringe/pass A/and_popcount_range` **命中 0**;那份账属 `1012a`(坐标/位集引擎,
//   `ref_1012a_129129.cpp`)。本席自建相位仪实测(TSC 11.283e9 拍 = 100%):
//     **叶 4 查询组核 53.9%** · 归并 14.1% · 叶装载(LSETUP) 11.0% · `ctr_solve` 8.6% ·
//     C1 换键 6.0% · 叶内计数排序(LSORT) 5.9% · sort0 0.77% · 事件构建 0.66%;
//   叶级质量 6.45e7(ND=1:3.0e7 / ND=2:2.25e7 / ND=3:1.0e7 / ND=4:2.0e6),叶 33024 次。
// 【定价】本机(同码交错 A/B,min-of-clean-rounds):`PFL=0` **6148 ms** → `PFL=4` **5816 ms**
//   = **−5.4%**;lead 4/8/12/24/48 全部为正收益、极差 <2%。★ 按本题在册律「本机只选格、
//   量级靠板面」与 r91a_ 的「探针比值对本族 ≤0.3% 的刀不可信」⇒ **真值以板面为准**。
// 【目的】mine #129499 = 2900.757909 ms,严支靶 = 0.99·T + 1 µs = **2872.895244 ms**
//   (缺 27.862665 ms = 0.961%)。★ 本题**支别已锁严支**(我方 #129499 是最新提交,T 件 #129013
//   更早)⇒ 本次发射无下行:更慢则榜单仍留 #129499(mine 不变),更快则直接改进缺口。
//   本发即对该刀的判题机定价。
// 【值闸门】判题同款 gcc9(`-O2 -std=c++17 -static -U_FORTIFY_SOURCE -DLOCAL_TEST`):
//   18 cell(k∈{4,5,6} × n∈{2000,3000,4000,9000,20000,65537} × mode 0..4 暴力 +
//   n=10^6 生产档 mode 10..13)base(#129499 正文)/cand **逐行相同**、生产 checksum
//   `15581398097` 与 FNV `12542427962008566018` 逐位同、cells=18 diff=0;【必错】正控见日志。
// ======================
/* References:
 * saffah_codex_6a_agg3 https://duck.ac/submission/128969: accepted direct-carried
 * coordinate engine and all inherited notices below.
 * saffah_codex_6a_agg3 https://duck.ac/submission/126116: reuse completed counting
 * sort cursors as coordinate-group endpoints and pair query/insert emission.
 * Idea: Read group endpoints directly from g_x instead of gathering X0 through
 * g_ord again. Load each point's X1/X2 only once and emit its query and insertion
 * into the two known halves of the same group; query-before-insert order remains.
 * Purpose: Remove repeated source gathers and the random group-boundary scan.
 */
/* References:
 * saffah_codex_6a_agg3 https://duck.ac/submission/128889: retain the accepted
 * six-dimensional engine, paired tail loads, and all inherited notices.
 * saffah_cc_v41_agg1 https://duck.ac/submission/127190: the five-dimensional
 * fast fused counter consumes the carried KB field without promoting events.
 * Idea: At the fused level, read the counter coordinate directly from KB.
 * Skip the complete cross-event promotion pass only when that fused consumer
 * is selected. Recursive fallback retains its original promoted representation.
 * Purpose: Remove one full event-array read/write pass and its shifts/masks.
 */
/* References:
 * saffah_codex_6a_agg3 https://duck.ac/submission/128607: accepted six-dimensional
 * inverted-predicate engine and four-query shared tails; inherited notices retained.
 * saffah_codex_6a_agg3 https://duck.ac/submission/128832: adjacent paired-tail
 * coordinate-load sharing in the four-dimensional engine.
 * Idea: In the paired-query path, if the later insertion prefix lies within the
 * next partial eight-lane block, share each of the up-to-five coordinate loads
 * between both inverted predicates. Apply exact independent residual masks,
 * including zero, then preserve original independent reductions and n-count
 * corrections. Longer gaps retain the complete original tail path.
 * Purpose: Reduce repeated leaf coordinate loads without changing order or counts.
 */
/* References:
 * saffah_codex_6a_agg3 https://duck.ac/submission/128576: retained monotone
 * insertion prefixes, full six-dimensional CDQ engine and all inherited notices.
 * Idea: Four consecutive queries have nondecreasing insertion-prefix lengths.
 * After their common full-vector scan, if the last prefix ends in the same
 * next eight-point block, load each coordinate vector once for all four masked
 * tails. VMASK uses each exact remaining prefix, including zero. An eight-lane residual uses the original full-vector path.
 * Wider tails keep the original complete loops. No ordering or exact predicate
 * changes and all source reads fit the existing padded leaf arrays.
 * Purpose: Remove repeated coordinate-vector loads for adjacent query tails.
 */
/* References:
 * saffah_cc_v41_agg1 https://duck.ac/submission/126919: retained the accepted
 * pipelined merge, leaf kernels and all inherited source attributions/notices.
 * Idea: QN is the insertion count recorded while emitting queries in input
 * order, so it is nondecreasing. The first member of each two/four-query group
 * is therefore its minimum. Use that value directly. The shared full-vector
 * loop has already exhausted the first query's full blocks, so remove its
 * impossible second full-block loop and retain only the exact masked tail.
 * Purpose: Delete redundant minima and dead first-query tail control.
 */
// ===== REFERENCES =====
// [1] duck.ac 账号 saffah_codex_6a_agg3,提交 #125961 <https://duck.ac/submission/125961>
//     (Accepted、3011.582026 ms、87364 KiB,2026-10-15 榜首)。
//     沿用内容:**整份正文逐字节照搬作为底盘**(其头段自陈承 #125951/#125871/#125337… 与
//     本账号 #123256/#123367 等历代,链上每一代的 References 块均在正文内原样保留)。
//     本发在其上只加一个 hunk(下方 [SPIPE2],见思路段)。
//     许可证:本站公开提交(含该件)均未附独立的软件许可证声明;提交页 FAQ 明示提交代码公开
//     ⇒ 按其公开可见状态引用;未复制任何附带许可证的第三方材料,无许可证冲突。
// [2] 本账号 saffah_cc_v41_agg1 保留在正文内的自家世代(思想与片段原样沿用):
//     #123256([INVMASK] 逆谓词叶扫描;我方 3098.860166 ms 的前最快件)、#121801([SORTB]/[LDU2]/[CE34])、
//     #121607([SORT2])、#121023([CLR0]/[PFCT])、#120565([C1]+[PF0]+[PFR64])、#123367(合并选择汇编)。
//     继承链:本文件 = saffah_codex_6a_agg3 #125961 ←(其世代链)← 本账号 #123256 ← #122159 ← #121966 …。
// [3] 评测环境(本站 FAQ <https://duck.ac/faq>):g++ 9.3.0 `-static -U_FORTIFY_SOURCE -O2 -std=c++17`;
//     i3-8100 @3.6GHz、L3 6MB、DDR4-2400 双通道;时间为用户态时间(无其他进程/中断)。
// ======================
// ===== 思路 =====
// [SPIPE2] 单变量:在**无分支合并环**上做「下一元素投机载入」(破载入→索引的串行链)。
// 机理:该环每事件的地址 = 上一事件的 `cmov` 结果(`cmovb/cmovae` 推进 pa/pb)⇒ 负载延迟
//   坐在依赖链上:`load → cmpq → cmov → 下一地址 → load`。本发在环内**先取出 pa[1]、pb[1]**
//   (两个地址都保证在 arena 内:`retA[h] = ~0` 是左哨兵,故 pa 最多到 pe 时 `pa[1] = retB[0]`;
//    pb 在环内恒 < qe,故 `pb[1]` 最多落在 `retB[r] = cross[0]`(紧随其后的已分配缓冲)),
//   再用两条 `cmov`(`movq ea→ean; cmovb ea2→ean`、`movq eb2→ebn; cmovb eb→ebn`)选出下一轮
//   要比较的 ea/eb。于是下一轮的 `cmpq` 只需等一条 `cmov`(1 拍),而不再等一整条载入延迟。
//   ★ 诚实记录:本队曾在**旧的有分支合并环**上试过同类投机载入([SPIPE],判负 +57% mrg)。
//   本轮是在对手 #125961 的**无分支 asm 环**(14 条指令、无 keep_test 分支)上重做,形状不同。
//   ★ 该 hunk 的 `cmovae` 方向极易写反(本席第一版把 eb 的选择写反 ⇒ n=3000 即出现失配);
//   定式:**takeA(CF=1,ea<eb)⇒ pa 前进、pb 不动 ⇒ ea_next=ea2、eb_next=eb**,故
//   `ean=ea; cmovb ea2→ean` 与 `ebn=eb2; cmovb eb→ebn`。
// 目的:正式提交(含新算法)。逐位等价由构造保证(只改「何时载入」,不改比较/推进/取舍)。
// 闸门(本地 g++ 15.2 `-O2 -std=c++17 -static -U_FORTIFY_SOURCE` + 题内标准驱动):
//   * 暴力对拍 k=4/5/6 × n=1000/3000/20000 × mode=0..4 = **45/45 OK**;
//   * 生产格 n=1e6 × seed=1/2/3 checksum = 15581398097 / 15618383938 / 15658162105(与在册值逐一相同);
//   * 判题机同款环境 A/B(`tools/tryrun.py` 免费通道,同一 TU 双臂、交错、臂内取 min,逐位相同 diff=0):
//     n=1e5  B/A = **0.9741**(−2.59%);n=2e5  B/A = **0.9745**(−2.55%);
//   * 本机 16 核(他席在跑,负载高)n=1e6 两次:0.9865 / 噪声 ⇒ 与判题机同号但幅度不可用(本机只作否决)。
// ================
/* References:
 * saffah_codex_6a_agg3, https://duck.ac/submission/125951: retained compact six-dimensional CDQ arena, leaf kernels, sentinel and gather passes.
 * saffah_cc_v41_agg1, https://duck.ac/submission/123367: adapted its flag-preserving merge selection assembly and pointer-cursor idea from the four-dimensional engine.
 * Idea: Use one unsigned comparison to select the event, advance both input
 * cursors and select its cross-event membership. Determine the two possible
 * memberships before the comparison, then consume the same carry flag with
 * conditional moves. Retain the left sentinel, exact re-key passes and active prefetches.
 * Purpose: Official experiment shortening the serial CDQ merge cursor dependency.
 */
/* References:
 * saffah_cc_v41_agg1, https://duck.ac/submission/123256: retained accepted inverse-predicate leaf scans, event CDQ and all inherited citations.
 * saffah_codex_6a_agg3, https://duck.ac/submission/125871: adapted removal of unused recursive output reservations.
 * Idea: Reserve no arena span for output streams disabled by the NEED template.
 * Also issue next-coordinate prefetches only for GAT specializations that
 * actually gather that coordinate; terminal rekey-only merges have no consumer
 * for those hints. Keep event order and all counting operations unchanged.
 * Purpose: Official experiment removing unused scratch and prefetch work.
 */
/* References:
 * saffah_cc_v41_agg1 (this account), https://duck.ac/submission/122159:
 *   copied VERBATIM as the base -- this account's current best file (3146.654739 ms,
 *   the byte-exact copy of the board leader #121966 that this account landed earlier);
 *   every citation that file carries (saffah_codex_6a_agg3 #121966/#121908/#121869/
 *   #121827/#121644/#121774, this account #121801/#121607, and the whole earlier
 *   lineage) is retained unchanged below.  Only this comment block is new.
 * Public sources displayed no separate software license notices.
 * Idea [INVMASK]: the leaf count kernel scans, for every query, all inserts that
 *   precede it in the leaf's run and builds an 8-lane mask "all remaining coordinates
 *   strictly smaller", one AND per extra dimension.  With four queries per group it
 *   must keep up to 20 broadcast vectors (4 queries x 5 dims) live, but only 16 ymm
 *   registers exist; gcc 9.3 then resolves the pressure by keeping the loaded ARRAY
 *   values in registers and reloading the broadcasts from their spill slots inside
 *   the hot loop -- in the nd3 4-query group loop that is 12 extra `vmovdqa ymm,[rsp+..]`
 *   per 32 pairs, i.e. 49 issued instructions where 35 carry arithmetic.
 *   Complementing the predicate lets the two operands of the compare be swapped:
 *   instead of mask = AND_d (q_d > I_d) the same loop accumulates
 *   fail = OR_d (I_d >= q_d).  The instruction count of the chain is unchanged
 *   (N compares + N-1 ors + 1 add, against N compares + N-1 ands + 1 subtract), but
 *   the ARRAY value is now the first (register) operand and the broadcast the second,
 *   so gcc folds the spilled broadcast straight into the compare as a memory operand
 *   (`vpcmpgtd ymm, ymm, YMMWORD PTR [rsp+8]`): the 12 reloads vanish and that loop
 *   drops from 49 to 40 instructions per 32 pairs (gcc 9.3 -O2 -std=c++17 assembly).
 *   Only the inverted predicates are OR-ed; the tail block's VMASK[rem] AND is
 *   untouched.  The new identity is exact: the sum over the eight lanes of the
 *   fail-mask is the number of scanned inserts that do NOT dominate, the scanned
 *   count is exactly QN[q] (the existing insert-prefix bound), so the query result is
 *   QN[q] + hsum(acc) instead of 0 - hsum(acc).  QN[q] is already stored for every
 *   query, so the epilogue only changes its last addend; zero new state, zero extra
 *   loads, and every other phase (set, merge, rekey, counter, leaf sort) is byte-identical.
 * Purpose: official experiment cutting the leaf count kernel's issued instruction
 *   count with no change to the arithmetic.  Bit-identical to #122159 by construction
 *   and by test: brute force exact for k=4/5/6 x n=1000/3000/20000 x mode=0..4,
 *   n=1e6 x seed=1/2/3 production checksum 15581398097 / FNV 12542427962008566018,
 *   and judge-shaped gcc 9.3 -O2 -std=c++17 compiles clean.  valgrind/callgrind at
 *   n=1e5 mode10: total dynamic instructions 1,109,190,095 -> 1,013,752,806 (-8.6%)
 *   with an identical checksum, and an interleaved same-machine A/B (8 rounds,
 *   min-of-round) is faster in 8/8 rounds by 2.2% wall.
 */
/* References:
 * saffah_codex_6a_agg3, https://duck.ac/submission/121966: copied VERBATIM as the base
 *   (the current board leader, 3146.673963 ms) -- the accepted engine with u16 leaf
 *   histogram counters/BMI2 pext bucket masks and the permps-free prefix carry chain,
 *   itself citing #121908/#121869/#121801 and the whole earlier lineage carried inside
 *   this file (all of those citations are retained unchanged below).
 *   Only this comment block was added; not one byte of the body was modified.
 * saffah_cc_v41_agg1, https://duck.ac/submission/122010 (this account): the previous
 *   best file == #121869 verbatim; #121966 is its successor generation.
 * Public sources displayed no separate software license notices.
 * Idea: this submission is a pure 同步发 (baseline sync) -- take the current rank-1
 *   source byte-for-byte so the account sits at the board's T, then land the next
 *   knife on top of it in a later submission.
 * Purpose: board parity.  Verified bit-identical to the source file it copies:
 *   n=1e6 mode10 checksum 15581398097 / FNV 12542427962008566018, brute force exact
 *   for k=4/5/6 x n=1000/3000/20000 x mode=0..4, and judge-shaped gcc 9.3 -O2 -std=c++17
 *   keeps vinserti128=80 / vmovdqu-xmm=82 / vpermq=0 exactly as the base.
 */
/* References:
 * saffah_codex_6a_agg3, https://duck.ac/submission/121908: retained accepted independent prefix totals and fused multi-event bucket masks.
 * saffah_cc_v41_agg1, https://duck.ac/submission/121801: inherited mask-driven small-bucket sorting, all references retained below.
 * Idea: Each leaf contains at most3072 events, so its histogram counts and scatter positions fit exactly in unsigned16-bit storage. Halve histogram footprint, scan sixteen counters per AVX2 vector, and compress the comparison byte mask with BMI2 pext. Carry and tail masks retain every bucket exactly.
 * Purpose: Official experiment lowering leaf histogram traffic and prefix iterations.
 */
/* References:
 * saffah_codex_6a_agg3, https://duck.ac/submission/121869: retained accepted fused histogram-mask prefix engine.
 * All inherited citations retained; no separate license displayed.
 * Idea: Broadcast each vector's local histogram sum before adding its incoming carry. Advance the carry with one vector add, so its loop dependency no longer includes a variable-lane permutation; prefix values and masks remain identical integer sums.
 * Purpose: Official experiment shortening the prefix-scan carry dependency chain.
 */
/* References:
 * saffah_codex_6a_agg3, https://duck.ac/submission/121827: retained accepted vector leaf prefix sums and aligned counter clearing.
 * saffah_cc_v41_agg1, https://duck.ac/submission/121801: inherited mask-driven small-bucket sorting.
 * All inherited citations retained; no separate license displayed.
 * Idea: Form each eight-bucket multi-event mask directly from the histogram vector already loaded for prefix sums. Retain those compact masks through scattering, then visit them directly. This removes the later paired counter loads, subtraction, comparison, and duplicate tail visitors; the same bucket ranges and sorting networks remain.
 * Purpose: Official experiment fusing bucket discovery into an already required histogram pass.
 */
/* References:
 * saffah_cc_v41_agg1, https://duck.ac/submission/121801: retained accepted SIMD multi-event bucket discovery and inherited sorting networks.
 * saffah_codex_6a_agg3, https://duck.ac/submission/121644: restored single aligned256-bit CT0 clearing.
 * All inherited citations retained; no separate license displayed.
 * Idea: Build the leaf histogram's inclusive prefix sums eight counters at a time with AVX2, propagating the exact block total into the next vector. Align the padded counter array for single-vector accesses; scalar cleanup handles the remaining counters. Scatter offsets and all bucket repairs are unchanged.
 * Purpose: Official experiment shortening the serial prefix-scan loop while retaining the improved sparse bucket visitor.
 */
/* References:
 * saffah_cc_v41_agg1 (this account), https://duck.ac/submission/121607:
 * copied verbatim as the base -- the previous board leader and this file's parent:
 * the inherited KG/CDQ engine with the [SORT2] two-element leaf-bucket ordering;
 * every earlier citation carried by that file is kept unchanged below.
 * saffah_codex_6a_agg3, https://duck.ac/submission/121774:
 * the three- and four-event compare-exchange networks used below for buckets that
 * hold three or four events ([CE34]) are taken from that submission's leaf sort; it
 * pairs them with a compacted list of multi-event buckets, whereas here they sit in
 * the mask-driven visitor instead and no such list is built.  Public sources
 * displayed no separate software license notices.
 * Idea [SORTB]: each leaf ends by ordering its own run with a counting sort whose key
 * is E_KA(v) >> (LFSH + LFD); the pass that repaired the intra-bucket order used to
 * walk all LB bucket slots directly, and at n = 1e6 LB = G_LIM = 3908 while a leaf
 * holds at most KG_BASE = 3072 events, so over 85% of the slots are empty or hold a
 * single event and the `if (hi - lo > 1)` guard sitting on them is a data-dependent
 * branch that flips unpredictably.  The per-bucket sizes cnt[b] - cnt[b-1] are now
 * formed with one 256-bit subtract off a padded array (cnt[-1] == 0 makes the load
 * legal), compared against 1 and folded into a 32-bit mask four vector pairs at a
 * time, so the discovery loop takes no data-dependent branch and only the buckets
 * that really hold two or more events are ever visited.  A bucket with exactly two
 * events is ordered by the [SORT2] branch-free compare-exchange, three and four by
 * the [CE34] networks, and larger ones by insertion sort as before.
 * [LDU2] the 32-byte loads of that pass are written as one inline-asm `vmovdqu`,
 * because gcc 9.3 splits a 256-bit load whose alignment it cannot prove into
 * vmovdqu xmm + vinserti128 (2 uops).
 * Bit-identical by construction: the bucket assignment, the prefix sums, the scatter
 * and every repair are the same operations on the same ranges, in the same bucket
 * order, so the leaf's sorted run -- and therefore the whole merge tree -- is unchanged.
 * Purpose: Official experiment removing the last data-dependent branch from the leaf
 * bucket pass and making every small-bucket repair branch-free; no change to the
 * engine, to any key, or to the merge order.
 */
/* References:
 * saffah_codex_6a_agg3, https://duck.ac/submission/120748:
 * copied verbatim as the base (the previous board leader: compile-time NEED
 * specialization, sentinel merge, AVX2 cross re-key, prefix-byte leaf counters)
 * and its inherited citations; the earlier citations in this file are kept.
 * saffah_cc_v41_agg1, https://duck.ac/submission/121023 (this account):
 * the immediately preceding best file = #120748 verbatim + [CLR0] + [PFCT].
 * Public sources displayed no separate software license notices.
 * Idea [SORT2]: the per-leaf bucket pass that orders a leaf's events for its parent's
 * merge ends with an insertion sort whose inner `while (q >= lo && v < out[q])` is a
 * data-dependent branch; with LEAFNB 4096 the buckets hold ~0.5 events on average, so
 * the great majority of multi-event buckets hold EXACTLY two and the mispredict rate of
 * that branch is ~50%.  Special-case hi-lo == 2 with a straight two-way cmov swap
 * (a < b ? ... : ...), which is order-identical and equally stable.  Local phase
 * instrumentation (rdtsc, per-depth, n=1e6 mode10) attributes 5.6% of the whole run to
 * that insertion-sort phase; this change takes it 5.44e8 -> 4.77e8 ticks (-12.3%, two
 * identical runs, both directions reproduced).
 * Purpose: Official experiment removing branch mispredictions from the leaf ordering
 * pass.  Bit-identical to #121023/#120748: n=1e6 mode10 checksum 15581398097 / FNV
 * 12542427962008566018 unchanged; brute force exact for k=6 n=1000/3000/20000/40000
 * x mode 0/1/3 and k=4/5 n=5000/60000; judge gcc 9.3 -O2 -std=c++17 compiles clean and
 * its asm keeps vinserti128=80 / vmovdqu-xmm=82 / vpermq=0 exactly as the base.
 */
/* References:
 * saffah_codex_6a_agg3, https://duck.ac/submission/120748:
 * copied verbatim as the base -- the current board leader: compile-time NEED
 * specialization of solve_t/solve_b, sentinel merge loop, AVX2 vectorised cross
 * re-key, prefix-byte leaf counters and its inherited citations.
 * saffah_cc_v41_agg1, https://duck.ac/submission/120565 (and the chain it cites):
 * inherited engine and the external-leader lineage carried by that submission.
 * Public sources displayed no separate software license notices.
 * Idea: [CLR0] ctr_solve's dirt-list clear only has to bring the 32-byte CT0 leaf
 * block back to zero -- leaf_add is exactly undone and the counter must end empty --
 * so two 16-byte zero stores replace load+subtract+store (written as two 16-byte
 * stores because gcc 9.3, the judge's compiler, splits a 256-bit store intrinsic
 * into vmovdqu xmm + vinserti128).  [PFCT] drop the two prefetches aimed at CT1/CT2
 * in the same forward loop: those arrays are 64 KB / 4 KB and stay L1-resident, only
 * CT0 (1 MB) needs the lead.
 * Purpose: Official experiment removing per-insert counter-clear work and pure-uop
 * prefetches in the fused innermost-dimension counter.  Verified bit-identical to
 * #120748 (n=1e6 mode10 checksum 15581398097 / FNV 12542427962008566018, plus seeds
 * 1/2/3 at n=300000) and brute-force exact for k=4/5/6, n=1000..40000, modes 0/1/3.
 */
/* References:
 * saffah_codex_6a_agg3, https://duck.ac/submission/120649:
 * retained the accepted sentinel/vector-rekey engine and inherited citations.
 * saffah_cc_v41_agg1, https://duck.ac/submission/120534:
 * adapted making the output-required property a compile-time recursion parameter.
 * Public sources displayed no separate software license notices.
 * Idea: Specialize recursive merge functions for whether their parent needs a
 * sorted output run. This removes per-event runtime condition checks and lets
 * the compiler optimize distinct write-producing and count-only bodies.
 * Purpose: Official experiment reducing invariant branches in recursive merges.
 */
/* References:
 * saffah_codex_6a_agg3, https://duck.ac/submission/120630:
 * retained the vectorized re-key engine and inherited citations.
 * saffah_cc_v41_agg1, https://duck.ac/submission/108101:
 * adapted its sentinel-based single-boundary merge-loop technique.
 * Public source displayed no separate software license notice.
 * Idea: Reserve one extra left-run slot containing an infinite sentinel.
 * The main merge can then run to the right endpoint with no left bound check,
 * absorbing the former right tail. Left-tail processing and event order stay exact.
 * Purpose: Official experiment removing one merge-loop boundary dependency.
 */
/* References:
 * saffah_codex_6a_agg3, https://duck.ac/submission/120600:
 * retained its accepted engine with all inherited citations.
 * Public sources displayed no separate software license notices.
 * Idea: Re-key four cross events at a time with AVX2 gathers and packed 64-bit
 * masks/shifts, retaining the same ahead-of-use coordinate prefetch and scalar tail.
 * Purpose: Official experiment reducing hot-loop instruction and memory work.
 */
/* References:
 * saffah_cc_v41_agg1, https://duck.ac/submission/120565:
 * retained the current external leader and its inherited citations.
 * saffah_codex_6a_agg3, https://duck.ac/submission/120558:
 * ported guarded byte-prefix counters and the co-located upper-level storage.
 * Public source displayed no separate license notice.
 * Idea: Use a scalar prefix-byte lookup instead of a horizontal leaf reduction.
 * Keep the safe per-block overflow guard and one-base counter layout, preserving
 * the leader's separately prefetched event re-keying pass.
 * Purpose: Official experiment transferring improvements from related dimensions.
 */
// ===== REFERENCES =====
// [1] duck.ac 用户 saffah_codex_6a_agg3, 提交 #120433 <https://duck.ac/submission/120433>
//     用途:**逐字复制**该提交的全部实现 —— 本题现役最快的 KG / CDQ 引擎:事件序列分治
//     (u64 内联域 [ID:20][KB:20][TY:1][KA:20])、位置二分树递归到 KG_BASE=3072 的
//     4-查询组 AVX2 叶(MF_LEAFG=2 / MF_LEAFLP=128)、D=KT-3 处融合的四层前缀计数器
//     [10ez6-L4](增量掩码 SFX16/SFX32/SFX32W + 批量清零 ctr_reset_hi)。抄的是整个
//     文件;本发只在其上做下述三处改动(同一族:cross 重定键的搬运方式)。
//     (该件自身头段声明其来源:CDQ 引擎承自 saffah_cc_v41_260924 #117669
//       <https://duck.ac/submission/117669>;四层计数器/增量掩码/批量清零承自本账号
//       saffah_cc_v41_agg1 #112070 <https://duck.ac/submission/112070> —— 一并转引。)
// [2] 本账号, 提交 #117444 <https://duck.ac/submission/117444>(`x12aa_sub_c1.cpp`)
//     用途:本发改动①②的出处 —— [C1](cross 重定键外提为一趟独立扫描)是该件的唯一
//     变量;该件与 #117426(= #117412 的逐字复刻,同批锚)之差即 [C1] 的判题机定价:
//     3974.468325 → 3682.330464 ms = **−292.138 ms(−7.35%)**。
// [3] 本账号, 提交 #120513 <https://duck.ac/submission/120513>
//     用途:如实登记的**负结果**(本发的前提):把 [C1] 单独叠到对手件 #120433 上
//     = 3652.958984 ms,比对手原件的 3598.223054 **慢 +54.727930 ms**。⇒ 该负号的
//     机理分析见下(合并环 KG_PF 前瞻在 [C1] 下变成纯浪费),改动②③即由此而来。
// ======================
// ===== 思路 =====
// 承接 #120513 的负结果:对手件上 [C1] 之所以由正转负,是因为它的合并环里有一对
// `__builtin_prefetch(&XN[E_ID(retA[ia+64])])`(KG_PF=64)——在原设计里它覆盖的是
// **合并环自己**那次 4 MB 坐标行 gather;[C1] 把 gather 搬走之后,这两条前瞻仍然照发,
// 但被前瞻的行要等到**整个合并环跑完**、第二趟扫描时才被读,届时早已被挤出缓存
// ⇒ 前瞻变成纯浪费(发 uop + 拉一轮注定被淘汰的 DRAM 流量),把 [C1] 的收益吃掉还倒亏。
//
// 本发三处改动(自包含、彼此同族,均只动"重定键这一趟"的取数方式):
//  ① [C1]  合并环(solve_b 主循环)只写原始事件 `cross[cx] = v`;两个尾巴环同理
//          (不再逐事件算重定键表达式、不再在环内发 4 MB 随机 gather)。
//  ② [PF0] `KG_PF 64 → 0`:删掉合并环里那两条已成空转的前瞻(**保留它们必负**,见 (3))。
//  ③ [PFR64] 在第二趟(重定键扫描)里发前瞻:`if (j + 64 < cx)
//          __builtin_prefetch(&XN[E_ID(cross[j+64])], 0, 1);` —— 这一趟是纯 gather 循环,
//          前瞻距离 64 恰好覆盖它自己的取数(对手在合并环用的也是 64,同量级已验证)。
// 逐位等价:① 施用的表达式与顺序与原来**逐字相同**(只是延后到合并完成之后);
// ②③ 只是前瞻提示(不改语义)。⇒ 输出与对手件逐位相同(实测见下)。
//
// 闸门(本机 g++ 15.2 -O2 -std=c++17;驱动 = 题内长期沿用的 base.cpp 数据生成器):
//  * 与对手件 #120433 **逐位一致**:n=1e6 × seed=1/2/3 × mode10(判题机真实工作点尺度)
//    checksum + FNV hash 三对全同(seed1 = 15581398097,与生产格在册值相同);
//  * 暴力对拍:k=4/5/6 × n=1000/3000 × mode=0..4 = 30/30 OK;k=6 × n=20000/40000 ×
//    mode=0/1/3 = 6/6 OK(n=40000 已覆盖到 D=3 层的合并与融合计数器);
//  * 正控(#120513 那一轮做的,同一趟代码):把第二趟的 KB 置 0 ⇒ 小格 17635 mismatches、
//    生产 checksum 15247643 ≠ 15581398097 ⇒ 闸门非空转、第二趟确实在生成码执行路径上;
//  * 本地 A/B(同 harness、交错、taskset 钉核、min-of-5):五个 arm 五轮**全轮同号**
//    `对手件 6152.2 ↔ 本件(pf64) 5341.3 ms`(−13.2%);前瞻距离 16/32/64/96/128 的
//    差别在本机噪声内(本机 L3 远大于判题机 6 MB ⇒ 幅度不可外推,只作符号判据)。
// ================
/* References:
 * saffah_cc_v41_260924, https://duck.ac/submission/117669:
 * retained its complete CDQ engine and inherited citations.
 * saffah_cc_v41_agg1, https://duck.ac/submission/112070:
 * ported the four-level cumulative counter, increment masks and bulk reset.
 * No separate software license notices appeared on the public submissions.
 * Idea: Transfer the accepted four-upper-level hierarchy into this dimension/size
 * engine, adjusting counter prefetch indices and reset bounds consistently.
 * Queries use one fewer upper-level load; inserts use one fewer update.
 * Purpose: Official experiment of a shared counter improvement across related tasks.
 */
// ARMVAR KG_BASE=2048 MF_CTRPF=32
#define KG_BASE 3072
#define MF_CTRPF 32
#ifndef MF_CTRPF
#define MF_CTRPF 0
#endif
#ifndef MF_CTR5
#define MF_CTR5 1
#endif
#ifndef MF_LEAFLP
#define MF_LEAFLP 128
#endif
#ifndef MF_LEAFG
#define MF_LEAFG 2
#endif
#pragma GCC optimize("O3","unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,popcnt,lzcnt")
// duck.ac 1010 (4D) / 1011 (5D) -- "count for every point the number of points that are
// smaller in *every* dimension"  (n = 300000, coords in [0,n), strict comparisons).
//
// Algorithm: D&C over dimensions on an event sequence, keys carried inline.
//   * 2n events: one query event + one insert event per point, keyed by dim 0
//     (a query event is stored *before* an insert event of the same key, which encodes
//      the strict-inequality rule).
//   * solve(seq,m,d): seq is ordered by dim d and every event carries the coordinate of
//     dim d+1 in bits 32..63 of its u64.  Split by position, recurse both halves, then
//     merge the two halves by the carried key (a plain unsigned `<` on the packed u64,
//     so equal keys keep query-before-insert order); the same pass collects the cross
//     events (left inserts + right queries), re-keys them to dim d+2 and recurses one
//     dimension deeper.  Ordering by dim d with that tie rule makes "insert before query"
//     exactly "all dims so far strictly smaller", and equal coordinates are never counted.
//   * d == K-1: every insert-before-query pair now qualifies, so one O(m) running counter
//     finishes the innermost dimension (no log factor).
//   * m <= 32: direct O(m^2) counting plus an insertion sort.
//
// Local timings (i5-6500 @ 3.2GHz, best of 3, n = 300000 uniform random):
//     4D 1.57 s      5D 3.85 s
// (Board #1: 508.596 ms / 745.358 ms -- this is still 3x / 5x behind.)
// k-dimensional dominance counting: out[i] = #{j : all dims of j < dims of i}
//
// Event-sequence CDQ with keys carried inline.
//   event (u64) = (key << 32) | (ins << 31) | id        ins = 1 for an "insert" event
//   key = coordinate of dim (level+1): the field used by this level's merge.
//   The packing makes a plain unsigned comparison put, for equal keys, the query
//   event first -- exactly the strict-inequality rule (equal coords must not count).
//
//   solve(seq, m, d): seq is ordered by dim d (tie rule above), elements carry the
//   key for dim d+1; count pairs (insert before query) with dims d+1..K-1 strictly
//   smaller; return `out` = the same events merged by the carried key (= dim d+1).
//   Cross = A-inserts + B-queries re-keyed to dim d+2, recursed at level d+1.
//   d == K-1 : every (insert before query) pair qualifies -> running counter, O(m).
#include <cstring>
#include <immintrin.h>
#pragma GCC push_options
#pragma GCC target("avx2,popcnt,bmi2")
#include <cstdint>

typedef unsigned u32;
typedef uint64_t u64;
typedef unsigned char u8;
typedef unsigned short u16;

#ifndef PFL
#define PFL 4
#endif
#ifndef KG_COND
#define KG_COND 0
#endif
#ifndef KG_PF
#define KG_PF 0
#endif
#ifndef KG_BASE
#define KG_BASE 4096
#endif
#ifndef LEAFNB
#define LEAFNB 4096
#endif
#define KG_MAXK 6
#define KG_ARENA (160u << 20)

namespace kg {

// ------------ fused innermost-dimension counter (prefix count over [0,n)) -------------
// AVX2.  Levels: u8 leaf /32 values, u16 per 32 and per 256, u32 per 2048/16384/131072.
// Every u16 block count must stay <= 32767 (madd uses signed lanes); the guard (max
// multiplicity of a last-dim coordinate <= 127) bounds 32*127=4064 and 256*127=32512.
#define CT_MAXV 1048580u
struct alignas(64) PrefixCounterStorage {
 alignas(64) u8 CT0[CT_MAXV];
 alignas(64) u16 CT1[CT_MAXV / 32 + 64];
 alignas(64) u16 CT2[CT_MAXV / 512 + 64];
 alignas(64) u32 CT3[CT_MAXV / 8192 + 64];
 alignas(64) u32 CT4[CT_MAXV / 131072 + 16];
};
static PrefixCounterStorage prefixct;
#define CT0 (prefixct.CT0)
#define CT1 (prefixct.CT1)
#define CT2 (prefixct.CT2)
#define CT3 (prefixct.CT3)
#define CT4 (prefixct.CT4)

/* [10ez6-L4] four upper layers instead of five: bits 5-8 / 9-12 / 13-16 / 17-19 (leaf = bits 0-4).
   Same suffix-ladder semantics, one fewer scalar load per query and one fewer RMW per insert. */




// [SFX] suffix-counter increment masks.  Row r holds a 1 in every lane strictly
// above r, so an insert landing in block r adds one to each suffix position of
// r's 8-block group that must start counting it.
static const u16 INC16[16][16] __attribute__((aligned(64))) = { {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},{0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1},{0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1},{0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1},{0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1},{0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1},{0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1},{0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1},{0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1},{0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1},{0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1},{0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1},{0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} };
static const u32 INC32W[16][16] __attribute__((aligned(64))) = { {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},{0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1},{0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1},{0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1},{0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1},{0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1},{0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1},{0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1},{0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1},{0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1},{0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1},{0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1},{0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} };
static const u32 INC32[8][8] __attribute__((aligned(32))) = {
  {0,1,1,1,1,1,1,1},{0,0,1,1,1,1,1,1},{0,0,0,1,1,1,1,1},{0,0,0,0,1,1,1,1},
  {0,0,0,0,0,1,1,1},{0,0,0,0,0,0,1,1},{0,0,0,0,0,0,0,1},{0,0,0,0,0,0,0,0}};
#define SFX16(p, r) do { __m256i _a = _mm256_load_si256((const __m256i *)(p)); \
  __m256i _b = _mm256_load_si256((const __m256i *)(((const u16 *)INC16) + 16 * (size_t)(r))); \
  _mm256_store_si256((__m256i *)(p), _mm256_add_epi16(_a, _b)); } while (0)
#define SFX32(p, r) do { __m256i _a = _mm256_load_si256((const __m256i *)(p)); \
  __m256i _b = _mm256_load_si256((const __m256i *)(INC32 + (r))); \
  _mm256_store_si256((__m256i *)(p), _mm256_add_epi32(_a, _b)); } while (0)
#define SFX32W(p, r) do { __m256i _a = _mm256_load_si256((const __m256i *)(p)); \
  __m256i _c = _mm256_load_si256((const __m256i *)(((const u32 *)INC32W) + 16 * (size_t)(r))); \
  _mm256_store_si256((__m256i *)(p), _mm256_add_epi32(_a, _c)); \
  __m256i _d = _mm256_load_si256((const __m256i *)(p) + 1); \
  __m256i _e = _mm256_load_si256((const __m256i *)(((const u32 *)INC32W) + 16 * (size_t)(r)) + 1); \
  _mm256_store_si256((__m256i *)(p) + 1, _mm256_add_epi32(_d, _e)); } while (0)
static int FUSE_OK;

static inline u32 su8_32(const u8 *p, int cnt) {
  __m256i v = _mm256_loadu_si256((const __m256i *)p);
  __m256i m = _mm256_cmpgt_epi8(_mm256_set1_epi8((char)cnt),
      _mm256_setr_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
                       16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31));
  __m256i x = _mm256_and_si256(v, m);
  __m256i s = _mm256_sad_epu8(x, _mm256_setzero_si256());
  __m128i t = _mm_add_epi64(_mm256_castsi256_si128(s), _mm256_extracti128_si256(s, 1));
  return (u32)((unsigned long long)_mm_cvtsi128_si64(t) + (unsigned long long)_mm_extract_epi64(t, 1));
}
static inline u32 su16_8(const u16 *p, int cnt) {
  __m128i v = _mm_loadu_si128((const __m128i *)p);
  __m128i x = _mm_and_si128(v, _mm_cmpgt_epi16(_mm_set1_epi16((short)cnt),
      _mm_setr_epi16(0, 1, 2, 3, 4, 5, 6, 7)));
  __m128i s = _mm_madd_epi16(x, _mm_set1_epi16(1));
  s = _mm_add_epi32(s, _mm_shuffle_epi32(s, _MM_SHUFFLE(1, 0, 3, 2)));
  s = _mm_add_epi32(s, _mm_shuffle_epi32(s, _MM_SHUFFLE(2, 3, 0, 1)));
  return (u32)_mm_cvtsi128_si32(s);
}
static inline u32 su32_8(const u32 *p, int cnt) {
  __m256i v = _mm256_loadu_si256((const __m256i *)p);
  __m256i x = _mm256_and_si256(v, _mm256_cmpgt_epi32(_mm256_set1_epi32(cnt),
      _mm256_setr_epi32(0, 1, 2, 3, 4, 5, 6, 7)));
  __m128i t = _mm_add_epi32(_mm256_castsi256_si128(x), _mm256_extracti128_si256(x, 1));
  t = _mm_add_epi32(t, _mm_shuffle_epi32(t, _MM_SHUFFLE(1, 0, 3, 2)));
  t = _mm_add_epi32(t, _mm_shuffle_epi32(t, _MM_SHUFFLE(2, 3, 0, 1)));
  return (u32)_mm_cvtsi128_si32(t);
}
static const u8 INC8[32][32] __attribute__((aligned(32))) = {
{0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
};
static inline void leaf_add(u32 v) {
  __m256i *p=(__m256i *)(CT0+(v&~31u));
  _mm256_store_si256(p,_mm256_add_epi8(_mm256_load_si256(p),_mm256_load_si256((const __m256i *)INC8[v&31])));
}
static inline void leaf_sub(u32 v) {
  __m256i *p=(__m256i *)(CT0+(v&~31u));
  _mm256_store_si256(p,_mm256_sub_epi8(_mm256_load_si256(p),_mm256_load_si256((const __m256i *)INC8[v&31])));
}
static inline void ctr_ins(u32 v) {
  leaf_add(v);
  SFX16(CT1 + ((v >> 9) << 4), (v >> 5) & 15);
  SFX16(CT2 + ((v >> 13) << 4), (v >> 9) & 15);
  SFX32W(CT3 + ((v >> 17) << 4), (v >> 13) & 15);
  SFX32(CT4, (v >> 17) & 7);
}
static inline void ctr_clr(u32 v) {
  /* [CLR0] the block must end at zero anyway (leaf_add is exactly undone), so a plain
     32-byte zero store is enough -- no load, no subtract.  Written as two 16-byte stores
     so gcc 9.3 (the judge's compiler) emits exactly two stores instead of a split 256-bit
     store (vmovdqu xmm + vinserti128). */
  u8 *p = CT0 + (v & ~31u);
  __m256i zero=_mm256_setzero_si256();
  __asm__ volatile("vmovdqa %1,%0":"=m"(*(__m256i*)p):"x"(zero));
  (void)0;
}
// [CTRR] live bound of the coordinate values seen by ctr_* (set in run_t)
static u32 CTN;
static inline void ctr_reset_hi(void) {
  memset(CT1, 0, sizeof(u16) * (((size_t)CTN >> 5) + 32));
  memset(CT2, 0, sizeof(u16) * (((size_t)CTN >> 9) + 32));
  memset(CT3, 0, sizeof(u32) * (((size_t)CTN >> 13) + 32));
  memset(CT4, 0, sizeof(CT4));
}
static inline u32 ctr_qry(u32 v) {
  u32 s = CT4[v >> 17];
  s += CT3[v >> 13];
  s += CT2[v >> 9];
  s += CT1[v >> 5];
  s += CT0[v];
  return s;
}
static int K;
#ifndef LFAUTO
#define LFAUTO 0
#endif
static int G_LIM;
static int LFSH;
static int LFD;
static const u32 *XD[KG_MAXK];
static u32 *OUT;
static u64 *AB, *ABtop;

// ===== v2 PACKED EVENT =====================================================
//  v = [KA:20][TY:1][KB:20][ID:20]   (bits 43..62, 42, 22..41, 0..19)
//  KA = the compare key for THIS level (dim D+1), KB = the key for the NEXT
//  level (dim D+2), carried so the cross needs no re-key gather.
//  A plain u64 compare gives (KA, TY, KB, ID) -- KA primary, TY breaks equal
//  KA with query(TY=0) before insert(TY=1) = the strict-inequality rule.
//  Requires id < 2^20 and every coordinate < 2^20 (true: n = 1e6 < 2^20).
#define E_ID(v) ((u32)((v) & 0xFFFFFu))
#define E_KB(v) ((u32)(((v) >> 22) & 0xFFFFFu))
#define E_TY(v) ((u32)(((v) >> 42) & 1u))
#define E_KA(v) ((u32)((v) >> 43))
static inline u64 mk2(u32 ka, u32 ty, u32 kb, u32 id) {
  return ((u64)ka << 43) | ((u64)ty << 42) | ((u64)kb << 22) | (u64)id;
}
static inline int eid(u64 v) { return (int)(v & 0x7FFFFFFFu); }
static inline int lfbucket(u64 v) { return (int)(((u32)(v >> 32)) >> LFSH); }
static inline int eq_(u64 v) { return (int)((v >> 31) & 1); }
static inline int keep_test(int takeA, int role) { return 1 - (takeA ^ role); }
static inline u64 mk(u32 key, int q, int id) {
  return ((u64)key << 32) | ((u64)(1 - q) << 31) | (u64)id;
}


// resolve a fusion-level cross: events carry the last dim (K-1) coordinate in bits 32..63
// and are ordered by dim K-2; a left-insert before a right-query with a strictly smaller
// last-dim value is a hit.
static void ctr_solve(u64 *cross, int cx, u32 *dirt) {
  int nd = 0;
  for (int i = 0; i < cx; i++) {
#if MF_CTRPF > 0
    if (i + MF_CTRPF < cx) {
      u32 vf = E_KB(cross[i + MF_CTRPF]);
      __builtin_prefetch(&CT0[vf], 1, 0);   /* [PFCT] CT1/CT2 live in L1; only CT0 (1 MB) needs the lead */

    }
#endif
    u64 v = cross[i];
    u32 val = E_KB(v);   // At the fused level dim K-1 is already in KB; consume it directly.
    if (E_TY(v)) { ctr_ins(val); dirt[nd++] = val; }
    else OUT[E_ID(v)] += ctr_qry(val);
  }
  for (int i = 0; i < nd; i++) {
#if MF_CTRPF > 0
    if (i + MF_CTRPF < nd) {
      u32 vf = dirt[i + MF_CTRPF];
      __builtin_prefetch(&CT0[vf], 1, 1);


    }
#endif
    ctr_clr(dirt[i]);
  }
  ctr_reset_hi();
}


// small base: compact insert list + SIMD comparison, then insertion sort by the key
static const u32 VMASK[8][8] = {
  {0,0,0,0,0,0,0,0},
  {~0u,0,0,0,0,0,0,0},
  {~0u,~0u,0,0,0,0,0,0},
  {~0u,~0u,~0u,0,0,0,0,0},
  {~0u,~0u,~0u,~0u,0,0,0,0},
  {~0u,~0u,~0u,~0u,~0u,0,0,0},
  {~0u,~0u,~0u,~0u,~0u,~0u,0,0},
  {~0u,~0u,~0u,~0u,~0u,~0u,~0u,0}};
// [LDU2] one 32-byte unaligned load; gcc 9.3 (judge) otherwise splits a 256-bit
// load whose alignment it cannot prove into vmovdqu xmm + vinserti128 (2 uops).
static inline __m256i ldu256(const void *p) {
  __m256i v;
  __asm__("vmovdqu %1, %0" : "=x"(v) : "m"(*(const __m256i *)p));
  return v;
}
static inline u32 hsum256(__m256i v) {
  __m128i t = _mm_add_epi32(_mm256_castsi256_si128(v), _mm256_extracti128_si256(v, 1));
  t = _mm_add_epi32(t, _mm_shuffle_epi32(t, _MM_SHUFFLE(1, 0, 3, 2)));
  t = _mm_add_epi32(t, _mm_shuffle_epi32(t, _MM_SHUFFLE(2, 3, 0, 1)));
  return (u32)_mm_cvtsi128_si32(t);
}
template<int ND>
static void base_case_t(u64 *seq, int m, int d, u64 *out, int needOut) {
  const int nd = ND;
  __attribute__((aligned(32)))
  u32 IK[KG_BASE + 8], IC0[KG_BASE + 8], IC1[KG_BASE + 8], IC2[KG_BASE + 8], IC3[KG_BASE + 8];
  u32 QK[KG_BASE + 8], QC0[KG_BASE + 8], QC1[KG_BASE + 8], QC2[KG_BASE + 8], QC3[KG_BASE + 8];
  u32 QID[KG_BASE + 8], QN[KG_BASE + 8];
  const u32 *X1 = nd > 1 ? XD[d + 3] : 0, *X2 = nd > 2 ? XD[d + 4] : 0,
            *X3 = nd > 3 ? XD[d + 5] : 0;
  int ni = 0, nq = 0;
  for (int t = 0; t < m; t++) {
#if MF_LEAFLP > 0
    if (t + MF_LEAFLP < m) {
      int idf = (int)E_ID(seq[t + MF_LEAFLP]);
      if (nd > 1) __builtin_prefetch(&X1[idf], 0, 1);
      if (nd > 2) __builtin_prefetch(&X2[idf], 0, 1);
      if (nd > 3) __builtin_prefetch(&X3[idf], 0, 1);
    }
#endif
    u64 v = seq[t];
    int id = (int)E_ID(v);
    u32 k = E_KA(v);
    u32 c0 = 0, c1 = 0, c2 = 0, c3 = 0;
    if (nd > 0) c0 = E_KB(v);          // dim d+2 is IN the event -- no gather
    if (nd > 1) c1 = X1[id];
    if (nd > 2) c2 = X2[id];
    if (nd > 3) c3 = X3[id];
    int isins = (int)E_TY(v);
    IK[ni] = k; IC0[ni] = c0; IC1[ni] = c1; IC2[ni] = c2, IC3[ni] = c3; ni += isins;
    QK[nq] = k; QC0[nq] = c0; QC1[nq] = c1; QC2[nq] = c2, QC3[nq] = c3; QID[nq] = (u32)id; QN[nq] = (u32)ni; nq += 1 - isins;
  }
#if MF_LEAFG >= 2
  /* c18/4-query group: one insert-block load feeds 4 chains */
  #define MIN4(a0,a1,a2,a3) ((((a0) < (a1) ? (a0) : (a1))) < (((a2) < (a3) ? (a2) : (a3))) ? (((a0) < (a1) ? (a0) : (a1))) : (((a2) < (a3) ? (a2) : (a3))))
  // The rolling hints begin at query 4*PFL, so prime the uncovered prefix.
#if PFL > 0
  const int prime_end = nq < 4 * PFL ? nq : 4 * PFL;
  for (int p = 0; p < prime_end; ++p)
    __asm__ __volatile__("prefetchw %0" :: "m"(*(const char *)(&OUT[QID[p]])));
#endif
  int q = 0;
  for (; q + 4 <= nq; q += 4) {
#if PFL > 0
    if (q + 4 * PFL + 3 < nq) {
      __asm__ __volatile__("prefetchw %0" ::"m"(*(const char *)(&OUT[QID[q + 4 * PFL + 0]])));
      __asm__ __volatile__("prefetchw %0" ::"m"(*(const char *)(&OUT[QID[q + 4 * PFL + 1]])));
      __asm__ __volatile__("prefetchw %0" ::"m"(*(const char *)(&OUT[QID[q + 4 * PFL + 2]])));
      __asm__ __volatile__("prefetchw %0" ::"m"(*(const char *)(&OUT[QID[q + 4 * PFL + 3]])));
    }
#endif
    const int n = (int)QN[q];
    const int nA = (int)QN[q], nB = (int)QN[q + 1];
    __m256i kvA = _mm256_set1_epi32((int)(QK[q]) - 1),     kvB = _mm256_set1_epi32((int)(QK[q + 1]) - 1);
    __m256i v0A = _mm256_set1_epi32((int)(QC0[q]) - 1),    v0B = _mm256_set1_epi32((int)(QC0[q + 1]) - 1);
    __m256i v1A = _mm256_set1_epi32((int)(QC1[q]) - 1),    v1B = _mm256_set1_epi32((int)(QC1[q + 1]) - 1);
    __m256i v2A = _mm256_set1_epi32((int)(QC2[q]) - 1),    v2B = _mm256_set1_epi32((int)(QC2[q + 1]) - 1);
    __m256i v3A = _mm256_set1_epi32((int)(QC3[q]) - 1),    v3B = _mm256_set1_epi32((int)(QC3[q + 1]) - 1);
    __m256i accA = _mm256_setzero_si256(), accB = _mm256_setzero_si256();
    const int nC = (int)QN[q + 2], nD = (int)QN[q + 3];
    __m256i kvC = _mm256_set1_epi32((int)(QK[q + 2]) - 1),     kvD = _mm256_set1_epi32((int)(QK[q + 3]) - 1);
    __m256i v0C = _mm256_set1_epi32((int)(QC0[q + 2]) - 1),    v0D = _mm256_set1_epi32((int)(QC0[q + 3]) - 1);
    __m256i v1C = _mm256_set1_epi32((int)(QC1[q + 2]) - 1),    v1D = _mm256_set1_epi32((int)(QC1[q + 3]) - 1);
    __m256i v2C = _mm256_set1_epi32((int)(QC2[q + 2]) - 1),    v2D = _mm256_set1_epi32((int)(QC2[q + 3]) - 1);
    __m256i v3C = _mm256_set1_epi32((int)(QC3[q + 2]) - 1),    v3D = _mm256_set1_epi32((int)(QC3[q + 3]) - 1);
    __m256i accC = _mm256_setzero_si256(), accD = _mm256_setzero_si256();
    int j = 0;
    if (nd >= 3) {
      for (; j + 8 <= n; j += 8) {
        __m256i IKv = _mm256_load_si256((const __m256i *)(IK + j));
        __m256i C0v = _mm256_load_si256((const __m256i *)(IC0 + j));
        __m256i C1v = _mm256_load_si256((const __m256i *)(IC1 + j));
        __m256i C2v = _mm256_load_si256((const __m256i *)(IC2 + j));
        __m256i mA = _mm256_or_si256(_mm256_cmpgt_epi32(IKv, kvA), _mm256_cmpgt_epi32(C0v, v0A));
        __m256i mC = _mm256_or_si256(_mm256_cmpgt_epi32(IKv, kvC), _mm256_cmpgt_epi32(C0v, v0C));
        __m256i mB = _mm256_or_si256(_mm256_cmpgt_epi32(IKv, kvB), _mm256_cmpgt_epi32(C0v, v0B));
        __m256i mD = _mm256_or_si256(_mm256_cmpgt_epi32(IKv, kvD), _mm256_cmpgt_epi32(C0v, v0D));
        mA = _mm256_or_si256(mA, _mm256_cmpgt_epi32(C1v, v1A));
        mC = _mm256_or_si256(mC, _mm256_cmpgt_epi32(C1v, v1C));
        mB = _mm256_or_si256(mB, _mm256_cmpgt_epi32(C1v, v1B));
        mD = _mm256_or_si256(mD, _mm256_cmpgt_epi32(C1v, v1D));
        mA = _mm256_or_si256(mA, _mm256_cmpgt_epi32(C2v, v2A));
        mC = _mm256_or_si256(mC, _mm256_cmpgt_epi32(C2v, v2C));
        mB = _mm256_or_si256(mB, _mm256_cmpgt_epi32(C2v, v2B));
        mD = _mm256_or_si256(mD, _mm256_cmpgt_epi32(C2v, v2D));
        if (nd > 3) {   /* m161i key 3 */
          __m256i C3v = _mm256_load_si256((const __m256i *)(IC3 + j));
          mA = _mm256_or_si256(mA, _mm256_cmpgt_epi32(C3v, v3A));
          mC = _mm256_or_si256(mC, _mm256_cmpgt_epi32(C3v, v3C));
          mB = _mm256_or_si256(mB, _mm256_cmpgt_epi32(C3v, v3B));
          mD = _mm256_or_si256(mD, _mm256_cmpgt_epi32(C3v, v3D));
        }
        accA = _mm256_add_epi32(accA, mA);
        accC = _mm256_add_epi32(accC, mC);
        accB = _mm256_add_epi32(accB, mB);
        accD = _mm256_add_epi32(accD, mD);
      }
    } else {
      for (; j + 8 <= n; j += 8) {
        __m256i IKv = _mm256_load_si256((const __m256i *)(IK + j));
        __m256i mA = _mm256_cmpgt_epi32(IKv, kvA);
        __m256i mC = _mm256_cmpgt_epi32(IKv, kvC);
        __m256i mB = _mm256_cmpgt_epi32(IKv, kvB);
        __m256i mD = _mm256_cmpgt_epi32(IKv, kvD);
        if (nd > 0) {
          __m256i C0v = _mm256_load_si256((const __m256i *)(IC0 + j));
          mA = _mm256_or_si256(mA, _mm256_cmpgt_epi32(C0v, v0A));
          mC = _mm256_or_si256(mC, _mm256_cmpgt_epi32(C0v, v0C));
          mB = _mm256_or_si256(mB, _mm256_cmpgt_epi32(C0v, v0B));
          mD = _mm256_or_si256(mD, _mm256_cmpgt_epi32(C0v, v0D));
        }
        if (nd > 1) {
          __m256i C1v = _mm256_load_si256((const __m256i *)(IC1 + j));
          mA = _mm256_or_si256(mA, _mm256_cmpgt_epi32(C1v, v1A));
          mC = _mm256_or_si256(mC, _mm256_cmpgt_epi32(C1v, v1C));
          mB = _mm256_or_si256(mB, _mm256_cmpgt_epi32(C1v, v1B));
          mD = _mm256_or_si256(mD, _mm256_cmpgt_epi32(C1v, v1D));
        }
        accA = _mm256_add_epi32(accA, mA);
        accC = _mm256_add_epi32(accC, mC);
        accB = _mm256_add_epi32(accB, mB);
        accD = _mm256_add_epi32(accD, mD);
      }
    }
    if(nD-j<8) {
      if(nD>j) {
        __m256i iv=_mm256_load_si256((const __m256i*)(IK+j));
        __m256i mA=_mm256_cmpgt_epi32(iv,kvA);
        __m256i mB=_mm256_cmpgt_epi32(iv,kvB);
        __m256i mC=_mm256_cmpgt_epi32(iv,kvC);
        __m256i mD=_mm256_cmpgt_epi32(iv,kvD);
        if(nd>0) {
          __m256i cv=_mm256_load_si256((const __m256i*)(IC0+j));
          mA=_mm256_or_si256(mA,_mm256_cmpgt_epi32(cv,v0A));
          mB=_mm256_or_si256(mB,_mm256_cmpgt_epi32(cv,v0B));
          mC=_mm256_or_si256(mC,_mm256_cmpgt_epi32(cv,v0C));
          mD=_mm256_or_si256(mD,_mm256_cmpgt_epi32(cv,v0D));
        }
        if(nd>1) {
          __m256i cv=_mm256_load_si256((const __m256i*)(IC1+j));
          mA=_mm256_or_si256(mA,_mm256_cmpgt_epi32(cv,v1A));
          mB=_mm256_or_si256(mB,_mm256_cmpgt_epi32(cv,v1B));
          mC=_mm256_or_si256(mC,_mm256_cmpgt_epi32(cv,v1C));
          mD=_mm256_or_si256(mD,_mm256_cmpgt_epi32(cv,v1D));
        }
        if(nd>2) {
          __m256i cv=_mm256_load_si256((const __m256i*)(IC2+j));
          mA=_mm256_or_si256(mA,_mm256_cmpgt_epi32(cv,v2A));
          mB=_mm256_or_si256(mB,_mm256_cmpgt_epi32(cv,v2B));
          mC=_mm256_or_si256(mC,_mm256_cmpgt_epi32(cv,v2C));
          mD=_mm256_or_si256(mD,_mm256_cmpgt_epi32(cv,v2D));
        }
        if(nd>3) {
          __m256i cv=_mm256_load_si256((const __m256i*)(IC3+j));
          mA=_mm256_or_si256(mA,_mm256_cmpgt_epi32(cv,v3A));
          mB=_mm256_or_si256(mB,_mm256_cmpgt_epi32(cv,v3B));
          mC=_mm256_or_si256(mC,_mm256_cmpgt_epi32(cv,v3C));
          mD=_mm256_or_si256(mD,_mm256_cmpgt_epi32(cv,v3D));
        }
        accA=_mm256_add_epi32(accA,_mm256_and_si256(mA,_mm256_loadu_si256((const __m256i*)VMASK[nA-j])));
        accB=_mm256_add_epi32(accB,_mm256_and_si256(mB,_mm256_loadu_si256((const __m256i*)VMASK[nB-j])));
        accC=_mm256_add_epi32(accC,_mm256_and_si256(mC,_mm256_loadu_si256((const __m256i*)VMASK[nC-j])));
        accD=_mm256_add_epi32(accD,_mm256_and_si256(mD,_mm256_loadu_si256((const __m256i*)VMASK[nD-j])));
      }
      OUT[QID[q+0]]+=(u32)((int)nA+(int)hsum256(accA));
      OUT[QID[q+1]]+=(u32)((int)nB+(int)hsum256(accB));
      OUT[QID[q+2]]+=(u32)((int)nC+(int)hsum256(accC));
      OUT[QID[q+3]]+=(u32)((int)nD+(int)hsum256(accD));
    } else {
    {
      int jj = j;
      __m256i acc = accA;

      if (jj < nA) {
        int n = nA;
        __m256i msk = _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IK + jj)), kvA);
        if (nd > 0) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC0 + jj)), v0A));
        if (nd > 1) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC1 + jj)), v1A));
        if (nd > 2) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC2 + jj)), v2A));
        if (nd > 3) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC3 + jj)), v3A));
        msk = _mm256_and_si256(msk, _mm256_loadu_si256((const __m256i *)VMASK[n - jj]));
        acc = _mm256_add_epi32(acc, msk);
      }
      OUT[QID[q]] += (u32)((int)nA + (int)hsum256(acc));
    }
    {
      int jj = j;
      __m256i acc = accB;
      for (; jj + 8 <= nB; jj += 8) {
        __m256i msk = _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IK + jj)), kvB);
        if (nd > 0) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC0 + jj)), v0B));
        if (nd > 1) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC1 + jj)), v1B));
        if (nd > 2) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC2 + jj)), v2B));
        if (nd > 3) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC3 + jj)), v3B));
        acc = _mm256_add_epi32(acc, msk);
      }
      if (jj < nB) {
        int n = nB;
        __m256i msk = _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IK + jj)), kvB);
        if (nd > 0) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC0 + jj)), v0B));
        if (nd > 1) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC1 + jj)), v1B));
        if (nd > 2) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC2 + jj)), v2B));
        if (nd > 3) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC3 + jj)), v3B));
        msk = _mm256_and_si256(msk, _mm256_loadu_si256((const __m256i *)VMASK[n - jj]));
        acc = _mm256_add_epi32(acc, msk);
      }
      OUT[QID[q + 1]] += (u32)((int)nB + (int)hsum256(acc));
    }
    {
      int jj = j;
      __m256i acc = accC;
      for (; jj + 8 <= nC; jj += 8) {
        __m256i msk = _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IK + jj)), kvC);
        if (nd > 0) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC0 + jj)), v0C));
        if (nd > 1) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC1 + jj)), v1C));
        if (nd > 2) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC2 + jj)), v2C));
        if (nd > 3) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC3 + jj)), v3C));
        acc = _mm256_add_epi32(acc, msk);
      }
      if (jj < nC) {
        int n = nC;
        __m256i msk = _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IK + jj)), kvC);
        if (nd > 0) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC0 + jj)), v0C));
        if (nd > 1) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC1 + jj)), v1C));
        if (nd > 2) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC2 + jj)), v2C));
        if (nd > 3) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC3 + jj)), v3C));
        msk = _mm256_and_si256(msk, _mm256_loadu_si256((const __m256i *)VMASK[n - jj]));
        acc = _mm256_add_epi32(acc, msk);
      }
      OUT[QID[q + 2]] += (u32)((int)nC + (int)hsum256(acc));
    }
    {
      int jj = j;
      __m256i acc = accD;
      for (; jj + 8 <= nD; jj += 8) {
        __m256i msk = _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IK + jj)), kvD);
        if (nd > 0) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC0 + jj)), v0D));
        if (nd > 1) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC1 + jj)), v1D));
        if (nd > 2) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC2 + jj)), v2D));
        if (nd > 3) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC3 + jj)), v3D));
        acc = _mm256_add_epi32(acc, msk);
      }
      if (jj < nD) {
        int n = nD;
        __m256i msk = _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IK + jj)), kvD);
        if (nd > 0) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC0 + jj)), v0D));
        if (nd > 1) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC1 + jj)), v1D));
        if (nd > 2) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC2 + jj)), v2D));
        if (nd > 3) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC3 + jj)), v3D));
        msk = _mm256_and_si256(msk, _mm256_loadu_si256((const __m256i *)VMASK[n - jj]));
        acc = _mm256_add_epi32(acc, msk);
      }
      OUT[QID[q + 3]] += (u32)((int)nD + (int)hsum256(acc));
    }

    }
  }
  for (; q + 2 <= nq; q += 2) {
    const int n = (int)QN[q];
    const int nA = (int)QN[q], nB = (int)QN[q + 1];
    __m256i kvA = _mm256_set1_epi32((int)(QK[q]) - 1),     kvB = _mm256_set1_epi32((int)(QK[q + 1]) - 1);
    __m256i v0A = _mm256_set1_epi32((int)(QC0[q]) - 1),    v0B = _mm256_set1_epi32((int)(QC0[q + 1]) - 1);
    __m256i v1A = _mm256_set1_epi32((int)(QC1[q]) - 1),    v1B = _mm256_set1_epi32((int)(QC1[q + 1]) - 1);
    __m256i v2A = _mm256_set1_epi32((int)(QC2[q]) - 1),    v2B = _mm256_set1_epi32((int)(QC2[q + 1]) - 1);
    __m256i v3A = _mm256_set1_epi32((int)(QC3[q]) - 1),    v3B = _mm256_set1_epi32((int)(QC3[q + 1]) - 1);
    __m256i accA = _mm256_setzero_si256(), accB = _mm256_setzero_si256();
    int j = 0;
    if (nd >= 3) {
      for (; j + 8 <= n; j += 8) {
        __m256i IKv = _mm256_load_si256((const __m256i *)(IK + j));
        __m256i C0v = _mm256_load_si256((const __m256i *)(IC0 + j));
        __m256i C1v = _mm256_load_si256((const __m256i *)(IC1 + j));
        __m256i C2v = _mm256_load_si256((const __m256i *)(IC2 + j));
        __m256i mA = _mm256_or_si256(_mm256_cmpgt_epi32(IKv, kvA), _mm256_cmpgt_epi32(C0v, v0A));
        __m256i mB = _mm256_or_si256(_mm256_cmpgt_epi32(IKv, kvB), _mm256_cmpgt_epi32(C0v, v0B));
        mA = _mm256_or_si256(mA, _mm256_cmpgt_epi32(C1v, v1A));
        mB = _mm256_or_si256(mB, _mm256_cmpgt_epi32(C1v, v1B));
        mA = _mm256_or_si256(mA, _mm256_cmpgt_epi32(C2v, v2A));
        mB = _mm256_or_si256(mB, _mm256_cmpgt_epi32(C2v, v2B));
        if (nd > 3) {   /* m161i key 3 */
          __m256i C3v = _mm256_load_si256((const __m256i *)(IC3 + j));
          mA = _mm256_or_si256(mA, _mm256_cmpgt_epi32(C3v, v3A));
          mB = _mm256_or_si256(mB, _mm256_cmpgt_epi32(C3v, v3B));
        }
        accA = _mm256_add_epi32(accA, mA);
        accB = _mm256_add_epi32(accB, mB);
      }
    } else {
      for (; j + 8 <= n; j += 8) {
        __m256i IKv = _mm256_load_si256((const __m256i *)(IK + j));
        __m256i mA = _mm256_cmpgt_epi32(IKv, kvA);
        __m256i mB = _mm256_cmpgt_epi32(IKv, kvB);
        if (nd > 0) {
          __m256i C0v = _mm256_load_si256((const __m256i *)(IC0 + j));
          mA = _mm256_or_si256(mA, _mm256_cmpgt_epi32(C0v, v0A));
          mB = _mm256_or_si256(mB, _mm256_cmpgt_epi32(C0v, v0B));
        }
        if (nd > 1) {
          __m256i C1v = _mm256_load_si256((const __m256i *)(IC1 + j));
          mA = _mm256_or_si256(mA, _mm256_cmpgt_epi32(C1v, v1A));
          mB = _mm256_or_si256(mB, _mm256_cmpgt_epi32(C1v, v1B));
        }
        accA = _mm256_add_epi32(accA, mA);
        accB = _mm256_add_epi32(accB, mB);
      }
    }
    if(nB-j<8){
      const __m256i ik=_mm256_load_si256((const __m256i*)(IK+j));
      __m256i ma=_mm256_cmpgt_epi32(ik,kvA),mb=_mm256_cmpgt_epi32(ik,kvB);
      if(nd>0){const __m256i v=_mm256_load_si256((const __m256i*)(IC0+j));
        ma=_mm256_or_si256(ma,_mm256_cmpgt_epi32(v,v0A));
        mb=_mm256_or_si256(mb,_mm256_cmpgt_epi32(v,v0B));}
      if(nd>1){const __m256i v=_mm256_load_si256((const __m256i*)(IC1+j));
        ma=_mm256_or_si256(ma,_mm256_cmpgt_epi32(v,v1A));
        mb=_mm256_or_si256(mb,_mm256_cmpgt_epi32(v,v1B));}
      if(nd>2){const __m256i v=_mm256_load_si256((const __m256i*)(IC2+j));
        ma=_mm256_or_si256(ma,_mm256_cmpgt_epi32(v,v2A));
        mb=_mm256_or_si256(mb,_mm256_cmpgt_epi32(v,v2B));}
      if(nd>3){const __m256i v=_mm256_load_si256((const __m256i*)(IC3+j));
        ma=_mm256_or_si256(ma,_mm256_cmpgt_epi32(v,v3A));
        mb=_mm256_or_si256(mb,_mm256_cmpgt_epi32(v,v3B));}
      accA=_mm256_add_epi32(accA,_mm256_and_si256(ma,_mm256_loadu_si256((const __m256i*)VMASK[nA-j])));
      accB=_mm256_add_epi32(accB,_mm256_and_si256(mb,_mm256_loadu_si256((const __m256i*)VMASK[nB-j])));
      OUT[QID[q]]+=(u32)((int)nA+(int)hsum256(accA));
      OUT[QID[q+1]]+=(u32)((int)nB+(int)hsum256(accB));
    }else{
    // per-query tails: each member finishes [j, QN[.]) on its own
    {
      int jj = j;
      __m256i acc = accA;

      if (jj < nA) {
        int n = nA;
        __m256i msk = _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IK + jj)), kvA);
        if (nd > 0) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC0 + jj)), v0A));
        if (nd > 1) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC1 + jj)), v1A));
        if (nd > 2) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC2 + jj)), v2A));
        if (nd > 3) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC3 + jj)), v3A));
        msk = _mm256_and_si256(msk, _mm256_loadu_si256((const __m256i *)VMASK[n - jj]));
        acc = _mm256_add_epi32(acc, msk);
      }
      OUT[QID[q]] += (u32)((int)nA + (int)hsum256(acc));
    }
    {
      int jj = j;
      __m256i acc = accB;
      for (; jj + 8 <= nB; jj += 8) {
        __m256i msk = _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IK + jj)), kvB);
        if (nd > 0) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC0 + jj)), v0B));
        if (nd > 1) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC1 + jj)), v1B));
        if (nd > 2) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC2 + jj)), v2B));
        if (nd > 3) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC3 + jj)), v3B));
        acc = _mm256_add_epi32(acc, msk);
      }
      if (jj < nB) {
        int n = nB;
        __m256i msk = _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IK + jj)), kvB);
        if (nd > 0) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC0 + jj)), v0B));
        if (nd > 1) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC1 + jj)), v1B));
        if (nd > 2) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC2 + jj)), v2B));
        if (nd > 3) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC3 + jj)), v3B));
        msk = _mm256_and_si256(msk, _mm256_loadu_si256((const __m256i *)VMASK[n - jj]));
        acc = _mm256_add_epi32(acc, msk);
      }
      OUT[QID[q + 1]] += (u32)((int)nB + (int)hsum256(acc));
    }
    }
  }
#endif
  for (; q < nq; q++) {
    const int n = (int)QN[q];
    __m256i kv = _mm256_set1_epi32((int)(QK[q]) - 1);
    __m256i v0 = _mm256_set1_epi32((int)(QC0[q]) - 1);
    __m256i v1 = _mm256_set1_epi32((int)(QC1[q]) - 1);
    __m256i v2 = _mm256_set1_epi32((int)(QC2[q]) - 1);
    __m256i v3 = _mm256_set1_epi32((int)(QC3[q]) - 1);
    __m256i acc = _mm256_setzero_si256();
    int j = 0;
    switch (nd) {
      case 0:
        for (; j + 8 <= n; j += 8)
          acc = _mm256_add_epi32(acc, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IK + j)), kv));
        break;
      case 1:
        for (; j + 8 <= n; j += 8) {
      __m256i msk = _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IK + j)), kv);
      msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC0 + j)), v0));
      acc = _mm256_add_epi32(acc, msk);
        }
        break;
      case 2:
        for (; j + 8 <= n; j += 8) {
      __m256i msk = _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IK + j)), kv);
      msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC0 + j)), v0));
      msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC1 + j)), v1));
      acc = _mm256_add_epi32(acc, msk);
        }
        break;
      default:
        for (; j + 8 <= n; j += 8) {
      __m256i msk = _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IK + j)), kv);
      msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC0 + j)), v0));
      msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC1 + j)), v1));
      msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC2 + j)), v2));
      if (nd > 3) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC3 + j)), v3));
      acc = _mm256_add_epi32(acc, msk);
        }
        break;
    }
    if (j < n) {                                  // partial block, masked by a table lookup
      __m256i msk = _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IK + j)), kv);
      if (nd > 0) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC0 + j)), v0));
      if (nd > 1) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC1 + j)), v1));
      if (nd > 2) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC2 + j)), v2));
      if (nd > 3) msk = _mm256_or_si256(msk, _mm256_cmpgt_epi32(_mm256_load_si256((const __m256i *)(IC3 + j)), v3));
      msk = _mm256_and_si256(msk, _mm256_loadu_si256((const __m256i *)VMASK[n - j]));
      acc = _mm256_add_epi32(acc, msk);
    }
    u32 c = hsum256(acc);
    OUT[QID[q]] += (u32)((int)n + (int)c);
  }
  if (!needOut) return;
#if LEAFNB
  {
    const int NB = (LFAUTO && m <= LEAFNB) ? (m < 8 ? 8 : m) : LEAFNB;
    const int LB = (G_LIM < NB) ? G_LIM : NB;   // used-bucket bound
    /* [SORTB] one extra leading slot so that cnt[-1] == 0 is a legal read: the
       bucket-b discovery pass below can then vectorise over every bucket. */
    alignas(32) unsigned short cntb[LEAFNB + 32];
    unsigned short *cnt = cntb + 15;
    u32 multib[(LEAFNB+31)/32];
    multib[(LB-2)>>5]=0;
    cnt[-1] = 0;
    for (int b = 0; b < LB; b++) cnt[b] = 0;
    for (int t = 0; t < m; t++) cnt[(int)(E_KA(seq[t]) >> (LFSH + LFD)) + 1]++;
    {int b=1;__m256i carry=_mm256_setzero_si256();
      const __m256i last=_mm256_setr_epi8(14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15);
      for(;b+16<=LB;b+=16){
        __m256i v=_mm256_load_si256((const __m256i*)(cnt+b));
        unsigned short mask=(unsigned short)_pext_u32((u32)_mm256_movemask_epi8(_mm256_cmpgt_epi16(v,_mm256_set1_epi16(1))),0xAAAAAAAAu);
        memcpy((unsigned char*)multib+((b-1)>>3),&mask,2);
        v=_mm256_add_epi16(v,_mm256_slli_si256(v,2));
        v=_mm256_add_epi16(v,_mm256_slli_si256(v,4));
        v=_mm256_add_epi16(v,_mm256_slli_si256(v,8));
        __m256i cross=_mm256_shuffle_epi8(v,last);
        v=_mm256_add_epi16(v,_mm256_permute2x128_si256(cross,cross,0x08));
        __m256i total=_mm256_shuffle_epi8(v,last);
        total=_mm256_permute2x128_si256(total,total,0x11);
        _mm256_store_si256((__m256i*)(cnt+b),_mm256_add_epi16(v,carry));
        carry=_mm256_add_epi16(carry,total);
      }
      u32 sum=(u32)_mm_extract_epi16(_mm256_castsi256_si128(carry),0);
      if(b<LB){unsigned short mask=0;int begin=b;for(;b<LB;b++){u32 c=cnt[b];mask|=(unsigned short)((c>1)<<(b-begin));sum+=c;cnt[b]=(unsigned short)sum;}memcpy((unsigned char*)multib+((begin-1)>>3),&mask,2);}
    }
    for (int t = 0; t < m; t++) { u64 v = seq[t]; out[cnt[(int)(E_KA(v) >> (LFSH + LFD))]++] = v; }
    /* [SORTB] buckets holding 0 or 1 events need no work, and with LEAFNB >= m the
       great majority are of that kind; a 256-bit subtract/compare/movemask finds the
       multi-event buckets eight at a time, so the scan loop takes no data-dependent
       branch at all -- only the 1/8-odd that really hold two or more are revisited. */
    {
      const __m256i one1 = _mm256_set1_epi32(1);
      int b = 0;
      /* [SORTB3] thirty-two buckets per iteration: four vector pairs build one
         32-bit mask, so the loop takes one empty-mask exit per 32 slots. */
      for (; b < LB - 1; b += 32) {
        unsigned mask=multib[b>>5];
        while (mask) {
          int k = __builtin_ctz(mask);
          mask &= mask - 1;
          int bb = b + k;
          int lo = (int)cnt[bb - 1];
          int hi = (int)cnt[bb];
          if (hi - lo == 2) {
            u64 a = out[lo], c = out[lo + 1];
            int lt = (a < c);
            out[lo] = lt ? a : c;
            out[lo + 1] = lt ? c : a;
          } else if (hi - lo <= 4) {
            /* [CE34] fixed compare-exchange networks for three and four events */
            u64 a = out[lo], b = out[lo + 1], c = out[lo + 2];
            if (hi - lo == 3) {
              u64 x = a, y = b; int lt = x < y; a = lt ? x : y; b = lt ? y : x;
              x = b; y = c; lt = x < y; b = lt ? x : y; c = lt ? y : x;
              x = a; y = b; lt = x < y; a = lt ? x : y; b = lt ? y : x;
              out[lo] = a; out[lo + 1] = b; out[lo + 2] = c;
            } else {
              u64 d = out[lo + 3], x, y; int lt;
              x = a; y = b; lt = x < y; a = lt ? x : y; b = lt ? y : x;
              x = c; y = d; lt = x < y; c = lt ? x : y; d = lt ? y : x;
              x = a; y = c; lt = x < y; a = lt ? x : y; c = lt ? y : x;
              x = b; y = d; lt = x < y; b = lt ? x : y; d = lt ? y : x;
              x = b; y = c; lt = x < y; b = lt ? x : y; c = lt ? y : x;
              out[lo] = a; out[lo + 1] = b; out[lo + 2] = c; out[lo + 3] = d;
            }
          } else
          for (int t = lo + 1; t < hi; t++) {
            u64 v = out[t];
            int q = t - 1;
            while (q >= lo && v < out[q]) { out[q + 1] = out[q]; q--; }
            out[q + 1] = v;
          }
        }
      }
    }
  }
#else
  for (int t = 1; t < m; t++) {
    u64 v = seq[t];
    int q = t - 1;
    while (q >= 0 && v < seq[q]) { seq[q + 1] = seq[q]; q--; }
    seq[q + 1] = v;
  }
  memcpy(out, seq, sizeof(u64) * (size_t)m);
#endif
}

static void base_case(u64 *seq, int m, int d, u64 *out, int needOut) {
  switch (K - (d + 2)) {
    case 0: base_case_t<0>(seq, m, d, out, needOut); break;
    case 1: base_case_t<1>(seq, m, d, out, needOut); break;
    case 2: base_case_t<2>(seq, m, d, out, needOut); break;
    case 3: base_case_t<3>(seq, m, d, out, needOut); break;
    case 4: base_case_t<4>(seq, m, d, out, needOut); break;
    default: base_case_t<4>(seq, m, d, out, needOut); break;
  }
}



// ---- ND specialisation dispatcher (the fleet's `DN` recipe) ----
static void base_case(u64 *seq, int m, int d, u64 *out, int needOut);

// ================= depth-templated solve: D and KT are compile-time =================
template <bool B> struct TB {};
template <int V> struct NCL { static const int v = (V < 0) ? 0 : ((V > 4) ? 4 : V); };

template <int KT, int D, bool NEED> static inline void solve_t(u64 *seq, int m, u64 *out);

// ---- terminal level (D == KT-1): every insert-before-query pair qualifies ----
template <int KT, int D, bool NEED>
static void solve_b(u64 *seq, int m, u64 *out, TB<true>) {
  int cnt = 0;
  for (int t = 0; t < m; t++) {
    u64 v = seq[t];
    if (E_TY(v)) cnt++;                             // insert
    else OUT[E_ID(v)] += (u32)cnt;                  // query
  }
}

// ---- general level (D < KT-1) ----
template <int KT, int D, bool NEED>
static void solve_b(u64 *seq, int m, u64 *out, TB<false>) {
  if (m <= KG_BASE) {
    base_case_t<NCL< KT - (D + 2) >::v>(seq, m, D, out, NEED);
    return;
  }
  int h = m >> 1, r = m - h;
  u64 *save = ABtop;
  u64 *retA = ABtop; ABtop += h+1;
  u64 *retB = ABtop; ABtop += r;
  solve_t<KT, D, true>(seq, h, retA);
  solve_t<KT, D, true>(seq + h, r, retB);
  u64 *cross = ABtop; ABtop += m + 1;
  // v2: PROMOTE moves the carried KB up into the KA slot (a new level's key);
  // GATHER fetches the next KB (dim D+3) -- the ONLY remaining per-level gather,
  // and it exists only at D = 0 for KT = 4.
  const int PROM = (D + 2 <= KT - 1);
  const int GAT = (D + 3 <= KT - 1);
  const u32 *XN = XD[(D + 3 <= KG_MAXK - 1) ? (D + 3) : 0];
  retA[h]=~0ULL;
  const u64 *pa=retA,*pb=retB,*const pe=retA+h,*const qe=retB+r;
  u64 *po=out,*pc=cross;
  u64 ea=*pa, eb=*pb;
  while(pb<qe){
#if KG_PF
    if(GAT){
      if(pe-pa>KG_PF)__builtin_prefetch(XN+E_ID(pa[KG_PF]),0,1);
      if(qe-pb>KG_PF)__builtin_prefetch(XN+E_ID(pb[KG_PF]),0,1);
    }
#endif
    const u64 ea2=pa[1], eb2=pb[1];   /* [SPIPE2] speculative: pa[1] is the */
    u64 v; const u64 *pan,*pbn; u32 ka,kb;   /* retA sentinel slot, pb[1] stays in-arena */
    (void)pe;
    __asm__("xorl %k[k0],%k[k0]\n\t"
            "xorl %k[k1],%k[k1]\n\t"
            "btq $42,%[ea]\n\t"
            "setc %b[k0]\n\t"
            "btq $42,%[eb]\n\t"
            "setnc %b[k1]\n\t"
            "cmpq %[eb],%[ea]\n\t"
            "movq %[eb],%[v]\n\t"
            "cmovb %[ea],%[v]\n\t"
            "leaq 8(%[pa]),%[pan]\n\t"
            "leaq 8(%[pb]),%[pbn]\n\t"
            "cmovb %[pan],%[pa]\n\t"
            "cmovae %[pbn],%[pb]\n\t"
            "cmovb %k[k0],%k[k1]\n\t"
            "cmovb %[ea2],%[ea]\n\t"
            "cmovae %[eb2],%[eb]"
      : [pa]"+&r"(pa),[pb]"+&r"(pb),[v]"=&r"(v),[k0]"=&r"(ka),[k1]"=&r"(kb),[pan]"=&r"(pan),[pbn]"=&r"(pbn),[ea]"+&r"(ea),[eb]"+&r"(eb)
      : [ea2]"r"(ea2),[eb2]"r"(eb2):"cc");
    if(NEED)*po++=v;
    *pc=v;pc+=kb;
  }
  while(pa<pe){u64 v=*pa++;if(NEED)*po++=v;if(E_TY(v))*pc++=v;}
  int cx=(int)(pc-cross);
  if (GAT) {                       // ----- C1: cross re-key, second pass -----
    int j=0;
    const __m256i idmask=_mm256_set1_epi64x(0xfffffULL);
    const __m256i kmask=_mm256_set1_epi64x(0xfffffULL<<43);
    const __m256i keepmask=_mm256_set1_epi64x((1ULL<<42)|0xfffffULL);
    for(;j+4<=cx;j+=4){
      if(j+67<cx)for(int z=0;z<4;z++)__builtin_prefetch(&XN[E_ID(cross[j+64+z])],0,1);
      __m256i v=_mm256_loadu_si256((const __m256i*)(cross+j));
      __m256i ix=_mm256_and_si256(v,idmask);
      __m128i c=_mm256_i64gather_epi32((const int*)XN,ix,4);
      __m256i kb=_mm256_slli_epi64(_mm256_cvtepu32_epi64(c),22);
      __m256i ka=_mm256_and_si256(_mm256_slli_epi64(v,21),kmask);
      __m256i res=_mm256_or_si256(_mm256_or_si256(ka,kb),_mm256_and_si256(v,keepmask));
      _mm256_storeu_si256((__m256i*)(cross+j),res);
    }
    for (; j < cx; j++) {
      if (j + 64 < cx) __builtin_prefetch(&XN[E_ID(cross[j + 64])], 0, 1);
      u64 v = cross[j];
      cross[j] = ((v << 21) & (0xFFFFFull << 43)) | (v & (1ull << 42)) | (v & 0xFFFFFull) |
                 ((u64)XN[E_ID(v)] << 22);
    }
  } else if (PROM && !(FUSE_OK && D == KT - 3)) {
    for (int j = 0; j < cx; j++) {
      u64 v = cross[j];
      cross[j] = ((v << 21) & (0xFFFFFull << 43)) | (v & (1ull << 42)) | (v & 0xFFFFFull);
    }
  }
  if (FUSE_OK && D == KT - 3) {
    u32 *dirt = (u32 *)ABtop; ABtop += (cx + 3) / 2 + 1;
    ctr_solve(cross, cx, dirt);
  } else {
    solve_t<KT, D + 1, false>(cross, cx, nullptr);
  }
  ABtop = save;
}

template <int KT, int D, bool NEED>
static inline void solve_t(u64 *seq, int m, u64 *out) {
  if (m <= 1) return;
  solve_b<KT, D, NEED>(seq, m, out, TB<(D >= KT - 1)>());
}
// ====================================================================================


static u32 *g_ord, *g_x;

static void sort0(int n) {
  const u32 *X0 = XD[0];
  u32 *cnt = g_x;
  memset(cnt, 0, sizeof(u32) * (size_t)(n + 1));
  for (int i = 0; i < n; i++) cnt[X0[i] + 1]++;
  for (int i = 0; i < n; i++) cnt[i + 1] += cnt[i];
  for (int i = 0; i < n; i++) g_ord[cnt[X0[i]]++] = (u32)i;
}

template <int KT>
static void run_t(int n, const u32 **x, u32 *out) {
  LFSH = 0; LFD = 0; CTN = (u32)n;
  for (int d = 0; d < KT; d++) XD[d] = x[d];
  OUT = out;
  ABtop = AB;
  if (n <= 1) return;
  FUSE_OK = (KT >= 4 && n > 2 && (u32)n < CT_MAXV);
  if(FUSE_OK){
    const u32*XL=XD[KT-1];size_t count=((size_t)n+31)/32;
    memset(CT1,0,(count+8)*sizeof(u16));
    for(int i=0;i<n;i++)if(++CT1[XL[i]>>5]>255){FUSE_OK=0;break;}
    memset(CT1,0,(count+8)*sizeof(u16));
  }
  {
    int bit = 0;
    while ((n >> bit) >= LEAFNB && bit < 30) bit++;
    LFSH = bit; LFD = 0;
  }
  G_LIM = (int)(((u32)(n - 1)) >> (LFSH + LFD)) + 2;
  sort0(n);
  const u32 *X0 = XD[0], *X1 = XD[1];
  u64 *ev = AB;                     // top-level event array: 2n entries
  int m=0,g=0;
  const u32 *X2=XD[2];
  for(int value=0;value<n;value++){
    int g1=(int)g_x[value], count=g1-g;
    for(int t=g;t<g1;t++){
      u32 q=g_ord[t];
      u64 v=mk2(X1[q],0,X2[q],q);
      ev[m+t-g]=v;
      ev[m+count+t-g]=v|(1ull<<42);
    }
    m+=2*count;g=g1;
  }
  ABtop = AB + m;
  solve_t<KT, 0, false>(ev, m, nullptr);
}

}  // namespace kg

static u64 g_arena[KG_ARENA];
static u32 g_ord_st[1048576], g_x_st[1048576];
static int g_ready = 0;

static void setup() {
  if (g_ready) return;
  g_ready = 1;
  kg::AB = g_arena;
  kg::g_ord = g_ord_st;
  kg::g_x = g_x_st;
}

void count_4d(int n, const unsigned *x[4], unsigned *out) {
  setup();
  memset(out, 0, sizeof(unsigned) * (size_t)n);
  kg::run_t<4>(n, (const unsigned **)x, out);
}
void count_5d(int n, const unsigned *x[5], unsigned *out) {
  setup();
  memset(out, 0, sizeof(unsigned) * (size_t)n);
  kg::run_t<5>(n, (const unsigned **)x, out);
}
void count_6d(int n, const unsigned *x[6], unsigned *out) {
  setup();
  memset(out, 0, sizeof(unsigned) * (size_t)n);
  kg::run_t<6>(n, (const unsigned **)x, out);
}
#pragma GCC pop_options

CompilationN/AN/ACompile OKScore: N/A

Testcase #12.569 s85 MB + 324 KBAcceptedScore: 100


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