问题的提出:是否可以用线性数据结构的方法解决动态统计子树权和的问题呢? 有的,树状数组。
假设当前数组为a[],元素个数为n。
1. 子区间的权和数组为sum,那么数组a[]中 i 到 j这段区间的数组元素和为sum[i,j]= a[k]的累加 【k属于(i->j)】
2. 现在定义前缀和数组s[],s[i]代表从a[i]---a[i]的和,那么又可以这样表示 sum[i,j] = s[j]-s[i-1].
3. lowbit(k)为整数k的二进制表示中 右边第一个1所代表的数字,lowbit(k)=k&(-k).
4. 树状数组为c[],c[k]存储的是从a[k]开始向 低的下标那边数lowbit(k)个元素之和,一层遍历。
注意:我们要把a[]数组的元素从下标1开始存储.
这里列举一下:
c[1]=a[1]; s[1]=c[1];
c[2]=a[2]+a[1]; s[2]=c[2];
c[3]=a[3]; s[3]=c[3]+c[2];
c[4]=a[4]+a[3]+a[2]+a[1]; s[4]=c[4];
c[5]=a[5]; s[5]=c[5]+c[4];
c[6]=a[6]+a[5]; s[6]=c[6]+c[4];
c[7]=a[7]; s[7]=c[7]+c[6]+c[4];
c[8]=a[8]+a[7]+a[6]+a[5]a[4]+a[3]+a[2]+a[1]; s[8]=c[8];
c[9]=a[9]; s[9]=c[9]+c[8];
5. 计算每个s[i]的复杂度是O( log2(n) ).
6. 代码:
#include <stdio.h>
#include <string.h>int a[101];
int c[101];
int s[101];int lowbit(int x)
{return x&(-x);
}int sum(int x)
{int s=0;while(x>0){s+=c[x];x=x-lowbit(x);}return s;
}int main()
{int i, j, k;for(i=1; i<=10; i++)a[i]=i;//创建a[]数组for(i=1; i<=10; i++){//计算每个c[i]c[i]=0;//c[i]从初始为0for(j=i-lowbit(i)+1; j<=i; j++){c[i]+=a[j];}}for(i=1; i<=10; i++){s[i]=sum(i);//计算i的前缀数组和}return 0;
}