莫队小记

抽象的算法

普通莫队

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

维护指针 l,r,通过区间 [l,r] 的答案得出区间 [l1,r],[l,r+1],[l+1,r],[l,r1] 的答案,并变化指针。

时间复杂度 O(qB+n2B),取 B=nO((n+q)n),取 B=nqO(nq)

注意指针变化的顺序(先执行区间变大),以及指针变化与贡献计算的相对顺序。

  • 奇偶块排序:相邻的两块中,前一块按照 r 升序排序,后一块按照 r 降序排序。

树上莫队使用 dfs 序或 dfn 序转到区间上,具体实现见例题。

带修莫队

在原来的基础上再加入一维修改指针 t,类似 l,r 一样移动即可。

思考块长 B 的取值,视 n,q 同阶。

  • l 的移动次数:l 跨块移动总次数为 n,每两个询问之间 l 的移动距离为 B,故总移动次数为 nB
  • r 的移动次数:l 跨块移动总次数为 nBl 不跨块总移动次数为 n2B
  • t 的移动次数,对于 l,r,一共有 min(n,n2B2) 个有效的块,每个块移动 n 次,故总复杂度为 n3B2min 取到 n 显然不优,于是令 B>n)。

综上,我们要确定一个 B 使得 max(nB,n2B,n3B2) 最小,当 B=n23 时,取得最小值 O(n53)

例题

P4462 [CQOI2018] 异或序列

作前缀和,转化为两点异或和为 k

cx 表示异或和为 x 的个数,新加入一个数 y 时,贡献就是 cky


P4396 [AHOI2013] 作业 & P4867 Gty的妹子序列

用树状数组或值域分块维护,时间复杂度 O(nnlogn)


CF877F Ann and Books

vi=s1is2i。即求有多少个 [l,r] 满足 vr=vl1+k。预先离散化即可。


P3604 美好的每一天

s[1:i] 每个字符的出现次数模 2 并状压,记为 ai。问题即求有多少个 i,j 满足 lijraral1 至多有一位是 1。枚举字符集即可。时间复杂度 O(nn×26)


P5268 [SNOI2017] 一个简单的询问

将询问差分成 x+[get(1,r1,x)get(1,l11,x)]×[get(1,r2,x)get(1,l21,x)]。即可拆成四个不同的询问,每个询问形如 get(1,i,x)×get(1,j,x)。这可以用莫队维护。注意指针的变化。


CF375D Tree and Queries

树上莫队,容易想到打在 dfn 序上,就变成简单题了。


SP10707 COT2 - Count on a tree II

这次不能用 dfn 序了,得用 dfs 序,这样不在链上的节点会被计算两次抵消掉。

钦定 stu<stv。分 u=LCA(u,v)uLCA(u,v) 两种情况进行讨论。前者对应的区间是 [stu,stv],后者是 [edu,stv] 再加上 lca 的贡献。新开一个数组记录该点是要 add 还是 del,从而将出现两次的节点去掉。


CF1479D Odd Mineral Resource

同上题的做法,查询时值域分块。注意一些实现细节。可以开一个栈或队列储存整块里面有用的颜色。也可以开个数组记录整块是否有贡献(但是我这样写 T 飞了)。

还有随机化的 O(nlogn) 的随机化+主席树的做法,但不会。


CF1476G Minimum Difference

cntti 表示 cntj=i 的个数。发现 i×cnttin,所以有用的 cnttin 级别的。用链表维护然后跑双指针即可。


P4689 [Ynoi2016] 这是我自己的发明

发现如果没有操作 1 的话,打到 dfn 序上就是 P5268。对于操作 1,考虑一下换根后每个子树的变化即可。

posted @   xishanmeigao  阅读(10)  评论(0编辑  收藏  举报
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示