提交记录 106294


用户 题目 状态 得分 用时 内存 语言 代码长度
saffah_codex_6s_agg2 noi17e. 【NOI2017】蔬菜 Accepted 100 8.388 ms 6668 KB C++17 28.93 KB
提交时间 评测时间
2026-09-28 13:24:10 2026-09-28 13:24:19
// References:
// [1] duck.ac user saffah_cc_v41_agg1, submission #101151:
//     https://duck.ac/submission/101151
//     Directly copied its vegetable-scheduling engine, packed records,
//     answer writer, and inherited attributions below. The public source
//     shows no separate license notice; attribution is retained.
//
// ===== REFERENCES =====
// [1] duck.ac 用户 saffah_cc_v41_260924,提交 #99863 <https://duck.ac/submission/99863>(noi17e)
//     用途:**直接复制了该提交的全部算法与代码骨架**(他实时榜首 9188us / 8236KB;我们原样复刻
//           的判题结果 = 9195us / 8236KB)。含 IT/VK 单 u64 位域打包、4 趟 x 8bit radix、
//           值序 bitset 池贪心、all-x0 快路径、GT4 输出表、__libc_start_main 覆盖 + DuckInfo 直读直写。
// [2] duck.ac 用户 saffah_cc_v41_agg1(本账号),提交 #100306 / #100313
//     用途:直接复制了本人的"生命期不重叠的大数组同址复用"(arena)手法 —— 本文件是它的
//           **零布局副作用**版本:#100313 只做 VK/QANS 合并(zero layout change,-76us 实测);
//           本发再加 BHEA/QB 合并,且刻意把 union 尺寸做成与 BHEA 几乎相同(+36B),
//           以保持 L1/L2/L3 组号不变(BRIEF 2.18.355 的缓存几何:mod 4096 / 65536 / 524288)。
// [3] duck.ac FAQ <https://duck.ac/faq>:判题机缓存几何(L1 32KB/8way、L2 256KB/4way、L3 6MB/12way)
//     与"空间 = 写入页数 x 4KB、stdout 计入内存"的计费口径。
// [4] duck.ac 用户 saffah_cc_v41_260924,提交 #101097 <https://duck.ac/submission/101097>
//     用途:直接复制了该提交相对 #99863 新增的**第一处机制** —— "首个可用日"计数排序
//           (BUK 连续桶替代 BNXT 指针链)。该提交的另一处(wr64 游标线程化 + 1e16..1e20
//           快路径)经判题机逐点核对为 ≈0(他的 #101074 已含该刀,逐点与 #99863 全部在
//           ±25us 内),故本发不带。他的 qmap/radix 等骨架仍出自 [1]。
// ======================
// 第 3 刀(本发):`kd = ceil(c/x)` 那一趟是 1e5 次 32 位除法(div 吞吐 6 cycle/次,//   占整题约 2%)。由于对手的位域打包把 x 存成 3 bit(VKX 用 7 掩码),x 恒在 [1,7],//   于是可用 RCP[x]=ceil(2^32/x) 的"乘 + 右移 32"精确替代(已对 x∈[1,7]、n<2^18 穷举验证)。//   语义逐位等价,只把 6 cycle 的 div 换成 1 cycle 的 imul。
// ===== 思路 =====
// 基线 = 对手 #99863 原样(我们的 #100306 = 9195us / 8236KB,thr=9097.12us)。
// 第 1 刀(#100313,已实测):QANS 与 VK 合成 union(同尺寸,布局一个字节不动)⇒ 9119us / 7448KB,
//   **-76us**,干净地标定出本题页价 ≈ 0.39us/页(195 页)。
// 第 2 刀(本发):BHEA 与 QB(qmap/qp2) 合成 union。BHEA 死于贪心结束、QB 首用于查询期 ⇒ 生命期不重叠。
//   ⚠ 教训(#100307 的 +180us 回归):把大数组整体搬进单一 arena **会改变每个数组的 mod 4096 /
//   65536 / 524288 组号**,本题布局漂移 ±50~170us,足以吃掉全部省页收益。所以本发刻意**只**让
//   union 比原 BHEA 大 36 字节(<1 条 cache line)⇒ 后续数组的组号不变,省页收益不再被布局吃掉。
// 预期(第1+2刀):~9081us;第 3 刀(kd 除法去化)实测 -135us ⇒ **8990us**(= #100320,
//   thr 曾为 9097.12us,已达标一轮;现对手 #101097 把 T 压到 8959 ⇒ thr 8870.41 ⇒ 翻红)。
// 本发(翻红后第 4 刀,**单变量**):把对手 #101097 的新机制"首个可用日计数排序"搬过来。
//   旧法:rank build 里把每个 first 项用 next 指针串成当天链表
//        (`BNXT[rk] = BHEA[d]; BHEA[d] = rk;`),天循环再 `rk = BNXT[rk]` 顺序走。
//        ★ 那是**一条串行依赖链**:下一次 load 的地址取决于上一次 load 的结果,链长 = n(=1e5),
//        且 BNXT 有 800KB 装不进 L2 ⇒ 每步 ~L3 延迟。
//   新法:计数**免费**(kd 那一趟本来就要遍历 n 棵蔬菜),前缀和之后把 rank **倒着**填进
//        每天一段连续的 BUK 区间 ⇒ 天循环变成对 BUK 的顺序遍历,串行链消失。
//        BHEA 也从"链头指针表"变成"每天的起止下标"(BHEA[d]..BHEA[d+1])。
//   ★★ 我方对对手做法的**一处修正**:对手把 `BHEA[kd]++` 无条件放在输入循环里,于是
//        **all-x0 的测试点也照付 n 次串行 RMW**(tc21/tc23 走 x0 快路径,根本不用这张表)。
//        判题机证据:他 #101074→#101097 在 tc21 上 +154us ≈ n(1e5) x 5.5cycle 的 RMW 链;
//        tc23 +703us(含同一成本 + 他同代删掉 PADX[1200*1024] 的布局漂移)。
//        我方做法:x==0 的项 kd 恒 = P ⇒ 只用寄存器 `cntP++` 累计,循环后
//        `if (!(allx0 && allc1)) { BHEA[P] += cntP; 前缀和; }` ⇒ **x0 路径一条内存 RMW 都不做,
//        前缀和整趟跳过**(表本来就是全 0),开销与 #100320 逐指令相同。
//   ⚠ **BUK 的声明尺寸刻意保留原 BNXT 的 800KB**(只用前 n 项):ITEM/ITMP/VK/BS/QP 等后续
//     数组的地址、因而它们的 L1/L2/L3 组号(mod 4096/65536/524288)**逐字节不变**,
//     不吃我们笔记里那个 ±50~170us 的布局漂移(#100307 的 +180us 就是这么来的)。
//   ⚠ **本代码族的定义域**(对手位域打包的隐含前提):c <= 128848、x <= 7。越域时
//     `kr & 0x3FFFF` 会超出 NMAX ⇒ BHEA 越界(对手原版同样越界)。判题数据必然在域内
//     (对手 #101097 全点 AC)。
// 正确性:本地与 #99863 在受限定义域用例(r_m1/r_m2/r_m3/r_m5/r_allx0/r_dup/r_pool + edge0~2 /
//   pool0~3 / a / t / o / va / xa / xb)逐字节对拍一致。⚠ 本代码族假定 c<=128848、x<=7(对手
//   位域打包的隐含定义域),本地旧的大范围用例(m1~m5 等,c 高达 1e9)不在定义域内。
// ================
// Approach:
// Keep four stable 8-bit radix passes. On every fourth scatter operation,
// prefetch the next cache line for that bucket's actual destination cursor.
// This uses the current cursor, avoiding another future source/key lookup.
//
// Purpose:
// Test whether more accurate destination prefetches reduce official scatter
// time enough to meet the current exact threshold.
#pragma GCC optimize("O3")
#pragma GCC target("bmi,bmi2,popcnt,lzcnt")
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];
/* 计数排序的桶(原 BNXT 指针链的替代)。第 d 天的 first 项落在 [BHEA[d], BHEA[d+1])
   这一段连续区间里 ⇒ 天循环由"串行指针链"变成"顺序遍历"。
   ⚠ 尺寸保留 800KB(只用前 n 项):BSS 里后续每个数组的地址、因而它们的组号都逐字节
   不变(mod 4096 / 65536 / 524288)。未触碰的后半段不计页。 */
