The dual of the prefix sum: range update in , then one pass to recover the final array.

vector<long long> d(n + 1, 0);
 
auto rangeAdd = [&](int l, int r, long long x) { d[l] += x; d[r + 1] -= x; };
 
// finalise: prefix sum recovers the array
for (int i = 1; i < n; i++) d[i] += d[i - 1];

updates and one final pass: total, versus naively.

2D difference array

Add to the rectangle with four point updates:

d[r1][c1]     += x;
d[r1][c2+1]   -= x;
d[r2+1][c1]   -= x;
d[r2+1][c2+1] += x;
 
// finalise with a 2D prefix sum
for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++) {
        if (i) d[i][j] += d[i-1][j];
        if (j) d[i][j] += d[i][j-1];
        if (i && j) d[i][j] -= d[i-1][j-1];
    }

Difference of differences

Applying the trick twice handles arithmetic progression updates — “add over ”:

// add an AP with first term a and common difference k over [l, r]
d[l]     += a;
d[l + 1] += k - a;
d[r + 1] -= a + (long long)(r - l) * k;      // stop the progression
d[r + 2] += a + (long long)(r - l - 1) * k;  // and cancel the slope
// then take the prefix sum TWICE

Getting the boundary terms right is fiddly; derive them by writing out a small example rather than memorising.

The difference array on a tree

Path updates without HLD. To add along the path :

diff[u] += x;
diff[v] += x;
diff[lca] -= x;
if (par[lca] != -1) diff[par[lca]] -= x;

Then one DFS accumulating subtree sums gives each vertex’s final value. per update (for the LCA) plus to finalise.

This is a genuinely important technique — it turns a large class of “add along many paths, then report all vertex values” problems into something you can write in ten lines. For edge updates, place the value on the child endpoint and subtract twice at the LCA.

When to use which

UpdatesQueriesStructure
range add, all at onceread all values at the enddifference array,
range add, interleaved point queriespointBIT on the difference array,
range addrange sumtwo BITs, or lazy segment tree
range assign / range minanythinglazy segment tree
path add on a tree, read at the endvertex valuestree difference array
path add on a tree, interleaved queriespath/subtreeHLD + lazy segment tree

The BIT-on-difference trick

Putting a Fenwick tree over the difference array gives range update, point query in with a plain BIT:

void rangeAdd(int l, int r, long long x) { bit.add(l, x); bit.add(r + 1, -x); }
long long pointGet(int i) { return bit.prefixSum(i); }

Two such BITs give range update, range query — see Fenwick Tree.

Typical uses

  • Booking / scheduling: “how many events overlap each moment” — at the start, at the end
  • Flight bookings, hotel occupancy, traffic counting
  • Grid stamping: apply many rectangle increments, then read the grid
  • Sweep-line event accumulation
  • Range updates that all precede all queries — always check for this, it is the cheapest possible solution

See also: Prefix Sum · Fenwick Tree · LCA