[树状数组]

树状数组

概念

树状数组,依旧是一个线性数组构成,但是其性质却如同树结构一样是立体的。如图所示

可以发现:c[1]=a[1];c[2]=a[1]+a[2];c[3]=a[3];c[4]=c[2]+a[3]+a[4]=a[1]+a[2]+a[3]+a[4];c[5]=a[5];c[6]=a[5]+a[6];c[7]=a[7];c[8]=c[4]+c[6]+a[7]=a[1]+a[2]+...+a[8]。

性质

对于\(c[i]\),他的值为从\(a[i-k+1]\)\(a[i]\) 的和。其中\(k\)\(i\)里面 2的最大次幂因子

例如,6中2的最大次幂因子为2,故 \(k=2\),\(c[6]\)的值为从\(a[5]\)\(a[6]\)

8中2的最大次幂因子为8,故\(k=8\)\(c[8]\)的值为从\(a[1]\)\(a[8]\)

构建

构建的话主要是获取\(k\)的值,而\(k\)可以通过一行代码来实现

int lowbit(int x)
{
  return x & (-x);
}

那么\(c\)数组的值就可以由这个来更新

void add(int x,int k)
{
    while(x <= n)
    {
      c[x] += k;
      x += lowbit(x);
    }
	return ;
}

查询(求和)

同理也可以用上面的方法查询

int sum(int x)
{
	int res = 0;
	while(x > 0)
	{
		res += c[x];
		x -= lowbit(x);
	}
	return res;
}

如果想要知道\([L,R]\)区间的值,就可以写\(sum(R)-sum(L-1)\)

posted @ 2019-03-01 20:19  -凨-  阅读(388)  评论(0)    收藏  举报