ツリー配列【テンプレート】


ツリー配列(BIT)は、下記の動作を行うことができるデータ構造である.
  • 所与i,計算a 1+a 2+...ai
  • はiとxを与え、ai+=x
  • を実行する.
    任意の区間の和は、プレフィックスおよび思想を用いて計算され得る.
    詳細解説は「チャレンジプログラム設計(第2版)」P 175を参照してください.
  • 計算ノードの親ノード
  • 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:
    ",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
    ",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; }