树状数组是为了在数组元素更新后更快速的求某个区间的和
在使用如图所示的树状数组时,对于a[]数组并没有创建,而是只创建了c数组,c数组中的每个元素都有各自的管辖范围。
比如:c[1]=a[1];c[4]=a[1]+a[2]+a[3]+a[4];。。。
这里有一个主要的计算:x&(-x),这个表达式求的是x的最后一个1表示的值,比如:6的二进制表示为(0110),6&(-6)=2说这个主要是为了引出x +=x&(-x)和x -= x&(-x);
x +=x&(-x):这个就可以得到更新点的父节点编号,比如更新的点是2,x+=x&(-x)的值就是4。
x -=x&(-x):这个就是得到该点的管辖区间的上一个区间的管辖点,比如x的值为6,经过x -= x&(-x),x的值为4,可以对照示意图进行理解。
下面是一个使用树状数组的例题:http://codevs.cn/problem/1080/
#include<iostream>
#include<string.h>
using namespace std;
const int N = 100000+10;
int n, p[N];
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int val) //x为更新点的位置,val为要更新的值
{
while(x<=n)
{
p[x] += val;
x += lowbit(x);
}
}
int getSum(int x)
{
int sum=0;
while(x>0)
{
sum += p[x];
x -= lowbit(x);
}
return sum;
}
int main()
{
int val,m,x,y,z;
memset(p,0,sizeof(p));
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>val;
update(i,val);
}
cin>>m;
while(m--)
{
cin>>x>>y>>z;
if(x==1)
{
update(y,z);
}
if(x==2)
{
cout<<getSum(z)-getSum(y-1)<<endl;
}
}
return 0;
}