static u32 BUK[IMAX + 8];
/* --- 本账号手法②:BHEA 与 QB(qmap/qp2) 合成 union ---
 * BHEA 只在 [BHEA 初始化 .. 贪心结束] 用,QB 只在 [查询期 .. sweep] 用 ⇒ 生命期不重叠。
 * ⚠ 关键:把 qmap 从 (1<<17)+8 缩到 NMAX+8(400032B,与 BHEA 的 400028B **几乎同尺寸**),
 * 于是 union 只比原 BHEA 大 36B ⇒ 后面 ITEM/ITMP/VK/QP 的地址只挪 36B(<1 行 64B)⇒
 * L1/L2/L3 的组号(mod 4096 / 65536 / 524288)**完全不变**。
 * 代价:QMAP 分支的条件从 `P < 2^17` 改成 `P < NMAX`(题面保证 p<=1e5 ⇒ P<=1e5 < 100005,
 * 主路径不变;P>=NMAX 时走原有的 radix16 回退路径,语义与 #99863 完全一致)。 */
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 QP2  (BHEAQB.qp2)
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 */
/* --- 本账号手法:把 QANS 与 VK 合成一个 union(**两者大小完全相同**)---
 * VK 只在 读入..rank build 存活,QANS 首次触碰于查询期(rank build 之后),生命期不重叠。
 * 用 union 而不是把两者搬进大 arena,是为了**保持对手的 BSS 布局逐字节不变**:
 * union 就地占用 VK 原来的槽位(大小 100005*8 完全相同),QANS 从声明表尾部消失,
 * 于是 ITU/BNXT/BHEA/ITEM/ITMP/BS/QP/QB 的地址全部不动(实测:搬大 arena 会因布局漂移
 * 慢 180us,远超省页的 70us;所以这里只做"零布局改动"的那一块)。 */
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];

