前缀和与差分 (Prefix Sum & Difference)
一 : 核心理论:算子对称性证明
设原序列为 。
1. 前缀和算子 (Summation Operator)
定义前缀和序列 为: 线性性质证明: 根据求和定义,区间 的和可表示为: 复杂度分析:单次区间查询由 优化至 。
2. 差分算子 (Difference Operator)
定义差分序列 满足 (约定 )。 基本定理:差分序列的前缀和即为原序列。 区间修改证明: 对区间 全体加上 ,反映在差分序列上,仅有 增加了 ( 增大),以及 减小了 ( 减小)。其余项 保持不变。
二 : 高维拓展与容斥原理
1. 二维前缀和 (2D Prefix Sum)
矩阵构建: 区域查询 :
2. 二维差分 (2D Difference)
矩阵修改:对矩形区域整体加 。
三 : 渐进性能矩阵
| 维度 | 构建复杂度 | 查询/修改 | 空间复杂度 | 备注 |
|---|---|---|---|---|
| 1D 前缀和 | 查询 | 适合静态区间和 | ||
| 1D 差分 | 修改 | 适合批量区间修改 | ||
| 2D 前缀和 | 查询 | 图像处理常用 | ||
| 3D 前缀和 | 查询 | 遵循容斥原理 项 |
四 : 教材化例题
例题 1:激光炸弹 (二维前缀和实战)
寻找 正方形覆盖的最大点权重和。
Check Solution
复杂度验证:
- 预处理:。
- 查询:。
- 总复杂度线性,适用于 级别规模。
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 5010;
int s[N][N];
int main() {
int n, r;
cin >> n >> r;
r = min(r, 5001);
for (int i = 0; i < n; i++) {
int x, y, w;
cin >> x >> y >> w;
s[x + 1][y + 1] += w;
}
for (int i = 1; i <= 5001; i++)
for (int j = 1; j <= 5001; j++)
s[i][j] += s[i-1][j] + s[i][j-1] - s[i-1][j-1];
int res = 0;
for (int i = r; i <= 5001; i++)
for (int j = r; j <= 5001; j++)
res = max(res, s[i][j] - s[i-r][j] - s[i][j-r] + s[i-r][j-r]);
cout << res << endl;
return 0;
}
五 : 综合练习库
练习 1:最高身高 (前缀和与差分综合)
头牛, 对互相能看见的关系 ,表示 之间所有牛都比 短。已知第 头牛最高。
Check Solution
建模推导: 相互看见意味着中间的牛高度至少减 1。这是一个区间减 1 的操作,使用差分数组维护。 最后求前缀和即可。
#include <iostream>
#include <set>
using namespace std;
const int N = 10010;
int d[N];
set<pair<int, int>> existed;
int main() {
int n, p, h, m;
cin >> n >> p >> h >> m;
while (m--) {
int a, b;
cin >> a >> b;
if (a > b) swap(a, b);
if (existed.count({a, b})) continue;
existed.insert({a, b});
d[a + 1]--, d[b]++;
}
int cur = 0;
for (int i = 1; i <= n; i++) {
cur += d[i];
cout << h + cur << endl;
}
return 0;
}
编者注:前缀和是“空间换时间”的极致体现。它告诉我们,通过 的预处理,可以将 的查询转化为 。