树状数组【模板】

树状数组(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
#include
#include
#include
#include
#include
#include
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;
}


你可能感兴趣的:(数据结构~树状数组)