总结

数据结构:

大体:

能离线还是先想离线处理,因为这样可以有很多解决问题的办法。
比如 CDQ,莫队,优化分块空间,时光倒流,猫树,整体二分 \(\sim\) 等离线算法。

树状数组:

可以用来维护前缀的,满足交换律,且可逆 的东西。
方便好写,常数极小,但使用范围不广。
很难维护更高级的运算,被线段树碾压。
有一种小特例:就是去维护满足交换不满足结合律的东西,不常见,也没见过。
trick: 二分套树状数组可以通过倍增来做到 \(O(\log n)\) 的。

并查集:

可以用来维护一些联通块,无论是数值的还是位置上的。
特征也比较明显,因为应该没人写 ds 时维护 bfs 的状态吧!
要求是必须只关心整个块的信息,不能关心某几个跟他链接的点的信息。
常数也很小,不亚于树状数组。
但通常合并时非常困难,好像只能 \(O(n)\) 以上的时间复杂度来合并并查集。

线段树:

算是一种非常常用的数据结构了。
可以在 \(O(merge) \log n\) 的时间复杂度内完成任何满足结合律的东西。
也支持修改,但有时空间巨大。
一些技巧:

大多数二分套线段树可以被线段树二分/单侧递归线段树等来做到 \(O(\log)\)

线段树合并 \(n\) 个大小为 \(n\) 的集合的时间复杂度为 \(O(n \log n)\),可以通过势能分析,没学过。

动态开点线段树:是一种时间,空间都比较劣的线段树,但可以支持范围很大,重要的点较少的线段树。

为什么很多时候不能用线段树呢?
因为若与子树前/后有关的话就不能拿线段树来写的。
但若只与兄弟有关的话可以在父亲那里打 tag。

例子:
2025省集D2T3

主席树:

就是可持久化线段树,可以快速地在空间,时间都为 \(O(n \log n)\) 地限制内求出类似查询区间不同数地数量这种较复杂的东西的线段树。
做法就是维护下标的差分。

比线段树的优势在于可以支持区间求数值的操作。
比线段树的劣势在于其自身不支持修改。
但可以通过树状数组树套树。
然后打 tag 时要记得开 3 倍空间,所以空间也挺寄。
一般是维护地权值线段树,然后建 \(n\) 棵线段树。
线段树其他能做的,主席树理论也可做。

猫树:

分治与线段树的杂交版,不支持在线。
但有时在时间上有巨大优势,比如
某场NOIP模拟赛 T3

这一场的 T3,如果拿线段树做的话时间复杂度瓶颈在大常数 \(O(n \times k^2 \log^2 n)\)
基本过不去,但如果是猫树的话,时间复杂度就是 \(O(q \times k^ 2 \log)\),常数及空间都小,可以通过。

所以猫树的优势在于,只要线段树能做的无强制在线且无修改的,猫树几乎都能做。
大体思路就是离线,然后分治,对于每个 \(x \in l \sim mid\)\(y \in mid + 1 \sim r\) 的查询,预处理出左边的每一个后缀,右边的每一个前缀,再暴力合并即可。
往往能达到很好的效果。
因为线段树合并并查集时时间复杂度有点寄寄,但猫树只需要合并一次。

平衡树(除treap,因为感觉和动态开点线段树没有什么区别,就算卡空间 fhq 也比它好写):

很全能的单 log 的数据结构。
除卡常外及难写外,能完全覆盖线段树。

支持 reverse 操作,这应该是唯一一个分块做不了的操作?

FHQ 的本质就是通过很多次分裂于合并让树高不会太高,好写但大常数。
Splay 的本质是时间复杂度均摊,每次将询问的点旋到根,且复杂度严格 \(log\),难写但块。
也就是因为复杂度均摊,所以 LCT 用 Splay 的话是单 log。

也挺明显的,有 reverse 操作时必须用平衡树了。

分块:

全能的数据结构。
他对于线段树的优势在于:能做更多的操作,比如许多全用线段树存会 MLE 的题目,分块可以通过用时间代价来换取小空间,或者难以 push_down 的题目。
但感觉主要还是在于子树不封闭?

前面分块唯一不能取代的就是不支持 reverse 操作。
且分块的常数和时间复杂度都不小。
谨慎使用。
所以这个是要总结好什么时候用,什么时候不用的。
下面是几个例题(有的还没过):

1. [Ynoi2018] 五彩斑斓的世界

这题是因为卡空间再加上不好push_down,如果拿线段树的话,每个节点都维护一个并查集空间直接炸了。

2. [BJOI2017] 开车

这题在拆完贡献之后相当于要维护一个绝对值成系数,然后有将绝对值 +1/-1 的操作。
所以线段树无法push_down以及快速获取答案。

3. [Ynoi2018] 未来日记

(怎么这么多并查集啊)
考虑分块套分块,因为如果拿线段树的话又要维护并查集了,所以第一个分块是用来干这个事情的。
第二个分块是为了省掉二分的 \(\log\),也算是经典套路了。

莫队:

也是一种离线算法,本质是基于分块的。
就是当你直接做不好做,且知道 \(l,r\) 之后就能快速知道 \(l,r+1\) 类似这种东西时可以考虑莫队。
还有就是莫队是可以自动帮你消掉一个维度的。
比如 [Cnoi2019] 数字游戏
这个题就是有值域和下标两个维度的数字。
做法就是先值域莫队一下,为了复杂度平衡里面又得放个分块。
所以删除的时候是很难的。
所以考虑回滚大常数。

回滚:就是只加,不删的莫队,具有很好的性质,不过也比较难写。
树上:就是把树上的路经通过 dfn 序转化,大致时出现次数一次的点才能对答案影响。

整体二分:

也是离线的。
这个东西其实还是挺有局部性的,当他不能通过类似“减”这种操作来直接体现前面对他的影响时,说明他大概率不能用整体二分。

CDQ:

没啥好说的,就是三/四维偏序,有时把时间也当一维。

根号分治:

本质是两个暴力拼在一起,常常有 \(\sum a = n\) 类似的性质。

posted @ 2025-05-07 22:59  positive_deviation  阅读(16)  评论(0)    收藏  举报