Each single cell (shown as an empty square on each row) is an array item, indexed from [1, n]. Each vertical bar (striped part + non-striped top cell) is an index range.
Index Ranges and Responsibility:
Each index range is named after it’s top cell, and its responsibility is given by the last -digit (and following
s). Range
has responsibility
, meaning it covers from
down to
. In other words, take the last
and move it to the end e.g.
to
,
to
,
to
.
Then, to add into any range, start by adding to each index range that lies completely within the add range. To add to
, well, that’s covered completely by
itself, so
gets added to range
, fini. To add
to
, that’s covered by
. The latter —
— is not a valid range! How’s that handled?
Index Values Too
Each item in the structure is both a range and an individual item, and its actual value is a sum of this item along with all responsible (covering) ranges. E.g. the value of item is its individual value + range values
. (Draw a line from the item straight left and see which ranges are hit.)
So, to answer the previous question, when we encounter our invalid range we simply add our value to item
itself; that’s the best we can do.
This implementation is suitable for:
– adding values to all indices across a range
– setting individual values
– querying individual values
Not suitable for:
– querying sum totals across a range
Interface:
int64 get(id)
void set(id, int64 value)
void add(ida, idb, int64 value)
Reference: TopCoder – Binary Indexed Trees
N.B. This reference enables a cumulative-sum query from individual inserts/additions. My implementation flips this, enabling addition to entire ranges with querying kept to individual values. (I’ll work on the former soon.)
My implementation is in git and below: