【树状数组】
问题的提出:是否可以用线性数据结构的方法解决动态统计子树权和的问题呢? 有的,树状数组。
假设当前数组为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]从初始为0 for(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; }