树状数组 基础篇

树状数组 基础篇

*大家可以先了解一下—>线段树

引入

数列操作:
给定一个初始值都为0的序列,动态地修改一些位置上的数字,加上一个数,减去一个数,或者乘上一个数,然后动态地提出问题,问题的形式是求出一段数字的和.

在这里插入图片描述

1.可以看出,这棵树的构造用二分便可以实现.复杂度是logN.
2.每个结点用数组a来表示该结点所表示范围内的数据之和.
3.修改一个位置上数字的值,就是修改一个叶子结点的值,而当程序由叶子结点返回根节点的同时顺便修改掉路径上的结点的a数组的值.
4.对于询问的回答,可以直接查找i…j范围内的值,遇到分叉时就兵分两路,最后再合起来.也可以先找出0…i-1的值和0…j的值,两个值减一减就行了.后者的实际操作次数比前者小一些.
5.这样修改与维护的复杂度是logN.询问的复杂度也是logN,对于M次询问,复杂度是MlogN.

这个东西,对于线段树来说是一个时间和空间上的飞跃,在空间上,最多只要开到原数组的2倍,而线段树要四倍,在时间上也略快于线段树。(最重要是代码短,懒人的福音)
在这里插入图片描述
问题:区间是如何划分的

对于序列a,我们设一个数组C定义C[i] = a[i – 2^k + 1] + … + a[i],k为i在二进制下末尾0的个数
K的计算可以这样: 2^k=x & (-x)
Examply 以6为例
(6)10=(0110)2
(-6)10=(1010)2
6 & -6=2

结构看上去要比线段树复杂,实际~~~~很短(相对于线段树)

敲重点 它的原理

我们定义lowbit(n)=n&(-n)表示取出非负整数n在二进制表示下最低位的1以及它后边的0构成的数值
c[x]保存序列A的区间[x- lowbit(x)+1,x]中所有数的和。
该结构满足以下性质:
1.每个内部节点c[x]保存以它为根的子树中所有叶节点的和。
2.每个内部节点c[x]的子节点个数等于 lowbit(x)的大小。
3.除树根外,每个内部节点c[x]的父节点是c[x+ lowbit(x)]。
4.树的深度为O(logN)

运用

1.对某个元素进行加法操作

树状数组支持单点增加,意思是给序列中的某个数A[x]加上y,同时正确维护序列的前缀和。根据上面给出的树形结构和它的性质,只有节点c[x]及其所有祖先节点保存的“区间和”包含A[x],而任意一个节点的祖先至多只有logN个,我们逐一对它们的c值进行更新即可。下面的代码在O(logN)时间内执行单点增加操作。<

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值