前缀和
定义
前缀和可以简单理解为「数列的前 项的和」,是一种重要的预处理方式,能大大降低查询的时间复杂度。1
C++ 标准库中实现了前缀和函数 std::partial_sum,定义于头文件 <numeric>
中。
例题
代码
#include <iostream>
using namespace std;
int N, A[10000], B[10000];
int main() {
cin >> N;
for (int i = 0; i < N; i++) {
cin >> A[i];
}
// 前缀和数组的第一项和原数组的第一项是相等的。
B[0] = A[0];
for (int i = 1; i < N; i++) {
// 前缀和数组的第 i 项 = 原数组的 0 到 i-1 项的和 + 原数组的第 i 项。
B[i] = B[i - 1] + A[i];
}
for (int i = 0; i < N; i++) {
cout << B[i] << " ";
}
return 0;
}
二维前缀和
参考代码
#include <algorithm>
#include <iostream>
using namespace std;
int a[103][103];
int b[103][103]; // 前缀和数组,相当于上文的 sum[]
int main() {
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> a[i][j];
b[i][j] =
b[i][j - 1] + b[i - 1][j] - b[i - 1][j - 1] + a[i][j]; // 求前缀和
}
}
int ans = 0;
int l = 1;
while (l <= min(n, m)) { // 判断条件
for (int i = l; i <= n; i++) {
for (int j = l; j <= m; j++) {
if (b[i][j] - b[i - l][j] - b[i][j - l] + b[i - l][j - l] == l * l) {
ans = max(ans, l); // 在这里统计答案
}
}
}
l++;
}
cout << ans << endl;
return 0;
}
逐维前缀和
特例
代码实现
#include <iostream>
#include <vector>
int main() {
int n;
std::cin >> n;
std::vector<int> a(1 << n);
for (int& x : a) std::cin >> x;
// Copy.
auto ps = a;
// Loop over dimensions.
for (int i = 0; i < n; ++i) {
// Loop over i-th dimension.
for (int st = 0; st < (1 << n); ++st) {
// This condition implies that i-th dimension is 1.
if ((st >> i) & 1) {
// ps[... 1 ...] += ps[... 0 ...]. (i-th dimension)
ps[st] += ps[st ^ (1 << i)];
}
}
}
for (int x : ps) std::cout << x << ' ';
return 0;
}
差分
示例
习题
前缀和:
- 洛谷 B3612【深进 1. 例 1】求区间和
- 洛谷 U69096 前缀和的逆
- AtCoder joi2007ho_a 最大の和
- 「USACO16JAN」子共七 Subsequences Summing to Sevens
- 「USACO05JAN」Moo Volume S
二维/多维前缀和:
- HDU 6514 Monitor
- 洛谷 P1387 最大正方形
- 「HNOI2003」激光炸弹
- CF 165E Compatible Numbers
- CF 383E Vowels
- ARC 100C Or Plus Max
树上前缀和:
差分:
树上差分: