Note that in addition to range sum, we can also use BIT to calculate range multiplication, range xor, range maximum number, range minimum number etc.
Binary Indexed
BIT nodes are indexed using the lowbit of their original index.
For those with lowest bits at index 0 (we count the bit index from the right), the value is directly saved into BIT. These are the leaf nodes of the BIT.
For those with lowest bits at index 1, they are located at the 2nd layer from the bottom. We not only add their own values to BIT, but also add their child values to it. Their child indices are one less than their own indices. For example, node[2] (00010) has node[1] (00001) as its child, so node[2] = A[2] + node[1] = 2 + 5 = 7
For those with lowest bits at index 2, they are located at the 3rd layer from the bottom. For example, node[4] (00100) has node[3] (00011) and node[2] (00010) as its direct children, so node[4] = A[4] + node[3] + node[2] = -3 + 9 + 7 = 13
Sum Query
To calculate sum(7) = A[1] + ... + A[7], we keep finding previous ranges by removing the lowbit from 7 = 111. So, sum(111) = node(111) + node(110) + node(100) = node[7] + node[6] + node[4]
Another example, sum(8) = sum(1000) = node(1000) = node[8]
Update
To add 10 to A[4], we need to update all the nodes containingA[4]. We find such nodes by adding lowbit. So, A[4] is contained by node[100] = node[4] and node[1000] = node[8].
Note
N + 1 elements.
When querying, keep REMOVING low bit. (find the previous intervals)
When updating, keep ADDing low bit. (updating the tree towards higher levels)
Implementation
// Author: github.com/lzl124631xclassBIT { vector<int> sum;staticinlineintlowbit(int x) { return x &-x; }public:BIT(int N) :sum(N +1) {}; // Add delta to A[i]voidupdate(int i,int delta) { // Note: this `i` is 1-based.for (; i <sum.size(); i +=lowbit(i)) sum[i] += delta; } // Return A[1] + ... + A[i]intquery(int i) { // Note: this `i` is 1-based.int ans =0;for (; i; i -=lowbit(i)) ans +=sum[i];return ans; } // Return A[i] + ... + A[j]intrangeQuery(int i,int j) { // Note: these `i` and `j` are 1-based.returnquery(j) -query(i -1); }};
// OJ: https://leetcode.com/problems/create-sorted-array-through-instructions/// Author: github.com/lzl124631x// Time: O(NlogM) where M is the range of A[i]// Space: O(M)// Ref: https://leetcode.com/problems/create-sorted-array-through-instructions/discuss/927531/JavaC%2B%2BPython-Binary-Indexed-Treeintc[100001] = {};classSolution {public:staticinlineintlowbit(int x) { return x &-x; }intcreateSortedArray(vector<int>& A) {memset(c,0,sizeof(c));int ans =0, N =A.size(), mod =1e9+7;for (int i =0; i < N; ++i) { ans = (ans +min(get(A[i] -1), i -get(A[i]))) % mod;update(A[i]); }return ans; }voidupdate(int x) {for (; x <100001; x +=lowbit(x)) c[x]++; }intget(int x) { // returns the sum of numbers <= xint ans =0;for (; x >0; x -=lowbit(x)) ans +=c[x];return ans; }};