ConceptDifficulty: Intermediate2 min

Prefix Sums: Any Range Sum From One Subtraction

Store the running total before each position once, and the sum of any range is the total at its end minus the total at its start.

A prefix sum array holds the running total of an array before each position, so the sum of any range of it is one subtraction. The cue is a property of the problem: many sums are asked over ranges of an array that does not change, or a run must add up to an exact total. Recomputing each range costs its length; the prefix array pays that cost once.

The array p has one more entry than the input. Its invariant is that p[i] is the sum of the first i elements, so p[0] is 0, the sum of none, and p[n] is the sum of all n. The sum of the elements at indices i to j inclusive is then p[j + 1] − p[i]: everything up to and including j, minus everything before i.

The values 2 6 1 4 3 show it.

What is the sum of the elements at indices 1 to 3?

11, the sum of 6 1 4. The trace builds the prefix array, and the table reads it.

Building the prefix array of 2 6 1 4 3

Inputvalues 2 6 1 4 3

  1. Start

    1. 0i

    p[0] = 0, the sum of no elements

  2. i 0

    1. 0
    2. 2i

    p[1] = p[0] + 2 = 2

  3. i 1

    1. 0
    2. 2
    3. 8i

    p[2] = p[1] + 6 = 8

  4. i 2

    1. 0
    2. 2
    3. 8
    4. 9i

    p[3] = p[2] + 1 = 9

  5. i 3

    1. 0
    2. 2
    3. 8
    4. 9
    5. 13i

    p[4] = p[3] + 4 = 13

  6. i 4

    1. 0
    2. 2
    3. 8
    4. 9
    5. 13
    6. 16i

    p[5] = p[4] + 3 = 16

ResultThe prefix array is 0 2 8 9 13 16, one entry longer than the values.

Three ranges read from it, each with one subtraction:

Ranges of 2 6 1 4 3 read from the prefix array 0 2 8 9 13 16
RangeFormulaValue
Indices 1 to 3p[4] − p[1] = 13 − 211
Indices 0 to 4p[5] − p[0] = 16 − 016
Indices 2 to 2p[3] − p[2] = 9 − 81

Building the array is O(n) time and O(n) extra space for n values, and each range then costs O(1). The array must not change after it is built: one changed value shifts every total after it.

A car's mileage reading at each town works the same way: the distance between two towns is the later reading minus the earlier one. The likeness breaks on direction. A mileage reading only goes up, while a prefix array over negative values goes down as well, and the subtraction still holds, which is why prefix sums handle the negative values that break a sliding window.