4

I read 2 - 3 tutorials of binary indexed tree(AKA Fenwick tree) on internet, but I didn't understand what it actually does and what is the idea behind BIT. The tutorial that I read is

Please help me to make me understand about BIT.

6
  • 5
    This kind of question is not well suited to SO's Q&A format. If you have failed to understand the tutorials you've already read, I despair of explaining this to you. What I suggest you do, though, is to write a program to implement a binary index tree. Programming is not a spectator sport, learning by doing is an excellent way of learning. As you write the code, continually ask yourself not just what the code is doing, but why. Commented Aug 3, 2012 at 10:37
  • ok, I try to make code using that tutorial, but without having feel of any concept, codding becomes boring, that's why I posted this question Commented Aug 7, 2012 at 1:36
  • 2
    This is not a good idea, programming without understanding what to do. Totally wrong in case of BIT. Such structures are abstract nit like UI devlopping which prototyping helps. Commented Feb 18, 2013 at 19:40
  • 2
    @FreakyCheeky the site you are pointing to looks simple enough and provide more than enough information. You should start by describing which specific part of it is hard to understand. It seems to me that not enough effort/time was put into trying to actually understanding it. Commented Feb 18, 2013 at 19:42
  • @mmgp I do not agrre, the introduction is not well explained. The details are better explained. You should try to get other articles, too. (Probably) the original Commented Feb 18, 2013 at 19:50

4 Answers 4

7
+25

The top coder article is not so clear. Here is the big idea that may get you started.

BITs are good for storing dense maps from integers to integers f[i], where i >= 1 and you are interested in retrieving sums over ranges of the map domain, i.e. sum_{i = a..b} f[i] for arbitrary a and b. If you were coding in C this would be:

sum = 0; for (i = a; i <= b; i++) sum += f[i];

By dense I mean f[i]>0 for most i. If you have a sparse map, other data structures are better.

BITs let you speed up this computation so that the run time of the sum - rather than being proportional to b - a - is instead proportional to log(b+a). Time to insert a new element is similar.

To do this, the BIT stores a different map g[k] rather than f[i]. The contents of g are defined in a clever way.

g[k] = sum_{i = k - d + 1 .. k} f[i]  

where d is the value of k with all but the lowest order bit set to zero. For example, if k=8, then d=8. If k=14, then d=2, etc.

Note there is no explicit tree. The tree is logical as shown in the tutorial pictures. The only storage is the array g.

Why is this a good idea? It turns out that to find sum_{i = a..b} f[i], you need only sum up at most 2 ceiling(log(b+a)) elements of g. These elements can be determined by analyzing the binary 1 bits of a and b. The details are shown in the tutorials.

The simplest example: if you want sum_{i = 1..p} f[i], then construct the series of indices p_1, p_2, ... p_n where p_1 = p and p_(i+i) is formed by removing the lowest order 1 bit from p_i. Therefore n is one less than the number of 1's in the binary representation of p. Now just compute

sum_{k = p_1, p_2 ... p_n} g[k]

If you experiment and think about this a bit (pun intended) you'll see why it works.

Sign up to request clarification or add additional context in comments.

5 Comments

I understand the whole algorithm after reading your answer and topcoder blog number of times. But my question is how this tree works , from where the idea comes, I want to know the basic idea behind this data structure.
And another question, what is the complexity to build tree array in the starting ?
And on same page there is one question(problem 2) regarding cards. Please explain that also. how they proceed using BIT ?
@devsda Data structures don't always have an intuitive picture. The idea is that you cover the set with precomputed interval sums in a clever way so that for any given input range the right set of interval sums to add up is both small and easy to determine. The "small" comes from the balanced tree structure. The "easy to determine" comes from mapping the intervals to index bits. What do you think the complexity is?
For odd indexs, it is constant time, O(1), and for even it is the sum of some indexes. So according to my understanding it is O(N). Am I right ?
2

