莫队小记

\[\text{抽象的算法} \]

普通莫队

将序列分块,将询问按左端点所在块的编号排序。

维护指针 \(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,考虑一下换根后每个子树的变化即可。

posted @ 2024-02-28 14:53  xishanmeigao  阅读(29)  评论(0)    收藏  举报