The two cheapest range techniques, and the first things to try. Full detail in Prefix Sum and Difference Array; this page is the decision guide.

The duality

Prefix sumDifference array
Fast operationrange queryrange update
Slow operationupdate ()query ()
Build
Finalise prefix pass
Best whenall updates precede all queriesall updates precede all queries (the other way round)

They are inverse transforms of each other: prefix-summing a difference array recovers the original.

The four combinations

UpdatesQueriesStructureCost
nonerange sumprefix sum per query
range addread everything at the enddifference array per update
pointrange sumBIT
range addpoint queryBIT over the difference array
range addrange sumtwo BITs
range assign / min / maxanythinglazy segment tree

Range update, range query with two BITs

For a range add of on and range-sum queries:

void rangeAdd(int l, int r, long long x) {
    b1.add(l, x);        b1.add(r + 1, -x);
    b2.add(l, x * (l-1)); b2.add(r + 1, -x * r);
}
long long prefix(int i) { return b1.sum(i) * i - b2.sum(i); }
long long rangeSum(int l, int r) { return prefix(r) - prefix(l - 1); }

Shorter and faster than a lazy segment tree for this specific pair of operations, and worth having in a template file.

Prefix tricks worth knowing

TrickUse
Prefix XORsubarray XOR in
Prefix counts per value”how many in
Prefix of “is constant”
Prefix min/maxnot decomposable — use a sparse table
Prefix product mod range product, with modular inverses
Prefix sums of the sorted array”sum of the smallest”
2D prefix sumssubmatrix sums, inclusion-exclusion
Prefix sums on a treeroot-to-node sums; combine with LCA for path sums

The pair-counting pattern

Nearly every “count subarrays with property ” problem becomes “count pairs of prefix values with property “:

QuestionPairs of prefixes
Subarrays with sum → hash map
Subarrays with sum divisible by equal residues → hash map
Subarrays with XOR → hash map or trie
Subarrays with equal 0s and 1smap 0 to , look for sum 0
Subarrays with sum in count prefixes in a range → BIT
Number of inversionscount smaller prefixes → BIT

Recognising this converts an enumeration into or .

Tree prefix sums

Root the tree and store distToRoot[v]. Then:

and for vertex values, add back the LCA’s own value. Combined with the tree difference array for updates, this handles a large class of tree problems without HLD.

Before reaching for a segment tree

Ask, in order:

  1. Are there no updates? → prefix sum or sparse table.
  2. Do all updates precede all queries? → difference array.
  3. Are the queries offline? → sort and sweep with a BIT.
  4. Is the update a point and the query a prefix? → BIT.
  5. Only then → segment tree.

Each step down this list roughly doubles the code length. Most problems stop at step 3.

See also: Prefix Sum · Difference Array · Offline Query Processing