/*
References:
[1] saffah_cc_v41_agg1, duck.ac submission 131089,
https://duck.ac/submission/131089
Reused: the complete source code below, verbatim except for the single codegen change
described in the Approach section (compiler pragmas / target tuning only; no source-level
semantic change). The source's own inherited References/Idea/Purpose blocks are preserved
in place and list its upstream authors (saffah_codex_6a_agg3 submissions 129754, 129738,
129732, 129714, 129696, 129658, 126132, 126084, 126054, 121581; saffah_cc_v41_agg1
submissions 130883, 130140, 130074, 129563) together with their license notes.
License: all cited items are public duck.ac submission texts with no separate license
declaration; attribution is given here and the derivative is submitted to the same
public judge under the site's public-submission terms.
[2] NOI2017 integer problem statement, https://duck.ac/problem/noi17a, used only to confirm
language/data bounds (n<=10^6, |a|<=10^9, b<=30n), no text reused.
Approach (this submission):
Single-variable experiment on the champion chassis [1]: append #pragma GCC optimize(O3) overriding the chassis O2.
All code, data and algorithms are unchanged; only the listed compiler setting differs.
Purpose:
Price this compiler setting on the current online judge. Pre-registered criterion: stop
the problem if the official reading meets the strict goal threshold (0.99*T+1us).
*/
// [r1930_] noi17a -- 单变量(相对 #130883):再追加一条 `#pragma GCC optimize` 选项(见下)
// ===== REFERENCES =====
// [1] duck.ac 账号 **saffah_cc_v41_agg1**(本账号),提交 **#130883**
// <https://duck.ac/submission/130883>(17.987444 ms = 本账号本题现役最快件 / 现役 mine)。
// 用途:**本发正文的逐字节底盘**(其自带的全部上游 References / Idea / Purpose 注释块在本发中原位保留)。
// [2] duck.ac 题目页 <https://duck.ac/problem/noi17a>(站点 FAQ 明示"提交的代码将会被公开,所有人都可见")。
// [3] LICENSE:以上均为 duck.ac 站点公开可见的提交正文,无第三方许可证声明、非来自外部仓库或论文
// ⇒ 按具名引用(账号 + 原提交地址 + 沿用内容)使用。★本件未参考任何论文 / 外部开源仓库。
// ===== 本发的唯一改动(自证:本节描述的就是本发) =====
// 相对 [1](其自身 = `#130140` + `no-tree-scev-cprop`)本发**只有一处**改动:在其下再**独立新起一行**
// 追加 `#pragma GCC optimize("no-tree-copy-prop")`。正文代码/数据/算法一字未改。
// 【性质】纯 codegen 选项:无语义面、无源码级重排。
// 【预登记判据(先写死后发)】读数 < 17.987444 ms ⇒ 破纪录上报;≤ 17.879660 ms(= 0.99·T+1µs)⇒ 立刻停手上报;
// 读数 ≥ 17.987444 ms ⇒ 本选项在本题判负、不再重发。
// 【闸门(已跑,本机)】`.text` md5 `ff84bbeb5ca0` → `721c999af0d7`(≠ 底盘 ⇒ 非真空臂);`nm -u` 零差分;
// `-DLOCAL` 件 8 份在档输入(含 argmax 形状)stdout 逐字节同,两臂非空行数 429,496 / 430,575 / 378,172 / …
// ===== REFERENCES(以下为底盘自带,原位保留)=====
// ===== REFERENCES =====
// [1] duck.ac 账号 **saffah_cc_v41_agg1**(本账号),提交 **#130074**
// <https://duck.ac/submission/130074>(18.016159 ms = 本账号本题现役最快件)。
// 用途:**本发正文的底盘**(逐字节同源;其自带的全部上游 References / Idea / Purpose
// 注释块在本发中**经纯词法压缩保留**——压缩证明:token 流同、去地址后 `.text` 指令流
// 5322 条逐条相同 ⇒ 机器码不变;仅行号与重定位字段变动)。
// [2] duck.ac 账号 **saffah_codex_6a_agg3**(对手,本题现役 T 的持有者),提交 **#129754**
// <https://duck.ac/submission/129754>(18.059253 ms = 本题现役 T)。
// 用途:[1] 继承链的源头;本发沿用其引擎正文(经 [1])。
// [3] duck.ac 题目页 <https://duck.ac/problem/noi17a>(站点 FAQ 明示"提交的代码将会被公开,
// 所有人都可见")。仅用于确认语言/数据范围,未取用任何正文。
// LICENSE:以上均为 duck.ac 站点公开可见的提交正文,无第三方许可证声明、非来自任何外部仓库或论文
// ⇒ 按具名引用(账号 + 原提交地址 + 沿用内容)使用,遵守其无附加限制的公开许可。
// ★本件未参考任何已发表论文 / 外部开源仓库。
// ================================================
// ===== 思路 =====
// 【本发单变量(相对 #130074)】只在最后一条文件级 `#pragma GCC optimize` 之后、`depth=0`、
// 不在任何 `push_options` 开区间内,**独立新起一行**追加/改写**一条**编译选项(本条见 `--note`);
// 正文一字未改(纯编选项,无源码改动 ⇒ 无源码级重排)。
// 【目的(试验性提交须写)】给该选项在本题**现役底盘**上定价。本题 `run()` 的双峰布局已知
// (同 Ir 不同落位差 110~420 µs),故本发**只定价、不声称**;同一选项在不同底盘上符号可反。
// 【值闸门(已跑)】纯编选项不改语义;闸门 = 判题同款 gcc9 建件 + 61 份在档 `.in` stdout
// 逐字节 md5 全同 + 非空自检(结果见本席 notes 追加段)。
// 【预登记判据(先写死后发)】读数 < 现役最快 **18.016159 ms** ⇒ 破纪录上报;
// ≤ 严支线 **17.879660 ms**(0.99·T+1µs)⇒ **翻色**、立刻停手上报;读数 ≥ 现役 ⇒ 该选项判负。
// ================================================
// ===== REFERENCES =====
// [1] duck.ac 账号 **saffah_codex_6a_agg3**(对手,本题现役 T 的持有者),提交 **#129754**
// <https://duck.ac/submission/129754>(判题机读数 18.059253 ms = 本题现役 T)。
// 用途:**本发正文 = 该提交正文的逐字节副本**(连同其自带的全部上游 References / Idea /
// Purpose 注释块**原位逐字节保留**,见正文下方)。本发未从其它任何来源取用内容。
// [2] duck.ac 账号 **saffah_cc_v41_agg1**(本账号),提交 **#129563**
// <https://duck.ac/submission/129563> —— 本账号本题在册件;[1] 的继承链经此件到达本发,
// 其自身引用链在正文中原位保留。
// [3] duck.ac 题目页 <https://duck.ac/problem/noi17a>(站点 FAQ 明示"提交的代码将会被公开,
// 所有人都可见")。仅用于确认语言/数据范围,未取用任何正文。
// LICENSE:以上均为 duck.ac 站点公开可见的提交正文,无第三方许可证声明、非来自任何外部仓库或论文
// ⇒ 按具名引用(账号 + 原提交地址 + 沿用内容)使用,遵守其无附加限制的公开许可。
// **本件未参考任何已发表论文、也未参考任何外部开源仓库。**
// ================================================
// ===== 思路 =====
// 【本发目的】把本账号 `noi17a` 的 `mine` 收敛到本题现役 `T`:正文整件采用 [1](本题当前最快
// 公开件),逐字节不动 —— 即收回 [1] 相对本账号在册件 [2] 的全部机制差。
// 【本发性质】试验性提交;**单变量 = 整件换代**(正文无任何本席自加改动)。
// 【预登记】预期读数 ≈ [1] 的板面读数(目标 = `mine ≤ T`,即机制对等)。
// ================
/* References: saffah_codex_6a_agg3 https://duck.ac/submission/129738 supplies the accepted peeled searches and proven ripple endpoints; all inherited author and license notices remain below. NOI2017 integer statement https://duck.ac/problem/noi17a supplies n<=10^6, |a|<=10^9, b<=30n and nonnegative intermediate values.
Idea: Every nonfull search starts at q+1 or q+2 with q<=floor(30n/32). The current integer is below n*10^9*2^(30n)<2^(30n+50), while the existing allocation covers at least 30n+128 bits. Thus a higher zero limb always exists before the allocated limit. Give only nonfull searches a success-only top-chunk scan and remove their unreachable missing-endpoint branch. Keep the nonempty search and its shared bounded helper unchanged, including preview failure recovery.
Purpose: Delete impossible nonfull top-level bounds checks without changing any bitmap, arithmetic, allocation, or empty-search behavior.
*/
/* References: saffah_codex_6a_agg3 https://duck.ac/submission/129732 supplies the accepted peeled-word searches and all inherited author/license notices below. Idea: retain that strongest engine and exploit the proven ripple endpoint preconditions: incBlock is reached only on a non-full block, decBlock only on a non-empty block. Decode only reachable word/block states, retaining the original arithmetic, pushChunk, assignments and summary writes. Purpose: combine eliminated search-loop work with the independent deletion of impossible endpoint branches. */
/* References: saffah_codex_6a_agg3 https://duck.ac/submission/129714 supplies the accepted parser and lazy integer hierarchy, including all inherited public credits and licenses below.
Idea: A nonfull/nonempty word bitmap certifies a candidate in every selected word. Only the current word can lose all candidates after discarding positions below p. Check that partial word once, then select at most one later complete word directly. Keep the same lazy uniform-word decoding, chunk search, and missing-candidate fallback.
Purpose: Delete the repeated current-word comparison and empty-result test from later words in carry/borrow search without changing bounds, representation, or arithmetic.
*/
/* References: saffah_codex_6a_agg3 https://duck.ac/submission/129696 supplies the complete accepted parser/integer engine, including the existing eight-byte digit-bit delimiter test; all original authors and licenses remain below. Idea: in the two nonnegative decimal fields parsed by parsePairF, every digit has ASCII bit4 set and each separating space/newline has it clear. Shift that bit into each byte sign position and invert the vector movemask to locate the same first two delimiters, preserving later decoding and all loads. Purpose: replace the compiler's compare-via-min/equality chain and constant operand with a single vector shift. */
/* References:
* saffah_codex_6a_agg3 https://duck.ac/submission/129658: current word-conjunction integer engine with all inherited public sources and notices below.
* NOI2017 integer https://duck.ac/problem/noi17a: |a|<=10^9, n<=10^6 and b<=30n bound canonical decimal field lengths.
* Idea: The only eqbN callers compare A-space-b-newline, whose length is at most20 and at least4. Complete positive/negative records have at least6/7 bytes. Delete their impossible upper/lower length recovery branches while retaining every sign, boundary, equality-mask and inverse-pair check.
* Purpose: Remove redundant cancellation-parser control flow without changing its compare instructions or applying any new cancellation rule.
*/
/* References:
* saffah_cc_v41_agg1 https://duck.ac/submission/129563: current parser and general integer engine, with all inherited references and notices retained below.
* saffah_codex_6a_agg3 https://duck.ac/submission/121581 and the inherited direct-bit conjunction logic: the word is mixed exactly when both nonfull and nonempty bits are set.
* Idea: Apply that exact mixed-state conjunction to the first word metadata lookup in getBlockPair, where the old path independently tests the two flags. Uniform recovery uses the retained nonfull bit, and all endpoint/cross-word rules and per-block decoding are unchanged.
* Purpose: Remove one data-dependent branch from deferred preview preparation without changing parsing or the update engine.
*/
/* References: saffah_codex_6a_agg3 https://duck.ac/submission/126132,
actual-value unit parser and general engine; inherited citations retained below.
The statement https://duck.ac/problem/noi17a bounds b,k by30*n with n<=1000000.
Idea: After unit-magnitude specialization, every parseNumF caller reads only b
or k, at most30000000 (eight decimal digits). Remove its impossible ninth/tenth
digit continuation. General magnitudes still use parsePairF or the safe parser.
Purpose: Remove an extra branch and delimiter read on eight-digit shift/query
tokens using the exact limits of every remaining fast-reader call site.
*/
/* References: saffah_codex_6a_agg3 https://duck.ac/submission/126084,
paired parser and summary engine; inherited citations remain below. Our
https://duck.ac/submission/126120 established the unit-header parsing route;
https://duck.ac/submission/126126 retains actual single-digit values correctly.
The documented t1<=2 subtask in https://duck.ac/problem/noi17a has unit magnitude.
Idea: Use the header to select the one-digit path, but read its actual magnitude
instead of replacing it by1. In particular zero is preserved. This combines
the faster header dispatch with the actual-value handling of the accepted path.
Purpose: Avoid redundant paired decoding and per-update width checks on the
one-digit subtasks while maintaining the general parser elsewhere.
*/
/* References: saffah_codex_6a_agg3 https://duck.ac/submission/126084,
our paired SIMD parser and integer engine; all inherited citations below.
The statement https://duck.ac/problem/noi17a guarantees |a|=1 when t1<=2.
Idea: In that subtask, skip the known one-digit magnitude and its following
space after the existing sign check. Parse only b with the eight-digit reader;
the buffered update value remains exactly one. The general-A and offline
paths keep their established implementations.
Purpose: Avoid a redundant paired decimal conversion on the large unit-update
subtasks, using a documented input guarantee rather than guessing token values.
*/
/* References: saffah_codex_6a_agg3 https://duck.ac/submission/126054,
fixed-window paired parser, with all original citations retained below.
Idea: One immediate qword permutation [0,1,1,2] creates both byte windows
[0..15] and [8..23] directly from the existing AVX load, replacing three
extract/align/insert operations. The problem's shift<=30*n<=30000000 is always
at most eight digits, so the extra shift-length guard and its always-zero
upper decimal chunk reconstruction are unnecessary.
Purpose: Realize the fixed-window parser with one permutation and one guard.
*/
/* References: saffah_codex_6a_agg3 https://duck.ac/submission/126022,
accepted paired parser/bit engine, preserving all original references below.
Our diagnostic https://duck.ac/submission/126044 shows parsing consumes about
49% of the slowest test's existing parse/apply phase cycles.
Idea: For 7-to-10-digit magnitudes, the shift field fits inside input bytes8..23.
Construct that fixed window from the already loaded 32 bytes, independent of the
first delimiter, and use one combined32-byte shuffle-table row for both values.
This removes a delimiter-dependent input reload and one shuffle-table load.
Short magnitude or longer shift cases keep the previous general parser.
Purpose: Shorten the paired-decimal parser's dependent memory chain.
*/
/* References: saffah_codex_6a_agg3 https://duck.ac/submission/125912,
current offline bins/online summary engine; earlier sources retained below.
Our noip18f https://duck.ac/submission/125984 provides the packed last decimal
stage and digit-bit delimiter observation. No separate license declared.
Idea: Eight-or-fewer-digit token groups produce two <=9999 partials, so pack
them into signed16 lanes and finish with one madd instead of scalar extract,
multiply and addition. ASCII digits all have bit4 set while whitespace clears
it, allowing one complemented mask. Also finish all offline carries beyond the
highest touched bin, including concentrated-update carry chains.
Purpose: Reduce the query-token conversion dependency chain, preserving values.
*/
/* References: saffah_cc_v41_agg1 https://duck.ac/submission/122248:
reused the general online integer engine and its parsers; all inherited source
attribution follows. https://duck.ac/problem/noi17a explicitly guarantees that
for t3=1 all updates precede all queries. No separate source license declared.
Idea: For that guaranteed offline shape, accumulate each signed shifted update
into two neighboring signed 64-bit base-2^32 bins, then normalize carries once
in one forward pass before answering queries directly from the final words.
Split the signed shifted amount into its unsigned low word and arithmetic high
word; at most one million updates keep both accumulation bins within int64.
The general t3=2 shape retains the original online engine.
Purpose: Replace repeated carry propagation and lazy metadata maintenance with
linear deferred normalization where the statement permits it.
*/
/* References: saffah_codex_6a_agg3 https://duck.ac/submission/121581,
reused the lazy bit engine, paired parser and direct-bit query path.
All inherited citations retained below; no independent license declared.
Idea: A bit-summary item is mixed exactly when both its nonfull and nonempty
bits are set. Test that conjunction once per level, and recover the uniform
answer from the nonfull flag. This replaces separate full and empty branches
at both query summary levels without changing update bookkeeping.
Purpose: Reduce decision branches in direct bit queries.
*/
/* References: saffah_cc_v41_agg1 https://duck.ac/submission/121418:
reused the integer engine and lazy endpoint bookkeeping. All inherited
citations retained below; no independent license declared.
Idea: Answer bit queries directly at each lazy level. Uniform chunks, words
and blocks return their Boolean bit immediately; only a mixed materialized
block needs the variable shift. Updates keep the original full-block reader.
Purpose: Avoid producing and subsequently shifting an all-zero/all-one word
for queries resolved by lazy metadata.
*/
/* References:
[1] saffah_cc_v41_agg1, https://duck.ac/submission/117173.
Reused the integer bit-block engine, buffered operations, cancellation logic,
SWAR tail reader and direct judge interface. Inherited citations are retained
below. No separate license is declared on the public source.
Idea: Parse each update's magnitude and shift together with AVX2: one delimiter
mask, independent length shuffles and packed decimal multiply-adds. Retain the
original query reader, short-tail fallback and exact cancellation checks.
Purpose: Measure reduced parsing work without changing operation scheduling.
*/
#pragma GCC optimize("O2","unroll-loops","schedule-insns2","tracer","no-caller-saves")
#pragma GCC optimize("align-functions=64","align-jumps=16","align-loops=16")
#pragma GCC optimize("no-tree-ch")
#pragma GCC optimize("web")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("no-tree-forwprop")
#pragma GCC optimize("no-tree-ccp")
#pragma GCC target("arch=skylake","tune=haswell")
#pragma GCC optimize("no-tree-scev-cprop")
#pragma GCC optimize("no-tree-copy-prop")
#pragma GCC optimize("O3")
#include <stdint.h>
#include <string.h>
#include <emmintrin.h>
#include <x86intrin.h>
typedef uint8_t u8;
typedef uint32_t u32;
typedef uint64_t u64;
typedef unsigned long ul;
#ifdef TIMING
#include <stdio.h>
static void rep(const char* k, unsigned long long v) { fprintf(stderr, "%s %llu\n", k, v); }
#endif
static inline __attribute__((always_inline)) int eqbN(const char* a, const char* b, size_t n) {
__m256i x = _mm256_loadu_si256((const __m256i*)a);
__m256i y = _mm256_loadu_si256((const __m256i*)b);
u32 eq = (u32)_mm256_movemask_epi8(_mm256_cmpeq_epi8(x,y));
u32 mask = (1u << n) - 1u;
return (eq & mask) == mask;
}
static inline void STU256(void* p, __m256i v) {
__asm__ volatile("vmovdqu %0, %1" :: "x"(v), "m"(*(__m256i*)p) : "memory");
}
static inline __attribute__((always_inline)) void fillU8(u8* p, u8 v, int n) {
__m256i y = _mm256_set1_epi8((char)v);
u64 q;
while (n >= 128) {
STU256((p + 0), y);
STU256((p + 32), y);
STU256((p + 64), y);
STU256((p + 96), y);
p += 128; n -= 128;
}
if (n >= 32) {
int k = n >> 5;
for (int i = 0; i < k; i++) STU256((p + (i << 5)), y);
if (n & 31) STU256((p + n - 32), y);
} else {
__m128i x = _mm_set1_epi8((char)v);
while (n >= 64) {
_mm_storeu_si128((__m128i*)(p + 0), x);
_mm_storeu_si128((__m128i*)(p + 16), x);
_mm_storeu_si128((__m128i*)(p + 32), x);
_mm_storeu_si128((__m128i*)(p + 48), x);
p += 64; n -= 64;
}
if (n >= 16) {
int k = n >> 4;
for (int i = 0; i < k; i++) _mm_storeu_si128((__m128i*)(p + (i << 4)), x);
if (n & 15) _mm_storeu_si128((__m128i*)(p + n - 16), x); // overlaps backwards, in-bounds
} else if (n >= 8) {
q = 0x0101010101010101ULL * v;
__builtin_memcpy(p, &q, 8); __builtin_memcpy(p + n - 8, &q, 8);
} else if (n >= 4) {
u32 w = 0x01010101u * (u32)v;
__builtin_memcpy(p, &w, 4); __builtin_memcpy(p + n - 4, &w, 4);
} else if (n >= 2) {
p[0] = v; p[1] = v; p[n - 2] = v; p[n - 1] = v;
} else if (n == 1) *p = v;
}
}
struct DI {
ul abi; const char* ip; ul is; char* op; ul ol, os; char* ep; ul el, es;
const char* IBp; ul IBl; char* OBp; ul OBl; ul tsc;
} __attribute__((packed));
#define BLK 0xFFFFFFFFu // 2^32-1 (W32)
#define ST_E 0
#define ST_F 1
#define ST_M 2
#define NBMAX 1000008
#define NWMAX ((NBMAX + 63) / 64)
#define NCMAX ((NWMAX + 63) / 64)
#define NFXW ((NCMAX + 63) / 64)
#define NFXW2 (NFXW + 2)
struct DS {
u32 valarr[NBMAX];
u64 nf0[NWMAX], ne0[NWMAX];
u8 lww[NWMAX + 64];
u64 nfw[NCMAX], newc[NCMAX];
u8 lcc[NCMAX];
u64 nfx[NFXW2], nex[NFXW2];
};
static DS D;
#ifdef PROBE
static u64 PC_add, PC_qry, PC_find, PC_assign, PC_units, PC_carry, PC_borrow, PC_blk;
static u64 PC_cy_add, PC_cy_qry, PC_cy_parse, PC_cy_assign, PC_cy_find, PC_qdeep;
static u64 PC_fw, PC_fww, PC_pc, PC_blkcnt;
#endif
static int NWU, NCU;
#define CHOPX 1
#ifndef CHOP
#define CHOP 65536
#endif
static long ocnt;
static inline u64 rangeMask(int lo, int hi) { // bits [lo,hi), 0<=lo<hi<=64
u64 m = ~0ULL << lo;
if (hi < 64) m &= ~0ULL >> (64 - hi);
return m;
}
static inline void markChunk(int c) {
u64 bit = 1ULL << (c & 63);
int cw = c >> 6;
u64 a = D.nfw[c], b = D.newc[c];
D.nfx[cw] = (D.nfx[cw] & ~bit) | (bit & (u64)-(long long)(a != 0));
D.nex[cw] = (D.nex[cw] & ~bit) | (bit & (u64)-(long long)(b != 0));
}
static inline void setChunkCode(int c, int st) {
u64 bit = 1ULL << (c & 63); int cw = c >> 6;
if (st != ST_F) D.nfx[cw] |= bit; else D.nfx[cw] &= ~bit;
if (st != ST_E) D.nex[cw] |= bit; else D.nex[cw] &= ~bit;
}
static inline void pushChunk(int c) {
u8 st = D.lcc[c];
#ifdef PROBE
PC_pc++;
#endif
if (st == ST_M) return;
if (st == ST_F) { D.nfw[c] = 0; D.newc[c] = ~0ULL; }
else { D.nfw[c] = ~0ULL; D.newc[c] = 0; }
D.lcc[c] = ST_M;
}
static inline u32 getBlock(int b) {
int w = b >> 6, c = w >> 6;
u8 s = D.lcc[c];
if (s != ST_M) return (s == ST_F) ? BLK : 0u;
u64 wbit = 1ULL << (w & 63);
if (!(D.nfw[c] & wbit)) return BLK; // n17ah: word is all-full
if (!(D.newc[c] & wbit)) return 0u; // n17ah: word is all-empty
u64 bit = 1ULL << (b & 63);
if (!(D.nf0[w] & bit)) return BLK;
if (!(D.ne0[w] & bit)) return 0u;
#ifdef PROBE
PC_qdeep++;
#endif
return D.valarr[b];
}
#define Q0 0x0A30u // '\n'<<8 | '0'
#define Q1 0x0A31u // '\n'<<8 | '1'
static inline u32 getBit(u32 k) {
int b=k>>5,w=b>>6,c=w>>6;u8 s=D.lcc[c];
if(s!=ST_M)return s==ST_F?Q1:Q0;
u64 wbit=1ull<<(w&63);
u64 nf=D.nfw[c],ne=D.newc[c];
if(!((nf&ne)&wbit))return (nf&wbit)?Q0:Q1;
u64 bit=1ull<<(b&63);
nf=D.nf0[w];ne=D.ne0[w];
if(!((nf&ne)&bit))return (nf&bit)?Q0:Q1;
return ((D.valarr[b]>>(k&31))&1u)?Q1:Q0;
}
static inline __attribute__((always_inline)) void setBlock(int b, u32 v) {
#ifdef PROBE
PC_blkcnt++;
#endif
int w = b >> 6, c = w >> 6;
pushChunk(c);
u64 bit = 1ULL << (b & 63);
u64 wbit = 1ULL << (w & 63);
u64 nfc = D.nfw[c], nec = D.newc[c];
u8 sw = (nfc & wbit) ? ((nec & wbit) ? ST_M : ST_E) : ST_F;
if (sw == ST_F) { D.nf0[w] = 0; D.ne0[w] = ~0ULL; }
else if (sw == ST_E) { D.nf0[w] = ~0ULL; D.ne0[w] = 0; }
if (v == 0) { D.nf0[w] |= bit; D.ne0[w] &= ~bit; }
else if (v == BLK) { D.nf0[w] &= ~bit; D.ne0[w] |= bit; }
else { D.nf0[w] |= bit; D.ne0[w] |= bit; D.valarr[b] = v; }
u8 st = (D.nf0[w] == 0) ? ST_F : ((D.ne0[w] == 0) ? ST_E : ST_M);
if (st != sw) {
if (st != ST_F) D.nfw[c] |= wbit; else D.nfw[c] &= ~wbit;
if (st != ST_E) D.newc[c] |= wbit; else D.newc[c] &= ~wbit;
markChunk(c);
}
}
static inline int firstChunkBit(const u64* bm, int c2) {
if (c2 >= NCU) return -1;
int cw = c2 >> 6;
u64 m = bm[cw] & (~0ULL << (c2 & 63));
while (!m) { if (++cw >= NFXW) return -1; m = bm[cw]; }
return (cw << 6) + __builtin_ctzll(m);
}
static inline int firstNonFullChunk(int c2) {
int cw = c2 >> 6;
u64 m = D.nfx[cw] & (~0ULL << (c2 & 63));
while (!m) m = D.nfx[++cw];
return (cw << 6) + __builtin_ctzll(m);
}
static __attribute__((noinline)) int findNonFull(int p) {
#ifdef PROBE
PC_find++;
u64 _tf = __rdtsc();
#endif
int w = p >> 6, c = w >> 6;
u8 s = D.lcc[c];
if (s == ST_E) return p;
if (s != ST_F) {
u64 m = D.nfw[c] & (~0ULL << (w & 63));
u64 here = 1ULL << (w & 63);
if (m & here) {
if (!(D.newc[c] & here)) return p;
u64 bits = D.nf0[w] & (~0ULL << (p & 63));
if (bits) return (w << 6) + __builtin_ctzll(bits);
m &= m - 1;
}
if (m) {
int W = (c << 6) + __builtin_ctzll(m);
if (!(D.newc[c] & (1ULL << (W & 63)))) return W << 6;
return (W << 6) + __builtin_ctzll(D.nf0[W]);
}
}
int C = firstNonFullChunk(c + 1);
#ifdef PROBE
PC_cy_find += __rdtsc() - _tf;
#endif
if (D.lcc[C] == ST_E) return C << 12;
int W = (C << 6) + __builtin_ctzll(D.nfw[C]);
if (!(D.newc[C] & (1ULL << (W & 63)))) return W << 6;
return (W << 6) + __builtin_ctzll(D.nf0[W]);
}
static __attribute__((noinline)) int findNonEmpty(int p) {
int w = p >> 6, c = w >> 6;
u8 s = D.lcc[c];
if (s == ST_F) return p;
if (s != ST_E) {
u64 m = D.newc[c] & (~0ULL << (w & 63));
u64 here = 1ULL << (w & 63);
if (m & here) {
if (!(D.nfw[c] & here)) return p;
u64 bits = D.ne0[w] & (~0ULL << (p & 63));
if (bits) return (w << 6) + __builtin_ctzll(bits);
m &= m - 1;
}
if (m) {
int W = (c << 6) + __builtin_ctzll(m);
if (!(D.nfw[c] & (1ULL << (W & 63)))) return W << 6;
return (W << 6) + __builtin_ctzll(D.ne0[W]);
}
}
int C = firstChunkBit(D.nex, c + 1);
if (C < 0) return -1;
if (D.lcc[C] == ST_F) return C << 12;
int W = (C << 6) + __builtin_ctzll(D.newc[C]);
if (!(D.nfw[C] & (1ULL << (W & 63)))) return W << 6;
return (W << 6) + __builtin_ctzll(D.ne0[W]);
}
static inline void finishWord(int w, int S) {
int c = w >> 6;
u8 st = (D.nf0[w] == 0) ? ST_F : ((D.ne0[w] == 0) ? ST_E : ST_M);
(void)S;
u64 wbit = 1ULL << (w & 63);
u64 nfc = D.nfw[c], nec = D.newc[c];
u8 sw = (nfc & wbit) ? ((nec & wbit) ? ST_M : ST_E) : ST_F;
if (st != sw) {
if (st != ST_F) D.nfw[c] |= wbit; else D.nfw[c] &= ~wbit;
if (st != ST_E) D.newc[c] |= wbit; else D.newc[c] &= ~wbit;
markChunk(c);
}
}
static inline void assignInWord(int w, int lo, int hi, int S) {
int c = w >> 6;
pushChunk(c);
u64 wbit = 1ULL << (w & 63);
u64 nfc = D.nfw[c], nec = D.newc[c];
u8 sw = (nfc & wbit) ? ((nec & wbit) ? ST_M : ST_E) : ST_F;
if (sw == ST_F) { D.nf0[w] = 0; D.ne0[w] = ~0ULL; }
else if (sw == ST_E) { D.nf0[w] = ~0ULL; D.ne0[w] = 0; }
u64 mask = rangeMask(lo, hi);
if (S == ST_F) { D.nf0[w] &= ~mask; D.ne0[w] |= mask; }
else { D.nf0[w] |= mask; D.ne0[w] &= ~mask; }
finishWord(w, S);
}
static inline void fillWords(int c, int lo, int hi, int S) {
if (lo >= hi) return;
pushChunk(c);
#ifdef PROBE
PC_fww += (u64)(hi - lo); PC_fw++;
#endif
u64 mask = rangeMask(lo, hi);
if (S == ST_F) { D.nfw[c] &= ~mask; D.newc[c] |= mask; }
else { D.nfw[c] |= mask; D.newc[c] &= ~mask; }
markChunk(c);
}
static inline void setBitRange(u64* bm, int lo, int hi, int val) {
if (lo >= hi) return;
int w0 = lo >> 6, w1 = (hi - 1) >> 6;
if (w0 == w1) {
u64 mask = rangeMask(lo & 63, ((hi - 1) & 63) + 1);
if (val) bm[w0] |= mask; else bm[w0] &= ~mask;
return;
}
u64 mask0_ = ~0ULL << (lo & 63);
if (val) bm[w0] |= mask0_; else bm[w0] &= ~mask0_;
u64 mask1 = rangeMask(0, ((hi - 1) & 63) + 1);
if (val) bm[w1] |= mask1; else bm[w1] &= ~mask1;
for (int j = w0 + 1; j < w1; j++) bm[j] = val ? ~0ULL : 0ULL;
}
static inline void fullChunks(int c1, int c2, int S) {
if (c1 >= c2) return;
#ifdef PROBE
PC_units += (u64)(c2 - c1); PC_fw += (u64)(c2 - c1);
#endif
fillU8(D.lcc + c1, (u8)S, c2 - c1);
}
static __attribute__((noinline)) void incBlock(int b) {
int w = b >> 6, c = w >> 6;
pushChunk(c);
u64 bit = 1ULL << (b & 63);
u64 wbit = 1ULL << (w & 63);
u64 nec = D.newc[c];
u8 sw = (nec & wbit) ? ST_M : ST_E;
u64 nf, ne; u32 v;
if (sw == ST_M) {
nf = D.nf0[w]; ne = D.ne0[w];
v = (ne & bit) ? D.valarr[b] : 0u;
} else { nf = ~0ULL; ne = 0ULL; v = 0u; }
u32 nv = v + 1u; // v != BLK by precondition => nv != 0
if (nv == BLK) { nf &= ~bit; ne |= bit; }
else { nf |= bit; ne |= bit; D.valarr[b] = nv; }
D.nf0[w] = nf; D.ne0[w] = ne;
u8 st = (nf == 0) ? ST_F : ((ne == 0) ? ST_E : ST_M);
if (st != sw) {
if (st != ST_F) D.nfw[c] |= wbit; else D.nfw[c] &= ~wbit;
if (st != ST_E) D.newc[c] |= wbit; else D.newc[c] &= ~wbit;
markChunk(c);
}
}
static __attribute__((noinline)) void decBlock(int b) {
int w = b >> 6, c = w >> 6;
pushChunk(c);
u64 bit = 1ULL << (b & 63);
u64 wbit = 1ULL << (w & 63);
u64 nfc = D.nfw[c];
u8 sw = (nfc & wbit) ? ST_M : ST_F;
u64 nf, ne; u32 v;
if (sw == ST_M) {
nf = D.nf0[w]; ne = D.ne0[w];
v = (nf & bit) ? D.valarr[b] : BLK;
} else { nf = 0ULL; ne = ~0ULL; v = BLK; }
u32 nv = v - 1u; // v != 0 by precondition => nv != BLK
if (nv == 0) { nf |= bit; ne &= ~bit; }
else { nf |= bit; ne |= bit; D.valarr[b] = nv; }
D.nf0[w] = nf; D.ne0[w] = ne;
u8 st = (nf == 0) ? ST_F : ((ne == 0) ? ST_E : ST_M);
if (st != sw) {
if (st != ST_F) D.nfw[c] |= wbit; else D.nfw[c] &= ~wbit;
if (st != ST_E) D.newc[c] |= wbit; else D.newc[c] &= ~wbit;
markChunk(c);
}
}
static inline void setWordBits(int w, int lo, int hi, int S) {
int c = w >> 6;
u64 wbit = 1ULL << (w & 63);
u64 nfc = D.nfw[c], nec = D.newc[c];
u8 sw = (nfc & wbit) ? ((nec & wbit) ? ST_M : ST_E) : ST_F;
u64 nf, ne;
if (sw == ST_M) { nf = D.nf0[w]; ne = D.ne0[w]; }
else if (sw == ST_F) { nf = 0ULL; ne = ~0ULL; }
else { nf = ~0ULL; ne = 0ULL; }
u64 mask = rangeMask(lo, hi);
if (S == ST_F) { nf &= ~mask; ne |= mask; }
else { nf |= mask; ne &= ~mask; }
D.nf0[w] = nf; D.ne0[w] = ne;
u8 st = (nf == 0) ? ST_F : ((ne == 0) ? ST_E : ST_M);
if (st != ST_F) D.nfw[c] |= wbit; else D.nfw[c] &= ~wbit;
if (st != ST_E) D.newc[c] |= wbit; else D.newc[c] &= ~wbit;
}
static inline void setWholeWords(int c, int lo, int hi, int S) {
if (lo >= hi) return;
u64 mask = rangeMask(lo, hi);
if (S == ST_F) { D.nfw[c] &= ~mask; D.newc[c] |= mask; }
else { D.nfw[c] |= mask; D.newc[c] &= ~mask; }
}
static inline void assignInChunk(int c, int l, int r, int S) {
int wl = l >> 6, wr = (r - 1) >> 6;
pushChunk(c);
if (wl == wr) {
setWordBits(wl, l & 63, ((r - 1) & 63) + 1, S);
} else {
setWordBits(wl, l & 63, 64, S);
setWholeWords(c, (wl & 63) + 1, wr & 63, S);
setWordBits(wr, 0, ((r - 1) & 63) + 1, S);
}
markChunk(c);
}
static inline void assignHead(int l, int S) {
int w = l >> 6, c = w >> 6, lo = l & 63;
u8 s0 = D.lcc[c];
if (s0 == S) return; // whole chunk already S => this assign is a no-op
if (s0 == ST_M) {
u64 mw = (1ULL << (u64)(w & 63)) - 1ULL; // words [c<<6, w)
int ok = (S == ST_F) ? ((D.nfw[c] & mw) == 0) : ((D.newc[c] & mw) == 0);
if (ok) {
u64 bw = 1ULL << (w & 63);
u8 sw = (D.nfw[c] & bw) ? ((D.newc[c] & bw) ? ST_M : ST_E) : ST_F;
if (sw == ST_M) {
u64 mb = (1ULL << (u64)lo) - 1ULL; // blocks [0, lo) of word w
ok = (S == ST_F) ? ((D.nf0[w] & mb) == 0) : ((D.ne0[w] & mb) == 0);
} else ok = (sw == S);
}
if (ok) {
if (S == ST_F) { D.nfw[c] = 0; D.newc[c] = ~0ULL; }
else { D.nfw[c] = ~0ULL; D.newc[c] = 0; }
D.lcc[c] = S; setChunkCode(c, S); // o17i_z1: endpoint bits set here, markRange is interior-only
return;
}
} else {
if (s0 == ST_F) { D.nfw[c] = 0; D.newc[c] = ~0ULL; }
else { D.nfw[c] = ~0ULL; D.newc[c] = 0; }
D.lcc[c] = ST_M;
}
setWordBits(w, lo, 64, S);
setWholeWords(c, (w & 63) + 1, 64, S);
markChunk(c); // o17i_z1: derive this endpoint's bits from its masks
}
static inline void assignTail(int r, int S) {
int w = (r - 1) >> 6, c = w >> 6, hi = ((r - 1) & 63) + 1;
u8 s0 = D.lcc[c];
if (s0 == S) return; // whole chunk already S => this assign is a no-op
if (s0 == ST_M) {
int ww = (w & 63) + 1; // words (w&63, 64) keep state
u64 mw = (ww >= 64) ? 0ULL : (~0ULL << (u64)ww);
int ok = (S == ST_F) ? ((D.nfw[c] & mw) == 0) : ((D.newc[c] & mw) == 0);
if (ok) {
u64 bw = 1ULL << (w & 63);
u8 sw = (D.nfw[c] & bw) ? ((D.newc[c] & bw) ? ST_M : ST_E) : ST_F;
if (sw == ST_M) {
u64 mb = (hi >= 64) ? 0ULL : (~0ULL << (u64)hi); // blocks [hi, 64) of word w
ok = (S == ST_F) ? ((D.nf0[w] & mb) == 0) : ((D.ne0[w] & mb) == 0);
} else ok = (sw == S);
}
if (ok) {
if (S == ST_F) { D.nfw[c] = 0; D.newc[c] = ~0ULL; }
else { D.nfw[c] = ~0ULL; D.newc[c] = 0; }
D.lcc[c] = S; setChunkCode(c, S); // o17i_z1: endpoint bits set here, markRange is interior-only
return;
}
} else {
if (s0 == ST_F) { D.nfw[c] = 0; D.newc[c] = ~0ULL; }
else { D.nfw[c] = ~0ULL; D.newc[c] = 0; }
D.lcc[c] = ST_M;
}
setWholeWords(c, 0, w & 63, S);
setWordBits(w, 0, hi, S);
markChunk(c); // o17i_z1: derive this endpoint's bits from its masks
}
static inline void markRange(int cA, int cB, int S) {
int cA0 = cA + 1, cB0 = cB; // o17i_z1: strictly interior chunks only
if (cA0 >= cB0) return;
u64 fill = (S == ST_E) ? ~0ULL : 0ULL, ifill = ~fill;
int w0 = cA0 >> 6, w1 = (cB0 - 1) >> 6;
if (w0 == w1) {
u64 m = rangeMask(cA0 & 63, ((cB0 - 1) & 63) + 1);
D.nfx[w0] = (D.nfx[w0] & ~m) | (fill & m);
D.nex[w0] = (D.nex[w0] & ~m) | (ifill & m);
return;
}
{ u64 m = ~0ULL << (cA0 & 63);
D.nfx[w0] = (D.nfx[w0] & ~m) | (fill & m);
D.nex[w0] = (D.nex[w0] & ~m) | (ifill & m); }
{ u64 m = rangeMask(0, ((cB0 - 1) & 63) + 1);
D.nfx[w1] = (D.nfx[w1] & ~m) | (fill & m);
D.nex[w1] = (D.nex[w1] & ~m) | (ifill & m); }
for (int j = w0 + 1; j < w1; j++) { D.nfx[j] = fill; D.nex[j] = ifill; }
}
static void assignBlocks(int l, int r, int S) {
if (l >= r) return;
int c1 = (l >> 6) >> 6, c2 = (((r - 1) >> 6)) >> 6;
if (c1 == c2) { // one chunk: unchanged path
int w1 = l >> 6, w2 = (r - 1) >> 6;
int lo1 = l & 63, hi2 = ((r - 1) & 63) + 1;
if (w1 == w2) { assignInWord(w1, lo1, hi2, S); return; }
assignInWord(w1, lo1, 64, S);
assignInWord(w2, 0, hi2, S);
int fw1 = w1 + 1, fw2 = w2;
if (fw1 < fw2) fillWords(c1, fw1 & 63, ((fw2 - 1) & 63) + 1, S);
return;
}
assignHead(l, S); // multi-chunk: fused endpoints
assignTail(r, S);
fullChunks(c1 + 1, c2, S);
markRange(c1, c2, S); // ONE fused bitmap RMW for [c1,c2]
}
static inline __attribute__((aligned(64))) void addAt(u32 A, u32 b) {
u32 q = b >> 5, r = b & 31u;
u64 v = ((u64)A) << r;
u32 lo = (u32)(v & BLK), hi = (u32)(v >> 32);
int w = (int)(q >> 6), c = w >> 6, off = (int)(q & 63);
if (off == 63) { // straddles two words: general path
u32 cur = getBlock((int)q);
u64 s = (u64)cur + lo;
setBlock((int)q, (u32)(s & BLK));
u32 carry = (u32)(s >> 32);
cur = getBlock((int)q + 1);
s = (u64)cur + hi + carry;
setBlock((int)q + 1, (u32)(s & BLK));
if (s >> 32) {
int e = findNonFull((int)q + 2);
assignBlocks((int)q + 2, e, ST_E);
setBlock(e, getBlock(e) + 1);
}
return;
}
if (D.lcc[c] != ST_M) pushChunk(c);
u64 bx = 1ULL << (w & 63);
u64 nfcx = D.nfw[c], necx = D.newc[c];
u8 sw = (nfcx & bx) ? ((necx & bx) ? ST_M : ST_E) : ST_F;
u64 bit0 = 1ULL << off, bit1 = bit0 << 1;
u64 nf, ne;
u32 v0, v1;
u64 nfh = D.nf0[w], neh = D.ne0[w]; // address depends only on w: issue above the sw branch
if (sw == ST_E) { nf = ~0ULL; ne = 0ULL; v0 = 0u; v1 = 0u; }
else if (sw == ST_F) { nf = 0ULL; ne = ~0ULL; v0 = BLK; v1 = BLK; }
else {
nf = nfh; ne = neh;
v0 = (nf & bit0) ? ((ne & bit0) ? D.valarr[q] : 0u) : BLK;
v1 = (nf & bit1) ? ((ne & bit1) ? D.valarr[q + 1] : 0u) : BLK;
}
u64 s0 = (u64)v0 + lo;
u32 nv0 = (u32)(s0 & BLK);
u64 s1 = (u64)v1 + hi + (s0 >> 32);
u32 nv1 = (u32)(s1 & BLK);
u64 f0 = (u64)-(long long)(nv0 == BLK), e0 = (u64)-(long long)(nv0 == 0);
u64 f1 = (u64)-(long long)(nv1 == BLK), e1 = (u64)-(long long)(nv1 == 0);
nf = ((nf & ~bit0) | (bit0 & ~f0)) & ~bit1 | (bit1 & ~f1);
ne = ((ne & ~bit0) | (bit0 & ~e0)) & ~bit1 | (bit1 & ~e1);
D.nf0[w] = nf; D.ne0[w] = ne;
*(u64*)(D.valarr + q) = ((u64)nv1 << 32) | (u64)nv0;
u8 st = (nf == 0) ? ST_F : ((ne == 0) ? ST_E : ST_M);
if (st != sw) {
if (st != ST_F) D.nfw[c] |= bx; else D.nfw[c] &= ~bx;
if (st != ST_E) D.newc[c] |= bx; else D.newc[c] &= ~bx;
markChunk(c);
}
if (s1 >> 32) {
int e = findNonFull((int)q + 2);
assignBlocks((int)q + 2, e, ST_E);
incBlock(e);
}
__asm__ __volatile__(".byte 0x66,0x0f,0x1f,0x44,0x00,0x00" ::: );
}
static inline __attribute__((aligned(64))) void addOneAt(u32 b) {
u32 q=b>>5,lo=1u<<(b&31u);
int w=q>>6,c=w>>6;
if(D.lcc[c]!=ST_M)pushChunk(c);
u64 bx=1ull<<(w&63),bit=1ull<<(q&63);
u64 nfc=D.nfw[c],nec=D.newc[c];
u8 sw=(nfc&bx)?((nec&bx)?ST_M:ST_E):ST_F;
u64 nf,ne;u32 v;
if(sw==ST_E){nf=~0ull;ne=0;v=0;}
else if(sw==ST_F){nf=0;ne=~0ull;v=BLK;}
else{nf=D.nf0[w];ne=D.ne0[w];v=(nf&bit)?((ne&bit)?D.valarr[q]:0u):BLK;}
u32 nv=v+lo;
nf=(nf&~bit)|(nv==BLK?0:bit);
ne=(ne&~bit)|(nv==0?0:bit);
D.nf0[w]=nf;D.ne0[w]=ne;D.valarr[q]=nv;
u8 st=nf==0?ST_F:(ne==0?ST_E:ST_M);
if(st!=sw){
if(st!=ST_F)D.nfw[c]|=bx;else D.nfw[c]&=~bx;
if(st!=ST_E)D.newc[c]|=bx;else D.newc[c]&=~bx;
markChunk(c);
}
if(nv<v){int e=findNonFull((int)q+1);assignBlocks((int)q+1,e,ST_E);incBlock(e);}
}
static inline __attribute__((aligned(64))) void subAt(u32 A, u32 b) {
u32 q = b >> 5, r = b & 31u;
u64 v = ((u64)A) << r;
u32 lo = (u32)(v & BLK), hi = (u32)(v >> 32);
int w = (int)(q >> 6), c = w >> 6, off = (int)(q & 63);
if (off == 63) {
u32 cur = getBlock((int)q);
u32 borrow = 0;
if (cur >= lo) setBlock((int)q, cur - lo);
else { setBlock((int)q, (u32)((u64)cur + 0x100000000ull - lo)); borrow = 1; }
cur = getBlock((int)q + 1);
u32 sub = hi + borrow;
if (cur >= sub) setBlock((int)q + 1, cur - sub);
else {
setBlock((int)q + 1, (u32)((u64)cur + 0x100000000ull - sub));
int e = findNonEmpty((int)q + 2);
assignBlocks((int)q + 2, e, ST_F);
setBlock(e, getBlock(e) - 1);
}
return;
}
if (D.lcc[c] != ST_M) pushChunk(c);
u64 bx = 1ULL << (w & 63);
u64 nfcx = D.nfw[c], necx = D.newc[c];
u8 sw = (nfcx & bx) ? ((necx & bx) ? ST_M : ST_E) : ST_F;
u64 bit0 = 1ULL << off, bit1 = bit0 << 1;
u64 nf, ne;
u32 v0, v1;
u64 nfh = D.nf0[w], neh = D.ne0[w]; // address depends only on w: issue above the sw branch
if (sw == ST_E) { nf = ~0ULL; ne = 0ULL; v0 = 0u; v1 = 0u; }
else if (sw == ST_F) { nf = 0ULL; ne = ~0ULL; v0 = BLK; v1 = BLK; }
else {
nf = nfh; ne = neh;
v0 = (nf & bit0) ? ((ne & bit0) ? D.valarr[q] : 0u) : BLK;
v1 = (nf & bit1) ? ((ne & bit1) ? D.valarr[q + 1] : 0u) : BLK;
}
u32 nv0, nv1;
u64 borrow = 0;
if (v0 >= lo) nv0 = v0 - lo;
else { nv0 = (u32)((u64)v0 + 0x100000000ull - lo); borrow = 1; }
u32 sub1 = hi + (u32)borrow;
if (v1 >= sub1) nv1 = v1 - sub1;
else { nv1 = (u32)((u64)v1 + 0x100000000ull - sub1); borrow = 2; }
u64 f0 = (u64)-(long long)(nv0 == BLK), e0 = (u64)-(long long)(nv0 == 0);
u64 f1 = (u64)-(long long)(nv1 == BLK), e1 = (u64)-(long long)(nv1 == 0);
nf = ((nf & ~bit0) | (bit0 & ~f0)) & ~bit1 | (bit1 & ~f1);
ne = ((ne & ~bit0) | (bit0 & ~e0)) & ~bit1 | (bit1 & ~e1);
D.nf0[w] = nf; D.ne0[w] = ne;
*(u64*)(D.valarr + q) = ((u64)nv1 << 32) | (u64)nv0;
u8 st = (nf == 0) ? ST_F : ((ne == 0) ? ST_E : ST_M);
if (st != sw) {
if (st != ST_F) D.nfw[c] |= bx; else D.nfw[c] &= ~bx;
if (st != ST_E) D.newc[c] |= bx; else D.newc[c] &= ~bx;
markChunk(c);
}
if (borrow == 2) {
int e = findNonEmpty((int)q + 2);
assignBlocks((int)q + 2, e, ST_F);
decBlock(e);
}
}
static inline u64 getBlockPair(u32 q){
int w=q>>6,c=w>>6;
u8 s=D.lcc[c];
if(s!=ST_M){u64 u=(s==ST_F)?~0ULL:0ULL; return u|(u<<32);}
u64 wbit=1ULL<<(w&63);
u64 nf=D.nfw[c],ne=D.newc[c];
if(!((nf&ne)&wbit)){u64 u=(nf&wbit)?0ULL:~0ULL; return u|(u<<32);}
u64 bit=1ULL<<(q&63);
u32 lo=(D.nf0[w]&bit)?((D.ne0[w]&bit)?D.valarr[q]:0u):BLK;
if((q&63)==63){
int w2=w+1,c2=w2>>6;
u8 s2=D.lcc[c2];
u32 hi=(s2!=ST_M)?((s2==ST_F)?BLK:0u):((!(D.nfw[c2]&(1ULL<<(w2&63)))||!(D.newc[c2]&(1ULL<<(w2&63))))?((D.nfw[c2]&(1ULL<<(w2&63)))?0u:BLK):((D.nf0[w2]&1ULL)?((D.ne0[w2]&1ULL)?D.valarr[q+1]:0u):BLK));
return (u64)lo|((u64)hi<<32);
}
u64 bit1=bit<<1;
u32 hi=(D.nf0[w]&bit1)?((D.ne0[w]&bit1)?D.valarr[q+1]:0u):BLK;
return (u64)lo|((u64)hi<<32);
}
__attribute__((noinline)) static u32 previewBit(u32 A,u32 b,bool neg,u32 k){
if(k<b)return getBit(k);
u32 q=b>>5,kb=k>>5;
u64 before=getBlockPair(q);
u64 delta=(u64)A<<(b&31),after=neg?before-delta:before+delta;
if(kb<=q+1)return Q0+(u32)((after>>(k-(q<<5)))&1u);
bool flow=neg?(before<delta):(after<before);
if(!flow)return getBit(k);
int e=neg?findNonEmpty(q+2):findNonFull(q+2);
if(kb<(u32)e)return neg?Q1:Q0;
if(kb==(u32)e){u32 v=getBlock(e);v=neg?v-1:v+1;return Q0+((v>>(k&31))&1u);}
return getBit(k);
}
static const u8 RAS[9][16] __attribute__((aligned(16))) = {
{0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80},
{0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, 0},
{0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, 0, 1},
{0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, 0, 1, 2},
{0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, 0, 1, 2, 3},
{0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, 0, 1, 2, 3, 4},
{0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, 0, 1, 2, 3, 4, 5},
{0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, 0, 1, 2, 3, 4, 5, 6},
{0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, 0, 1, 2, 3, 4, 5, 6, 7},
};
static inline u32 swar8b(u64 v, int& nd) {
u64 t = (~v) & 0x1010101010101010ULL;
nd = t ? (int)(__builtin_ctzll(t) >> 3) : 8;
__m128i x = _mm_cvtsi64_si128((long long)v);
__m128i d = _mm_sub_epi8(x, _mm_set1_epi8(48));
__m128i z = _mm_shuffle_epi8(d, _mm_load_si128((const __m128i*)(RAS[nd])));
__m128i q1 = _mm_maddubs_epi16(z, _mm_set1_epi32(0x010A010A));
__m128i q2 = _mm_madd_epi16(q1, _mm_set1_epi32(0x00010064));
__m128i q3=_mm_madd_epi16(_mm_packs_epi32(q2,q2),_mm_set1_epi32(0x00012710));
return (u32)_mm_extract_epi32(q3,1);
}
static const u8 SH10[176] __attribute__((aligned(16)))={128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,0,128,128,128,128,128,128,128,128,128,128,128,128,128,128,0,1,128,128,128,128,128,128,128,128,128,128,128,128,128,0,1,2,128,128,128,128,128,128,128,128,128,128,128,128,0,1,2,3,128,128,128,128,128,128,128,128,128,128,128,0,1,2,3,4,128,128,128,128,128,128,128,128,128,128,0,1,2,3,4,5,128,128,128,128,128,128,128,128,128,0,1,2,3,4,5,6,128,128,128,128,128,128,128,128,0,1,2,3,4,5,6,7,128,128,128,128,128,128,128,128,1,2,3,4,5,6,7,8,128,128,128,128,128,128,128,0,2,3,4,5,6,7,8,9,128,128,128,128,128,128,0,1};
alignas(32) static const u8 PAIRWIN[1152]={128,0,1,2,3,4,5,6,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,0,1,2,3,4,5,6,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,0,128,128,128,128,128,128,128,128,128,0,1,2,3,4,5,6,128,128,128,128,128,128,128,128,128,128,128,128,128,128,0,1,128,128,128,128,128,128,128,128,128,0,1,2,3,4,5,6,128,128,128,128,128,128,128,128,128,128,128,128,128,0,1,2,128,128,128,128,128,128,128,128,128,0,1,2,3,4,5,6,128,128,128,128,128,128,128,128,128,128,128,128,0,1,2,3,128,128,128,128,128,128,128,128,128,0,1,2,3,4,5,6,128,128,128,128,128,128,128,128,128,128,128,0,1,2,3,4,128,128,128,128,128,128,128,128,128,0,1,2,3,4,5,6,128,128,128,128,128,128,128,128,128,128,0,1,2,3,4,5,128,128,128,128,128,128,128,128,128,0,1,2,3,4,5,6,128,128,128,128,128,128,128,128,128,0,1,2,3,4,5,6,128,128,128,128,128,128,128,128,128,0,1,2,3,4,5,6,128,128,128,128,128,128,128,128,0,1,2,3,4,5,6,7,128,128,128,128,128,128,128,128,0,1,2,3,4,5,6,7,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,0,1,2,3,4,5,6,7,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,1,128,128,128,128,128,128,128,128,0,1,2,3,4,5,6,7,128,128,128,128,128,128,128,128,128,128,128,128,128,128,1,2,128,128,128,128,128,128,128,128,0,1,2,3,4,5,6,7,128,128,128,128,128,128,128,128,128,128,128,128,128,1,2,3,128,128,128,128,128,128,128,128,0,1,2,3,4,5,6,7,128,128,128,128,128,128,128,128,128,128,128,128,1,2,3,4,128,128,128,128,128,128,128,128,0,1,2,3,4,5,6,7,128,128,128,128,128,128,128,128,128,128,128,1,2,3,4,5,128,128,128,128,128,128,128,128,0,1,2,3,4,5,6,7,128,128,128,128,128,128,128,128,128,128,1,2,3,4,5,6,128,128,128,128,128,128,128,128,0,1,2,3,4,5,6,7,128,128,128,128,128,128,128,128,128,1,2,3,4,5,6,7,128,128,128,128,128,128,128,128,0,1,2,3,4,5,6,7,128,128,128,128,128,128,128,128,1,2,3,4,5,6,7,8,128,128,128,128,128,128,128,128,1,2,3,4,5,6,7,8,128,128,128,128,128,128,128,0,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,1,2,3,4,5,6,7,8,128,128,128,128,128,128,128,0,128,128,128,128,128,128,128,2,128,128,128,128,128,128,128,128,1,2,3,4,5,6,7,8,128,128,128,128,128,128,128,0,128,128,128,128,128,128,2,3,128,128,128,128,128,128,128,128,1,2,3,4,5,6,7,8,128,128,128,128,128,128,128,0,128,128,128,128,128,2,3,4,128,128,128,128,128,128,128,128,1,2,3,4,5,6,7,8,128,128,128,128,128,128,128,0,128,128,128,128,2,3,4,5,128,128,128,128,128,128,128,128,1,2,3,4,5,6,7,8,128,128,128,128,128,128,128,0,128,128,128,2,3,4,5,6,128,128,128,128,128,128,128,128,1,2,3,4,5,6,7,8,128,128,128,128,128,128,128,0,128,128,2,3,4,5,6,7,128,128,128,128,128,128,128,128,1,2,3,4,5,6,7,8,128,128,128,128,128,128,128,0,128,2,3,4,5,6,7,8,128,128,128,128,128,128,128,128,1,2,3,4,5,6,7,8,128,128,128,128,128,128,128,0,2,3,4,5,6,7,8,9,128,128,128,128,128,128,128,128,2,3,4,5,6,7,8,9,128,128,128,128,128,128,0,1,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,2,3,4,5,6,7,8,9,128,128,128,128,128,128,0,1,128,128,128,128,128,128,128,3,128,128,128,128,128,128,128,128,2,3,4,5,6,7,8,9,128,128,128,128,128,128,0,1,128,128,128,128,128,128,3,4,128,128,128,128,128,128,128,128,2,3,4,5,6,7,8,9,128,128,128,128,128,128,0,1,128,128,128,128,128,3,4,5,128,128,128,128,128,128,128,128,2,3,4,5,6,7,8,9,128,128,128,128,128,128,0,1,128,128,128,128,3,4,5,6,128,128,128,128,128,128,128,128,2,3,4,5,6,7,8,9,128,128,128,128,128,128,0,1,128,128,128,3,4,5,6,7,128,128,128,128,128,128,128,128,2,3,4,5,6,7,8,9,128,128,128,128,128,128,0,1,128,128,3,4,5,6,7,8,128,128,128,128,128,128,128,128,2,3,4,5,6,7,8,9,128,128,128,128,128,128,0,1,128,3,4,5,6,7,8,9,128,128,128,128,128,128,128,128,2,3,4,5,6,7,8,9,128,128,128,128,128,128,0,1,3,4,5,6,7,8,9,10,128,128,128,128,128,128,128,128};
static inline const char* parsePairF(const char* in,u32 &a,u32 &b) {
const u8 *p=(const u8*)in;
__m256i v=_mm256_loadu_si256((const __m256i *)p);
unsigned mask=~(unsigned)_mm256_movemask_epi8(_mm256_slli_epi16(v,3));
unsigned ka=(unsigned)__builtin_ctz(mask),end=(unsigned)__builtin_ctz(mask&(mask-1)),kb=end-ka-1;
__m256i d,sh;
if(ka>=7){
d=_mm256_permute4x64_epi64(v,0x94);
sh=_mm256_load_si256((const __m256i*)(PAIRWIN+32*((ka-7)*9+kb)));
}else{
d=_mm256_castsi128_si256(_mm256_castsi256_si128(v));
d=_mm256_inserti128_si256(d,_mm_loadu_si128((const __m128i *)(p+ka+1)),1);
sh=_mm256_castsi128_si256(_mm_load_si128((const __m128i *)(SH10+16*ka)));
sh=_mm256_inserti128_si256(sh,_mm_load_si128((const __m128i *)(SH10+16*kb)),1);
}
d=_mm256_shuffle_epi8(_mm256_and_si256(d,_mm256_set1_epi8(15)),sh);
d=_mm256_maddubs_epi16(d,_mm256_set1_epi16(0x010a));
d=_mm256_madd_epi16(d,_mm256_set1_epi32(0x00010064));
d=_mm256_madd_epi16(_mm256_packs_epi32(d,d),_mm256_set1_epi32(0x00012710));
u64 va=(u64)_mm_cvtsi128_si64(_mm256_castsi256_si128(d)),vb=(u64)_mm_cvtsi128_si64(_mm256_extracti128_si256(d,1));
a=(u32)va+(u32)(va>>32)*100000000u;b=(u32)vb;return (const char*)(p+end);
}
static const char* g_lim;
static inline const char* parseNumF(const char* p, u32& out) {
u64 v;
__builtin_memcpy(&v, p, 8);
int nd;
u32 r = swar8b(v, nd);
p += nd;
out = r;
return p;
}
static inline const char* parseNum(const char* p, u32& out) {
if (p < g_lim) {
u64 v;
__builtin_memcpy(&v, p, 8);
int nd;
u32 r = swar8b(v, nd);
p += nd;
if (nd == 8) {
while (*p >= '0' && *p <= '9') { r = r * 10 + (u32)(*p - '0'); ++p; }
}
out = r;
return p;
}
u32 v = 0;
while (*p >= '0' && *p <= '9') { v = v * 10 + (u32)(*p - '0'); ++p; }
out = v;
return p;
}
static inline const char* parseNums(const char* p, u32* outv, int cnt) {
for (int i = 0; i < cnt; i++) {
u32 v = 0;
while (*p >= '0' && *p <= '9') { v = v * 10 + (u32)(*p - '0'); ++p; }
outv[i] = v;
if (*p == ' ') ++p;
}
return p;
}
#ifdef PROBE
static volatile char leakarray[1u << 28] __attribute__((aligned(4096)));
#endif
static void initStructNB(int NB) {
NWU = (NB + 63) >> 6;
NCU = (NWU + 63) >> 6;
for (int c = 0; c < NCU; c++) { D.lcc[c] = ST_E; D.nfw[c] = ~0ULL; D.newc[c] = 0; }
for (int j = 0; j < NFXW2; j++) { D.nfx[j] = 0; D.nex[j] = 0; }
setBitRange(D.nfx, 0, NCU, 1);
}
static long long offline_acc[NBMAX];
__attribute__((noinline)) static ul offline_run(const char*p,u32 n,char*out){
u32 i=0,mx=0;
for(;i<n && *p=='1';i++){
p+=2;bool neg=(*p=='-');if(neg)++p;u32 A,b;
if(p<g_lim)p=parsePairF(p,A,b);
else{p=parseNum(p,A);++p;p=parseNum(p,b);}++p;
long long sa=neg?-(long long)A:(long long)A;
u64 v=(u64)sa<<(b&31);u32 q=b>>5;
offline_acc[q]+=(u32)v;offline_acc[q+1]+=(long long)v>>32;
if(q+1>mx)mx=q+1;
}
long long carry=0;
for(u32 j=0;j<=mx || carry;j++){
long long v=offline_acc[j]+carry;D.valarr[j]=(u32)v;carry=v>>32;
}
char*o=out;
for(;i<n;i++){
p+=2;u32 k;p=p<g_lim?parseNumF(p,k):parseNum(p,k);++p;
*(uint16_t*)o=(uint16_t)(Q0+((D.valarr[k>>5]>>(k&31))&1));o+=2;
}
return o-out;
}
__attribute__((noinline)) static ul t1_run(const char* in, ul insz, const char* p, char* out, u32 n) {
char* o = out;
const char* gsafe = insz > 128 ? in + insz - 64 : in;
u32 i = 0;
for (; i < n && p < gsafe; i++) {
int ty = (int)p[0] - '0';
p += 2;
if (ty == 1) { u32 b; p += 2; p = parseNumF(p, b); ++p; addOneAt(b); }
else { u32 k; p = parseNumF(p, k); ++p; *(uint16_t*)o = (uint16_t)getBit(k); o += 2; }
}
for (; i < n; i++) {
int ty = (int)p[0] - '0';
p += 2;
if (ty == 1) { u32 b; p += 2; p = parseNum(p, b); ++p; addOneAt(b); }
else { u32 k; p = parseNum(p, k); ++p; *(uint16_t*)o = (uint16_t)getBit(k); o += 2; }
}
return (ul)(o - out);
}
static ul run(const char* in, ul insz, char* out) {
(void)insz;
#ifdef TIMING
u64 t_start = __rdtsc();
#endif
const char* p = in;
u32 hdr[4];
p = parseNums(p, hdr, 4);
u32 n = hdr[0];
const bool unit_magnitude=hdr[1]<=2;
const bool one_mag = (hdr[1] == 1);
++p; // newline after the header
if(hdr[3]==1){g_lim=insz>64?in+insz-32:in;return offline_run(p,n,out);}
int NB = (int)(((long long)n * 30 + 31) / 32) + 4; // W32
initStructNB(NB);
g_lim = insz > 64 ? in + insz - 32 : in;
char* o = out;
#ifdef PROBE
u64 _tp = 0, _tstart_q = 0, _tstart_a = 0;
#endif
#ifdef TIMING
u64 t_ops0 = __rdtsc();
rep("parse_init_cycles", t_ops0 - t_start);
#endif
if (one_mag) {
ocnt = t1_run(in, insz, p, out, n);
} else {
char* o = out;
u64 ob[CHOP + 2];
u32 base = 0;
while (base < n) {
u32 lim = base + CHOP; if (lim > n) lim = n;
u64* qq = ob; u32 cnt = 0;
{ const char* gsafe = insz > 128 ? in + insz - 64 : in;
u32 i = base;
u64 pendx = ~0ULL; u32 pend_idx = 0;
for (; i < lim && p < gsafe; i++) {
int ty = (int)p[0] - '0';
p += 2;
if (ty == 1) {
const char* ps = p - 2; // at the leading '1'
u32 A, b; u64 sgn = 0;
int hadsign = (*p == '-');
if (hadsign) { sgn = 1ULL << 31; ++p; }
if(unit_magnitude){A=(u32)(p[0]-'0');p+=2;p=parseNumF(p,b);}
else p = parsePairF(p,A,b);
++p;
u64 ww = ((u64)b << 32) | (u64)A | sgn;
const char* pe = p; // one past this line's '\n'
if (i + 1 < lim && p[0] == '1' && p[1] == ' ') {
size_t Li = (size_t)(pe - ps);
if (!hadsign) {
if (p[2] == '-' && eqbN(p + 3, ps + 2, Li - 2)) {
(void)ww;
p += Li + 1; ++i; continue;
}
} else {
if (p[2] != '-' && eqbN(p + 2, ps + 3, Li - 3)) {
(void)ww;
p += Li - 1; ++i; continue;
}
}
}
if (ww == pendx) {
u32 rl = cnt - pend_idx - 1u;
if (rl <= 31u) {
ob[pend_idx] |= (1ULL << 62) | ((u64)rl << 57);
pendx = ~0ULL;
continue;
}
}
pendx = ww ^ (1ULL << 31);
pend_idx = cnt;
*qq++ = ww; ++cnt;
} else {
u32 k;
p = parseNumF(p, k);
++p;
*qq++ = (1ULL << 63) | k; ++cnt;
}
}
for (; i < lim; i++) {
int ty = (int)p[0] - '0';
p += 2;
if (ty == 1) {
u32 A, b; u64 sgn = 0;
if (*p == '-') { sgn = 1ULL << 31; ++p; }
p = parseNum(p, A);
++p;
p = parseNum(p, b);
++p;
*qq++ = ((u64)b << 32) | (u64)A | sgn; ++cnt;
} else {
u32 k;
p = parseNum(p, k);
++p;
*qq++ = (1ULL << 63) | k; ++cnt;
}
}
}
ob[cnt] = ~0ULL; ob[cnt + 1] = ~0ULL; // o17r_ sentinels: see the loop below
qq = ob;
u32 pact = 0, pB = 0, pq = 0, pe = 0, pflow = 0, pneg = 0;
u32 pA = 0, pready = 0, pendready = 0;
u64 pafter = 0;
for (u32 j = 0; j < cnt; j++) {
u64 w = *qq++;
if (w >> 63) {
u32 k = (u32)w, ans;
if (pact) {
--pact;
if (k < pB) ans = getBit(k);
else {
if (!pready) {
u64 delta = (u64)pA << (pB & 31u);
u64 before = getBlockPair(pq);
pafter = pneg ? before - delta : before + delta;
pflow = pneg ? (before < delta) : (pafter < before);
pready = 1;
}
u32 kb = k >> 5;
if (kb <= pq + 1u) ans = Q0 + (u32)((pafter >> (k - (pq << 5))) & 1u);
else if (!pflow) ans = getBit(k);
else {
if (!pendready) {
pe = (u32)(pneg ? findNonEmpty((int)pq + 2) : findNonFull((int)pq + 2));
pendready = 1;
}
if (kb < pe) ans = pneg ? Q1 : Q0;
else if (kb == pe) { u32 v = getBlock((int)pe); v = pneg ? v - 1u : v + 1u;
ans = Q0 + ((v >> (k & 31)) & 1u); }
else ans = getBit(k);
}
}
} else ans = getBit(k);
*(uint16_t*)o = (uint16_t)ans;
o += 2;
} else if (w & (1ULL << 62)) {
pB = ((u32)(w >> 32)) & 0x1ffffffu;
pneg = (u32)((w >> 31) & 1u);
pact = (u32)((w >> 57) & 31u);
pq = pB >> 5; pA = (u32)w & 0x7fffffffu;
pready = pendready = 0;
} else if (0) {
++qq; ++j;
} else if (0) {
*(uint16_t*)o = (uint16_t)previewBit((u32)w&0x7fffffffu,(u32)(w>>32),(w&(1ull<<31))!=0,(u32)*qq);
o += 2;
qq += 2; j += 2;
} else {
u32 b = (u32)(w >> 32), A = (u32)(w & 0x7FFFFFFFu);
if (!(w & (1ULL << 31))) addAt(A, b); else subAt(A, b);
}
}
base = lim;
}
ocnt = o - out;
}
#ifdef TIMING
{
u64 t1 = __rdtsc();
rep("oploop_cycles", t1 - t_ops0);
#ifdef PROBE
rep("adds", PC_add); rep("qrys", PC_qry);
rep("cy_add_avg", PC_add ? PC_cy_add / PC_add : 0);
rep("cy_qry_avg", PC_qry ? PC_cy_qry / PC_qry : 0);
rep("cy_parse_avg", (PC_add + PC_qry) ? PC_cy_parse / (PC_add + PC_qry) : 0);
rep("cy_find_avg", PC_find ? PC_cy_find / PC_find : 0);
rep("cy_assign_avg", PC_assign ? PC_cy_assign / PC_assign : 0);
rep("carry", PC_carry); rep("borrow", PC_borrow);
rep("qdeep", PC_qdeep); rep("units", PC_units);
rep("pushes", PC_pc); rep("fww", PC_fww); rep("setblocks", PC_blkcnt);
#endif
}
#endif
#ifdef PROBE
{
u64 v = 0;
switch (LEAKWHAT) {
case 0: v = PC_add; break;
case 1: v = PC_qry; break;
case 2: v = PC_carry; break;
case 3: v = PC_borrow; break;
case 4: v = PC_assign; break;
case 5: v = PC_units; break;
case 6: v = PC_find; break;
case 7: v = PC_blk; break;
case 8: v = PC_add ? (PC_cy_add * 100 / PC_add) : 0; break;
case 9: v = PC_qry ? (PC_cy_qry * 100 / PC_qry) : 0; break;
case 10: { u64 tot = PC_add + PC_qry; v = tot ? (PC_cy_parse * 100 / tot) : 0; } break;
case 11: v = PC_find ? (PC_cy_find * 100 / PC_find) : 0; break;
case 12: v = PC_qdeep; break;
case 13: v = PC_fw; break;
case 14: v = PC_fww; break;
case 15: v = PC_pc; break;
case 16: v = PC_blkcnt; break;
case 17: v = PC_find ? (PC_cy_assign * 100 / PC_find) : 0; break;
}
unsigned chunk = (unsigned)((v >> LEAKSHIFT) & 0xFFFFu);
for (unsigned j = 0; j < chunk; j++) leakarray[(unsigned long)j << 12] = 1;
}
#endif
return (ul)ocnt;
}
#ifndef LOCAL
int main() { return 0; }
extern "C" void __libc_start_main(void* mm, int argc, char** argv) {
ul* p = (ul*)(argv + argc + 1);
while (*p) p++;
p++;
DI* d = 0;
for (; p[0]; p += 2) if (p[0] == 0x6b637564UL) { d = (DI*)p[1]; break; }
if (d) {
const char* in = d->ip;
ul insz = d->is;
if (!insz) { in = d->IBp; insz = d->IBl; }
char* out = d->op;
d->os = run(in, insz, out);
}
__asm__ volatile("syscall" :: "a"(60), "D"(0) : "rcx", "r11", "memory");
for (;;);
}
#else
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
static char inbuf[40000000];
static char outbuf[8000000];
int main() {
ul n = 0;
while (n < sizeof(inbuf)) {
ssize_t r = read(0, inbuf + n, sizeof(inbuf) - n);
if (r <= 0) break;
n += (ul)r;
}
ul len = 0;
int K = 1; { const char* e = getenv("BENCHK"); if (e) K = atoi(e); }
u64 best = ~0ULL;
for (int k = 0; k < K; k++) { u64 _t0 = __rdtsc(); len = run(inbuf, (ul)n, outbuf); u64 _t1 = __rdtsc(); if (_t1-_t0<best) best=_t1-_t0; }
if (getenv("BENCH")) fprintf(stderr, "%lu\n", (unsigned long)best);
ssize_t off = 0;
while ((ul)off < len) {
ssize_t w = write(1, outbuf + off, len - (ul)off);
if (w <= 0) break;
off += w;
}
return 0;
}
#endif
| Compilation | N/A | N/A | Compile OK | Score: N/A | 显示更多 |
| Testcase #1 | 38.98 us | 540 KB | Accepted | Score: 4 | 显示更多 |
| Testcase #2 | 43.76 us | 540 KB | Accepted | Score: 4 | 显示更多 |
| Testcase #3 | 93.24 us | 540 KB | Accepted | Score: 4 | 显示更多 |
| Testcase #4 | 83.02 us | 540 KB | Accepted | Score: 4 | 显示更多 |
| Testcase #5 | 99.05 us | 528 KB | Accepted | Score: 4 | 显示更多 |
| Testcase #6 | 188.63 us | 544 KB | Accepted | Score: 4 | 显示更多 |
| Testcase #7 | 209.76 us | 580 KB | Accepted | Score: 4 | 显示更多 |
| Testcase #8 | 200.3 us | 544 KB | Accepted | Score: 4 | 显示更多 |
| Testcase #9 | 584.04 us | 672 KB | Accepted | Score: 4 | 显示更多 |
| Testcase #10 | 567.23 us | 808 KB | Accepted | Score: 4 | 显示更多 |
| Testcase #11 | 943.98 us | 584 KB | Accepted | Score: 4 | 显示更多 |
| Testcase #12 | 1.238 ms | 828 KB | Accepted | Score: 4 | 显示更多 |
| Testcase #13 | 1.252 ms | 852 KB | Accepted | Score: 4 | 显示更多 |
| Testcase #14 | 3.505 ms | 1 MB + 408 KB | Accepted | Score: 4 | 显示更多 |
| Testcase #15 | 5.57 ms | 1 MB + 856 KB | Accepted | Score: 4 | 显示更多 |
| Testcase #16 | 7.15 ms | 2 MB + 284 KB | Accepted | Score: 4 | 显示更多 |
| Testcase #17 | 7.746 ms | 900 KB | Accepted | Score: 4 | 显示更多 |
| Testcase #18 | 11.043 ms | 3 MB + 156 KB | Accepted | Score: 4 | 显示更多 |
| Testcase #19 | 12.883 ms | 3 MB + 608 KB | Accepted | Score: 4 | 显示更多 |
| Testcase #20 | 14.555 ms | 4 MB + 336 KB | Accepted | Score: 4 | 显示更多 |
| Testcase #21 | 17.524 ms | 4 MB + 484 KB | Accepted | Score: 4 | 显示更多 |
| Testcase #22 | 14.373 ms | 1 MB + 188 KB | Accepted | Score: 4 | 显示更多 |
| Testcase #23 | 11.38 ms | 5 MB + 804 KB | Accepted | Score: 4 | 显示更多 |
| Testcase #24 | 15.153 ms | 1 MB + 232 KB | Accepted | Score: 4 | 显示更多 |
| Testcase #25 | 17.983 ms | 4 MB + 924 KB | Accepted | Score: 4 | 显示更多 |