一个一维数组tree[]
其中tree[i]表示
[i-(i&(-i))+1,i]这个区间内a数组元素的和
想求a[1]~a[15]的值?
15=(1111)2
tree[15]=sum[15,15]
tree[14]=sum[13,14]
tree[12]=sum[9,12]
tree[8]=sum[1,8]
sum[1,15]=tree[8]+tree[12]+tree[14]+tree[15]
执行的次数和二进制中‘1’的位数有关
定义lowbit()
int lowbit(int x)
{ return x&(-x); }
lowbit效果
取出x二级制最末尾的一个1
更新单点的值
void update(int loc,int val)
{
for(int i = loc; i <= maxn; i += lowbit(i))
{
Tree[i] += val;
}
}
查询
int query(int loc)
{
int ans = 0;
for(int i = loc; i >= 1; i -= lowbit(i))
{
ans += Tree[i];
}
return ans;
}
树状数组如何区间更新(区间[l, r]内所有数加上value),单点求值(求位置loc当前的值是多少)
树状数组维护一个新的数组,b[1]~b[N],b[1]等于a[1], b[i] = a[i] - a[i - 1]
区间[l, r]更新,update(l, value), update(r + 1, -value)
单点求和query(loc)
假设现在有一个原数组a(假设a[0] = 0),有一个数组d,d[i] = a[i] - a[i-1],那么
a[i] = d[1] + d[2] + .... + d[i]
d数组就是差分数组
所以求a[i]就可以用树状数组维护d[i]的前缀和
区间修改,单点查询:
根据d的定义,对[l,r]区间加上x,那么a[l]和a[l-1]的差增加了x,a[r+1]与a[r]的差减少了x,所以就对差分数组的前缀和进行修改
设c是差分数组的前缀和