Fenwick 树很棒!

这篇文章主要介绍了 Fenwick 树(二进制索引树),包括其基本操作、构建、优化以及一些扩展应用等方面:

  • 基本操作

    • Update(i, v):将数组 A 中索引 i 的元素加上 v,时间复杂度为 O(1)
    • RangeQuery(i, j):计算数组 A 中索引 [i, j] 范围内元素的和,普通数组实现时间复杂度为 O(N),通过前缀和优化后可变为 O(1),但更新前缀和会导致后续索引的前缀和出错。
  • 构建优化

    • 朴素方法是对数组 A 中每个元素进行 Update(i, A[i]),时间复杂度为 O(N log N)
    • 更优的方法是从节点 1 开始,将节点值向上传播,时间复杂度为 O(N)
  • 更快的范围查询优化:通过在 RangeQuery(i, j) 中停止 Query(j) 一旦到达节点小于 i,可稍微加快查询速度,对于 N = 2^B 的情况,大约有 5%的速度提升。
  • 前缀搜索:通过在 Fenwick 树的黄色树(二进制树)中从顶部节点开始向下走,根据左子树的和与随机数 s 的比较来确定索引,时间复杂度为 O(log N),此操作较为 obscure。
  • 范围更新:通过在 DAA 的离散导数)上构建 Fenwick 树,可以实现范围更新和点查询操作,RangeUpdate(i, j, v) 只需改变 DA[i]DA[j + 1],时间复杂度为 O(log N)
  • 范围更新和范围查询:通过构建两个 Fenwick 树,一个处理 RangeUpdate,一个处理 RangeQuery,借助一些数学推导和技巧实现了范围更新和范围查询的操作,时间复杂度为 O(log N)
  • 其他扩展:Fenwick 树还有很多扩展应用,如返回范围内任意函数而不仅仅是和,文章未详细探讨性能和实现考虑因素,如与缓存的交互等,同时给出了用于 flash 卡片应用的 Fenwick 树库的可运行代码。

总的来说,Fenwick 树是一种高效的数据结构,具有多种实用操作和扩展能力,尽管其实现和原理可能有些复杂,但在某些情况下能提供很好的性能。

阅读 10
0 条评论