Prefix Sum Array

Precompute cumulative sums to answer range sum queries in constant time.

Prefix Sum Array

A prefix sum array stores cumulative sums so that any range sum can be computed in constant time.

You use it when many range sum queries are performed on static data.

Problem

Given an array $A$ of length $n$, support queries of the form:

$$ \sum_{i=l}^{r} A[i] $$

where

$$ 0 \le l \le r < n $$

Structure

Define a prefix array $P$ such that:

$$ P[i] = A[0] + A[1] + \dots + A[i] $$

Algorithm

Build the prefix array:

build_prefix(A):
    n = length(A)
    P[0] = A[0]
    for i from 1 to n - 1:
        P[i] = P[i - 1] + A[i]
    return P

Answer a range query:

range_sum(P, l, r):
    if l == 0:
        return P[r]
    return P[r] - P[l - 1]

Example

Let

$$ A = [8, 3, 5, 1, 9] $$

Compute:

$$ P = [8, 11, 16, 17, 26] $$

Query sum from index $1$ to $3$:

$$ \sum_{i=1}^{3} A[i] = 3 + 5 + 1 = 9 $$

Using prefix sums:

$$ P[3] - P[0] = 17 - 8 = 9 $$

step value
P[3] 17
P[0] 8
result 9

Correctness

Each prefix value $P[i]$ stores the sum of elements from index $0$ to $i$. Subtracting $P[l-1]$ removes the contribution of elements before index $l$, leaving exactly the sum over $[l, r]$.

Complexity

operation time
build $O(n)$
query $O(1)$

Space usage:

$$ O(n) $$

When to Use

Prefix sums are appropriate when:

  • the array does not change
  • many range sum queries are required
  • preprocessing time is acceptable

They are less suitable when:

  • frequent updates occur
  • memory must remain minimal

In those cases, use Fenwick trees or segment trees.

Implementation

def build_prefix(a):
    p = [0] * len(a)
    p[0] = a[0]
    for i in range(1, len(a)):
        p[i] = p[i - 1] + a[i]
    return p

def range_sum(p, l, r):
    if l == 0:
        return p[r]
    return p[r] - p[l - 1]
func BuildPrefix(a []int) []int {
    n := len(a)
    p := make([]int, n)
    p[0] = a[0]
    for i := 1; i < n; i++ {
        p[i] = p[i-1] + a[i]
    }
    return p
}

func RangeSum(p []int, l, r int) int {
    if l == 0 {
        return p[r]
    }
    return p[r] - p[l-1]
}