莫队
作者:互联网
\(\quad\)对于莫队的复杂度计算,我们首先块长,然后分别分析左右端点的移动,然后就会得到一个式子,为了使这个式子最小,适当调整分块块长即可。
普通莫队
\(\quad\)对于普通莫队,一般的复杂度是 $O(n\sqrt n) $ 。
\(\quad\)最优的分块方式是对于端点分块,块长为 \(\frac{n}{\sqrt m}\) ,然后以左端点的块为第一关键字,右端点的块为第二关键字,同时实行奇偶排序,就是对于第二关键字,如果第一关键字是奇数块那么从左到右排,否则从右到左排。
带修莫队
\(\quad\)带修莫队就是加一个时间轴,唯一要注意的是每次滚时间轴的时候要把时间轴记录的改变值和当前值互换一下,这样再滚回去的时候就可以还原之前的值。一般块长为 \(O(n^{\frac{2}{3}})\)
回滚莫队
\(\quad\)对于一类很像莫队,但是它在指针移动的时候只能考虑增/减的贡献,这个时候,就需要用回滚莫队
\(\quad\)假设只能增,那么排序的时候,以左端点的块为第一关键字,右端点的 值 为第二关键字升序排序,那么对于左端点在同一块的我们一起考虑。对于左端点在一个块中的区间,我们每次让左端点赋初值为当前块的右端点+1 ,右端点因为是递增的,所以可以直接一直扫下去,那么最后分析复杂度仍然是 \(O(n\sqrt m)\) ,至于只能减的情况,其实是一样的。
莫队套值域分块
\(\quad\)值域分块就是在值域上分块,做到 \(O(1)\) 插入,\(O(\sqrt S)\) 查询,和莫队简直是天作之合。
\(\quad\)贪心的来看就是最多的上升子序列的个数,这个个数一定大于等于区间众数的个数,这个显然,事实上可以构造成区间众数的个数,所以就是要求区间众数的个数。这个东西就可以用莫队套一个值域分块。
\(\quad\)不过事实上我第一眼看这个题,觉得是回滚莫队。而事实上求区间众数这种只能加不能减的题,确实是可以用回滚莫队做。
莫队二次离线
\(\quad\)有这么一类莫队的题目,它的每次转移做不到 \(O(1)\) ,这个时候就需要二次离线。
\(\quad\)莫队本身是第一次离线。
\(\quad\)对于每次转移会有一个状态表达式,如果能 差分 的话,就可以转换成两个有关前缀和查询的东西,我们将这个东西存下来,也就是 二次离线 ,最后再扫一遍,求解即可。
\(\quad\)注意为了保证总体的复杂度仍然为 \(O(n\sqrt n)\) ,最后扫一遍时也要保证是这个复杂度。但因为移动的次数就有这个复杂度了,所以我们需要 \(O(1)\) 处理离线下来的操作,又因为只有 \(O(n)\) 的插入,我们完全可以套个根号,于是我们经常用值域分块来中和这里的复杂度。
P5047 [Ynoi2019 模拟赛] Yuno loves sqrt technology II
\(\quad\)套个值域分块扫就可以了,每一个块维护比自己小的值的个数,在块的内部维护一个数组表示在块内比自己小的数的个数。
\(\quad\)这个题目似乎是上面题目的姊妹题,维护比一个数大的数的和,仍然用值域分块维护即可。
树上莫队
\(\quad\)似乎是有两种写法,一种是直接在树上分块,一种是转换成欧拉序,然后转换成序列上的操作,个人认为第二种应该好理解,于是写的第二种。
\(\quad\)这是个带修树上莫队板子。
莫队套 bitset
\(\quad\)这个东西可以解决一类的计数问题,比如有关区间数的次数的问题,可以考虑用 bitset
压位乱搞。常用的 bitset
语法:
bit.count() //返回 1 的个数
bit.any() //返回是否有 1
bit.set() //全部变成 1
bit.set(p) //将第 p+1 位变成 1 (bitset 是从 0 位开始的)
bit.set(p,x) //将第 P+1 为变成 x
bit.reset() //全部变成 0
bit.reset(p) //将第 p+1 位变成 0
\(\quad\)首先离散化一下,答案就是总的长度和减去交集的长度乘 3 ,于是我们就是要求三个区间数的交集的个数。因为只有 n 个数字,所以对每一个数字离散化一下,这样在 bitset
中就会有对应的位置。每次莫队记录一下每一个数的个数,然后在 bitset
里面实现修改操作,最后取个并即可。
\(\quad\)对于值域维护两个 bitset
,对于每个数 x ,则 b1.insert(x),b2.insert(N-x)
,那么对于加减就好说了,对于乘直接枚举根号一下的数,对于除要分类处理。
\(\quad\)对于除,如果 \(x\leq \sqrt n\) ,我们单独预处理一下。考虑枚举 x ,然后扫描线们对于每个位置维护这个位置及之前能做贡献的一对数左边的数最大的位置,假设为 tp[x]
,那么同时要维护一个 pre[x]
表示上一次出现 x 的位置,那么对于一个区间则当 tp[q[i].r]>=q[i].l
时满足条件。对于 $x\geq \sqrt n $ ,就直接枚举它的倍数就可以了。
标签:分块,值域,sqrt,端点,quad,莫队 来源: https://www.cnblogs.com/kzos/p/16388944.html