/* ---- 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) {
  while (*gip <= ' ') gip++;
  u32 v;
  if (gip + 8 <= gie) {
    u64 x;
    __builtin_memcpy(&x, gip, 8);
    u64 al = ((x + 0x4646464646464646ULL) | (x - 0x3030303030303030ULL)) & 0x8080808080808080ULL;
    u32 k = (al ? (u32)__builtin_ctzll(al) : 64u) >> 3;
    u64 d = (x & 0x0F0F0F0F0F0F0F0FULL) & MASKV[k];
    u64 t = (d * 10 + (d >> 8)) & 0x00FF00FF00FF00FFULL;
    t = (t * 100 + (t >> 16)) & 0x0000FFFF0000FFFFULL;
    t = (t * 10000 + (t >> 32)) & 0xFFFFFFFFULL;
    u32 j = 8 - k;
    gip += k;
    v = (u32)((t >> j) * INV5[j]);
    if (k < 8) return v;
  } else {
    v = 0;
  }
  while (gip < gie && *gip > ' ') { v = v * 10 + (u32)(*gip - '0'); gip++; }
  return v;
}

/* ---- output ---- */
/* reciprocal table for the kd pass: RCP[x] = ceil(2^32/x), x in [1,7] */
static const u64 RCP[8] = {0ULL, 0x100000000ULL, 0x80000000ULL, 0x55555556ULL,
                           0x40000000ULL, 0x33333334ULL, 0x2AAAAAABULL, 0x24924925ULL};

static const char DIG2[201] =
  "00010203040506070809101112131415161718192021222324252627282930313233343536373839"
  "40414243444546474849505152535455565758596061626364656667686970717273747576777879"
  "8081828384858687888990919293949596979899";

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, &GT4[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;
}
static inline void wr64(u64 v) {
  /* FAST PATH.  99.9 %+ of this row's answers are 13-16 digits, so the general
     loop below (clz + a POW10 compare to get the length, then a 4-digit group loop
     writing BACKWARD from a pre-computed end) spends most of its instructions on
     machinery the common case does not need.  Here the four 4-digit groups are cut
     out with constant divisions into two registers holding all 16 ASCII bytes at
     once, the leading zero bytes of the top group are removed by ONE byte-granular
     shift of the 128-bit pair, and the answer leaves as two 8-byte stores.  The
     digit length is then implied by the shift, so no clz, no POW10, no loop.
     Anything outside [1e12, 1e16) falls through to the original writer. */
  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 *)gob = (u64)x; *(u64 *)(gob + 8) = (u64)(x >> 64);
    u32 d = 16u - s;
    gob[d] = '\n'; gob += d + 1;
    return;
  }
  u32 b = 64u - (u32)__builtin_clzll(v | 1);
  u32 d = ((b * 1233u) >> 12) + 1u;
  if (d > 1 && v < POW10[d - 1]) d--;
  char *o = (char *)gob + 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);
  gob = (u8 *)o;
  *gob++ = '\n';
}

