根号大杂烩

序列分块

把一个数组简单地划分为若干块,若操作范围覆盖整块则整体操作,反之则暴力操作。由均值不等式可证,块长取 n\sqrt{n} 可得到最优理论复杂度。
由于可以暴力操作且具有简单的结构,它有着比树形数据结构更为灵活的优势。同时,它还具有常数小的优势。

习题:

以下是比较板的题:

以下是比较有挑战的题:

[SNOI2022] 军队
题意简述:区间相同颜色加,区间两种颜色合并,区间求和。
注意到块内的颜色数单调不增。因此我们每个块内维护一个森林,叶子节点即为每个城市,向上代表颜色。接下来详细讲解各种操作:

  • 整块:

    • 颜色加:直接在颜色节点打 tagtag
    • 颜色合并:若两种颜色都存在则新建父节点,将两种颜色合并上去,否则直接改颜色。可以证明最多新建 22 倍叶子节点数量的节点数。
  • 散块:
    全部依靠暴力重构操作。

    • 颜色加:重构期间判断新颜色,直接加。
    • 颜色合并:重构期间记录新颜色,直接合并。

如果重构部分写 pushdown 状物复杂度是线性的,如果从底加到顶要带个 log\log。不过带 log\log 也能过。
可以离线后逐块处理实现线性空间。

[Ynoi2018] 五彩斑斓的世界
突刺贯穿的第二分块。
解法:分块+并查集。开一个值域大小的并查集,这样我们就可以 O(1)O(1) 修改所有块内相同的值。同时通过维护 sizsiz 数组来快速查询某数出现的次数,且可以随并查集的合并而合并。
接下来进行复杂度分析。注意到,对于本题的修改操作,块内的最大值 maxnmaxn 单调不增。maxnmaxn 最大为 105+110^5+1mm 最大为 5×1055\times 10^5,可以视为均摊 O(1)O(1)
对于整块的修改操作,我们分两种情况讨论:
2xmaxn2x\ge maxn 时,令所有大于 xx 的数减去 xx,此时暴力更新 maxnmaxn
2x<maxn2x< maxn 时,令所有小于等于 xx 的数加上 xx,再将块上的 tagtagxx,表示真实值为整体减 tagtag
对于散块,暴力拆散原来的并查集,直接修改并更新 maxnmaxn 就好。
整块更新是均摊 O(1)O(1),散块更新是均摊 O(n)O(\sqrt n)
同上一道题,离线后逐块处理以实现线性空间。
以上方法无法正确处理 ai=0a_i=0 的情况。注意到,修改操作不会产生新的 00,所以直接在一开始用前缀和处理掉 00 的询问,之后就不用管了。

莫队

很神的技巧。对于一些题目,如果所求的东西难以用常规数据结构维护且可以离线,那就可以尝试莫队。我们可以来看模板题 [国家集训队] 小 Z 的袜子
考虑维护双指针 l,rl,r 表示当前考虑区间 [l,r][l,r],我们可以容易地从 [l1,r],[l+1,r],[l,r1],[l,r+1][l-1,r],[l+1,r],[l,r-1],[l,r+1] 转移过来。那么在移动指针的同时 O(1)O(1) 修改当前的每种颜色袜子数的平方和即可。设当前某颜色的袜子数为 xix_i,答案就是

xi2+xi(rl+1)(rl)\frac{\sum x_i^2+\sum x_i}{(r-l+1)(r-l)}

现在考虑优化以减少指针移动次数。将询问离线,并将 nn 分块,以询问左端点所在块编号为第一关键字,右端点为第二关键字升序排序。块长设置为 nm\dfrac{n}{\sqrt m},这样做的时间复杂度是 O(nm)O(n\sqrt{m}) 的。

时间复杂度证明

序列长度为 nn,询问次数为 mm
首先证明最优块长。设块长为 lenlen,则总块数为 nlen\dfrac{n}{len},左指针共移动 O(mlen)O(m\cdot len) 次,右指针共移动 O(n2len)O\left(\dfrac{n^2}{len}\right) 次。总共移动 mlen+n2lenm\cdot len+\dfrac{n^2}{len} 次。由均值不等式,有

mlen+n2len2nmm\cdot len+\frac{n^2}{len}\ge 2n\sqrt{m}

当且仅当 mlen=n2lenm\cdot len=\dfrac{n^2}{len} 时等号成立,此时 len=nmlen=\dfrac{n}{\sqrt{m}}
代入,得

mlen+n2len=2nmm\cdot len+\frac{n^2}{len}=2n\sqrt{m}

故时间复杂度 O(nm)O(n\sqrt{m}),在块长 len=nmlen=\cfrac{n}{\sqrt m} 时取到。

