accumulate、partial_sum、iota —— 来自 <numeric> 头文件的数值类算法,求和、前缀和、批量赋值。
把区间内所有元素累加起来。第三个参数是初始值,同时也决定了返回值的类型。
| 1 | vector<int> v = {1, 2, 3, 4, 5}; |
| 2 | int sum = accumulate(v.begin(), v.end(), 0); |
| 3 | cout << "求和: " << sum << endl; // 求和: 15 |
| 4 | |
| 5 | // 第三个参数是初始值,也是返回值的类型 |
| 6 | long long big_sum = accumulate(v.begin(), v.end(), 0LL); |
0LL 而不是 0,否则结果可能溢出 int。这是因为 accumulate 的返回类型是根据初始值的类型推导的——写 0 就是按 int 一路累加(容易溢出),写 0LL 就是按 long long 累加。计算前缀和数组:结果数组的第 i 个元素,等于原数组前 i+1 个元素的总和。竞赛中常用前缀和快速计算"任意区间的和"。
pre[2] = 6 表示 v[0] + v[1] + v[2] = 1 + 2 + 3 = 6。有了前缀和数组,想知道"原数组某一段区间的和"就不用每次重新累加,直接用两个前缀和相减即可(O(1) 查询)。| 1 | vector<int> v = {1, 2, 3, 4, 5}; |
| 2 | vector<int> pre(v.size()); |
| 3 | partial_sum(v.begin(), v.end(), pre.begin()); |
| 4 | // pre 变成 {1, 3, 6, 10, 15} |
把区间内的元素依次填充成从某个起始值开始、每次加 1 的连续整数。常用于快速生成"下标数组"(比如配合 sort 间接排序时用到的索引序列)。
| 1 | vector<int> v(5); |
| 2 | iota(v.begin(), v.end(), 1); |
| 3 | // v 变成 {1, 2, 3, 4, 5} |
| 4 | |
| 5 | iota(v.begin(), v.end(), 10); |
| 6 | // v 变成 {10, 11, 12, 13, 14} |
iota 生成 {0, 1, 2, ...} 的下标数组,再用自定义比较函数对下标数组 sort,排序依据是 v[下标] 的大小。这样原数组不被破坏,还能拿到排序后的下标顺序。