数据结构

数据结构总结

功能

可以用于维护整体的一个最值,插入删除均为O(logn),求最值为O(1)。

实现

用一个二叉树维护,父亲比儿子更满足条件,每次插入就加,然后再浮上来,删除就把最后一个树放过来然后再删除

运用

用处比较广,可以优化DP,降低复杂度,在短时间内求出最值,一般可以直接使用priority_queue实现

并查集

功能

可以维护一个多个集合,查询两对象是否在同一集合,合并操作

实现

通过记住父亲节点,一般先将父亲指向自己,查询时通过root判断是否在一个集合里

运用

可以使用路径压缩以及按秩合并,可以从O(n)压到O(1),一般都用于维护集合

Hash

功能

可以将一些比较大的数或一些数压缩到范围可控你的一个数,用这个数来判断和其他的关系

实现

一般是用一定的函数实现,计算贡献为一个数,通过取模运算控制得到的数的范围,对于可能产生的冲突可以通过多层hash降低冲突概率。

运用

字符串比较比较常用,与处理后O1比较字符串是否相同,以及可以在搜索中压缩状态。对于冲突,一般双hash的冲突概率就很小了,基本够用

KMP

功能

可以比较模式串在文本串中出现的位置的次数

实现

使用失配函数,减少回的步数,优化匹配

运用

用于字符串的匹配

Trie

功能

字典树可以在O(len)的时间加入和查询一个词是否在字典中,同时也可以用些骚操作维护其他的数字,经典有01trie

实现

以字符串为例子,trie是一颗树,每个节点都存有一个字母,查询时每次通向下个字符所在边。

运用

大多是判断一个字符串是否出现过为基础,同时也可以存数字,01trie是个很好的例子,可以用01来表示二进制里的数字,甚至可以做平衡树板子

AC自动机

功能

可以查询多个模式串在文本串中出现的次数。

实现

可以说是吧KMP的思想放到Trie上,用fail指针在trie上跳动,来满足要求

运用

一般就用于字符串的问题

树状数组

功能

可以动态维护前缀和

实现

通过一些需要依靠图片我没有的解释但技巧,使得空间在O(n),复杂度在O(logn)的范围内实现

运用

一般就是动态维护前缀和,单点修改,也可维护差分数组,来实现区间修改。

线段树

功能

包含所有树状数组的功能以及一些树状数组不能维护的东东。

实现

叶子节点存下当前位置的值,每个父亲都存下儿子的答案。一般复杂度是O(\(\log n\))的,常数较大,空间复杂度也大,代码长度也比较长。但是运用情况非常多,可以解决大部分情况。

运用

基本都是在维护方式和push_down操作上出题,一般思维比较大。然后线段树可以和很多数据结构并用也是一些数据结构的基础。

ST表

功能

O(\(n \log n\))预处理查询区间最值。

实现

这是倍增的产物,通过 \(f_{i,j}\) 表示从 \(i\)开始长度为 \(1\ll j\) 的部分的最值,查询的时候直接首位开始交叉形成查询空间。

运用

可以以很短的代码长度以及很快的速度求出区间最值,也可用于末尾加数。

LCA

功能

查询最近公共祖先

实现

可以用倍增来优化速度,使用倍增算法可以快速的找出最近公共祖先

也可以通过树剖来实现,没写过只听说过。

运用

运用的话基本就是辅助功能,查询最近公共祖先,可以在树上差分,树上前缀和。

平衡树

功能

是二叉查找树的优化版,查找删除一个数,查询前驱后继,查询排名。由于二叉查找树可能退化到O(n),所以要用平衡树保证深度大致在\(\log n\)的范围。

实现

treap

是tree和heap的产物,对每个点随机一个值,在满足二叉查找树的同时维护随机值为一个堆,基本上随机的情况下只有 \(\log n\) 的深度,满足情况。

Splay

通过对每次查询的值旋转到根节点来满足要求。

运用

树链剖分

功能

将一棵树剖分为很多条链,重新编号,满足链上编号的相同,可以用其他数据结构维护。

实现

这里用的是重链剖分,将连接重儿子的链称为重边,将所有重边连成的链叫重链,这样就可以区间维护了。

运用

一般是和线段树一起用,这样可以维护子树,最短路径上的情况。

LCT

功能

维护一个森林, 支持删除某条边,加⼊某条边,并保证加边,删边之后仍是森林。我们要维护这个森林的一些信息。

实现

可以先用实链剖分,我们建很多个Splay 来维护每个链区间的信息。

这里用上辅助树,辅助树是可以在满足辅助树、Splay 的性质下任意换根的。

运用

可以类似于树链剖分,但这个是维护一个森林。

posted @ 2020-04-12 20:33  ztz_cpp  阅读(152)  评论(0编辑  收藏  举报