莫队技巧

  • 奇偶排序优化
    在排序右端点时,若当前左端点块编号为奇数则升序排序,反之则降序排序。可以减小左指针跨块时右指针的移动次数。

  • 指针移动顺序
    由于莫队经常要维护桶,在指针移动时若先执行 delete 操作,容易访问桶的负下标造成 RE,所以应当先写 add 操作再写 delete 操作。

  • 莫队+值域分块
    值域分块 O(1)O(1) 单点修改的特性很适合莫队的指针移动。

  • 莫队+bitset
    和值域分块类似,但是更好写一些。

  • 带修莫队
    模板题 [国家集训队] 数颜色 / 维护队列
    现在仅 l,rl,r 不足以表达当前状态,需要加上时间维度,即 l,r,tl,r,t
    现在排序以左端点所在块为第一关键字,右端点所在块为第二关键字,时间为第三关键字。设 n,m,tn,m,t 同阶,块长设为 n2/3n^{2/3},可得到理论最优时间复杂度 O(n5/3)O(n^{5/3})。详细证明及 n,m,tn,m,t 不同阶时的具体分析较为繁琐,可以看 OI Wiki 中的证明。

  • 树上莫队
    把树拍到括号序上,记录 visvis 数组表示当前选/不选节点,每次访问到节点时反转 visvis 即可。

根号分治

[NOI Online #1 入门组] 跑步
对和为 nn 的可重集计数。
考虑两种方法:

  • fi,jf_{i,j} 表示集合中的数不超过 ii 且和为 jj 的方案数,使用类似完全背包的转移:

    fi,j=fi1,j+fi,jif_{i,j}=f_{i-1,j}+f_{i,j-i}

    fn,nf_{n,n} 即为答案,时间复杂度 O(n2)O(n^2)
  • gi,jg_{i,j} 表示集合中有 ii 个数且和为 jj 的方案数,我们每次可以给集合中新加入一个 11 或者令集合中的数整体加 11

    gi,j=gi1,j1+gi,jig_{i,j}=g_{i-1,j-1}+g_{i,j-i}

    i=0ngi,n\sum_{i=0}^n g_{i,n} 即为答案,时间复杂度 O(n2)O(n^2)

考虑将这两个做法融合一下:我们令小于 BB 的数使用第一个方法,时间复杂度 O(Bn)O(Bn),大于等于 BB 的数使用第二个方法,时间复杂度 O(Bn)O(Bn)(把加入 11 和整体加 11 中的 11 改为 BB),之后可以枚举使用第一个方法选出和为 ii 的方案数,求用第二个方法选出和为 nin-i 的方案数相乘后累加即可,取 B=nB=\sqrt n 可以做到 O(nn)O(n\sqrt n) 的复杂度。


无向图三元环计数
将无向图定向:若 u,vu,v 度数不同,则方向为度数小的向度数大的连边,否则编号小的向编号大的连边。容易证明这样定向后的图是有向无环图。同时也容易得出原图上的三元环 (u,v,w)(u,v,w) 在新图上一定是一个形如 (uv),(vw),(uw)(u\to v),(v\to w),(u\to w) 的子图。则我们直接暴力遍历所有 uu,先将 uu 可达的点打上标记,遍历 v,wv,w,检查 ww 是否被打上标记即可。
下面证明这个算法的复杂度是 O(mm)O(m\sqrt m) 的:
EE 为原图,EE' 为新图,outdeg(u)\text{outdeg}(u) 表示 uuEE' 上的出度,deg(u)\text{deg}(u) 表示 uuEE 上的度数。
将所有点分配到以下两个集合:

  • S1={udeg(u)m}S_1=\{u|\text{deg}(u)\le \sqrt m\}
  • S2={udeg(u)>m}S_2=\{u|\text{deg}(u)>\sqrt m\}

则该算法时间复杂度为:

O((uv)Eoutdeg(v))O\left(\sum_{(u\to v)\in E'}\text{outdeg}(v)\right)

下证所有 uuoutdeg(u)\text{outdeg}(u) 都是 O(m)O(\sqrt m) 的:

  • uS1u\in S_1
    显然 outdeg(u)deg(u)m\text{outdeg}(u)\le \text{deg}(u)\le \sqrt m
  • uS2u\in S_2
    事实上,deg(u)\text{deg}(u) 大于 m\sqrt muu 只有 O(m)O(\sqrt m) 个:

    S2m<uS2deg(u)2m|S_2|\cdot \sqrt m<\sum_{u\in S_2}\text{deg}(u)\le 2m

    S22m|S_2|\le 2\sqrt m
    而根据连边规则,uu 只能向 deg(v)deg(u)\text{deg}(v)\ge \text{deg}(u) 的点 vv 连边,所以 deg(v)>m\text{deg}(v)>\sqrt m,故最多连 O(m)O(\sqrt m) 条边。

又因为 E|E'|O(m)O(m) 的,所以该算法为 O(mm)O(m\sqrt m) 的。
同时,我们也证明了无向图三元环的数量是 O(mm)O(m\sqrt m) 的。


根号大杂烩
https://headless-piston.github.io/2025/09/30/根号大杂烩/
作者
headless-piston
发布于
2025年9月30日
许可协议