Four Russian
Four Russian 是一种处理区间问题的方法,一般用于处理静态区间半群信息查询。
主要思路是分块,块外使用别的数据结构套上去,块内直接枚举所有本质不同的块去做。
这个算法其实可以告诉我们:如果可以将所有可能的序列分成若干种,要求种类数值域无关,记为 \(O(f(n))\),那么复杂度可以做到 \(O(n\log_n^*f(n))-O(1)\)。
显然在几乎所有情况下,这就是 \(O(n)-O(1)\) 了。
例 1
给你一个数列,保证相邻两项的差值的绝对值为 \(1\),每次询问求区间最小值。
对序列用 \(B\) 分块,块间用 ST 表。
考虑块内,答案显然只和首项和差分数组有关,可以钦定首项为 \(0\),然后做完后再加上首项即可。
差分数组只有 \(2^B\) 种取值,直接枚举所有可能的差分数组和每一个区间算答案,是 \(O(2^BB^2)\) 的。
那么时间复杂度就是 \(O(\frac{n}{B}\log\frac{n}{B}+2^BB^2)\),取 \(B=\frac{\log n}{2}\) 即可做到 \(O(n)-O(1)\)。
例 2
给你一棵树,每次询问给定两点求 LCA。
对树建出欧拉环游序,注意到两点 LCA 为他们之间 dep 最小的点,并且欧拉环游序上每个相邻的点 dep 都只差 1,那么就可以用例 1 的方法。
例 3
给你一个数列,每次询问求区间最小值。
对数列建出笛卡尔树,注意到两点间的最小值为它们在笛卡尔树上的 LCA,那么就可以用例 2 的方法。
例 4
给你两个 01 矩阵,求它们的 01 积。
这个比较简单。但是比较特殊。
用 \(B=\sqrt{\log n}\) 二维分块,块间 \(O(\frac{n^3}{\log^{\frac{3}{2}}n})\) 块内预处理 \(O(4^{B^2}B^3)=O(n^2\log^{\frac{3}{2}}n)\)。这样就可以做到 \(O(\frac{n^3}{\log^{\frac{3}{2}}n})\)。
然后你发现这个做法有一个问题就是你二维都分块了之后不能 bitset 优化了。考虑分一维的块,另一维加 bitset 优化。这里一定要注意要分一维的块的时候 A 和 B 分块的那一位不同。这样是能做到 \(O(\frac{n^3}{w\log n})\) 的。
例 5
给你一个数列,每次询问求区间绝对众数,这里绝对众数的定义是出现次数大于序列长度一半的数,若不存在可以输出任意数。
首先有个东西叫做摩尔投票,这使得绝对众数是一个区间半群信息。
但是这个东西明显不可重,所以不能用 ST 表。
然而有个东西叫做猫树,和 ST 表一样,可以 \(O(n\log n)-O(1)\) 的解决区间半群问题,但是不需要可重。
那么就可以做了。
唯一的问题是这里本质不同的序列个数变成了 \(B^B\)(每个块可以哈希映射一下),取 \(B=\log n\) 时复杂度甚至大于暴力。
那么我们可以分两层,第一层 \(\log\),第二层 \(\log\log\) 就可以解决问题了。
例 6
给你一个序列,每次询问求区间最大子段和,值域是 \(\log\) 级别,即 \(-\ln n\le a_i\le\ln n\)。
虽然说 Four Russian 一般要求种类数是值域无关,但是这个值域一看就有玄机。
首先最大子段和是一个经典的半群信息,维护前缀、后缀、区间三个区间即可。
做一次对 \(\log\) 分块,块间同样猫树,块内有 \((\log n)^{\log n}\) 种块,不能直接做。
那么仿照例 5,我们也分两层块,这样块内就有 \((\log n)^{\log\log n}\) 种块,这样比 \(n\) 是要小的。
这样就可以做到 \(O(n)-O(1)\)。
例 7
给你一棵树,值域是 \(\pm 1\),每次询问求链最大子段和。
对树使用 top cluster 树分块,建出收缩树。
对收缩树建出点分树,这样两点之间的信息可以用这两点在点分树上的 LCA 合并。LCA 用 \(O(n\log n)-O(1)\) 的方法即可。
这下我们要算本质不同的树的数量。
先是形态,考虑记下每个点父亲,粗略估算 \((B-1)!\) 种,然后边权是 \(2^B\) 种。用斯特林公式得到树的形态是 \(B^B\),也就是说式子和例 5 是一样的,分两次即可。
例 8
欢迎大家来提供需要分三次块的题,我放这里。

浙公网安备 33010602011771号