谈谈对树状数组的理解

树状数组的功能: 区间查询  单点修改 O(logn)

举个例子

16个数的数组 eg:

8 6 1 4 5 5 1 1 3 2 1 4 9 0 7 4

两两合并求和  以便查询

14 5 10 2 5 5 9 11

再合并

19 12 10 20

31  30

61

一直计算只剩一个元素为止

例如计算前15个只需计算4个即可

再观察  有些数字是根本不会被用到的  会重复算 

 例如5计算前两个和前三个时用不上   计算前四个和前五个直接用19即可

结论  每一层的第偶数个数都可以去掉

观察剩下的数据  恰好还剩个n个  即为树状数组

先认识一下 lowbit函数   求出二进制位最低位代表哪一个数字  

int lowbit(int x)
{
    return x&(-1);
}

观察树状数组发现  第一行数据区间长度为2 ....每一层区间长度即为  lowbit(i)

*序号为i的序列正好是长度为lowbit(i)并且以i结尾的序列*

还有一个性质  序列b[i]正上方的的序列正好就是b[i+lowbit(i)]    即其父节点

所以我们在修改某一个值时只需要不断加上lowbit(i)  就可以找到上方的所有序列进行修改

为啥修改是对的?修改为啥只需要改其父节点呢?

因为子节点对应唯一的父节点 只能影响到唯一的父节点

第x个数加上k

​
void add(int x, int k)
{
    for(int i = x; i <= n; i += lowbit(i))
        t[i] += k;
}

​

查询前x个数的和

查询这个点的前缀和,需要从这个点向左上找到上一个结点,将加上其结点的值

int ask(int x)
{
    int sum = 0;
    for(int i = x; i; i -= lowbit(i))
        sum += t[i];
    return sum;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值