树状数组(BIT)是能够完成下述操作的数据结构。
- 给定i,计算a1+a2+...ai
- 给定i和x,执行ai+=x
可以利用前缀和的思想计算任意区间的和。
详细讲解参考《挑战程序设计(第2版)》P175
- 计算节点的父节点
int lowbit(int x)
{
return x&(-x);
}
- 修改节点
void add(int i,int x)
{
while(i<=n)
{
bit[i]+=x;
i+=lowbit(i);
}
}
void sub(int i,int x)
{
while(i<=n)
{
bit[i]-=x;
i+=lowbit(i);
}
}
- 求和
int sum(int i)
{
int s=0;
while(i>0)
{
s+=bit[i];
i-=lowbit(i);
}
return s;
}
例题:HDU - 1166
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<stack>
#include<stdlib.h>
#include<ctype.h>
using namespace std;
#define LL long long
#define MAXN 50005
#define inf 1<<29
int bit[MAXN],n,a[MAXN];
int lowbit(int x)
{
return x&(-x);
}
void add(int i,int x)
{
while(i<=n)
{
bit[i]+=x;
i+=lowbit(i);
}
}
void sub(int i,int x)
{
while(i<=n)
{
bit[i]-=x;
i+=lowbit(i);
}
}
int sum(int i)
{
int s=0;
while(i>0)
{
s+=bit[i];
i-=lowbit(i);
}
return s;
}
int main()
{
int t;
scanf("%d",&t);
for(int tt=1;tt<=t;tt++)
{
printf("Case %d:\n",tt);
scanf("%d",&n);
memset(bit,0,sizeof bit);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
add(i,a[i]);
}
char str[10];
while(scanf("%s",str) && str[0]!='E')
{
if(str[0]=='Q')
{
int u,v;
scanf("%d%d",&u,&v);
printf("%d\n",sum(v)-sum(u-1));
}
else if(str[0]=='A')
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
}
else if(str[0]=='S')
{
int u,v;
scanf("%d%d",&u,&v);
sub(u,v);
}
}
}
return 0;
}
本文详细介绍树状数组(Binary Indexed Tree, BIT)这一高效数据结构。通过具体实例讲解了如何利用树状数组进行区间求和及单点更新操作,并提供了一个完整的编程实现示例,帮助读者更好地理解和掌握树状数组的使用。

2422





