分块和莫队总结
分块
算法属性
离线/在线 | 在线 |
---|---|
时间复杂度 | 因题而异,但经常是 \(O(n\sqrt n)\) |
空间复杂度 | 因题而异,但经常是 \(O(n\sqrt n)\) 或 \(O(n)\) |
实用性 | 广 |
算法简介
分块其实是一种思想而并非算法。
分块的思想是将序列每 \(len\) 长经行一次划分,然后在每一块中单独处理信息,在修改或查询时对整块部分直接修改或查询,对散点暴力,即可做到 \(O(qn\div len)\) 的优秀时间复杂度(因题而异)。
这么说有点空洞,还是看几到题吧:
[hdu1166 敌兵布阵](Problem - 1166 (hdu.edu.cn))
题意
维护一个长度为 \(n\) 的序列支持单点修改,区间求和。
思路
读完题后发现是经典数据结构题,线段树树状数组啥的都能做,但我们要讲的是分块。
考虑将序列分成 \(\sqrt n\) 块,对于每块维护区间和,修改时直接修改本块和和单点,查询时吧所有整块(最多 \(\sqrt n\) 块)和左右的散点(最多 \(\sqrt n\) 个)加起来即可,注意特判左右端点在一块的情况。
[[HNOI2010] 弹飞绵羊]([P3203 HNOI2010] 弹飞绵羊 - 洛谷 (luogu.com.cn))
题意
原题面挺清晰的。。。
思路
把原序列分块,对于每块维护要几步弹出和弹出后会飞到哪里,修改时直接块内暴力重构,查询时就一直跳直到飞走。
[[Violet] 蒲公英]([P4168 Violet] 蒲公英 - 洛谷 (luogu.com.cn))
题意
求区间最小众数,不带修。
思路
预处理出:
- \(p_{i,j}\) 表示第 \(i\) 个块到第 \(j\) 个块的最小众数
- \(s_{i,j}\) 表示前 \(i\) 个块中 \(j\) 出现了几次
对于查询,我们暴力统计散块,然后和整块的答案合并起来即可。
[教主的魔法](P2801 教主的魔法 - 洛谷 (luogu.com.cn))
题意
维护一个长度为 \(n\) 的序列支持区间增值,区间求 \(rk\)。
思路
把每一块排序后二分查找 \(rk\),散点暴力遍历所处整块,修改就给整块打懒标记,散点增值后重新排序即可。
莫队
算法属性
在线/离线 | 离线 |
---|---|
时间复杂度 | \(O(n\sqrt n)\) |
空间复杂度 | \(O(n)\) |
实用度 | 高 |
算法简介
如果从 \([l,r]\) 的答案能够 \(O(1)\) 扩展到与 \([l,r]\) 相邻的区间的答案,那么可以离线分块后将查询的 \(l\) 所在块为第一关键字,\(r\) 为第二关键字排序,在 \(O(n\sqrt{n})\) 的复杂度内求出所有询问的答案,复杂度分析
小B的询问
题意
原题面很明晰了。
思路
板题,开一个桶和数组记录答案,然后用小学数学就会的方法拆平方差的贡献就秒了。
[国家集训队] 小 Z 的袜子
也是做上国集题了啊。
题意
原题面很明晰了。
思路
清晰推式子题。
[AHOI2013] 作业
题意
求一段区间中大小在 \([a,b]\) 的数的个数和大于等于 \(a\) 或小于等于 \(b\) 的数的个数。
思路
维护两个树状数组,一个表示数的个数,一个表示不同数值的个数即可,还有更优的方法懒得写了。
BZOJ4358 permu
题意
给出一个长度为 n 的排列 \(P(P1,P2,...Pn)\),以及m个询问。每次询问某个区间[\([l,r]\)中,最长的值域连续段长度。
思路
回滚莫队板题,维护 \(L\) 和 \(R\) 数组表示连续段能向左向右多远,然后注意到每次加点都只用更新连续段的最左和最右的 \(L\) 和 \(R\),原因是别的地方你加了也没贡献,只有点落在最左最右才能更新答案,我们考虑到正常莫队的话右端点是单调上升的不用撤回,于是考虑左端点的撤销,我们可以考虑对于所有左端点在一块的查询让左端点从右往左扫,然后每到下一块暴力清楚一遍。
[WC2013] 糖果公园
题意
给你一棵被染色的树,要求支持:
-
对于询问的一条最短路径求每个点的颜色价值之和乘每个颜色出现次数的价值之和。
-
修改单点颜色。
思路
这种看着就很抽象还没有可加性的题考虑先将树拍扁后用带修莫队搞,但我们注意到我们需要在遍历完子树后清空子树的贡献,所以不能拿 dfs 序搞。
做法,是什么呢好难猜啊于是考虑括号序列,如果发现一个点被扫了两次就清除贡献,特判一下 \(lca\) 和起点即可。