重修 分散层叠算法(Fractional Cascading)
作者:互联网
新学的知识不能算重修了吧
自己想到的一个类似的东西:
顺势疗法(homeopathy):首先,把某种物质在酒精中浸泡几个星期,过滤浸泡液得到该物质的“母酊剂”。然后,使用一些母酊剂通过用水反复地稀释和强烈的摇动,得到最终的药剂。直到现在,仍然用相同的基本的基本程序来制造顺势疗法的药剂。
最后得到的药剂往往甚至不含有原始物质的一个分子,正统的科学认为,这会致使药剂失去活性。
生物化学博士方舟子曾撰写《“分子顺势疗法”来了》一文:
市场上销售的顺势疗法药物常见的有用蒸馏水把药物稀释了 \(10^{30}\) 的。这是什么概念呢?往海洋里滴一滴水,也不过被稀释了 \(10^{26}\),也就是说,其有效成分的浓度,比沧海一粟还要低 \(1\) 万倍,事实上是什么都没有。根据阿芙伽德罗定律,\(1\) 摩尔的任何物质包含有大约 \(10^{24}\) 个分子,也就是说,稀释到 \(10^{24}\) 以后,已不可能含有被稀释的成分的一个分子,全都是水分子了。
学完后你就会发现分散层叠算法和这个过程很像不过不是伪科学。
P6466 分散层叠算法(Fractional Cascading)
还是讲一下大体:
题面
给出 \(k\) 个长度为 \(n\) 的升序数组。保证所有数组中出现过的数不重复(如果有的题重复,离散化即可)。
现在有 \(q\) 个查询:给出数 \(x\),分别求出每个数组中大于等于 \(x\) 的最小的数(lower_bound)(不存在则定义为 \(0\))。
由于不让瓶颈在 IO 上,每个查询输出 \(k\) 个后继的异或和。
还是由于不让瓶颈在 IO 上,只要编号为 \(d\) 倍数的询问要输出。
强制在线。
\(O(nk+q(k+\log n))\) 时间 \(O(nk)\) 空间内解决。
题解
我们先设原 \(k\) 个序列为 \(A^{(1)},A^{(2)},\dots,A^{(k)}\)。
对应地,创建 \(k\) 个序列 \(B^{(1)},B^{(2)},\dots,B^{(k)}\),但是每个元素实现中不只是一个 int,存有两个下标 \(nxt1,nxt2\),意义后面说。
初始化
文中有序数组之间的 \(+\) 均定义为归并。
\[B^{(k)}=A^{(k)} \]之后 \(s\) 遍历 \((k-1)\to 1\),每一步中:
\(C\) 数组为 \(B^{(s+1)}\) 提取偶数下标元素得到的数组。
\[B^{(s)}=A^{(s)}+C \]归并的同时 \(B^{(s)}\) 中每个元素 \(x\) 记录:
-
\(nxt1\):\(x\) 在 \(A^{(s)}\) 中的 lower_bound 下标。
-
\(nxt2\):\(x\) 在 \(B^{(s+1)}\) 中的 lower_bound 下标。注意是 \(B^{(s+1)}\) 而不是 \(C\)。
因为
\[\frac{\frac{\frac{\ddots}{2}+n}{2}+n}{2}+n=2n \]所以 \(B^{(s)}\) 数组长度的上界是 \(2n\),所以空间 \(O(nk)\) 满足。
由于归并是线性复杂度的,初始化时间为 \(O(nk)\)。
询问
设询问的值在 \(B^{(1)}\) 中的 lower_bound 下标为 \(p\)。注意是 \(B\) 而不是 \(A\)。
\(s\) 遍历 \(1\to k\):
-
将 \(p\) 位置 \(O(1)\) 微调。(虽然这一步在 \(s=1\) 无用,但后面有)
-
设 \(pos=B^{(s)}_p.nxt1\) 将 \(A^{(s)}_{pos}\) 统计入答案(本题 \(\text{xor}\))。
-
\(p:=B^{(s)}_p.nxt2\),此时 \(p\) 可能不是 \(B^{(s+1)}\) 正确的 lower_bound,但是下一轮循环开始时会有微调。由于 \(C\) 是 \(B\) 隔位取位得来的,所以当前的 \(p\) 与真正的 \(p\) 之间相差不超过 \(1\),所以第一步的微调 \(O(1)\) 得证。
全过程记得特判 \(p\) 越 \(B^{(s)}\) 界的情况。
单次询问的时间复杂度是 \(O(\log n+k)\)(第一次 lower_bound + 后面 \(k\) 次微调)
标签:10,lower,nk,层叠,bound,Cascading,数组,Fractional,下标 来源: https://www.cnblogs.com/zhangshaojia/p/16376543.html