莫队小记
普通莫队
将序列分块,将询问按左端点所在块的编号排序。
维护指针 \(l,r\),通过区间 \([l,r]\) 的答案得出区间 \([l-1,r],[l,r+1],[l+1,r],[l,r-1]\) 的答案,并变化指针。
时间复杂度 \(\mathcal{O}(qB+\dfrac{n^2}{B})\),取 \(B=\sqrt{n}\) 有 \(\mathcal{O}((n+q)\sqrt{n})\),取 \(B=\dfrac{n}{\sqrt{q}}\) 有 \(\mathcal{O}(n\sqrt{q})\)。
注意指针变化的顺序(先执行区间变大),以及指针变化与贡献计算的相对顺序。
- 奇偶块排序:相邻的两块中,前一块按照 \(r\) 升序排序,后一块按照 \(r\) 降序排序。
树上莫队使用 dfs 序或 dfn 序转到区间上,具体实现见例题。
带修莫队
在原来的基础上再加入一维修改指针 \(t\),类似 \(l,r\) 一样移动即可。
思考块长 \(B\) 的取值,视 \(n,q\) 同阶。
- \(l\) 的移动次数:\(l\) 跨块移动总次数为 \(n\),每两个询问之间 \(l\) 的移动距离为 \(B\),故总移动次数为 \(nB\)。
- \(r\) 的移动次数:\(l\) 跨块移动总次数为 \(nB\),\(l\) 不跨块总移动次数为 \(\dfrac{n^2}{B}\)。
- \(t\) 的移动次数,对于 \(l,r\),一共有 \(\min\left(n,\dfrac{n^2}{B^2}\right)\) 个有效的块,每个块移动 \(n\) 次,故总复杂度为 \(\dfrac{n^3}{B^2}\)(\(\min\) 取到 \(n\) 显然不优,于是令 \(B>\sqrt{n}\))。
综上,我们要确定一个 \(B\) 使得 \(\max\left(nB,\dfrac{n^2}{B},\dfrac{n^3}{B^2}\right)\) 最小,当 \(B=n^{\frac{2}{3}}\) 时,取得最小值 \(\mathcal{O}(n^{\frac{5}{3}})\)。
例题
P4462 [CQOI2018] 异或序列
作前缀和,转化为两点异或和为 \(k\)。
记 \(c_x\) 表示异或和为 \(x\) 的个数,新加入一个数 \(y\) 时,贡献就是 \(c_{k\oplus y}\)。
P4396 [AHOI2013] 作业 & P4867 Gty的妹子序列
用树状数组或值域分块维护,时间复杂度 \(\mathcal{O}(n\sqrt{n}\log n)\)。
CF877F Ann and Books
即 \(v_i=s1_i-s2_i\)。即求有多少个 \([l,r]\) 满足 \(v_r=v_{l-1}+k\)。预先离散化即可。
P3604 美好的每一天
将 \(s[1:i]\) 每个字符的出现次数模 \(2\) 并状压,记为 \(a_i\)。问题即求有多少个 \(i,j\) 满足 \(l\leq i\leq j\leq r\) 且 \(a_r\oplus a_{l-1}\) 至多有一位是 \(1\)。枚举字符集即可。时间复杂度 \(\mathcal{O}(n\sqrt{n}\times 26)\)。
P5268 [SNOI2017] 一个简单的询问
将询问差分成 \(\sum\limits_x^{+\infty}{[\operatorname{get}(1,r_1,x)-\operatorname{get}(1,l_1-1,x)]\times [\operatorname{get}(1,r_2,x)-\operatorname{get}(1,l_2-1,x)]}\)。即可拆成四个不同的询问,每个询问形如 \(\sum \operatorname{get}(1,i,x)\times \operatorname{get}(1,j,x)\)。这可以用莫队维护。注意指针的变化。
CF375D Tree and Queries
树上莫队,容易想到打在 dfn 序上,就变成简单题了。
SP10707 COT2 - Count on a tree II
这次不能用 dfn 序了,得用 dfs 序,这样不在链上的节点会被计算两次抵消掉。
钦定 \(st_u<st_v\)。分 \(u=\operatorname{LCA}(u,v)\) 和 \(u\ne \operatorname{LCA}(u,v)\) 两种情况进行讨论。前者对应的区间是 \([st_u,st_v]\),后者是 \([ed_u,st_v]\) 再加上 \(lca\) 的贡献。新开一个数组记录该点是要 \(\operatorname {add}\) 还是 \(\operatorname{del}\),从而将出现两次的节点去掉。
CF1479D Odd Mineral Resource
同上题的做法,查询时值域分块。注意一些实现细节。可以开一个栈或队列储存整块里面有用的颜色。也可以开个数组记录整块是否有贡献(但是我这样写 T 飞了)。
还有随机化的 \(\mathcal{O}(n\log n)\) 的随机化+主席树的做法,但不会。
CF1476G Minimum Difference
记 \(cntt_i\) 表示 \(cnt_j=i\) 的个数。发现 \(\sum i\times cntt_i\leq n\),所以有用的 \(cntt_i\) 是 \(\sqrt{n}\) 级别的。用链表维护然后跑双指针即可。
P4689 [Ynoi2016] 这是我自己的发明
发现如果没有操作 1 的话,打到 dfn 序上就是 P5268。对于操作 1,考虑一下换根后每个子树的变化即可。

浙公网安备 33010602011771号