蓝桥杯备赛--带你入门树状数组

概念

树状数组是用数据压缩的思想由二进制实现的数据结构。有单点修改+区间查询或区间修改+单点查询的作用。
A[]为一维数组,C[]为树状数组
蓝桥杯备赛--带你入门树状数组_第1张图片
由图可知:

	C[1] = A[1]
	C[2] = A[1]+A[2]
	C[3] = A[3]
	C[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] = A[1]+A[2]+A[3]+A[4]+A[5]+A[6]+A[7]+A[8]
	C[N] = A[N-2^K+1] + A[N-2^K+2] + ····· + A[N]   (K为N的二进制数的最低1前0的个数,如1000,则K为3)

可以明显看出,在数据量大时,树状数组求和更快,对于长度为n的数组,求和的时间复杂度为o(logn)。
那么如何构建树状数组呢?下面就需要引入lowbit()函数。
lowbit()函数求得下一步要去哪里

// x 为数组下标
int lowbit(int x) {
     
	return x & -x;
}

lowbit()函数实际上就是求最低位1的位置,如x = 110,-x = 010, 再求与得 010,说明最低位在第2位,K = 2,即下一层是在第二层,就可以开始一层一层构建树状数组了!

下面引入add()函数来构建树状数组。

// x为插入值,y为当前索引号,n为数组长度
void add(int x, int y, int n){
     
	for (int i = y; i <= n; i += lowbit(i)) c[i] += x;
}

看不懂没关系,我们来举个例子演示一下。
比如现在要在长度为4的数组的第一位中插入1,即add(1,1,4)
蓝桥杯备赛--带你入门树状数组_第2张图片

再向长度为4的数组的第二位插入1,即add(1,2,4)。
蓝桥杯备赛--带你入门树状数组_第3张图片
再向长度为4的数组的第三位插入1,即add(1,3,4)。
蓝桥杯备赛--带你入门树状数组_第4张图片
这样大概明白了吧。
而求和与add()函数类似,只是方向相反。

// 求 1 ~ x 的和
int getSum(int x){
     
	int ans = 0;
	for (int i = x; i; i -= lowbit(i)) ans += c[i];
	return ans;
}

例题:

  • 树状数组模板1
  • 树状数组模板2

你可能感兴趣的:(数据结构与算法,算法,c++,acm竞赛)