有关数据结构
写在前面:
说实话本蒟蒻并没有足够的实力与自信去完成这样一件作品,所谓的“优化”也不过是我个人拙劣理解,但是形成这样一个完整的知识框架必然有益无害,与我而言,这件事一定要做,所以本蒟蒻会坚持很长时间,去完善本篇博客。因此本博客在某种意义上相当于我个人的成长记录,在它逐渐成型的过程中必然伴随着漏洞,谬误,以及幼稚的思考与拙劣的模仿,所以不管阅读这篇博客的您是某位学弟,同学,陌生人甚至是未来某一天的我自己,都请您善待我这篇粗浅的“处女作”,毕竟在本人短暂且并不平坦的 OI 生涯中,这也算一份回忆录,承载了一段旧时光。希望未来某时,我能想起这段小有缺憾的美好时光
\(\mathbf{Part}\) \(\mathbf{1}\) 数据结构简介:
前言:本文目的不在于科普各种数据结构,因此本部分会尽量简短,同时也起到一个总体概括的目录作用。
树状数组:
树状数组是一种以 lowbit
为核心操作的数据结构,其本质是一棵二叉树,将原序列下标按 lowbit
分别存储在每个节点,询问时求解 log 层即可。树状数组基于一种特殊的“前缀和”思想运作,因此其所维护的内容在大部分情况下需有鲜明的“区间累加性”,扩展性不佳,但树状数组拥有更低的常数与代码复杂度,因而在 OI 中有十分重要的地位。
例题:
线段树
线段树利用分段思想,将原序列分别折半划分开来,以二叉树的父子节点反映管辖的区间关系,求解 log 层来 push_up
。线段树基于一种区间分治思想进行维护,因此只要能够将贡献不断合并的内容均能维护,有更强的扩展性。
线段树的操作更加灵活多变,区间维护不拘泥于“和”,“最值”等“累加性”鲜明的形式。
例题:
GSS1 - Can you answer these queries I
注意:由于线段树的区间标记在 push_up
时不需要从儿子节点传递,因此线段树容易出现初始化不完全等问题,从而在 Linux 环境下 UB。
分块&莫队:
分块将原数列分为若干“块”进行维护,采取“整块标记,散块暴力”的思想。为了使复杂度得到平衡,块的长度与个数应平衡出一个根号,因此分块算法复杂度一般和 \(\Theta(\sqrt{n})\) 有关,分块作为一种“优雅的暴力”,可维护的内容及其广泛,在 OI 中同样有极其重要的地位。
分块有许多经典的题目与tips,本文中以具体题目来描述分块的各种经典操作。
例题:
莫队算法是由莫涛提出的算法。在莫涛提出莫队算法之前,莫队算法已经在 Codeforces 的高手圈里小范围流传,但是莫涛是第一个对莫队算法进行详细归纳总结的人。莫涛提出莫队算法时,只分析了普通莫队算法,但是经过 OIer 和 ACMer 的集体智慧改造,莫队有了多种扩展版本。
莫队算法可以解决一类离线区间询问问题,适用性极为广泛。同时将其加以扩展,便能轻松处理树上路径询问以及支持修改操作。
\(\mathbf{Part}\) \(\mathbf{2}\) 具体应用:
前言:本部分内容重在整理对于部分数据结构的应用及进阶应用,本人不太能想到什么巧妙的分类方法,因此暂时不进行提纲分类,待竣工后再装修润色。
-
常见的 DP 递推优化
-
有一些问题可以抽象出图论模型求解,然而实现时建图的时空复杂度太高,此时可以考虑线段树优化建图,在线段树节点上的区间建边,以降低时空复杂度。
\(\mathbf{Part}\) \(\mathbf{3}\) 一些Tricks
前言:本部分更偏重一些强大的Trick,随时补充。
-
比较常见的技巧,将问题划分中点,每次只考虑计算跨区间中点算贡献,然后递归左右区间分开统计答案即可,当然你也可以叫它“序列分治”。
-
线段树与时间轴结合,大概是将各种与时间,操作,询问有关的问题放在线段树上维护,本人没有想到该叫本部分什么好的名字(大佬可以在评论区分享一下)。
-
与顺序相关的 \(n\) 元组求值问题,往往利用线段树进行维护,算一种经典的操作。
Upd 2023.10.10:更新 \(\mathbf{Part}\) \(\mathbf{1}\) “分块&莫队”部分,重新排版。
Upd 2023.10.15:\(\mathbf{Part}\) \(\mathbf{2,3}\) 不便在一篇博客内呈现与实时更新,因此改为链接+简介的形式进行排版。
Upd 2023.10.16:更新 \(\mathbf{Part}\) \(\mathbf{3}\) “维护逆(顺)序对(组)问题”链接。
Upd 2023.10.28:更新 \(\mathbf{Part}\) \(\mathbf{3}\) “小清新线段树与zkw线段树” 链接及 \(\mathbf{Part}\) \(\mathbf{2}\) “数据结构优化DP转移“简介。