Binary indexed tree also known as Fenwick tree, i think binary indexed tree is less known as compared to Fenwick tree, so when we find for binary indexed tree we find less material, but this is just my feeling!

In simple words, Fenwick tree (aka Binary indexed tree) is a data structure that maintains a sequence of elements, and is able to compute cumulative sum of any range of consecutive elements in O(logn) time. Changing value of any single element needs O(logn) time as well. The structure is space-efficient in the sense that it needs the same amount of storage as just a simple array of n elements.

A practical example to illustrate above can be found at various places over net, i.e.

http://codeforces.com/blog/entry/619

http://michaelnielsen.org/polymath1/index.php?title=Updating_partial_sums_with_Fenwick_tree

And there are lot more example over net...

Comments

1

A binary index tree is a data structure allowing retrieval of a value by its prefix. My understanding of binary index trees is that they are more or less analogous to tries. For example, lets say you have three numbers 1323, 1697 and 1642. You could store the numbers in a tree:

1-3-2-3  
 -6-9-7  
   -4-2

where each node represents a 10s place. Now you can look up any number like you can look up a name in a telephone directory, letter by letter. Here, each node is by 10s, but you can choose a different base to make the representation as compact as possible. For example, you might use base 8 in which case each node stores 4 bits.

This data structure allows you to add numbers easily. For example, lets say you want to add numbers #1 (1323) and #3 (1642). Then you start at the leaf representing each number and work upward, multiplying by a power of the radix (here 10) as you go: 3+2, then (2+4)*10, then (6+3)*100, then (1+1)*1000.

Comments

0

BIT is a very fancy thing, the key to understand it is knowing how quick-segment algorithms work.

The very basic idea of a quick-segment algorithm & data structure is to 'skip' something.Think about a array a[1..n] of integers.Now you want yet another array C[1..n],in C[i] contains the sum of C[i],C[i-1] to C[k(i)](k is some sort of magic function (O-O) ).

When you want to get the sum of a[1..i], you can write:

    int get_sum(int i) {
        if (i == 0)
            return 0;
        return get_sum(k(i)-1)+C[i];
    }

It is quite simple to understand yeh? We just use C[i] = sum(a[k(i)..i]) instead of going though the whole segment.And when we want to change some element, we use a array called 'add(pos, i)' means add i in a[pos]:

(k'(x) is a function returns the smallest y >= x that k(y) <= x)

    void add(int pos, int i) {
        if (pos <= n) {
            C[pos] += i;
            add(k'(pos), i);
        }
    }

The core of the code is also 'skip'.It is clear that C[k'(pos)] is the smallest element whose 'control segment(C[k(i)..i])' contains C[pos].We only update the elements that is bound up with C[pos] instead of dealing with all of the elements.

Now the question changed into : 'Finding out a suitable k(x) & k'(x) to finish the code'. k(x) = x-sqrt(n) is a simple function,with it the operation above is O(sqrt(n)). Well a better choice is the function BIT(i).

BIT(i) is to count the first '1' in the binary of i, something like:

    (110100)2 --BIT--> (100)2
    (111)2    --BIT--> (1)2
    (100000)2 --BIT--> (100000)2

A quick way to calculate BIT is using binary operators:

    BIT(x) = x & ((~x) + 1)

Let us suppose x = (101100)2, ~x = (010011)2, (~x)+1 = (010100)2, x & ((~x) + 1) = (000100)2. It really work! (~x)+1 makes all of the bits except BIT(x) be opposite, and the '&' clear the useless bits.

Because of -x = (~x)+1 (See how negative integers is turned into binary) BIT(x) = x & (-x)

Now we get a powerful function. I give the method without explaining(It's better for you to understand them by yourself):

    k(i) = i-BIT(i)+1
    k'(i) = i+BIT(i)

Try to use the k & k' to see the code above.

[Graph][https://i.sstatic.net/j5z5e.png]

Graph is from the Internet

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.