Binary Index Tree 美其名曰 树状数组
那到底是树呢😃 还是数组呢😂 从严格意义上来说 其实它就是数组 但是绝非普通
废话不说 放张图再说废话🤣
它强大就强大在 对于区间问题 不管是单点修改 还是区间求和 算法复杂度都为
log
(
n
)
\log(n)
log(n)级别。
从图中可以清楚看到 它就是数组只不过存储的内容不太一样,满足一下的递推式
我们假设原数组是最下面一行,新建一个数组C来存储原数组的内容
c
[
1
]
=
a
[
1
]
c[1]=a[1]
c[1]=a[1]
c
[
2
]
=
c
[
1
]
+
a
[
2
]
c[2]=c[1]+a[2]
c[2]=c[1]+a[2]
c
[
3
]
=
a
[
3
]
c[3]=a[3]
c[3]=a[3]
c
[
4
]
=
c
[
2
]
+
c
[
3
]
+
a
[
4
]
c[4]=c[2]+c[3]+a[4]
c[4]=c[2]+c[3]+a[4]
c
[
5
]
=
a
[
5
]
c[5]=a[5]
c[5]=a[5]
c
[
6
]
=
c
[
5
]
+
a
[
6
]
c[6]=c[5]+a[6]
c[6]=c[5]+a[6]
c
[
7
]
=
a
[
7
]
c[7]=a[7]
c[7]=a[7]
c
[
8
]
=
c
[
4
]
+
c
[
6
]
+
c
[
7
]
+
a
[
8
]
c[8]=c[4]+c[6]+c[7]+a[8]
c[8]=c[4]+c[6]+c[7]+a[8]
c
[
9
]
=
a
[
9
]
c[9]=a[9]
c[9]=a[9]
c
[
10
]
=
c
[
9
]
+
a
[
10
]
c[10]=c[9]+a[10]
c[10]=c[9]+a[10]
这种关系看得我云里雾里的,完全不知道怎么来的,怎么办。放弃😒 不 世界这么大,这么玄妙的数据结构怎么能放过呢。
下面说点实际的,能不能构造出这样的数组C呢
或者怎么给C数组赋初值呢 大家可以再看看上面的两张图 再结合下面的代码
单点修改
void update(int x,int k){
while(x<=n){
tree[x]+=k;
x+=lowbit(x);
}
}
区间求和
int sum(int x){
int ret=0;
while(x>0){
ret+=tree[x];
x-=lowbit(x);
}
}
首先呢 先将原数组更新到数组C ,其实就相当于把将各项都为0的数组修改为K 时间复杂度为
O
(
n
log
(
n
)
)
O(n\log(n))
O(nlog(n)) 循环n次 完成n次单点修改。
接下来 进行单点修改和区间求和 都是
O
(
log
(
n
)
)
O(\log(n))
O(log(n))的。所以总的复杂度为
n
log
(
n
)
n\log(n)
nlog(n)
这里作个对比 如果要求
1.对某个区间的每个数 加上k 2.输出第n个数的值
估计差不多也是
n
log
(
n
)
n\log(n)
nlog(n)