树状数组:
例题: Vijos 1066
给定同一平面内一些点 \((x_i,y_i)\),
对于每一个点, 求满足\(x_j<x_i, y_j<y_i\)的点的个数.
点按照横坐标排序.
树状数组维护, 已被添加进序列的, 纵坐标在\(\le\) 给定参数的点的数量.
每将一段相同的横坐标扫描完毕后, 将它们加入树状数组.
线段树:
例题: Luogu P4246
给定一由\(2n\)个点组成的点阵, 长为\(n\)宽为2. 给定操作:
将相邻的两个点连接 , 将一条路径删除 ,查询两点之间是否联通。
大力分类讨论.
多维线段树:
维护 \(n^d\) 维矩阵的信息, \(d\)层线段树套起来.
以二维线段树为例 :
长这个样:
预处理 :
枚举每一个矩阵中的点, 复杂度\(O(n^2)\)
区间查询 ,修改时:
- 现在第一维找到 横坐标拆分成的的\(\log n\)个点.
- 在上述点中 找到纵坐标拆分成的 \(\log m\)个点.
- 复杂度 \(O(\log^2 n)\)
查询时下传标记, 只下传会影响查询区间的标记, 而不是将父节点所有信息全部下传.
否则下传标记的复杂度不能保证\(O(1)\), 线段树的复杂度会退化到\(O(n^2)\)
例题: HDU 4819
矩阵单点修改, 查询矩阵极值.
Spaly
单点插入删除, 单点修改, 区间求和...
- 将序列转化为一棵树, 树的中序遍历即为原序列.
- 左旋:
旋转后 中序遍历不变, x的深度减小1. 右旋: 将上图中左旋后结果旋转回来, y的深度增加 1.
- spaly(x, s)
要求 x 为 s的子节点.
将x旋转到s的位置, 即将x的深度不断减小.
若x为其父节点的左儿子, 左旋, 否则右旋.- 优化:
若出现上述结构, 先左旋y, 再左旋x.
会有用, 但没有证明(大雾)
- 优化:
单点修改:
修改第i个点, 通过子树大小 确定i的树上位置.
修改i后, 将i spaly至根, 以保证均摊复杂度.单点插入:
先找到第i个点.
不断向下递归寻找右儿子.
递归到底, 找不到右儿子后, 新建一个左儿子.
若已有左儿子 则新建一右儿子.
保证插入点 在i的所有右儿子之前, 即在i之后.单点删除:
将i spaly至根.区间修改查询:
将L spaly至根, 将R spaly至根的右儿子.
R的左子树即为查询区间.
可以通过维护子树信息, 来实现快速查询.区间翻转:
对于中序遍历, 翻转相当于将其左右儿子交换.
按照区间修改查询的方法对l,r进行处理.
对R的左子树根节点打翻转标记懒惰更新.查询排名:
记录子树大小, 根据做子树大小确定向左/向右递归.
左偏树:
建堆, 取极值, 删除极值, 快速堆合并.
普通的堆合并 最低复杂度显然为\(O(n\log n)\).
以下以小跟堆为例:
- 一个点最多有两个子节点, 父节点比子结点小.
- 若一个点子节点数\(<2\), 则称为外子节点.
- 一个点权值定义为 到达最近的外子节点的距离.
对于一个非外子节点, 其左子节点 \(\ge\) 右子节点.
- 一个点权值为其右子节点权值 + 1 (左子节点 \(\ge\) 右子节点)
- 深度为\(d\)的左偏树, 至少有\(2^d\)个节点.
- 归纳证明:
d = 0, 有 \(2^0\)个节点.
当\(d<k\)时, 若其满足此性质.
d = k时, 由两个d = k - 1 的左偏树组成.
则节点数为 \(2 \times 2 ^ {k - 1} = 2 ^ k\). - 则节点数为\(n\)的左偏树深度为 \(\log n\).
- 归纳证明:
左偏树合并时:
- 比较根节点权值大小, 较大的点成为根,
- 较大点的左儿子继承, 再将较大点的右儿子与另一棵树合并.
成为新树的右儿子, 递归进行. - 上述过程完成后, 若左儿子 > 右儿子, 则交换左右儿子.
复杂度 \(O(2\log n)\)
左偏树插入 :
将院左偏树 与 一个只有一个点的左偏树合并.
例题: HDU1512
左偏树裸体 + 并查集.
可持久化线段树:
支持还原历史状态 的 线段树.
显然不能覆盖历史状态, 考虑新建线段树节点.
每次单点修改操作, 只会修改从叶结点向上共 \(\log n\)个节点.
则每次单点修改操作 只会新建 \(\log n\)个节点.
对于每个节点 都维护时刻指针, 指针指向不同修改时刻的 子节点.
按照指针进行跳跃移动.
对于区间修改, 下传懒标记时 不需要新建节点.
树链剖分:
将树拆分成数列, 由此将树上问题 转化为序列问题.
详见 Luogu题解.
任何一条树上路径都可以被拆分成 至多 \(\log n\) 条数列.
然后就可以用序列数据结构 进行维护.
LCT:
咕咕咕
\(NB\) 题目选讲:
CF274E
反射位置有限, 发现最多反射 \(n + m + k\)次.
需要使用 某种数据结构, 快速找到 某次反射的终点即可.
统计
- 如果有弹回的情况,