当我们处理一个长度为 n 的原始数组 arr 时,前缀和数组 prefixSum 是一个包含 n 个元素的数组。其中,每个元素表示原始数组中从开头到当前位置的元素和。通常,前缀和数组的第一个元素是原始数组的第一个元素,而其他元素则是原始数组前面所有元素的累积和。
前缀和数组的定义如下:
prefixSum[i] = Σ(arr[k]) //其中 k 范围从 0 到 i
在这里,prefixSum[i] 表示原始数组 arr 从索引 0 到 i 的元素和。
前缀和数组的优势在于,在计算任意区间的和时,我们可以在常数时间内得到结果。对于区间 [L, R] 的和,可以使用如下公式:
**Sum[L, R] = prefixSum[R] - prefixSum[L-1]**
需要注意的是,为了避免数组越界,需要确保 L > 0 时才使用 prefixSum[L-1]。
使用前缀和数组的典型情况包括处理多次查询区间和的问题。通过预处理计算前缀和,可以大幅提高查询效率,避免重复计算。这在累积和、区间和查询等问题中是非常有用的技巧。
如下例题
题目描述
给定a1……an一共N个整数,有M次查询,每次需要查询区间【L,R】的和。
输入描述:
第一行包含两个数:N,M
第二行输入N个整数
接下来的M行,每行有两个整数,L R,中间用空格隔开,数据保证L<=R1<=N,M<=1e5,-1e5<=ai<=1e5
输出描述:
输出共M行,即每次查询的区间和
import java.math.BigInteger;
import java.util.Scanner;
public class Nk1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
}
BigInteger[] prefixSum = new BigInteger[n];
prefixSum[0] = BigInteger.valueOf(arr[0]);
// 计算前缀和
for (int i = 1; i < n; i++) {
prefixSum[i] = prefixSum[i - 1].add(BigInteger.valueOf(arr[i]));
}
// 处理每个查询
for (int i = 0; i < m; i++) {
int b = sc.nextInt() - 1;
int e = sc.nextInt() - 1;
// 查询区间和
BigInteger querySum = b > 0 ? prefixSum[e].subtract(prefixSum[b - 1]) : prefixSum[e];
System.out.println(querySum);
}
}
}