Data Structure - Fenwick tree

1. Fenwick tree

Similar data structure: segment tree (Segment Tree)

Fenwick tree with the tree line difference:

  • Fenwick tree can do, segment tree can do! (Tree line features more cattle)
  • Fenwick tree code is simple, easy to implement than the segment tree (tree code simpler array)

Query and modify complex array of tree are log ( n ) \log(n)

Here Insert Picture Description

  • A former array is
  • Fenwick tree is C
C1 = A1
C2 = C1 + A2 = A1 + A2
C3 = A3
C4 = C2 + C3 + A4 = A1 + A2 + A3 + A4
C5 = A5
C6 = C5 + A6 = A5 + A6
C7 = A7
C8 = C4 + C6 + C7 + A8 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8
  • To C8 (2 binary 8 is 1000, there are three behind 0, so he was in possession with the number 3 C4、C6、C7, as well as their own A8)
  • No end of odd 0, so odd bit only their own
  • Then how to calculate the number of tubes with a few numbers it?

2. Single point query, modify a single point

Tree array core function lowbit(int m): the role of obtaining a position m 1 binary representation of the end, to query for the prefix and m, m = m - lowbit(m)on behalf of the end of the continuous binary 1 1 operation continuously performed until m == 0 completed, can be obtained which is composed of a prefix and a few Cm

int lowbit(int m){
    return m & (-m);//(获取最后一个1的10进制值)
}
int getsum(int i){    //求A[1],A[2],...A[i]的和
    int res = 0;
    while(i > 0){
        res += c[i];
        i -= lowbit(i);
    }
    return res;
}

Eight ( 1000) to count follows:
NOTE: negative binary numbers are positive end negated +1

8 & (-8) = 1000 & (.111..1000) = 1000 = 8....8-8=0,sum=C8=A[1]+..A[8]
-------------
6 & (-6) =  0110 & (1010) = 10 = 2 .... 6-2=4,sum=C6
4 & (-4) = 0100 & (1100) = 100 = 4.....4-4=0,sum+=C4=C6+C4=A[1]+...A[6]
-------------
奇数上面操作结果均为 1
#include <bits/stdc++.h>
using namespace std;

int n = 8;
int a[9]={-1,1,2,3,4,5,6,7,8}, c[9] = {0}; //对应原数组和树状数组

int lowbit(int x){
    return x&(-x);
}

void update(int i, int delta){    //在i位置加上delta
    while(i <= n){
        c[i] += delta;
        i += lowbit(i);
    }
}

int getsum(int i){    //求A[1],A[2],...A[i]的和
    int res = 0;
    while(i > 0){
        res += c[i];
        i -= lowbit(i);
    }
    return res;
}

int main(){
    for(int i = 1; i < 9; ++i)
        update(i,a[i]);//读取原数据,插入树状数组
    cout << getsum(3) << endl;//获取前3个数的和
    cout << getsum(8) << endl;
    update(3,2);
    cout << getsum(3) << endl;
    cout << getsum(8) << endl;
    cout << getsum(4)-getsum(2) << endl;//获取A[3],A[4]的区间和
    return 0;
}

result:

6
36
8
38
9

3. Single point query, modify the interval

After the update learning.

Reference :

Published 799 original articles · won praise 1360 · Views 350,000 +

Guess you like

Origin blog.csdn.net/qq_21201267/article/details/105252368
Recommended