Introduction to Prefix Sums
Authors: Darren Yao, Dustin Miao
Computing range sum queries in constant time over a fixed 1D array.
Focus Problem – try your best to solve this problem before continuing!
Resources
Resources: Additional | ||||
---|---|---|---|---|
IUSACO | module is based off this | |||
CPH | rather brief | |||
PAPS | also rather brief |
1D Prefix Sums
Let's say we have a one-indexed integer array of size and we want to compute the value of
for different pairs satisfying . We'll use the following example with :
Index | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|
1 | 6 | 4 | 2 | 5 | 3 |
Naively, for every query, we can iterate through all entries from index to index to add them up. Since we have queries and each query requires a maximum of operations to calculate the sum, our total time complexity is . For most problems of this nature, the constraints will be , so is on the order of . This is not acceptable; it will almost certainly exceed the time limit.
Instead, we can use prefix sums to process these array sum queries. We designate a prefix sum array . First, because we're 1-indexing the array, set , then for indices such that , define the prefix sum array as follows:
Basically, what this means is that the element at index of the prefix sum array stores the sum of all the elements in the original array from index up to . This can be calculated easily in by the following formula for each :
For the example case, our prefix sum array looks like this:
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|---|
0 | 1 | 7 | 11 | 13 | 18 | 21 |
Now, when we want to query for the sum of the elements of between (1-indexed) indices and inclusive, we can use the following formula:
Using our definition of the elements in the prefix sum array, we have
Since we are only querying two elements in the prefix sum array, we can calculate subarray sums in per query, which is much better than the per query that we had before. Now, after an preprocessing to calculate the prefix sum array, each of the queries takes time. Thus, our total time complexity is , which should now pass the time limit.
Let's do an example query and find the subarray sum between indices and , inclusive, in the 1-indexed . From looking at the original array, we see that this is
Index | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|
1 | 6 | 4 | 2 | 5 | 3 |
Using prefix sums:
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|---|
0 | 1 | 7 | 11 | 13 | 18 | 21 |
These are also known as partial sums.
Solution - Static Range Sum
C++
In C++ we can use
std::partial_sum
,
although it doesn't shorten the code by much.
#include <bits/stdc++.h>using namespace std;#define sz(x) (int)size(x)using ll = long long;using vl = vector<ll>;vl psum(const vl &a) {vl psum(sz(a) + 1);
Java
import java.io.*;import java.util.*;public class Main {static int N, Q;public static void main(String[] args) throws IOException {BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));PrintWriter writer = new PrintWriter(System.out);StringTokenizer st = new StringTokenizer(reader.readLine());N = Integer.parseInt(st.nextToken());
Python
def psum(a):psum = [0]for i in a:psum.append(psum[-1] + i)return psumN, Q = map(int, input().split())a = list(map(int, input().split()))p = psum(a)for i in range(Q):l, r = map(int, input().split())print(p[r] - p[l])
An alternative approach is to use itertools.accumulate
.
Notice that we need to add a to the front of the array.
If using a newer version, you can use the optional parameter initial=0
as well.
import itertoolsdef psum(a):return [0] + list(itertools.accumulate(a))Code Snippet: Same code as above (Click to expand)
Problems
Warning!
"Haybale Stacking" isn't submittable on the USACO website; Use this link to submit instead.
Status | Source | Problem Name | Difficulty | Tags | |
---|---|---|---|---|---|
Silver | Very Easy | Show TagsPrefix Sums | |||
Silver | Easy | Show TagsPrefix Sums | |||
Silver | Easy | Show TagsPrefix Sums | |||
CSES | Easy | Show TagsPrefix Sums | |||
CSES | Easy | Show TagsPrefix Sums | |||
Silver | Easy | Show TagsPrefix Sums | |||
Old Bronze | Normal | Show TagsPrefix Sums | |||
CF | Normal | Show TagsMath, Prefix Sums | |||
AC | Normal | Show TagsPrefix Sums | |||
CF | Normal | Show TagsPrefix Sums | |||
CF | Normal | Show TagsPrefix Sums | |||
AC | Hard | Show TagsPrefix Sums |
Quiz
What is the optimal time complexity of calculating the prefix sum array of some array of length ?
Module Progress:
Join the USACO Forum!
Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!