树状数组

会有一股神秘感。 提交于 2020-03-30 09:11:14

树状数组

简介

为什么需要树状数组?

举一个简单的例子,有一个数组[ 9 , 3 , 2 , 5 , 7 ],当我们需要计算数组任意X~X+N项元素的和,若采用传统方式,则需要从X开始一路加到X+N,需要的时间复杂度o(n)。

若要进一步优化我们可以求出含有对应位置前n项和的数组,例如上述数组对应结果为T[9 , 12 , 14 , 19 , 26],若要再求X~X+N个元素的和,只需计算T[X+N] - T[X]即可,但问题是当在数组某个位置重新插入一个元素时,需要将其位置后面的所有元素都更新,时间复杂度仍是O(N)

这个时候树状数组就出现了,树状数组的插入和查询任意n项和的时间复杂度都是o(log n)

以[1 , 2 , 3 , 4 , 5 , 6 , 7 , 8]为节点的一颗完整树状数组如下图

树状数组每个节点的父节点为pos += lowbit(i),i<n

  • lowbit是指一个整数的二进制表示,从后往前数一直到第一个1所代表的大小

    例如 3 = 011 那么3的lowbit即为1

   6 =0110 那么6的lowbit为 2

​ 关于lowbit有一个很简单的求法那就是( X&~X )

插入或更新元素

当我们需要插入一个元素时,从这个元素开始,依次更新这个节点一直到树根中所有元素

以2号节点元素加上5为例,初始化pos = 2

1.更新2号元素  3+5=8

2.pos+=lowbit(2) pos = 4 

3.更新4号元素  10+5=15

4.pos+=lowbit(4) pos = 8

5.更新8号元素   36+5=41

6.8号已到达数组末尾,更新结束 

查询

当我们需要查询某位置对应的前n项和,则依次从对应位置开始依次访问直到pos==0

以节点5前n项和为例,先初始化ans=0,pos = 5

1.ans+=t[pos] pos = 5 ans = 5

2.pos -= lowbit(5) pos = 4 ans = 5

3.ans += t[pos] pos = 4 ans = 15

4.pos -= lowbit(5) pos = 0 ans = 15

前5项和为15

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!