「杂谈」莫队复杂度相关


原理略过

关于莫队复杂度的浅谈

设块长为 \(B\),易分析得出端点移动次数为 \(\frac{n^2}{B}+mS\),若 \(n,m\) 同阶,取 \(B=\sqrt n\) 最优。但实际上,根据数据生成的方式不同,不同的块长在效率上也有所不同,但我们这里暂且讨论复杂度上问题,不考虑数据不同带来的影响。

莫队掌握的经典技巧是复杂度平衡。

如果 \(m,取块长 \(\frac{n}{\sqrt m}\),移动次数和查询次数得到平衡,左右端点移动次数和查询次数均为 \(\mathcal{O}(n\sqrt m)\),这一步是根据均值不等式来得出的。

举个栗子,例如每次端点移动是区间修改,查询是单点查询,\(n,m\) 同阶。这个时候如果用线段树或者树状数组,复杂度为 \(\mathcal{O}(n\sqrt n\log n)\).但是注意到询问只有 \(m\) 次,询问的复杂度比修改的复杂度还要低,尝试平衡修改和询问的复杂度,采用序列分块来做到 \(\mathcal{O}(1)\) 修改 \(\sqrt n\) 查询,这样总复杂度就是 \(\mathcal{O}(n\sqrt n)\)

还有诸如把 \(\log\) 放进根号里面的技巧,当然这都是理论上的东西,在实践中,由于实现不同部分的常数差异,块长有时候取得更大或者更小是更优的。

回滚莫队

在正常的问题中,普通莫队是不断移动左右端点来维护答案。

但有的问题,插入和删除复杂度是不一样的。有时候插入更快一些,有时候删除更快一些。

采用只插入不删除,或者只删除不插入的莫队,称之为回滚莫队。

仍是按照左端点所在的块为第一关键字,按照右端点为第二关键字排序。

只插入莫队:初始左端点为所在块右端点,右端点从小往大扫,每次处理询问的时候直接撤销左端点的影响,重新从块的右端点开始移动。

只删除莫队:类似地,初始左端点为所在块左端点,右端点从大往小扫,每次处理询问的时候直接撤销左端点的影响,重新从块的左端点开始移动。

很多博客都是让左右端点在同一块内的暴力扫,但如果散块询问不好暴力扫得出,一并加入到最后扫莫队也是不影响的。

举一反三,分块也可以沿用类似的思路,常见的分块是整块处理答案,散块暴力扫,这对应的是"只插入莫队",考虑只删除的话,那就是记录全局的答案,预处理两侧的整块删除后对答案的影响,然后散块暴力删除。不知道有没有类似的例题,只是我临时起意想出来的一个东西,有时间或许会根据这个思想编一道题。

带修莫队

待补。