データ構造--ツリー配列

3991 ワード

Feature
To deal with dynamic continuous and query problem, and for a given array: $A_1, A_2,\dotsc A_n$, we're asked to support these two operations:
  • let $A_x$ increase $d$
  • calculate $A_L+A_{L+ 1}+\dotsc +A_R$

  • To make our algorithm cost less time, we introduce (Binary Indexed Tree, BIT). Before we introduce the concept of the BIT, we need to discuss lowbit
    Lowbit
    It's the number that is represented by the rightmost "1".
    Property
    If $i$ is left child, then it's father's index is $i+lowbit(i)$, and right child is correspond to $i-lowbit(i)$.
    If we set the nodes by set the same lowbit of their index at the same height layer, we can gain a beautiful binary tree.
    Calculate Lowbit With Bit-operation
    $lowbit(x)= x\& -x$
    Important Auxiliary Array
    $C_i= A_{i-lowbit(i)+1}+A_{i-lowbit(i)}+\dotsc +A_i$
    Take picture lowbit tree 2 for example$C_i$ represents the sum of the red line which contains the index $i$. For example, $C_{12}$ is the sum of the red line, and this red line contain $A_9, A_{10}, A_{11}, A_{12}$.
    Use $C_i$ Calculate The Sum Of Prefix
    "Climb the tree". Here are the rules.
  • Begin from the end of the prefix sum.
  • Find the higher node which has smaller index.
  • Find the nearest node which satisfy the second rules.
  • Sum the $C_i$ up along the way you climb.

  • Update $C_i$ If Some $A_j$ Changes
    "Climb the tree". Here are the rules.
  • Begin from the changed point.
  • Find the higher node which has bigger index.
  • Stop at the highest node of the current BIT.
  • Change the $C_i$ you met along the way you climb.

  • Code
    int C[MAX_N+1], n;       //n represent the length of A
    int Sum(int i)
    {
        int s= 0;
        while (i> 0){
            s+= C[i];
            i-= i& -i;
        }
        return s;
    }
    void Add(int i, int x)
    {
        while(i<= n){
            C[i]+= x;
            i+= i&-i;
        }
    }

    2-D BIT
    The second dimension is a bit whose nodes' element is also a BIT.
    OJ Practise
    POJ 1656
    My first code, it's still use the idea of 1-D BIT and it doesn't have a high efficiency.
    #include 
    #include 
    #include 
    #include 
    
    const int wd= 101;
    
    int bo[wd][wd];
    int C[wd][wd];
    
    inline int Lowbit(int x){
        return x & (-x);
    }
    int Sum(int x, int y)   //(x, y)
    {
        int s= 0;
        while (y>0){
            s+= C[x][y];
            y-= Lowbit(y);
        }
    
        return s;
    }
    void Add(int x, int y, int d)
    {
        while (y< wd){
            C[x][y]+= d;
            y+= Lowbit(y);
        }
    }
    void BUpdate(int x, int y, int L)
    {
        for (int i= x; i

    This has $O(\log (N)\times\log (W))$ time. $N\& W$ is the length and the width of the rectangle.
    #include 
    #include 
    #include 
    #include 
    
    const int wd= 101;
    
    int bo[wd][wd];
    int C[wd][wd];
    
    inline int Lowbit(int x){
        return x & (-x);
    }
    int Sum(int x, int y)   //(x, y)
    {
        int s= 0, tpy;
        while (x>0){
            tpy= y;
            while (tpy>0){
                s+= C[x][tpy];
                tpy-= Lowbit(tpy);
            }
            x-= Lowbit(x);
        }
    
        return s;
    }
    void Add(int x, int y, int d)
    {
        int tpy;
        while (x