题目链接

【模板】静态区间和(前缀和)

题目描述

对于给定的长度为 的数组 ,你需要构建一个能够维护区间和信息的数据结构,使得其能支持多次区间和查询

区间和查询:输出区间 中的元素之和,即

解题思路

本题是静态区间求和的经典问题,即数组内容不会发生改变。如果每次查询都通过循环遍历从 的元素并求和,当查询次数 很大时,总时间复杂度会达到 ,这在 都很大时是无法接受的。

解决这个问题的标准方法是使用前缀和(Prefix Sum)数组。

1. 构建前缀和数组

我们创建一个新的数组,称之为前缀和数组,记为 的值定义为原始数组 从第一个元素到第 个元素的累计总和。

为了计算方便,我们通常让前缀和数组的长度比原数组多一个,并令 。然后, 表示原数组前 个元素的和(即 的和)。

前缀和数组的递推公式为: (其中 )

或者说,

这个构建过程只需要一次遍历,时间复杂度为

2. 区间和查询

利用构建好的前缀和数组,我们可以用 的时间计算出任意区间 的和。

区间 的和等于 (前 个元素的和) - (前 个元素的和)。 用公式表示就是:

这样,我们通过 的预处理,将每次查询的复杂度从 降到了

代码

#include <iostream>
#include <vector>
#include <numeric>

using namespace std;
using LL = long long;

int main() {
    int n, m;
    cin >> n >> m;

    // 前缀和数组,大小为 n+1,索引从1开始
    vector<LL> prefix_sum(n + 1, 0);
    for (int i = 1; i <= n; ++i) {
        LL current_val;
        cin >> current_val;
        prefix_sum[i] = prefix_sum[i - 1] + current_val;
    }

    for (int k = 0; k < m; ++k) {
        int l, r;
        cin >> l >> r;
        // 计算区间和 S[r] - S[l-1]
        cout << prefix_sum[r] - prefix_sum[l - 1] << endl;
    }

    return 0;
}
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();

        // 前缀和数组,大小为 n+1,索引从1开始
        long[] prefixSum = new long[n + 1];
        prefixSum[0] = 0;
        for (int i = 1; i <= n; i++) {
            prefixSum[i] = prefixSum[i - 1] + sc.nextLong();
        }

        for (int k = 0; k < m; k++) {
            int l = sc.nextInt();
            int r = sc.nextInt();
            // 计算区间和 S[r] - S[l-1]
            System.out.println(prefixSum[r] - prefixSum[l - 1]);
        }
    }
}
# 读取n和m
n, m = map(int, input().split())
# 读取原始数组
a = list(map(int, input().split()))

# 构建前缀和数组
# prefix_sum[i] 存储 a[0]...a[i-1] 的和
prefix_sum = [0] * (n + 1)
for i in range(n):
    prefix_sum[i+1] = prefix_sum[i] + a[i]

# 处理m次查询
for _ in range(m):
    l, r = map(int, input().split())
    # 原始数组的 [l, r] 区间 (1-based)
    # 对应前缀和数组的 prefix_sum[r] - prefix_sum[l-1]
    result = prefix_sum[r] - prefix_sum[l-1]
    print(result)

算法及复杂度

  • 算法:前缀和 (Prefix Sum)
  • 时间复杂度:。其中 用于构建前缀和数组, 用于回答 次查询,每次查询
  • 空间复杂度:,用于存储前缀和数组。