Блог пользователя Jajceslav

Автор Jajceslav, история, 3 месяца назад, По-английски

Fenwick Tree in 5 minutes

Fenwick tree is a dynamic prefix sums array. You can:

  • Add values to elements in $$$O(\log N)$$$
  • Get prefix sum in $$$O(\log N)$$$

Structure

Fenwick tree is a single array. Each element $$$i$$$ has sum of elements on some range. Each range ends in its element, but they have different sizes.

Here's how the segments look for each element:

See a pattern? Sizes of ranges go like $$$1, 2, 1, 4, 1, 2, 1, 8, \dots$$$

How do we get size of range for element $$$i$$$?

Answer

So each element in fenwick array will keep the sum of its segment. Initially the array is filled with zeroes.

Adding Values

What happens when you add $$$x$$$ to element at position $$$i$$$? You need to increment $$${tre}[i]$$$ by $$$x$$$. But also, you need to update other ranges that contain this position. How do we find them?

Answer

To find such index we'll use some binary magic. Try to figure this out for yourself.

Answer

Getting Prefix Sum

To get prefix sum of first $$$i$$$ elements, we'll start at position $$$i-1$$$. We'll take the sum on the range for that index, and jump to the next index.

To do that, we simply subtract the range size. But, there is a cleaner solution, using bitwise magic again.

Answer

Time Complexity

As i said at the start, time complexity for both operations is $$$O(\log N)$$$. Why?

  • For addition, every iteration turns one bit into a one. So number of iterations is at most number of bits, which is $$$O(\log N)$$$.
  • For sum, every iteration increases the size of the segment of ones. So number of iterations is also at most number of bits. $$$O(\log N)$$$

Full Code

const int MAXN = 200005;

struct fenwick
{
    int tre[MAXN];
 
    fenwick() {}
 
    inline void clear(int n)
    {
        for(int i = 0; i < n; i++)
        {
            tre[i] = 0;
        }
    }
 
    inline void add(int i, int x)
    {
        for(; i < MAXN; i |= (i+1))
        {
            tre[i] += x;
        }
    }
 
    inline int sum(int r)
    {
        r--;
        int res = 0;
        for(; r >= 0; r = (r & (r+1))-1)
        {
            res += tre[r];
        }
        return res;
    }
};

Conclusion

Fenwick tree is used to keep a dynamic prefix sums array with every operation being $$$O(\log N)$$$.

Can it be used for other prefix values, like minimum or maximum?
What about segment trees?
Can i get a Bolba?
  • Проголосовать: нравится
  • +56
  • Проголосовать: не нравится

»
3 месяца назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

Auto comment: topic has been updated by Jajceslav (previous revision, new revision, compare).

»
3 месяца назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

Auto comment: topic has been updated by Jajceslav (previous revision, new revision, compare).

»
3 месяца назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

"Segment trees are far more versatile, but the implementation for fenwick tree is much simpler and faster."

True, but the implementation for iterative segtree is is also very concise.

Here is mine:

const int MAXN = 500005;
int tre[MAXN * 2];
int query(int left, int right){
    int total = 0;
    for(left += MAXN, right += MAXN; right > left; left /= 2, right /= 2) {
        if(left & 1) total += tre[left++];
        if(right & 1) total += tre[--right];
    }
    return total;
}
void update(int index, int val) {
    tre[index + MAXN] = val;
    for(int i  = (index + MAXN) / 2; i > 0; i/=2) tre[i] = tre[i * 2] + tre[i * 2 + 1];
}

Fenwick trees are also pretty cool :)

»
3 месяца назад, скрыть # |
 
Проголосовать: нравится +16 Проголосовать: не нравится

For add function, I use i+=i&-i, and for the sum function I use r-=r&-r. Much simpler as its the same thing for both just with direction changing.

»
3 месяца назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

You should add time complexity for creating a fenwick tree too.

»
3 месяца назад, скрыть # |
Rev. 2  
Проголосовать: нравится +8 Проголосовать: не нравится

orz blog tysm, can u do smth abt binary search tree later or segment tree