根号大杂烩
序列分块
把一个数组简单地划分为若干块,若操作范围覆盖整块则整体操作,反之则暴力操作。由均值不等式可证,块长取 可得到最优理论复杂度。
由于可以暴力操作且具有简单的结构,它有着比树形数据结构更为灵活的优势。同时,它还具有常数小的优势。
习题:
以下是比较板的题:
-
教主的魔法,分块+二分答案。
-
[Ynoi Easy Round 2017] 由乃打扑克,分块+二分答案+二分查找。
以下是比较有挑战的题:
[SNOI2022] 军队
题意简述:区间相同颜色加,区间两种颜色合并,区间求和。
注意到块内的颜色数单调不增。因此我们每个块内维护一个森林,叶子节点即为每个城市,向上代表颜色。接下来详细讲解各种操作:
-
整块:
- 颜色加:直接在颜色节点打 。
- 颜色合并:若两种颜色都存在则新建父节点,将两种颜色合并上去,否则直接改颜色。可以证明最多新建 倍叶子节点数量的节点数。
-
散块:
全部依靠暴力重构操作。- 颜色加:重构期间判断新颜色,直接加。
- 颜色合并:重构期间记录新颜色,直接合并。
如果重构部分写 pushdown 状物复杂度是线性的,如果从底加到顶要带个 。不过带 也能过。
可以离线后逐块处理实现线性空间。
[Ynoi2018] 五彩斑斓的世界
突刺贯穿的第二分块。
解法:分块+并查集。开一个值域大小的并查集,这样我们就可以 修改所有块内相同的值。同时通过维护 数组来快速查询某数出现的次数,且可以随并查集的合并而合并。
接下来进行复杂度分析。注意到,对于本题的修改操作,块内的最大值 单调不增。 最大为 , 最大为 ,可以视为均摊 。
对于整块的修改操作,我们分两种情况讨论:
当 时,令所有大于 的数减去 ,此时暴力更新 。
当 时,令所有小于等于 的数加上 ,再将块上的 加 ,表示真实值为整体减 。
对于散块,暴力拆散原来的并查集,直接修改并更新 就好。
整块更新是均摊 ,散块更新是均摊 。
同上一道题,离线后逐块处理以实现线性空间。
以上方法无法正确处理 的情况。注意到,修改操作不会产生新的 ,所以直接在一开始用前缀和处理掉 的询问,之后就不用管了。
莫队
很神的技巧。对于一些题目,如果所求的东西难以用常规数据结构维护且可以离线,那就可以尝试莫队。我们可以来看模板题 [国家集训队] 小 Z 的袜子。
考虑维护双指针 表示当前考虑区间 ,我们可以容易地从 转移过来。那么在移动指针的同时 修改当前的每种颜色袜子数的平方和即可。设当前某颜色的袜子数为 ,答案就是
现在考虑优化以减少指针移动次数。将询问离线,并将 分块,以询问左端点所在块编号为第一关键字,右端点为第二关键字升序排序。块长设置为 ,这样做的时间复杂度是 的。
时间复杂度证明
序列长度为 ,询问次数为 。
首先证明最优块长。设块长为 ,则总块数为 ,左指针共移动 次,右指针共移动 次。总共移动 次。由均值不等式,有
当且仅当 时等号成立,此时 。
代入,得
故时间复杂度 ,在块长 时取到。
莫队技巧
-
奇偶排序优化
在排序右端点时,若当前左端点块编号为奇数则升序排序,反之则降序排序。可以减小左指针跨块时右指针的移动次数。 -
指针移动顺序
由于莫队经常要维护桶,在指针移动时若先执行 delete 操作,容易访问桶的负下标造成 RE,所以应当先写 add 操作再写 delete 操作。 -
莫队+值域分块
值域分块 单点修改的特性很适合莫队的指针移动。 -
莫队+bitset
和值域分块类似,但是更好写一些。 -
带修莫队
模板题 [国家集训队] 数颜色 / 维护队列。
现在仅 不足以表达当前状态,需要加上时间维度,即 。
现在排序以左端点所在块为第一关键字,右端点所在块为第二关键字,时间为第三关键字。设 同阶,块长设为 ,可得到理论最优时间复杂度 。详细证明及 不同阶时的具体分析较为繁琐,可以看 OI Wiki 中的证明。 -
树上莫队
把树拍到括号序上,记录 数组表示当前选/不选节点,每次访问到节点时反转 即可。
根号分治
[NOI Online #1 入门组] 跑步
对和为 的可重集计数。
考虑两种方法:
- 设 表示集合中的数不超过 且和为 的方案数,使用类似完全背包的转移:
即为答案,时间复杂度 。
- 设 表示集合中有 个数且和为 的方案数,我们每次可以给集合中新加入一个 或者令集合中的数整体加 :
即为答案,时间复杂度 。
考虑将这两个做法融合一下:我们令小于 的数使用第一个方法,时间复杂度 ,大于等于 的数使用第二个方法,时间复杂度 (把加入 和整体加 中的 改为 ),之后可以枚举使用第一个方法选出和为 的方案数,求用第二个方法选出和为 的方案数相乘后累加即可,取 可以做到 的复杂度。
无向图三元环计数
将无向图定向:若 度数不同,则方向为度数小的向度数大的连边,否则编号小的向编号大的连边。容易证明这样定向后的图是有向无环图。同时也容易得出原图上的三元环 在新图上一定是一个形如 的子图。则我们直接暴力遍历所有 ,先将 可达的点打上标记,遍历 ,检查 是否被打上标记即可。
下面证明这个算法的复杂度是 的:
设 为原图, 为新图, 表示 在 上的出度, 表示 在 上的度数。
将所有点分配到以下两个集合:
- ;
- 。
则该算法时间复杂度为:
下证所有 的 都是 的:
- :
显然 。 - :
事实上, 大于 的 只有 个:故 。
而根据连边规则, 只能向 的点 连边,所以 ,故最多连 条边。
又因为 是 的,所以该算法为 的。
同时,我们也证明了无向图三元环的数量是 的。