Lesson 29 of 50 intermediate

Prefix Sum — The Running Total

Answer range sum queries in the blink of an eye

Open interactive version (quiz + challenge)

Real-world analogy

Imagine a cash register receipt that shows a running total after each item. If you bought items costing 3, 5, 2, 8, the receipt shows totals: 3, 8, 10, 18. Now if someone asks 'how much did items 2 through 4 cost?' you just subtract: 18 - 3 = 15. You did not have to add 5 + 2 + 8 manually! That is prefix sum — pre-calculate running totals so you can answer range questions instantly.

What is it?

A prefix sum is a pre-computed array where each element stores the cumulative sum of all elements from the beginning up to that position. By building this array once in O(n), you can answer any range sum query (what is the sum from index l to index r?) in O(1) time. This transforms slow repeated calculations into instant lookups.

Real-world relevance

Prefix sums are used in financial running balances (bank statements show running totals), in image processing (integral images for fast blur operations), in databases (cumulative aggregations), and in statistics (cumulative distribution functions). Any time you need running totals or range queries, prefix sums are the tool.

Key points

Code example

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n, q;           // n = number of elements, q = number of queries
    cin >> n >> q;

    // 1-indexed prefix sum (easier formula — prefix[0] = 0 avoids edge cases)
    vector<long long> arr(n + 1), prefix(n + 1, 0);  // prefix[i] will hold sum of arr[1..i]
    for (int i = 1; i <= n; i++) {
        cin >> arr[i];                          // Read each element
        prefix[i] = prefix[i - 1] + arr[i];    // Running total: add current to previous sum
    }

    // Answer q range sum queries in O(1) each
    while (q--) {
        int l, r;
        cin >> l >> r;
        // Sum from l to r = (sum from 1 to r) minus (sum from 1 to l-1)
        long long rangeSum = prefix[r] - prefix[l - 1];
        cout << rangeSum << "\n";
    }

    return 0;
}

Line-by-line walkthrough

  1. 1. vector prefix(n + 1, 0); — we create a prefix sum array of size n+1, filled with zeros. We use 1-based indexing with prefix[0] = 0 so the range sum formula works cleanly.
  2. 2. prefix[i] = prefix[i - 1] + arr[i]; — each prefix sum entry equals the previous total plus the current element. After this loop, prefix[i] holds the sum of arr[1] through arr[i].
  3. 3. long long rangeSum = prefix[r] - prefix[l - 1]; — the magic formula! The sum from l to r equals (sum from 1 to r) minus (sum from 1 to l-1). Two lookups and one subtraction — O(1)!
  4. 4. We use long long because sums can get very large. If each element is up to 10^9 and we have 200,000 elements, the total sum could be up to 2 * 10^14, which overflows a 32-bit int.

Spot the bug

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n = 5;
    int arr[] = {2, 4, 6, 8, 10};
    int prefix[5];

    prefix[0] = arr[0];
    for (int i = 1; i < n; i++) {
        prefix[i] = prefix[i - 1] + arr[i];
    }

    // Query: sum from index 0 to 3
    cout << prefix[3] << "\n"; // Correct: 20

    // Query: sum from index 2 to 4
    cout << prefix[4] - prefix[1] << "\n"; // Should be 6+8+10 = 24

    // Query: sum from index 0 to 0
    cout << prefix[0] - prefix[-1] << "\n"; // Just element 0 = 2

    return 0;
}
Need a hint?
Look at the last query. What is prefix[-1]? Is that a valid array index?
Show answer
The bug is accessing prefix[-1] which is out of bounds — undefined behavior! With 0-indexed prefix sums, the formula sum(l,r) = prefix[r] - prefix[l-1] breaks when l = 0 because l-1 = -1. Fix: use 1-indexed prefix sums with prefix[0] = 0, or add a special case: if l == 0, just use prefix[r] directly.

Explain like I'm 5

Imagine you are counting steps as you walk. After 1 block you have walked 10 steps. After 2 blocks, 25 steps total. After 3 blocks, 45 steps total. Now your friend asks 'how many steps was block 2 to block 3?' Instead of counting again, you just subtract: 45 - 10 = 35 steps. You saved the running total at each block, so answering any 'how many between X and Y' question is just one subtraction. That is prefix sum — save running totals, answer questions instantly!

Fun fact

Prefix sums in 2D are called 'integral images' and were a key innovation in the Viola-Jones face detection algorithm (2001), which was one of the first real-time face detectors. Your phone camera detecting faces uses a descendant of 2D prefix sums! The technique lets the algorithm compute the sum of any rectangular region in constant time, making face detection fast enough to run in real-time.

Hands-on challenge

Read an array of n numbers and q queries. Each query gives l and r. Print the sum of elements from index l to r (1-indexed). Also print the maximum range sum across all queries. Test with array [1, 3, 5, 7, 9] and queries: (1,3) should give 9, (2,5) should give 24, (1,5) should give 25.

More resources

Open interactive version (quiz + challenge) ← Back to course: CP Zero to Hero