前缀和数组应初始化为长度 n+1,首元素 sum[0]=0;若设为长度 n,则访问 sum[n] 会导致越界。正确写法:vector<int> sum(n + 1, 0)。

前缀和数组怎么初始化才不会越界
初始化时最容易犯的错是把前缀和数组长度设成 n 而不是 n+1。原数组下标从 0 到 n-1,但前缀和要支持「区间 [l, r] 求和」用 sum[r+1] - sum[l] 这个公式,所以 sum 必须有 n+1 个元素,其中 sum[0] = 0。
-
vector<int> sum(n + 1, 0)</int>是安全写法;写成vector<int> sum(n)</int>后续访问sum[n]就是未定义行为 - 循环填值时,用
for (int i = 0; i ,别用 <code>i从1开始去对齐——容易漏掉第一个元素或搞混偏移 - 如果原数组是
long long类型,前缀和也得用long long,否则中间累加就溢出,连int都撑不住 1e5 个 1e4 的数
查询区间和时为什么总是差一个数
问题几乎都出在边界映射上。前缀和本质是「sum[i] 表示前 i 个元素之和(即 a[0] 到 a[i-1])」,所以 [l, r](闭区间,0-indexed)对应的是 sum[r + 1] - sum[l]。
- 查
[0, 0]:要写sum[1] - sum[0],不是sum[0] - sum[0] - 查
[2, 5]:是sum[6] - sum[2],不是sum[5] - sum[2] - 如果题目给的查询是 1-indexed(比如「第 l 个到第 r 个」),直接用
sum[r] - sum[l - 1],此时你建的sum仍是n+1长,但索引含义变成「前 i 个」
二维前缀和的递推式为什么是 sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + a[i-1][j-1]
因为二维里重复加了左上角那块。画个图就清楚:sum[i-1][j] 覆盖了上方矩形,sum[i][j-1] 覆盖了左方矩形,它们重叠的部分是 sum[i-1][j-1],必须减一次,再补上当前格子 a[i-1][j-1](注意这里又出现偏移:sum 是 (n+1)×(m+1),而 a 是 n×m)。
- 初始化
vector<vector long>> sum(n + 1, vector<long long>(m + 1, 0))</long></vector>,别省那个+1 - 查矩形
[r1, c1]到[r2, c2](0-indexed,闭区间):结果是sum[r2 + 1][c2 + 1] - sum[r1][c2 + 1] - sum[r2 + 1][c1] + sum[r1][c1] - 如果用
int存二维前缀和,1000×1000 的矩阵里每个数 1e6,总和就到 1e12,早爆了
什么时候不该用前缀和
前缀和只适合静态数组、单次预处理多次查询的场景。一旦有修改操作,就得换线段树或树状数组。
立即学习“C++免费学习笔记(深入)”;
- 原数组会频繁单点修改(比如「把第 i 个数改成 x」):前缀和每次改都要 O(n) 重建,不如用
std::vector配合std::accumulate临时算——或者直接上BIT - 内存敏感场景(比如嵌入式或超大数组):前缀和多占一份空间,O(n) 空间开销不是零成本
- 只是查一两次区间和:现场用
for循环累加反而更快,免去预处理和额外空间
真正要注意的是:前缀和不是银弹,它把时间换成了空间和静态性。边界偏移、类型溢出、维度对齐——这三个地方错一个,结果就全歪了。











