📂C/C++
🔖C++
2022-04-30 21:41阅读: 38评论: 0推荐: 0

树状数组BIT

BIT

  • 树状数组或二叉索引树,全称 Binary Indexed Tree。本质就是用数组模拟树形结构,时间复杂度O(log2n)
  • 线段树也能实现树状数组功能。树状数组的复杂度和线段树同级,但代码量更为简洁。

1 问题引入

  • 一个长度为n的数组,要求如下两个操作
    • 对第i个数加k,复杂度为O(1)
    • 对区间[1,i]求和,复杂度为O(n)
  • 当对此修改与查询,最坏为O(n2)。当数据量很大时是难以接受的。
  • 而树状数组单点更新与区间查询都为O(log2n),可以大大降低复杂度。
  • 总结一下,当某点经常更新,且要用到前缀和时可以使用树状数组,来降低复杂度。

2 树状数组

  • 树状数组是一种可以动态维护序列前缀和的数据结构,它的基本功能是:
    • 单点更新 update(i, v): 把序列 i 位置的数加上一个值 v,O(log2n)
    • 区间查询 query(i): 查询序列[1⋯i] 区间的区间和,即 i 位置的前缀和,O(log2n)
  • 如图所示,树状数组C存储的是对数组A各个位置的前缀和。
    BIT
    • C[1] = A[1]
    • C[2] = A[1] + A[2]
    • C[3] = A[3]
    • C[4] = A[1] + A[2] + C[3] + A[4]
    • ……
    • C[7] = A[7]
    • C[8] = A[1] + A[2] + C[3] + A[4] + A[5] + A[6] + A[7] + A[8]

2.1 lowbit()操作

  • 树状数组的前缀和,被分成了不同区间的和。与动态规划中的存储之前计算过的值来降低复杂度一样,树状数组也是用之前的区间值来累加,避免重复计算。
copy
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
// 求最低位二进制为1的数 // 10100 -> 00100 = 4 // 01110 -> 00010 = 2 // 原码& double lowbit(double x){ return x&(-x); }
  • 正数的原码、反码、补码相同,负数等于反码+1。通过x&(-x)可以只保留最低位为1的数。
    • 如原码10100变反码01011,反码01011再加1等于01100,最终相与得 00100

2.2 query()操作

  • 树状数组C[X]等于 [X-lowbit(X)+1,X] 中所有值的和。
  • 当要求X的前缀和时,query(X)= C[X] + C[X-lowbit(X)]+...
    • 直到 X = 0
copy
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
int query(int x) { int ret = 0; while (x) { ret += C[x]; x -= lowbit(x); } return ret; }

2.3 update() 操作

  • 当对该点更新时,需要对其父结点同步更新
    • 如当A[6]更新时,需要更新后面的C[6]、C[8]等。
copy
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
void update(int x) { while (x <= n) { ++C[x]; x += lowbit(x); } }
BIT.cpp
copy
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
class BIT { private: vector<int> tree; int n; public: BIT(int _n): n(_n), tree(_n + 1) {} static int lowbit(int x) { return x & (-x); } int query(int x) { int ret = 0; while (x) { ret += tree[x]; x -= lowbit(x); } return ret; } void update(int x,int v=1) { while (x <= n) { tree[x] += v; x += lowbit(x); } } };

3 应用

  • 树状数组与逆序对
  • ...

参考资料:
https://www.bilibili.com/video/BV1xq4y1i7et
https://blog.csdn.net/qq_40941722/article/details/104406126
https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/

本文作者:oniisan

本文链接:https://www.cnblogs.com/oniisan/p/BIT.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Oniisan_Rui  阅读(38)  评论(0编辑  收藏  举报
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
点击右上角即可分享
微信分享提示