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 of length , support queries of the form:
where
Structure
Define a prefix array such that:
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 PAnswer a range query:
range_sum(P, l, r):
if l == 0:
return P[r]
return P[r] - P[l - 1]Example
Let
Compute:
Query sum from index to :
Using prefix sums:
| step | value |
|---|---|
| P[3] | 17 |
| P[0] | 8 |
| result | 9 |
Correctness
Each prefix value stores the sum of elements from index to . Subtracting removes the contribution of elements before index , leaving exactly the sum over .
Complexity
| operation | time |
|---|---|
| build | |
| query |
Space usage:
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]
}