QBXT2020 WC 数据结构= =


树状数组:

例题: 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为其父节点的左儿子, 左旋, 否则右旋.
    • 优化:
      1
      若出现上述结构, 先左旋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\).

左偏树合并时:

  1. 比较根节点权值大小, 较大的点成为根,
  2. 较大点的左儿子继承, 再将较大点的右儿子与另一棵树合并.
    成为新树的右儿子, 递归进行.
  3. 上述过程完成后, 若左儿子 > 右儿子, 则交换左右儿子.
    复杂度 \(O(2\log n)\)

左偏树插入 :
将院左偏树 与 一个只有一个点的左偏树合并.

例题: HDU1512

左偏树裸体 + 并查集.

可持久化线段树:

支持还原历史状态 的 线段树.

显然不能覆盖历史状态, 考虑新建线段树节点.

每次单点修改操作, 只会修改从叶结点向上共 \(\log n\)个节点.
则每次单点修改操作 只会新建 \(\log n\)个节点.

对于每个节点 都维护时刻指针, 指针指向不同修改时刻的 子节点.
按照指针进行跳跃移动.

对于区间修改, 下传懒标记时 不需要新建节点.

树链剖分:

将树拆分成数列, 由此将树上问题 转化为序列问题.
详见 Luogu题解.

任何一条树上路径都可以被拆分成 至多 \(\log n\) 条数列.
然后就可以用序列数据结构 进行维护.

LCT:

咕咕咕

\(NB\) 题目选讲:

CF274E

反射位置有限, 发现最多反射 \(n + m + k\)次.
需要使用 某种数据结构, 快速找到 某次反射的终点即可.

统计

  • 如果有弹回的情况,

猜你喜欢

转载自www.cnblogs.com/luckyblock/p/12201343.html
wc