参考链接为:
https://blog.csdn.net/Small_Orange_glory/article/details/81290634
https://blog.csdn.net/int64Ago/article/details/7429868
C[i]代表子树的叶子节点的权值之和
C[1]=A[1]
C[2]=A[1]+A[2]
C[3]=A[3]
C[4]=A[1]+A[2]+A[3]+A[4]
……
将节点序号转化为二进制,发现
C[i]=A[i-2^k+1]+A[i-2^k+2]+……+A[i] (k为i的二进制的末尾0的个数)
引入lowbit( x ) 取出x的最低位1,也就是说lowbit(x)=2^k
int lowbit(int t){
return t&(-t);
}
在上面运算的过程中是用带符号的二进制数计算的,其中 - 表示求反码
那么 C[i] = A[i-lowbit(i)+1]+A[i-lowbit(i)+2]+.......+A[i]
另一种说法是C[0110]代表着从0110开始计算0010个数的和
树状数组有两个代码公式,一个是区间查询,也就是求A数组中前i项的和
按照参考网址给出的示例,得到对应的代码 getsum(x)
int getsum(int pos){
int ans=0;
while(pos){
ans+=C[pos];
pos-=lowbit(pos);
}
return ans;
}
另一个为单点更新,数组A更新时如何更新数组C呢
void update(int pos,int delta){
while(pos<=n){
C[pos]+=delta;
pos+=lowbit(pos);
}
}
数组维护和查询都是O(logn) 的复杂度。