传送门 : 树状数组(这个博主写的不错点个赞)
假设数组a[1..n],那么查询a[1]+…+a[n]的时间是log级别的,而且是一个在线的数据结构,支持随时修改某个元素的值,复杂度也为log级别。
- C1 = A1
- C2 = A1 + A2
- C3 = A3
- C4 = A1 + A2 + A3 + A4
- C5 = A5
- C6 = A5 + A6
- C7 = A7
- C8 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8
… - C16 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8 + A9 + A10 + A11 + A12 + A13 + A14 + A15 + A16
看到以上的这些了,C代表节点,后面代表这个节点是那些数据的和。
那么到底是哪些的和是怎么来的呢?
节点数值转换成二进制后,末尾有k个0,就有2的k次方个数据的和。
例如:
C1节点数字为1,二进制是:0001,末尾没有0,就是2的0次方,就是1,也就是只有一个数据的和。C1 = A1
如果是C2节点,数字为2,二进制: 0010,末尾一个0,就是2的1次方,就是两个数据的和。 C2 = A1+A2.
依次类推。
==通过与运算得到C的数组下标==
C++的新用法还是挺方便的。。。。吼吼吼
#include<iostream>
#include<string>
using namespace std;
//树状数组
int lowbit(int x){
return x&(-x);
}
//节点数值转换成二进制后,末尾有k个0,就有2的k次方个数据的和。
int sum_n(int C[],int n)
{
int sum = 0; // 第一步定义和为0
while(n > 0)
{
sum += C[n]; // 第二步 在 n > 0的情况 加上第n个节点
n -= lowbit(n); //第三步 让n跳到上一个需要加的位置
}
return sum;
}
//
void update(int C[],int n,int pos, int newdata)
{
//如果更新第i个数据,让其 +1
while(pos <= n) //一共n个数据,第0号节点无数据,所以下标到n
{
C[pos] += newdata; // 更新数据
pos += lowbit(pos); // 下一个要更新的位置
}
}
int main()
{
int arrayInt[] = {1,2,3,4,5,6,7,8,9};
int C[] = {0,1,3,3,10,5,11,7,28,9};
for(auto i:C){
cout<<i<<"\t";
}
cout<<"The sum of 0-5 is "<<sum_n(C,5)<<endl;
update(C,sizeof(C)/sizeof(int),3,2);
cout<<"After update C[3]+2\n";
for(auto i:C){
cout<<i<<"\t";
}
return 0;
}
/*
0 1 3 3 10 5 11 7 28 9
The sum of 0-5 is 15
After update C[3]+2
0 1 3 5 12 5 11 7 30 9
Process returned 0 (0x0) execution time : 0.030 s
Press any key to continue.
*/