树状数组 binary indexed tree的应用:
适合解决单点更新,区间求和,更新情况少的场景。 求和时间复杂度logn
如果是更新则需要n
树状数组为了方便,数组下标从1开始。对于已知数组a[i] ,重新构建一个c[i]. 其中c[i]=a[i-2^k+1]+…+a[i];
其中k是一个数的二进制表示中从右边数遇到1之前0的个数比如对于数字4(100) k=2.
2^k可以用O(1)求出来
public int lowbit(int x){
return x&(-x);
}
c[i]=a[i-lowbit(i)+1]+…+a[i];
//init c array
for(int j=i-lowbit(i)+1;j<=i;j++){
c[i]+=a[j];
}
update 操作
//update add v to index i
public void update(int i,int v){
while(int i<=n){
c[i]+=v;
i+=lowbit(i);
}
}
求和操作
求从1到x整个区间的和
public int sum(int x){
int ans=0;
while(x>0){
sum+=c[x];
x-=lowbit(x);
}
}
最终代码:
public class BinaryIndexedTree {
private int [] a; //index from 1
private int [] c;
private int n;
public BinaryIndexedTree(int [] array){
this.n=array.length;
a=new int[n+1];
c=new int[n+1];
for(int i=0;i<n;i++){
a[i+1]=array[i];
}
init();
}
private int lowbit(int x){
return x&(-x);
}
private void init(){
for(int i=1;i<=n;i++){
for(int j=i-lowbit(i)+1;j<=i;j++){
c[i]+=a[j];
}
}
}
public void update(int i,int v){
while(i<=n){
c[i]+=v;
i+=lowbit(i);
}
}
public int sum(int i){
int ans=0;
while(i>0){
ans+=c[i];
i-=lowbit(i);
}
return ans;
}
}
树状数组的几个典型应用场景:
- 求 [m,n] 区间和
直接 sum(n)-sum(m-1);
- 求逆序对
- 有时候树状数组还和离散化相结合,因为如果数字很大的话,直接创建很大的数组,开销很大。所以需要离散化,进行映射,节省空间和时间。
本文深入讲解了树状数组(binary indexed tree)的应用,包括单点更新、区间求和等操作的时间复杂度,以及如何通过树状数组高效求解区间和与逆序对等问题。同时介绍了树状数组与离散化的结合使用,以节省空间和提高效率。
423

被折叠的 条评论
为什么被折叠?



