// ===== REFERENCES =====
// [1] duck.ac 用户 **saffah_cc_v41_260924**,提交 #107885 <https://duck.ac/submission/107885>(noi17e)
// 用途:**本文件的代码骨架与全部算法直接复制自该提交**(他实时榜首 7870us / 7876KB)。
// 含 IT/VK 单 u64 位域打包、**R11F 三趟 11-bit LSD radix(直方图"一趟建三张":
// 排序只置换多重集、不改变它 ⇒ 每趟的数字直方图恒同)**、**CJ3 散射目标行预取**
// (读 src[i+16] 的顺序流,用目标桶游标 cnt[bb] 预测 i 那一步的落行)、
// 值序 bitset 池贪心 + 天循环 keep 语义、all-x0 快路径、BUK 连续桶计数排序、
// GT4 输出表、`__libc_start_main` 覆盖 + DuckInfo 直读直写。
// [2] duck.ac 用户 **saffah_cc_v41_agg1**(本账号),提交 #106449 <https://duck.ac/submission/106449>
// 用途:**复制其 union 手法**——VK∪QANS 与 BHEA∪qmap∪qp2 同址复用(本账号 #100306/#106449
// 实测零布局副作用);本发把对手的 qmap 阈值 (1<<17) 一并收到 NMAX 以配合 union 尺寸。
// [3] duck.ac FAQ <https://duck.ac/faq>:判题机缓存几何与"空间 = 写入页数 x 4KB"的计费口径。
// ======================
// ===== 思路 =====
// 本发属"抄对手 + 再叠一刀"(BRIEF 2.18.349 / 2.19.828):引用 [1] 是逐字节复刻的新基座,
// 引用 [2] 是本账号已验证过的 union 手法;下面 [F] 是本席位本次唯一的新思路。
//
// ★ **[F] 把三个 11-bit 基数直方图融合进读入段(删掉 HST 整趟扫描)**
// 对手([1] 的 R11F)在排序前单独扫一遍 2n 个 64 位键来建三张 2048 桶直方图:
// 每个元素付 1 次 1.6MB 顺序读 + 3 次 `HST[p][(v>>sh)&2047]++`(3 次 RMW 进 24KB)。
// 但**这三个数字在构造键的那一行就已经在寄存器里**:键 = `(value<<18)|idx`,于是
// 数字0 = (v>>18)&2047 = value & 2047
// 数字1 = (v>>29)&2047 = (value>>11) & 2047
// 数字2 = (v>>40)&2047 = (value>>22) & 2047
// 而读入段本来就同时持有 a 与 b=a+s(两者就是两条键的 value)⇒ 把 6 次自增
// (a 三次 + b 三次)挪进读入循环即可,**整个 HST 扫描趟消失**,只剩 3×2048 的前缀和。
// 直方图的"趟不变"性质不受影响(它只依赖"排序是置换"这一事实,与在哪里计数无关)。
// ⚠ 与"省一趟"的区别:这不是把同一趟挪个位置,而是**该趟的载荷(1.6MB 键读)不再存在**;
// 代价只是读入段多 6 条 RMW(目标表 24KB、全在 L1)。
//
// 判题机同输入多臂探针(`tools/probe.py`,xmax=0 档案 = tc21/tc23 的快路径形态,
// 读数为**判题机自己的 rdtscp 周期**;每个变体同一份合成输入、同一次运行内取相位):
// | 变体 | COLD总(=生产口径) | WARM总 | WARM rxrb | WARM parse | mem |
// | v0 对手原样 | 24.129M | 22.298M | 8.930M | 6.635M | 11164KB |
// | vU 仅 union | 24.025M | 22.248M | 8.780M | 6.599M | 9996KB |
// | **vF 仅 [F]** | 23.307M | 21.464M | 8.008M | 6.764M | 11164KB |
// | **vUF = 本发** | **23.297M** | 21.528M | 7.874M | 6.766M | **9996KB** |
// | vUSP(另加我方旧刀)| 24.711M | 22.806M | 9.493M | 6.744M | 9996KB |
// ⇒ [F] 的机理兑现:rxrb -10.3%(省掉整趟 1.6MB 读 + 600k 次键上移位),parse 只 +0.13M
// (读入段多 6 次 L1 RMW)⇒ 净 -3.45%(COLD 口径)。
// ⇒ ★ **同批被否掉的两把我方旧刀(本发刻意不带)**:SIMD `rd()` 与 rank build 单 store
// 在对手的新基座上让 COLD 变成 24.711M(**更慢**)⇒ "自家旧刀"必须在新基座上重新定价,
// 不能默认继承(BRIEF 2.19.806/846 的同族)。这也是本发只叠 [F] + union 的原因。
//
// 正确性:与已达标本账号件 `#106449` 在 6 组域内生产规模输入上**逐字节相同**
// (r_m2 / allx0big / n17g_mix,含一般路与 all-x0 两形态),并通过 `e17z_rand.py`
// 域内随机差分 200 例(8 种形态 × 25 轮)零失败。
// ======================
#pragma GCC optimize("O3","no-tree-vectorize","web")
#pragma GCC target("bmi,bmi2,popcnt,lzcnt")
#include <cstring>
typedef unsigned long long u64;
typedef long long i64;
typedef unsigned int u32;
typedef unsigned char u8;
static const u8 *gip;
static const u8 *gie;
static u8 *gob;
/* noi17e 【NOI2017】蔬菜 -- reverse-day greedy, bitset pool over value ranks.
*
* Day t = P..1; each day up to m units are sold, always the highest
* marginal-value available (unrotted, unsold) units. Vegetable i's first sold
* unit is worth a_i+s_i, every further unit a_i.
* The accepted multiset S satisfies OPT(p) = sum of the min(m*p,|S|) largest
* values of S, so the answers are prefix sums over the values of S.
*
* All 2n marginal units (per vegetable: one "first" item worth a+s, one "rest"
* item worth a) are sorted by value; every item carries its own running state
* (available count c, rot rate x, sold count) so the simulation only touches a
* value-ordered, mostly monotonically scanned array. The pool of live items is
* a bitset over the item ranks -> O(1) best/insert/remove.
*/
#define NMAX 100005
#define IMAX 200005
#define WMAX ((IMAX >> 6) + 8)
#define W2MAX ((WMAX >> 6) + 8)
typedef unsigned long long u64;
typedef long long i64;
typedef unsigned int u32;
typedef unsigned char u8;
/* IT and the radix sort's scratch buffer are the SAME 3.2 MB of pages. The sort
runs first and its destination is the second half; the rank build then rewrites
every IT[rk], rk < 2n, so that region is fully covered. This removes a whole
1.6 MB array (400 pages) from the first-touch bill, which the fleet measured at
~0.29-0.5 us per page on this row. */
/* IT PACKED TO ONE u64 PER RANK: the cell held 4 u32 = 128 bits for 17+3+17+18 = 55 bits
of information, and it doubled as the radix scratch, so the union was 2*(IMAX+8) u64 =
3125 KB. Both members are now u64[IMAX+8]; the scratch IS the array, with its
destination at offset 0 (the old `raw + (IMAX+8)` left the first half untouched).
Union gone: 3125 KB -> 1563 KB, ~390 pages. nrm's "rest item" marker 0xFFFFFFFF ->
0x3FFFF (max real rank 2n-1 = 199999). */
#define I_CM 0x1FFFFULL
#define I_XS 17
#define I_SS 20
#define I_NS 37
#define ITMARK 0x3FFFFu
#define ITC_(v) ((u32)((v) & I_CM))
#define ITX_(v) ((u32)(((v) >> I_XS) & 7u))
#define ITSOLD_(v) ((u32)(((v) >> I_SS) & I_CM))
#define ITNRM_(v) ((u32)(((v) >> I_NS) & 0x3FFFFu))
#define IT_UPD(r, m, sh, val) (ITU[(r)] = (ITU[(r)] & ~((u64)(m) << (sh))) | ((u64)(val) << (sh)))
static u64 __attribute__((aligned(64))) ITU[IMAX + 8];
static u32 HST[3][2048];
static u32 BUK[NMAX + 2]; /* counting-sort buckets: day d's first-items live in
[BHEA[d], BHEA[d+1]) -- contiguous, no pointer chase */
static u64 __attribute__((aligned(64))) ITEM[IMAX + 8];
static u64 ITMP[NMAX + 8]; /* only the rare P>=2^17 query radix uses this */
/* ONE 16-byte, 16-byte-ALIGNED entry per vegetable. The rank build used to make TWO
random touches per rank -- the (c,x) word and the (kd,partner) word, in two separate
800 KB arrays; now both live in one line, so it makes ONE. Merging streams, not
eliminating a read: the species that paid in K1. */
/* VK PACKED INTO ONE u64. Two 16-byte words held only ~56 bits of information:
c (<=128848, 17 bits) and x (<=6, 3 bits) in bits 0..19; kd/take (<=2^18) and
rank rk (<=2n=200000 < 2^18) in bits 20..55. Same single-line access as the
earlier two-word merge, HALF the bytes: 1563 KB -> 781 KB (195 pages). */
#define VKCX(v) ((u32)((v) & 0x1FFFFu)) /* c | x<<17 */
#define VKCR(v) ((u32)(v) & 0x1FFFFu) /* same, as c */
#define VKX(v) ((u32)(((v) >> 17) & 7u))
#define VKKR(v) ((v) >> 20) /* kd/take | rk<<18 */
static union VKQ_t { u64 vku[NMAX]; u64 qansu[NMAX]; } VKQ __attribute__((aligned(64)));
#define VK (VKQ.vku)
#define QANS (VKQ.qansu)
static u64 __attribute__((aligned(64))) BS0[WMAX], BS1[W2MAX], BS2[4];
static u32 QP[NMAX];
/* QP2 (P >= 2^17 path) and QMAP (P < 2^17 path) are mutually exclusive, so they
share one allocation: -400 KB of first-touched pages. */
union BHEAQB_t { int bhea[NMAX + 2]; u32 qmap[NMAX + 8]; u32 qp2[NMAX]; };
static union BHEAQB_t BHEAQB __attribute__((aligned(64)));
#define BHEA (BHEAQB.bhea)
#define QMAPU (BHEAQB.qmap)
#define QP2 (BHEAQB.qp2)
/* ---- input ---- */
static const u64 MASKV[9] = {0ULL, 0xFFULL, 0xFFFFULL, 0xFFFFFFULL, 0xFFFFFFFFULL,
0xFFFFFFFFFFULL, 0xFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL};
static const u64 INV5[9] = {1ULL,
0xCCCCCCCCCCCCCCCDULL, 0x8F5C28F5C28F5C29ULL, 0x1CAC083126E978D5ULL, 0xD288CE703AFB7E91ULL,
0x5D4E8FB00BCBE61DULL, 0x790FB65668C26139ULL, 0xE5032477AE8D46A5ULL, 0xC767074B22E90E21ULL};
static inline u32 rd(void) {
const u8 *p = gip;
while (*p <= ' ') p++;
u32 v = 0;
while (*p > ' ') { v = v * 10u + (u32)(*p - '0'); p++; }
gip = p;
return v;
}
/* ---- output ---- */
static const char DIG2[201] =
"00010203040506070809101112131415161718192021222324252627282930313233343536373839"
"40414243444546474849505152535455565758596061626364656667686970717273747576777879"
"8081828384858687888990919293949596979899";
static const u64 RXP[8] = {0ULL, 1099511627776ULL, 549755813888ULL, 366503875926ULL,
274877906944ULL, 219902325556ULL, 183251937963ULL, 157073089683ULL};
static const u64 POW10[20] = {1ULL, 10ULL, 100ULL, 1000ULL, 10000ULL, 100000ULL, 1000000ULL,
10000000ULL, 100000000ULL, 1000000000ULL, 10000000000ULL, 100000000000ULL, 1000000000000ULL,
10000000000000ULL, 100000000000000ULL, 1000000000000000ULL, 10000000000000000ULL,
100000000000000000ULL, 1000000000000000000ULL, 10000000000000000000ULL};
static inline char *st2(char *p, u32 r) { p -= 2; __builtin_memcpy(p, DIG2 + r * 2, 2); return p; }
/* The 4-digit ASCII table is built at COMPILE time (C++14 constexpr with a loop),
so it lives in .rodata: no runtime init and ten fewer first-touched pages. */
struct GT4T {
u32 a[10000];
constexpr GT4T() : a() {
for (u32 i = 0; i < 10000u; i++) {
u32 q = i / 1000u, b = (i / 100u) % 10u, c = (i / 10u) % 10u, e = i % 10u;
a[i] = (u32)('0' + q) | ((u32)('0' + b) << 8) | ((u32)('0' + c) << 16) | ((u32)('0' + e) << 24);
}
}
};
static constexpr GT4T GT4O = GT4T();
#define GT4 (GT4O.a)
static inline char *st4t(char *p, u32 r) { p -= 4; __builtin_memcpy(p, >4[r], 4); return p; }
static inline char *st4(char *p, u32 r) {
u32 hi = r / 100;
p -= 4;
__builtin_memcpy(p, DIG2 + hi * 2, 2);
__builtin_memcpy(p + 2, DIG2 + (r - hi * 100) * 2, 2);
return p;
}
/* WRITER REWRITE (row17e_al). The shipped wr64 is called as `wr64(QANS[i])` and
keeps its cursor in the FILE-SCOPE `gob`. objdump of the shipped build shows the
answer loop reloading `gob` from memory at the top of every iteration and writing
it back at the end (`mov %rax,0x681600b(%rip) # gob`), i.e. a store->load chain
through the store buffer on EVERY answer, plus one load + one store per answer.
Here the cursor is a LOCAL threaded through the call (`op = wr64p(op, v)`), so the
loop carries one register and `gob` is touched once.
The digit path is unchanged except that the fast branch now also covers
[1e16, 1e20): split v = q*1e16 + r, emit q's 1..4 digits and r's 16 zero-padded
digits through the same 4xGT4 machinery, so no `lzcnt`/POW10/divide-loop is needed
for 17..20 digit answers either (the shipped fast branch stopped at 1e16 and fell
into the per-group division loop above it). */
static inline char *wr64p(char *op, u64 v) {
if (v >= 1000000000000ULL && v < 10000000000000000ULL) {
u64 q1 = v / 10000u; u32 g0 = (u32)(v - q1 * 10000u);
u64 q2 = q1 / 10000u; u32 g1 = (u32)(q1 - q2 * 10000u);
u32 g3 = (u32)(q2 / 10000u); u32 g2 = (u32)(q2 - (u64)g3 * 10000u);
u64 lo = (u64)GT4[g3] | ((u64)GT4[g2] << 32);
u64 hi = (u64)GT4[g1] | ((u64)GT4[g0] << 32);
u32 s = 3u - (u32)(g3 >= 10u) - (u32)(g3 >= 100u) - (u32)(g3 >= 1000u);
unsigned __int128 x = (((unsigned __int128)hi) << 64) | lo;
x >>= (8u * s);
*(u64 *)op = (u64)x; *(u64 *)(op + 8) = (u64)(x >> 64);
u32 d = 16u - s;
op[d] = '\n'; return op + d + 1;
}
if (v >= 10000000000000000ULL) { /* 17..20 digits: 1..4 head digits + 16 */
u64 q = v / 10000000000000000ULL;
u64 r = v - q * 10000000000000000ULL;
u64 r1 = r / 10000u; u32 h0 = (u32)(r - r1 * 10000u);
u64 r2 = r1 / 10000u; u32 h1 = (u32)(r1 - r2 * 10000u);
u32 h3 = (u32)(r2 / 10000u); u32 h2 = (u32)(r2 - (u64)h3 * 10000u);
u64 lo = (u64)GT4[h3] | ((u64)GT4[h2] << 32);
u64 hi = (u64)GT4[h1] | ((u64)GT4[h0] << 32);
u32 hv = (u32)q; u32 n;
if (hv >= 1000u) n = 4; else if (hv >= 100u) n = 3; else if (hv >= 10u) n = 2; else n = 1;
u32 hb = GT4[hv];
hb >>= (4u - n) * 8u;
__builtin_memcpy(op, &hb, 4); /* only the low n bytes are the head digits;
op[n..n+3] is garbage and is overwritten next */
*(u64 *)(op + n) = lo; *(u64 *)(op + n + 8) = hi;
op[16 + n] = '\n';
return op + 16 + n + 1;
}
u32 b = 64u - (u32)__builtin_clzll(v | 1);
u32 d = ((b * 1233u) >> 12) + 1u;
if (d > 1 && v < POW10[d - 1]) d--;
char *o = op + d;
char *p = o;
u64 x = v;
while (x >= 10000) { u32 r = (u32)(x % 10000); x /= 10000; p = st4t(p, r); }
u32 w = (u32)x;
if (w >= 100) { u32 q = w / 100; p = st2(p, w - q * 100); w = q; }
if (w >= 10) p = st2(p, w); else *--p = (char)('0' + w);
*o = '\n';
return o + 1;
}
/* ---- pool bitset ---- */
#define BSET(r) do { u32 _r = (u32)(r); u32 _w0 = _r >> 6; u64 *_w = &BS0[_w0]; \
if (!*_w) { u32 _w1 = _w0 >> 6; u64 *_v = &BS1[_w1]; \
if (!*_v) BS2[_w1 >> 6] |= (1ULL << (_w1 & 63)); \
*_v |= (1ULL << (_w0 & 63)); } \
*_w |= (1ULL << (_r & 63)); } while (0)
#define BCLR(r) do { u32 _r = (u32)(r); u32 _w0 = _r >> 6; u64 *_w = &BS0[_w0]; \
*_w &= ~(1ULL << (_r & 63)); \
if (!*_w) { u32 _w1 = _w0 >> 6; u64 *_v = &BS1[_w1]; \
*_v &= ~(1ULL << (_w0 & 63)); \
if (!*_v) BS2[_w1 >> 6] &= ~(1ULL << (_w1 & 63)); } } while (0)
static inline int bfirst_above(u32 w0min) {
u32 q = w0min >> 6;
u64 s = BS1[q] & (~0ULL << (w0min & 63));
for (;;) {
while (s) {
u32 w0 = (q << 6) + (u32)__builtin_ctzll(s);
u64 b = BS0[w0];
if (b) return (int)((w0 << 6) + (u32)__builtin_ctzll(b));
s &= s - 1;
}
if (++q >= W2MAX) return -1;
s = BS1[q];
}
}
static inline int bfirst(void) {
u64 s2 = BS2[0];
if (!s2) return -1;
u32 w1 = (u32)__builtin_ctzll(s2);
u64 s1 = BS1[w1];
if (!s1) { BS2[0] &= ~(1ULL << w1); return -1; }
u32 w0 = (w1 << 6) + (u32)__builtin_ctzll(s1);
return (int)((w0 << 6) + (u32)__builtin_ctzll(BS0[w0]));
}
static inline void radix11(u64 *a, u64 *tmp, i64 n, int sh0, int passes) {
for (int pass = 0; pass < passes; pass++) {
int sh = sh0 + pass * 11;
u32 cnt[2048];
for (int b = 0; b < 2048; b++) cnt[b] = 0;
for (i64 i = 0; i < n; i++) cnt[(a[i] >> sh) & 2047]++;
u32 acc = 0;
for (int b = 0; b < 2048; b++) { u32 c = cnt[b]; cnt[b] = acc; acc += c; }
for (i64 i = 0; i < n; i++) {
u32 b = (u32)((a[i] >> sh) & 2047);
tmp[cnt[b]++] = a[i];
}
for (i64 i = 0; i < n; i++) a[i] = tmp[i];
}
}
static inline void radix16(u64 *a, u64 *tmp, i64 n, int sh0, int passes) {
for (int pass = 0; pass < passes; pass++) {
int sh = sh0 + pass * 16;
u32 cnt[65536];
for (int b = 0; b < 65536; b++) cnt[b] = 0;
for (i64 i = 0; i < n; i++) cnt[(a[i] >> sh) & 65535]++;
u32 acc = 0;
for (int b = 0; b < 65536; b++) { u32 c = cnt[b]; cnt[b] = acc; acc += c; }
for (i64 i = 0; i < n; i++) {
u32 b = (u32)((a[i] >> sh) & 65535);
tmp[cnt[b]++] = a[i];
}
for (i64 i = 0; i < n; i++) a[i] = tmp[i];
}
}
static void solve(void) {
i64 n = (i64)rd(), m = (i64)rd(), kq = (i64)rd();
i64 i, t;
int allx0 = 1, allc1 = 1;
for (t = 0; t < 6144; t++) ((u32 *)HST)[t] = 0;
for (i = 0; i < n; i++) {
u32 a = rd(), s = rd(), c = rd(), x = rd();
if (x) allx0 = 0;
if (c < 1u) allc1 = 0;
ITU[2 * i] = ((u64)a << 18) | (u64)(2 * i); /* "rest" items */
ITU[2 * i + 1] = (((u64)a + s) << 18) | (u64)(2 * i + 1); /* "first" unit item */
VK[i] = (u64)c | ((u64)x << 17);
{ u32 b = a + s; /* the three radix-11 digits, already here */
HST[0][a & 2047]++; HST[1][(a >> 11) & 2047]++; HST[2][(a >> 22) & 2047]++;
HST[0][b & 2047]++; HST[1][(b >> 11) & 2047]++; HST[2][(b >> 22) & 2047]++; }
}
i64 P = 0;
for (i = 0; i < kq; i++) {
i64 p = (i64)rd();
if (p > P) P = p;
QP[i] = (u32)p;
}
if (P < 1) P = 1;
/* ================= COUNTING SORT OF THE FIRST ITEMS BY FIRST DAY =================
lane noi17e_lane2. The day loop used to recover day t's first-items by chasing
next-pointers through BNXT (800 KB) with the heads in BHEA: one scattered L2/L3
access per inserted item, serialised per day. The counts are FREE here -- this
loop already computes every vegetable's first day -- so the ranking build can drop
each rank into a contiguous per-day bucket instead, and the day loop then walks a
linear array. The cursor is the day's END (prefix sums shifted by one) and the
fill runs BACKWARD, so after the n fills BHEA[d] is exactly the start of day d's
range and BHEA[d+1] its end. BNXT is gone: 800 KB -> 400 KB, and the day loop's
data is sequential. */
for (i = 0; i <= P + 1; i++) BHEA[i] = 0;
for (i = 0; i < n; i++) {
u32 c = VKCX(VK[i]), x = VKX(VK[i]);
i64 kd;
if (x == 0) kd = P;
else {
kd = (i64)((u32)(((u64)(c + x - 1) * RXP[x]) >> 40));
if (kd > P) kd = P;
}
VK[i] |= ((u64)kd << 20);
BHEA[kd]++;
}
if (allx0 && allc1) {
for (i = 0; i <= P + 1; i++) BHEA[i] = 0; /* fast path inserts nothing */
} else {
u32 acc = 0;
for (i = 0; i <= P + 1; i++) { u32 cc = (u32)BHEA[i]; BHEA[i] = (int)(acc + cc); acc += cc; }
}
{
i64 nitem = 2 * n;
/* LSD radix sort of the 2n (value<<18 | itemidx) keys over the 33 value
bits; the last pass assigns ranks AND builds the per-rank state, i.e.
the sort and the rank/state walk are fused into a single traversal.
rank 0 = largest value -> destination rank = nitem-1-ascending_pos. */
{ /* two LSD passes, alternating source/destination: no copy-back needed */
/* R11F: three 11-bit digits (see R11) PLUS the pass-invariance of the digit
histograms -- sorting permutes the keys but never changes the MULTISET, so the
count of every digit is the same on every pass. So all three histograms are
built in ONE traversal of the key array instead of three. */
u64 *src = ITU, *dst = ITEM;
{ /* F: the histograms are pass-invariant (sorting permutes the multiset, never
changes it) AND the digits are already known while the keys are BUILT, so all
three are counted in the input loop -- the whole HST sweep is gone. */
for (int p = 0; p < 3; p++) { u32 acc = 0; for (int b = 0; b < 2048; b++) { u32 cc = HST[p][b]; HST[p][b] = acc; acc += cc; } }
}
for (int pass = 0; pass < 3; pass++) {
u32 cnt[2048];
memcpy(cnt, HST[pass], sizeof cnt);
const int SH = 18 + pass * 11;
/* CJ3: the scatter's DESTINATION line is unpredictable (2048 bucket streams). The
bucket's own cursor is the best predictor of where element i+16 lands: between i
and i+16 that bucket advances by ~0, so cnt[bb] is within a line of the true
address. Read src[i+16] (sequential, HW-prefetched) and prefetch dst[cnt[bb]]. */
for (i = 0; i + 16 < nitem; i++) {
u32 bb = (u32)((src[i + 16] >> SH) & 2047);
__builtin_prefetch(&dst[cnt[bb]], 1, 3);
u32 b = (u32)((src[i] >> SH) & 2047);
dst[cnt[b]++] = src[i];
}
for (; i < nitem; i++) {
u32 b = (u32)((src[i] >> SH) & 2047);
dst[cnt[b]++] = src[i];
}
u64 *t = src; src = dst; dst = t;
}
}
if (allx0 && allc1) {
/* ================= x == 0 FAST PATH =================
No vegetable rots, so every first item enters the pool on day P and an item's
availability is `c - sold`, independent of the day. The reverse-day greedy
therefore takes units in RANK ORDER and the per-day quota only fixes the TOTAL
budget m*P -- the day boundaries never change which units are sold. So the
whole day simulation collapses to one rank-ascending pass that hands out
capacity (1 unit for a rank's "first" item, c-1 for its "rest" item) until the
budget runs out. Skipped: BHEA/BNXT, the pool bitset, PEND, bfirst, the entire
day loop. Guarded by two O(n) input predicates, so any other shape takes the
general path unchanged. */
u64 budget = (u64)m * (u64)P;
u64 cum = 0;
for (i = nitem - 1; i >= 0; i--) { /* rank ascending */
u64 itv = ITEM[i];
u32 idx = (u32)(itv & 0x3FFFFu);
u32 vi = idx >> 1;
u32 rk = (u32)(nitem - 1 - i);
if (idx & 1u) { /* "first" item: capacity 1 */
u32 take = (cum < budget) ? 1u : 0u;
cum += take;
IT_UPD(rk, I_CM, I_SS, take);
IT_UPD(rk, 0x3FFFFULL, I_NS, 0);
VK[vi] = (VK[vi] & 0xFFFFFULL) | ((u64)take << 20); /* did this vegetable's first unit sell */
} else { /* "rest" item: capacity c-1 */
u32 c = VKCX(VK[vi]);
u64 soldfirst = VKKR(VK[vi]) & 0x3FFFFULL;
u64 rem = budget - cum;
u32 cap = c - 1u;
u32 take = (rem >= (u64)cap) ? cap : (u32)rem;
cum += take;
IT_UPD(rk, I_CM, I_SS, (u32)(soldfirst + (soldfirst ? (u64)take : 0ull)));
IT_UPD(rk, 0x3FFFFULL, I_NS, ITMARK);
}
}
} else {
for (i = 0; i < nitem; i++) {
u64 it = ITEM[i];
u32 rk = (u32)(nitem - 1 - i);
u32 idx = (u32)(it & 0x3FFFFu);
u32 vi = idx >> 1;
if (i + 12 < nitem) { u32 vf = (u32)(ITEM[i + 12] & 0x3FFFFu) >> 1; __builtin_prefetch(&VK[vf], 0, 3); }
u64 cx = VK[vi]; u64 kr = VKKR(VK[vi]); /* ONE u64: both words of this vegetable */
/* VAL[] eliminated: rank rk's value is ITEM[nitem-1-rk]>>18, and the sweep walks
ranks ASCENDING, i.e. ITEM DESCENDING -- still one sequential stream. */
ITU[rk] = (u64)VKCX(cx) | ((u64)VKX(cx) << I_XS);
if (idx & 1u) { /* "first": partner rank + day, ONE load */
IT_UPD(rk, 0x3FFFFULL, I_NS, (u32)(kr >> 18));
int d = (int)(kr & 0x3FFFFu); /* only the "first" item enters the pool */
BHEA[d]--; BUK[(u32)BHEA[d]] = (u32)rk; /* fill each day's bucket backward */
} else { /* "rest": value(rest)=a <= a+s=value(first),
and the array is now FULLY value-sorted with a
stable sort, so this rank is always seen first */
IT_UPD(rk, 0x3FFFFULL, I_NS, ITMARK);
VK[vi] = (VK[vi] & 0xFFFFFULL) | (((kr & 0x3FFFFULL) | ((u64)rk << 18)) << 20);
}
}
}
if (!(allx0 && allc1)) {
u32 w = (u32)((nitem >> 6) + 1);
for (i = 0; i < (i64)w; i++) BS0[i] = 0;
w = (u32)((nitem >> 12) + 1);
for (i = 0; i < (i64)w; i++) BS1[i] = 0;
BS2[0] = 0; BS2[1] = 0; BS2[2] = 0; BS2[3] = 0;
}
{
i64 nins = n; /* first items not yet inserted into the pool */
for (t = P; t >= 1; t--) {
for (i64 _z = BHEA[t]; _z < BHEA[t + 1]; _z++) { BSET(BUK[_z]); nins--; }
/* EARLY EXIT. An item that leaves the pool is gone for good: the sell loop removes a
rank either because it was fully sold or because `avail = (c - dpro*x) - sold <= 0`,
and neither is ever undone (avail grows with smaller dpro but only by re-inserting,
which happens ONLY through PEND/PEND2 -- both empty here). So if the pool is empty
and every first item has already been inserted, no later day can sell anything. */
if (BS2[0] == 0 && nins == 0) break;
i64 quota = m;
i64 dpro = t - 1;
/* ---- KEEP: an item that saturates on day t (x>0, t>1) is valid again
tomorrow by construction -- avail at day t-1 is exactly x > 0 -- so the clear
is NOT stored in BS0. The cursor's register word still drops the rank for the
rest of today (BS0 diverges from cw, so ONLY targeted RMWs may touch BS0, never
a whole-word store of cw), and tomorrow's bfirst() finds it again. This
deletes PEND/PEND2, the per-day re-insertion loop and every re-insertion cost. ---- */
int rk = bfirst();
u32 cw0 = 0;
u64 cw = 0;
if (rk >= 0) { cw0 = (u32)rk >> 6; cw = BS0[cw0]; }
while (rk >= 0 && quota > 0) {
// ONE load for the packed rank state, register accessors from here.
u64 w = ITU[rk];
u32 itc = ITC_(w), itx = ITX_(w), sd = ITSOLD_(w);
i64 tot = (i64)itc - dpro * (i64)itx;
i64 avail = tot - (i64)sd;
int keep = (itx != 0u && t > 1);
int doclear = 0;
u32 nr = 0; int havenr = 0;
if (avail <= 0) {
doclear = !keep;
} else if (sd == 0) {
doclear = 1;
IT_UPD(rk, I_CM, I_SS, 1);
quota--;
nr = ITNRM_(w); havenr = 1;
} else {
i64 take = quota < avail ? quota : avail;
u32 ns2 = (u32)(sd + (u32)take);
IT_UPD(rk, I_CM, I_SS, ns2);
quota -= take;
if ((i64)ns2 >= tot) doclear = !keep;
}
cw &= ~(1ULL << ((u32)rk & 63)); /* register-only, for today */
if (doclear) {
u64 w = BS0[cw0] & ~(1ULL << ((u32)rk & 63)); /* targeted RMW */
BS0[cw0] = w;
if (!w) {
u32 q1 = cw0 >> 6;
u64 v = BS1[q1] & ~(1ULL << (cw0 & 63));
BS1[q1] = v;
if (!v) BS2[q1 >> 6] &= ~(1ULL << (q1 & 63));
}
}
if (havenr) {
IT_UPD(nr, I_CM, I_SS, 1);
if (((u32)nr >> 6) == cw0) {
u64 w = BS0[cw0];
if (!w) {
u32 q1 = cw0 >> 6;
BS1[q1] |= (1ULL << (cw0 & 63));
BS2[q1 >> 6] |= (1ULL << (q1 & 63));
}
BS0[cw0] = w | (1ULL << ((u32)nr & 63));
cw |= (1ULL << ((u32)nr & 63));
} else BSET(nr);
}
if (!cw) {
rk = bfirst_above(cw0 + 1); /* never fall back below the cursor */
if (rk < 0) break;
cw0 = (u32)rk >> 6; cw = BS0[cw0];
} else {
rk = (int)((cw0 << 6) + (u32)__builtin_ctzll(cw));
}
}
}
}
}
/* query order: queries have distinct p, so index them by p directly */
u32 *QMAP = QMAPU;
if (P < NMAX) {
for (i = 0; i <= (i64)P; i++) QMAP[i] = 0xFFFFFFFFu;
for (i = 0; i < kq; i++) {
if (QMAP[QP[i]] != 0xFFFFFFFFu) { P = NMAX; break; } /* duplicate p: statement says distinct, fall back if not */
QMAP[QP[i]] = (u32)i;
}
}
if (P >= NMAX) {
for (i = 0; i < kq; i++) QANS[i] = ((u64)QP[i] << 20) | (u64)i;
radix16(QANS, ITMP, kq, 20, 2);
for (i = 0; i < kq; i++) QP2[i] = (u32)(QANS[i] & 0xFFFFFu);
}
/* sweep ranks (descending value); item counts from the per-item sold state */
{
i64 gi = 0;
i64 gleft = 0;
u32 gval = 0;
i64 acc = 0;
u64 sum = 0;
if (P < NMAX) {
for (i64 p = 0; p <= (i64)P; p++) {
u32 qi = QMAP[p];
if (qi == 0xFFFFFFFFu) continue;
u64 need = (u64)m * (u64)p;
while ((u64)acc < need) {
if (gleft == 0) {
for (;;) {
if (gi >= 2 * n) break;
u64 ig = ITU[gi]; u32 sd = ITSOLD_(ig);
u32 cnt = sd - ((ITNRM_(ig) == ITMARK) & (sd != 0u));
if (cnt) { gleft = (i64)cnt; gval = (u32)(ITEM[2 * n - 1 - gi] >> 18); gi++; break; }
gi++;
}
if (gleft == 0) { acc = (u64)-1; break; }
}
i64 rem = (i64)need - acc;
i64 take = rem < gleft ? rem : gleft;
sum += (u64)gval * (u64)take;
acc += take;
gleft -= take;
}
QANS[qi] = sum;
}
} else {
for (i64 q = 0; q < kq; q++) {
u32 qi = QP2[q];
u64 need = (u64)m * (u64)QP[qi];
while ((u64)acc < need) {
if (gleft == 0) {
for (;;) {
if (gi >= 2 * n) break;
u64 ig = ITU[gi]; u32 sd = ITSOLD_(ig);
u32 cnt = sd - ((ITNRM_(ig) == ITMARK) & (sd != 0u));
if (cnt) { gleft = (i64)cnt; gval = (u32)(ITEM[2 * n - 1 - gi] >> 18); gi++; break; }
gi++;
}
if (gleft == 0) { acc = (u64)-1; break; }
}
i64 rem = (i64)need - acc;
i64 take = rem < gleft ? rem : gleft;
sum += (u64)gval * (u64)take;
acc += take;
gleft -= take;
}
QANS[qi] = sum;
}
}
}
{ char *op = (char *)gob;
for (i = 0; i < kq; i++) op = wr64p(op, QANS[i]);
gob = (u8 *)op; }
}
struct DUCKDI{unsigned long abi;const char*sp;unsigned long sn;char*op;unsigned long ol,os;char*ep;unsigned long el,es;const char*IB;unsigned long IBl;char*OB;unsigned long OBl;unsigned long tsc;}__attribute__((packed));
extern "C" void __libc_start_main(void*m,int argc,char**argv){
unsigned long*p=(unsigned long*)(argv+argc+1);while(*p)p++;p++;
DUCKDI*d=0;for(;p[0];p+=2)if(p[0]==0x6b637564UL){d=(DUCKDI*)p[1];break;}
if(d){ gip=(const u8*)d->sp; gie=gip+d->sn; gob=(u8*)d->op; solve(); d->os=(unsigned long)(gob-(u8*)d->op); }
__asm__ volatile("syscall"::"a"(60),"D"(0):"rcx","r11","memory");
for(;;);
}
int main(){return 0;}