浅谈 Method of Four Russians
(如果文章有什么错误请指出)
前言
今年(2021)的 CSP-S 初赛的最后一题就是这个东西。救我一程。
这个东西是非常有趣的。可惜的是,他在序列或树上半群并不 practical(我认为)。因为我们有简单的严格
例 1
以经典题目引入:
给出一个序列,相邻两项之差为
\pm1 ,每次求区间最大值。
序列分块,块长
将每块的最大值提取出来,得到一个长为
那么对这个序列建立 ST 表,就可以完成求
那么现在问题转为了求散块内的最大值。即一个长为
既然序列长度为
注意到相邻两项之差为
事实上这里可以
我们称两块本质不同,当且仅当两块的差分序列不同。
那么我们把每个块映射到预处理出来的对应的差分序列上,直接查询即可。
举个例子:
两个块 1 2 3|4 5 6
。
那么差分序列是 0 1 1|0 1 1
。
这个 0 1 1
所对应的序列是 0 1 2
。
那么预处理出 0 1 2
这个序列的每个子段的最大值。(其实我们要预处理的是所有不同的差分数组共
比如查询 0 1 2
的区间
那么我们就
解法和 CSP-S 2021 初赛的解法略有不同。这个更加广义一些。
差分序列只是在这个例子种因为题目特性而成为判断本质不同的一种方法,后文的阅读中,不要将思想局限于差分序列。
例 2
更进一步的:
给出一个序列,每次求区间最大值。
考虑用
对序列求出笛卡尔树。
那么区间最大值就转为了 LCA。(笛卡尔树基本性质)
对笛卡尔树求出欧拉序。那么 LCA 问题转为了 RMQ(区间最值)问题。
考虑到这个序列的相邻两项之差为
上面每一步的时间复杂度均为
例 3
给出一个序列,每次求区间严格众数(出现次数大于区间长度的一半)。若不存在则任意输出。
之所以可以“任意输出”,是因为 check 求出来的答案是否确实为区间严格众数与主题无关。我可以给出一个离线的简单做法
还需要知道序列上区间半群是可以
考虑一下本质不同的情况是什么。很显然就是这个序列的每个数都在
唯一的问题就是本质不同的情况个数。有
所以就要在保证整块处理的时间复杂度仍为
我们把这个结构迭代一层,即对块内继续分块。那么这时候块长下降到了
此时预处理时间复杂度为
两边取对数得到
故而我们
这个思想是很有用的。在令
例 4
介绍一个上树的方法:
给出一棵树,边带权(
\pm1 ),每次查询两点之间路径上的最大子链和。
要会 top cluster
(虽然说 top cluster 不保证每个块大小为严格的
最大子链和是一个经典的半群信息。也就是说我们要在收缩树上做半群信息维护。
考虑对收缩树建立点分树,
那么当簇大小
那么现在的问题仍是两点在同一簇内。即一个大小为
如何表示本质不同的簇(树)?首先是树的结构。一个很好的方法是,把每个点的父亲记录下来。粗略估计下来,共有
然后是边权。这个就是
还是做两层 top cluster 分块,第一层
那么要证明
显然两边取对数得到
最后一步,识别每个簇属于哪个本质不同的情况。这个也可以用 hash 解决。
于是我们
例 5
一些奇特的应用(来自和 w33z 的讨论):
给出一个序列,数的种类数为
c (c 为常数),每次修改单点修改(保证数的种类数仍为c ),每次询问查询区间最大子段和。要求O(1) 修改。
设块长为
两边取对数得到
每个块用一个 word 表示出来(word-RAM model 告诉我们可以这么做)。
然后单点修改可以
那么查询的时候,直接暴力扫,就可以做到
这里介绍的是用四毛子加速特殊的维护区间半群信息
对于这题,若
那么对于由整块组成的长度为
两边取对数得到
那么我们得到了一个
这个方法是进一步的识别本质不同的块,不过适用面会更窄一些。
思考题
给出一棵树,每次查询一个点的若干级祖先
^5 。给出一棵树,每次操作将一个节点合并到父亲,每次询问查询一个点已合并的祖先
^6 。给出一棵树,边带权。每次查询两点之间路径上边权的最大值
^7 (提示:瓶颈在于整数排序!如何线性地对O(\log n/\log \log n) 个数排序呢!)。给出一个序列,每次修改单点修改,每次询问查询区间严格众数(若不存在则任意输出)。要求
O(1) 修改,o(\dfrac n {\log \log n}) 查询。
参考文献
- dqstz 题解 P7252 [JSOI2011] 棒棒糖
- hqztrue 一个RMQ问题的快速算法,以及区间众数
- Judge_Cheung 一种神奇的数据结构——猫树
- 周欣 《浅谈一类树分块的构建算法及其应用》(2021 国家集训队论文)
- 约瑟夫用脑玩 易懂科技:将LCA、RMQ、LA优化至理论最优复杂度
- ljt12138 RMQ标准算法和线性树上并查集
- 感谢 myh 学长,ccz,lxl 的指导!