std::partial_sum最省事,需注意迭代器范围和目标容器容量;手写循环更可控但易出索引越界和初始化错误。

用 std::partial_sum 最省事
标准库提供了现成工具,不用手写循环。它在 <numeric> 头文件里,对原数组(或容器)做一次遍历就能生成前缀和序列。
常见错误是传错迭代器范围,比如把 end() 写成 end() - 1,导致漏掉最后一个元素;或者目标容器没预留空间,引发未定义行为。
- 输入和输出可以是同一容器(原地计算),但必须确保输出迭代器不覆盖尚未读取的输入元素 —— 所以推荐用
std::vector并提前resize - 如果原数组是裸指针(如
int arr[5]),传arr和arr + 5即可 - 默认是累加(
+),也可传自定义二元函数,比如求前缀最小值:std::partial_sum(arr, arr+5, out, [](int a, int b){ return std::min(a,b); })
手写循环更可控,适合嵌入式或性能敏感场景
当不能依赖 STL、或需要精确控制边界(比如前缀和从下标 1 开始、0 位置留空),手写更直接。
典型坑是索引越界和初始值处理:有人习惯让 sum[0] = arr[0],结果后续所有下标偏移一格;也有人忘记初始化 sum[0] 就直接用 sum[i-1],导致读取未定义值。
立即学习“C++免费学习笔记(深入)”;
- 若要 0-indexed 前缀和(
sum[i]表示arr[0..i]和),则sum[0] = arr[0],然后for (int i = 1; i - 若要 1-indexed(常用在树状数组/线段树接口中),申请
n+1长度,sum[0] = 0,再for (int i = 1; i - 注意整数溢出:
int累加可能溢出,必要时换long long
静态数组 vs std::vector:内存布局影响不大,但初始化方式不同
前缀和本身不关心底层是栈上数组还是堆上 vector,关键在访问是否连续、长度是否可知。
容易被忽略的是:裸数组(如 int a[10])没有 .size(),必须手动传长度;而 vector 可用 v.size(),但若用 v.data() 传给 partial_sum,仍需配合 v.data() + v.size()。
- 静态数组:长度必须编译期已知或由调用方保证,否则运行时无法安全遍历
-
std::vector:推荐,尤其配合reserve()和resize()避免多次分配 - 千万别对
std::array直接用begin()/end()以外的方式取地址 —— 它的data()是合法的,但某些旧编译器对std::array<T,N>::operator[]的 constexpr 支持不一致
前缀和数组修改后怎么快速更新?
纯前缀和不支持高效单点修改 —— 改一个原数组元素,后面所有前缀和都要重算,O(n)。这时候该考虑 std::vector + 重算,或换数据结构。
如果真有频繁修改+查询需求,前缀和不是正确选择。别硬撑,直接上 std::vector 配合 std::lower_bound 做离散化前缀和,或改用 std::set / 树状数组(BIT)。
- 临时改一两次?直接重跑一遍
partial_sum或手写循环,简单可靠 - 修改超过 log n 次?STL 前缀和就该被替掉了
- 注意:
std::partial_sum不提供“增量更新”接口,别找它
前缀和看着简单,但下标起始、内存所有权、修改频率这三点一旦没理清,后期 debug 成本远高于初期多写两行检查。


















