Skip to content

方法Method

平方根分解

Square-root decomposition · Sqrt decomposition · 根号分解

将数组分成可维护的连续块,在两端直接扫描、中间整块查询,并按摘要能力核算更新与块长。

形式陈述 ​

一层块,而不是递归的树 ​

给定长度n的数组A,选正整数块长B。非空数组取1≤B≤n;第j块为

Ij=[jB,min{(j+1)B,n}),0≤j<⌈n/B⌉.

块互不相交,按下标顺序覆盖数组。每块保存原元素和一份摘要。查询半开区间[l,r)时,将其分成左端零散项、连续完整块、右端零散项;每个位置只计一次。若两端落在同一块,就直接扫描该段,不把它误算成两个相交的边界段。

摘要决定能回答什么。例如保存每块的和,可以把完整块的和直接相加;保存每块的有序元素表,则能回答“区间中有多少个值不超过k”。本页实现后一种接口:assign(i,x) 把A[i]赋为x,count_le(l,r,k) 返回满足l≤i<r且A[i]≤k的位置数。重复值按出现位置计数。输入是整数,查询须满足0≤l≤r≤n。[1, PDF pp.4–21]

算法不要求提前知道未来查询,可以在每次赋值后立刻返回下一次查询的答案。名称中的“平方根”来自一类成本平衡,B并非必须恰等于√n。

直觉

用摘要省掉整块内部的工作 ​

若B很小,边界扫描便宜,但一个长区间会跨越很多块;B很大,块数少,却可能要扫描很长的边界。对常数大小、常数时间可合并的摘要,一次查询成本为O(B+n/B),B接近√n时两项平衡。

这里的“可合并”包含次序要求。字符串连接这样的非交换运算,也能按下标从左到右依次合并片段;把右边界先并入左累加器则可能改变答案。另一方面,只有两个块各自的不同值个数,不能求并块后的不同值个数,因为不知道它们出现了哪些相同的值。

排序表不改变原来的位置 ​

每块另存一份非降排序表Sⱼ,保持“它的多重集合恰等于A在Iⱼ中的元素”。原数组仍按下标排列,所以边界部分可以逐项检查;完整块则在Sⱼ中用二分查找求第一个大于k的位置,该下标恰是≤k的元素个数。

赋值A[i]=x时,先在所属排序表中找到旧值的一次出现并删除,再插入新值的一次出现,最后改原数组。这保留全部其他位置,也保留重复元素的正确份数。删掉所有等于旧值的项,会破坏多重集合不变量。

覆盖不变量给出查询正确性 ​

实现保存当前尚未处理的左端l和累计答案。先逐项前进到块边界;随后每次处理一个完全落在查询内的整块;余下不足B项逐项处理。每一步都恰好处理尚未计入的最左片段,因此已计入部分与余下部分不交,合起来始终等于原查询区间。

零散项直接检查定义,完整块由排序表不变量得到正确计数。循环结束时余段为空,累计值就是全部目标位置数。空区间在第一步就结束并返回零。

例子与边界

同一次查询混合两种表示 ​

取A=[3,1,3,2,1,4,2,3],B=3。三块原序列为[3,1,3]、[2,1,4]、[2,3],排序表为[1,3,3]、[1,2,4]、[2,3]。求 count_le(1,7,2):左段下标1、2只计入1;整块[3,6)贡献2;右段下标6贡献1,总数4。

执行 assign(2,1),第一块排序表从[1,3,3]变成[1,1,3]。此后 count_le(0,4,1) 返回2。再把下标5赋成1,第二块排序表成为[1,1,2],count_le(2,8,2) 返回5。把下标2再次赋成1,仍只删除并插回一次1,不会改变计数。

更新的快慢不能从“分块”二字推出 ​

若摘要是和,赋值后只需将块和增加x−旧值,更新本身O(1)。若摘要是最小值,把唯一最小元素改大后,单凭旧最小值无法恢复新最小值;可以扫描整块重建,成本O(B)。排序表虽然只需O(log(B+1))次比较找到位置,但数组删除和插入要搬动最多B项,更新总成本仍是O(B)。

在[1,4,7]中删去1后,旧摘要“最小值1”无法告诉你答案是4;换成[1,5,7],旧摘要相同,新答案却是5。这个反例说明摘要丢失的信息不能靠一条更新公式凭空恢复。

空数组没有块,只允许[0,0)查询;不能赋值某个不存在的位置。末块可以不足B项。附件把过大的B夹到max(1,n),拒绝零、负数和非整数块长;固定长度接口不支持插入新位置。

推论与应用

分清比较成本与移动成本 ​

对排序块实现,初始化为O(n log(B+1)),空间O(n);一次赋值为O(B),一次计数为

O(B+⌈nB⌉log⁡(B+1)).

边界至多扫描2B项,每个完整块各做一次二分。B≈√n给出O(√n log(n+1))的查询上界,不能套用常数摘要版本的O(√n)。若U次更新、Q次查询已知,可用

O(nlog⁡(B+1)+UB+Q(B+nBlog⁡(B+1)))

比较候选块长,而不是无条件固定√n。这里假设下标、数值及计数装入常数个机器字,整数比较与加减为常数;大整数需要另计位成本。

在同一工作负载上选择接口 ​

线段树用递归层次组织可合并摘要,树状数组擅长可逆的前缀聚合;排序块提供的是容易局部重建的一层结构。若请求必须立刻回答,本页实现可以直接工作。若请求全部已知且数组不变,莫队算法能重排窗口,以频次状态处理不便用小摘要合并的统计。

批量查询终结任务把上述赋值轨迹再转成CDQ三维支配事件,分别用在线排序块与离线统计核对4、2、5、0。两份答案相同,但可接收输入的时机和维护状态不同。

参考资料
  1. Jeremy Chow,Square Root Decomposition,HKOI Training,2019-07-01,原始讲义,物理第4–11页的数组分块与第12–21页的排序块。讲义还讨论整块延迟增量,本页限定为点赋值。
  2. nkhg / yp155136,根號算法,NTU Sprout,2019-05-18,课程讲义。固定块与块内数据结构必须一起核算;本页不扩展为可变长序列插删。
关系图谱5 个相邻概念 · 2 类关系

拖动节点调整位置。

显示关系

显示:依赖

  1. 前置三跳
  2. 前置二跳
  3. 前置一跳
  4. 当前条目
  5. 后续一跳
  6. 后续二跳
  7. 后续三跳
文字版关系按与当前条目的最短距离分组
类型化关系

使用的工具

被这些条目使用