Step 1. Cell i already gives us the last block: ∑k=i−lowbit(i)+1iak.
Why? That's literally its definition.
Step 2. What's left is prefix(i−lowbit(i)) — the part before that block.
Why? Removing the lowbit-sized chunk leaves us needing the prefix up to a smaller index.
Step 3. Recurse: keep adding tree[i] and stripping the lowest bit until i=0.
Why this terminates fast? Each step removes one set bit from i, so it runs at most (number of set bits) ≤log2n times.
prefix(i)=∑tree[i],i←i−lowbit(i)until i=0
def query(tree, i): # prefix sum a[1..i] s = 0 while i > 0: s += tree[i] i -= i & (-i) # strip lowest set bit return s
Adding δ to aj must fix every cell whose block contains index j.
Step 1. Cell j contains aj (its block ends at j). Add δ there.
Step 2. The next cell up that contains j is at index j+lowbit(j).
Why? The next larger block that still includes j starts at the same left edge but extends further; its index is j plus its own lowbit, which equals j+lowbit(j) by the nesting structure of these blocks.
Step 3. Repeat while j≤n.
update: tree[j]+=δ,j←j+lowbit(j)until j>n
def update(tree, n, j, delta): # a[j] += delta while j <= n: tree[j] += delta j += j & (-j) # go to next responsible cell
Linear build (the 80/20 trick): initialize tree[i] = a[i], then for each i from 1 to n, push your block sum into your parent: if i+lowbit(i) <= n: tree[i+lowbit(i)] += tree[i]. Why? Each cell first becomes complete, then donates its block to the next responsible cell — one pass, O(n).
What does Fenwick cell tree[i] store?
The sum of a[i-lowbit(i)+1 .. i], a block of length lowbit(i) ending at i.
How do you compute lowbit(i)?
i & (-i), the value of the lowest set bit (uses two's-complement negation).
Query (prefix sum) loop direction?
Add tree[i], then i -= i & (-i), until i == 0 (move DOWN).
Update (point add) loop direction?
Add delta to tree[j], then j += j & (-j), while j <= n (move UP).
Time complexity of update and query?
O(log n) each, since each step changes one bit of the index.
How to get range sum [l, r]?
query(r) - query(l-1).
Why must a Fenwick tree be 1-indexed?
lowbit(0)=0, so loops at index 0 never progress; index 0 has no lowest set bit.
How many cells contain a given element index j?
O(log n) — the chain j, j+lowbit(j), ... up to n.
What is the O(n) build trick?
tree[i]=a[i]; then for each i, if i+lowbit(i)<=n: tree[i+lowbit(i)] += tree[i].
Plain prefix-sum array's weakness that Fenwick fixes?
O(n) per update; Fenwick makes update O(log n) while keeping fast queries.
Recall Feynman: explain to a 12-year-old
Imagine numbered boxes in a row. Instead of asking each box one by one to add a total (slow), some special boxes keep a running subtotal of a chunk of boxes before them. The chunk size is decided by a number trick: look at the rightmost 1 in the box's number written in binary — that tells you how many boxes it summarizes. To get "total up to box 6," you only visit a couple of these subtotal boxes and add them — like grabbing two pre-packed bundles instead of counting candies one by one. To change one candy count, you only fix the few bundles that contain it. Either way: just a handful of steps, never the whole row.
Fenwick tree ka basic problem ye hai: agar tum ek simple array rakho toh element update karna fast (O(1)) hai par prefix sum nikalna slow (O(n)) hota hai. Aur agar precomputed prefix-sum array rakho toh query fast hai par update slow. Fenwick tree dono ko balance karke O(log n) mein le aata hai — ek hi array se.
Asli trick hai lowbit, yaani i & (-i) — ye number ke binary representation ka sabse last waala set bit deta hai. Har Fenwick cell tree[i] apne se pehle ke lowbit(i) elements ka sum store karta hai, jis ka block i par khatam hota hai. Isliye chhota ya bada block, sab power-of-two size ke hote hain, aur kisi bhi prefix ko sirf thode se blocks se cover kar sakte ho.
Do main operations yaad rakho: query (prefix sum) neeche jaata hai — i -= i & (-i) karke 0 tak, sum jodte jao. Update upar jaata hai — j += j & (-j) karke n tak, har responsible cell mein delta add karo. Dono mein sirf jitne set bits utne steps, isliye O(log n). Mnemonic: "Query Quits Down, Update Ups."
Ek important baat: Fenwick tree hamesha 1-indexed rakho, kyunki lowbit(0) = 0 hota hai aur loop kabhi aage nahi badhega. Range sum [l, r] ke liye query(r) - query(l-1) use karo — l-1 isliye kyunki index l ko bhi count karna hai. Inversion counting, competitive programming mein ye structure bahut kaam aata hai, simple aur fast hone ki wajah se.