声明:本博客所有随笔都参照了网络资料或其他博客,仅为博主想加深理解而写,如有疑问欢迎与博主讨论✧。٩(ˊᗜˋ)و✧*。
|
|
树状数组 线段树
树状数组
支持:
(1.)单点修改/查询
(2.)区间加减/查询(差分)
优点:好理解;代码实现简单
缺点:支持的功能少(其实都是和前缀和有关的)
线段树
支持:
(1.)单点修改/查询
(2.)区间加减乘平方/查询
优点:功能相对多(懒标记挺好用,可以进行很多转化),可以树套线段树之类(例如树链剖分)
缺点:暂时想不到?
时间复杂度:(O(log n))
总评
这俩原本能解决的问题都很有限,顶多弄个单点修改区间查询,但是树状数组有了差分,线段树有了懒标记,于是它们的运用范围就变广很多了。
这是最基本的数据结构,在后面也会不断运用到,所以对于它们的熟练程度应该有★★★★★
|
|
ST表 RMQ LCA
其实这三个数据结构都运用到了同一种重要的思想:倍增
(ST)表:倍增+动态规划
的思想,是离线处理,先利用倍增
的思想处理好 (f[i][j]) 数组(表示 (i - i + 2^j)),查询则为两段的并
(RMQ):实际上就是(ST)表的运用
(LCA):相当于把(ST)表运用到树上,更为巧妙。同样为 (f[i][j]) 表示 (i) 往上走 (2^j) 步的父亲,查询时则先跳到同一高度,再一起跳
时间复杂度:(O(log n))
总评
这三个原理是一样,都是倍增的思想,而略有不同。但感觉我运用得还不是很多?大概都用上俩去了哈哈哈,熟练程度应为★★★★★
|
|
KMP Trie AC自动机
(KMP):优化在于把原来模式串中已匹配过的前缀不需再次匹配,大大减小了时间复杂度为 (O(n+m))
(Trie):这个没什么好讲的?不过第一次知道的时候还是被其神奇的应用性和简洁的代码惊叹到了
(AC)自动机:把 (KMP) 放到 (Trie) 上用,对于每个节点,都有一个 (next) 指向 最长的为此串的后缀的串的末尾(这句话好绕啊哈哈哈)
|
|
平衡树
(splay):
更新一个值后则 (splay(x, y)) 表示将 (x) 旋转为 (y) 的儿子,保证 (BST) 不会退化为一条链(其余可参考【学习笔记】splay入门(更新中))
替罪羊树:
相对于 (splay) 来说更好理解,有一定的暴力思想,在 (BST) 不平衡时直接将整棵树拍扁重建;
如何知道 (BST) 不平衡?自己定义一个 (0.5< alpha < 1)(一般为 (0.75),可根据题目需要进行变动),若子树与整棵树大小之比超过了 (alpha) 则重建
|
|
树链剖分 点分治 LCT
树链剖分
一些定义
(1.)重儿子:儿子中 (size) 最大
(2.)轻儿子:除去重儿子其余都为轻儿子
(3.)重边:父亲节点和重儿子的连边
(4.)轻边:父亲节点和轻儿子的连边
(5.)重链:由重边连成的链((ge 1))
(6.)轻链:由轻边连成的链((ge 1))
支持
(1.)修改点 (x) 到点 (y) 路径上各点的值
(2.)查询点 (x) 到点 (y) 路径上各点的值
(3.)修改点 (x) 子树上各点的值
(4.)查询点 (x) 子树上各点的值
剩下的其实很简单了,给所有节点表上新的 (id),一般用线段树来维护(注意:一定不要把原编号与 (id) 弄混了
点分治
推一篇个人觉得写得很好的博客
实际上点分治也是有一些暴力思想的;功能和树链剖分有点像,但是更广一点,还可求路径为k等一系列问题;还有更高级的动态点分治
LCT
支持:
(1.)查询/修改链
(2.)换根
(3.)动态连边/删边
(4.)动态维护连通性
由于 (LCT) 是动态维护的,所以用更灵活的 (splay) 来操作。最开始觉得超级难,多复习几遍就好多了。
总评
个人觉得树剖和点分治其实都挺好写的,多做几道题目就差不多了,都比较类似(当然黑题可能就不是了...)(LCT) 也是多写就好了
|
|
总结:
原本听到要学很多 又难又陌生 数据结构时真的有点害怕,但连续的集训也坚持下来了,收获真的超级大!谁能知道在这之前我打个线段树都超级不熟练呢hhh,也从这段学习中悟到了:
数据结构虐我千百遍 我待它仍如初恋 2333