目录
制作不易,点个赞再走呗
什么是树状数组
树状数组(Binary Index Tree, BIT)是很多竞赛队员心中最简洁优美的数据结构之一。最简单的树状数组支持两种操作,时间复杂度均为 O(logn) :
单点修改: 更新指定点的数据
区间查询: 查询指定区间内的数据的和
当然,树状数组的作用远不止这些,这里只讨论基本的数据结构。但是树状数组的操作比较局限,虽然代码比线段树少,但却没有线段树进行的操作多,我也写过一个线段树的博客,有兴趣的可以了解一下
结合模板题更好理解该算法:
树状数组的作用
先了解树状数组是怎样的
想必大家也不愿意看那些一大串的文字,那么我就用图来讲解。

这样写描述是不是更加直白一些了。
了解到了图形的结构,那么我们就来探讨一下怎么构造这个结构。
因为我们是通过二进制来进行构造结构的,又通过图形,我们知道了我们想求哪一层就需要找到那个最小位的那个1是在哪个位置,这是我们需要应用一个函数 (lowbit 函数), 通过这个函数我们可以求得最小位那个1是在哪个位置。
代码实现:
int lowbit(int x)
{
return x&-x;
}
浅谈一下为什么 x&-x 可以实现找到最后一位:
-x在二进制中可以表示补码,而补码就是原码取反再加一

那么取 x&-x 就可以求得最小位置的那个1。
单点修改
有同学可能会问了,为什么没有建树这以环节,那当然是因为,这个树不用建,只需要一一对应修改就好了,这就是为什么叫树状数组,而不叫树。
int tree[N];
int lowbit(int x)
{
return x&-x;
}
void add(int x,int k)
{
for(int i = x; i <= n; i+=lowbit(i)) tree[i] += k;
}
区间查询
int lowbit(int x)
{
return x&-x;
}
int sum(int x)
{
int res = 0;
for(int i = x; i ; i -= lowbit(i)) res += tree[i];
return res;
}
这个就好理解了,就是将tree前面对应的阶段对应的所有值加在一起,返回一个求1-x 的值。
那么我们就可以用 s[1,r] - s[1,l-1] 求得 s[l , r] 的和。
代码实现树状数组
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 500005;
int arr[N];
int tree[N];
int n,m;
int lowbit(int x)
{
return x&-x;
}
void add(int x,int k)
{
for(int i = x; i <= n; i+=lowbit(i)) tree[i] += k;
}
int sum(int x)
{
int res = 0;
for(int i = x; i ; i -= lowbit(i)) res += tree[i];
return res;
}
int main ()
{
cin >> n >> m;
for(int i = 1; i <= n; i++)
{
scanf("%d",&arr[i]);
add(i,arr[i]);
}
for(int i = 1; i <= m; i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(a == 1)
{
add(b,c);
}
else {
printf("%d\n",sum(c)-sum(b-1));
}
}
return 0;
}
树状数组是一种高效的数据结构,支持单点修改和区间查询操作,时间复杂度为O(logn)。它基于二进制构造,利用lowbit函数找到最小位的1,实现快速更新和查询。文章通过代码示例解释了如何实现树状数组以及如何进行操作。
911