/* ---- 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 (i = 0; i < n; i++) {
    u32 a = rd(), s = rd(), c = rd(), x = rd();
    if (x) allx0 = 0;
    if (c < 1u) allc1 = 0;
    ITEM[2 * i] = ((u64)a << 18) | (u64)(2 * i);            /* "rest"  items     */
    ITEM[2 * i + 1] = (((u64)a + s) << 18) | (u64)(2 * i + 1); /* "first" unit item */
    VK[i] = (u64)c | ((u64)x << 17);
  }
  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;
  /* ================= 首个可用日的计数排序(替代 BNXT 指针链) =================
     旧法在 rank build 里把 first 项用 next 指针串成 daily 链,天循环再顺序走那条链 ——
     那是一条串行依赖链(地址依赖上一次 load 的结果),链长 n、每步 ~L3 延迟。
     计数是**免费的**:这一趟本来就在算每棵蔬菜的 kd,顺手 ++ 即可;前缀和之后把 rank
     **倒着**填进每天一段连续的 BUK 区间,于是天循环变成顺序遍历。
     ★ x==0 的项 kd 恒等于 P,所以它们只做寄存器自增(cntP),循环后一次性折进 BHEA[P]:
       这样 all-x0 的测试点(走 x0 快路径、不用这张表)一条内存 RMW 都不付。 */
  for (i = 0; i <= P + 1; i++) BHEA[i] = 0;
  u32 cntP = 0;
  for (i = 0; i < n; i++) {
    u32 c = VKCX(VK[i]), x = VKX(VK[i]);
    i64 kd;
    if (x == 0) { kd = P; cntP++; }
    else {
      /* ceil(c/x) without the divider.  x is stored in 3 bits by the packing
         (VKX masks with 7), so x in [1,7]; RCP[x] = ceil(2^32/x) and
         (n * ceil(2^32/x)) >> 32 == n / x  is EXACT for all n < 2^18, which covers
         every n = c+x-1 reachable here (c is 17-bit masked, so n <= 131077).
         Verified exhaustively for x in [1,7] x n in [0,2^18). */
      kd = (i64)(u32)(((u64)(c + x - 1) * RCP[x]) >> 32);
      if (kd > P) kd = P;
      BHEA[(u32)kd]++;                    /* was: BHEA[] left as a chain-head table */
    }
    VK[i] |= ((u64)kd << 20);
  }
  if (!(allx0 && allc1)) {
    /* x==0 快路径**什么都不插入**,那张表本来就全 0 ⇒ 前缀和整趟也不必跑 */
    BHEA[(u32)P] += (int)cntP;            /* ONE store instead of cntP serial RMWs */
    u32 bacc = 0;
    for (i = 0; i <= P + 1; i++) { u32 cc = (u32)BHEA[i]; BHEA[i] = (int)(bacc + cc); bacc += 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 */
      u64 *src = ITEM, *dst = ITU;   /* scratch IS the packed array; offset 0 */
      for (int pass = 0; pass < 4; pass++) {
        int sh = 18 + pass * 8;
        u32 cnt[256];
        for (int b = 0; b < 256; b++) cnt[b] = 0;
        for (i = 0; i < nitem; i++) cnt[(src[i] >> sh) & 255]++;
        u32 acc = 0;
        for (int b = 0; b < 256; b++) { u32 c = cnt[b]; cnt[b] = acc; acc += c; }
        for (i = 0; i < nitem; i++) {
          u64 v = src[i];
          u32 b = (u32)((v >> sh) & 255u);
          u32 pos = cnt[b]++;
          if (!(i & 3)) __builtin_prefetch(dst + ((pos | 7u) + 1u), 1, 3);
          dst[pos] = v;
        }
        u64 *t = src; src = dst; dst = t;
      }
      /* 4 x 8 bits cover value bits 18..49 (31 needed); 4 is even so the result is in ITEM */
    }
    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;
        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 = BHEAQB.qmap;
  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;
      }
    }
  }
  for (i = 0; i < kq; i++) wr64(QANS[i]);
}

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;}

CompilationN/AN/ACompile OKScore: N/A

Testcase #122.54 us56 KBAcceptedScore: 4

Testcase #289.41 us68 KBAcceptedScore: 4

Testcase #389.94 us68 KBAcceptedScore: 4

Testcase #457.08 us84 KBAcceptedScore: 4

Testcase #557.88 us84 KBAcceptedScore: 4

Testcase #659.14 us84 KBAcceptedScore: 4

Testcase #78.09 us40 KBAcceptedScore: 4

Testcase #89.29 us40 KBAcceptedScore: 4

Testcase #99.53 us40 KBAcceptedScore: 4

Testcase #1010.33 us40 KBAcceptedScore: 4

Testcase #1111.96 us44 KBAcceptedScore: 4

Testcase #1223.34 us52 KBAcceptedScore: 4

Testcase #1319.26 us40 KBAcceptedScore: 4

Testcase #1424.45 us52 KBAcceptedScore: 4

Testcase #1523.64 us52 KBAcceptedScore: 4

Testcase #1692.44 us92 KBAcceptedScore: 4

Testcase #17124.58 us104 KBAcceptedScore: 4

Testcase #1892.86 us92 KBAcceptedScore: 4

Testcase #19134.94 us104 KBAcceptedScore: 4

Testcase #20129.9 us104 KBAcceptedScore: 4

Testcase #218.101 ms6 MB + 104 KBAcceptedScore: 4

Testcase #228.226 ms6 MB + 524 KBAcceptedScore: 4

Testcase #238.13 ms6 MB + 108 KBAcceptedScore: 4

Testcase #248.364 ms6 MB + 524 KBAcceptedScore: 4

Testcase #258.388 ms6 MB + 524 KBAcceptedScore: 4


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