题解:P11696 [JRKSJ ExR] 七影蝶
我是区。
P11696 [JRKSJ ExR] 七影蝶
Subtask 4,6:\(O(nlog^2V)\)
拆位,\(a_i+j\) 的第 k 位为 1 可以转化为 j 的后 k 位在一个或两个值域区间内,因此能使第 k 位为 1 的位置可以用若干个区间表示出来,区间贡献 +1,拍到线段树上。建主席树,有 \(logV\) 个版本,第 \(i\) 个版本维护值域 \([0,2^i)\),左右都连第 \(i-1\) 版本。
时空都是 \(O(nlog^2V)\),视 nq 同阶。搬一下出题人的代码。
正解 \(O(nlogV)\)
首先有个结论:第 \(k+1\) 位对应的贡献区间完全包括第 \(k\) 位对应的贡献区间。
证明:
第 \(k\) 层在域 \([0, 2^k)\) 上的端点集为 \(B_k = \{(-a_i)\bmod 2^k\}\)(端点组成的区间左闭右开)。把它复制接到后面,得到域 \([0,2^{k+1})\) 上的"复制端点集" \(C_k = B_k \cup (B_k + 2^k)\)。第 \(k+1\) 层的端点集为 \(B_{k+1} = \{(-a_i)\bmod 2^{k+1}\}\)。
对任意 \(a_i\),设 \(p = (-a_i)\bmod 2^k\)。则 \((-a_i)\bmod 2^{k+1}\) 在 \([0,2^{k+1})\) 中与 \(p\) 同余于模 \(2^k\),故只能是 \(p\) 或 \(p+2^k\),二者都属于 \(C_k\)。
因此 \(B_{k+1} \subseteq C_k\)。即第 \(k+1\) 位的贡献区间端点集合是第 \(k\) 位的子集。
端点集越小,划分越粗(断点少 → 段大)。\(B_{k+1} \subseteq C_k\) 意味着 \(B_{k+1}\) 诱导的划分比 \(C_k\) 诱导的划分更粗。而 \(C_k\) 诱导的划分恰好就是第 \(k\) 层的两份复制。粗划分的每条段是若干细划分段的并,即细段整条落在粗段里——这就是"第 \(k\) 层的所有区间都被某个第 \(k+1\) 层区间完全包含"。
直观图:
可以发现无论取绿色箭头分割的中间一段还是旁边两端,都包括完整的红色块。
因此将原本贡献的可交区间,拆成不相交的区间(原本重复的部分计到区间的值里),维护区间的最大值,每一次进入到下一位的时候,用贡献区间内的最大值加上本身的区间值。这个可以线性扫。这样就不用主席树了,每次合并区间得到新序列。

将所有位都处理完之后,查询就是在最终得到的序列上 RMQ。但是有个问题是 \(L\) 和 \(R\) 不一定为整块端点,那就得查询两边一堆散块和中间一堆整块,散块的查询需要往下递归,就得用 \(O(n)−O(1)\) RMQ,但是我们可以绕过这个东西:直接强制让 \(L\) 和 \(R+1\) 成为整块端点(注意左闭右开),然后就可以直接查询整块 RMQ 了,这个直接用普通 st 表维护一下即可。

浙公网安备 33010602011771号