前缀和
前缀和是一种重要的预处理,能大大降低查询的时间复杂度。可以简单理解为:数列的前n项的和
一维前缀和
B[i] = B[i-1] + A[i]
#include <bits/stdc++.h>using namespace std;const int N = 10010;int a[N],b[N],n;int main(){cin >> n;for (int i = 1;i <= n;i ++) {cin >> a[i];}for (int i = 1;i <= n;i ++) {// 前缀和数组的第i项 = 原数组的 0 到 i-1 项的和 + 原数组的第 i 项b[i] = b[i-1] + a[i];}for (int i = 1;i <= n;i ++) {cout << b[i] << " ";}return 0;}
二维前缀和
基于容斥原理
S[i,j] = S[i-1,j] + S[i,j-1] - S[i-1,j-1] + A[i,j]
#include <bits/stdc++.h>using namespace std;const int N = 10010;int a[N][N],b[N][N],n,m;int main(){cin >> n >> m;for (int i = 1;i <= n;i ++) {for (int j = 1;j <= m;j ++) {cin >> a[i][j];}}for (int i = 1;i <= n;i ++) {for (int j = 1;j <= m;j ++) {b[i][j] = b[i-1][j] + b[i][j-1] - b[i-1][j-1] + a[i][j];}}for(int i = 1;i <= n;i ++ ) {for(int j = 1;j <= m;j++ ) {cout << b[i][j] << " ";}cout << endl;}return 0;}
(x1,y1) - (x2,y2) = S[x2,y2] - S[x1-1,y2] - S[x2,y1-1] + S[x1-1,y1-1]
差分
差分是一种和前缀和相对的策略,可以当做是求和的逆运算给区间[l, r]中的每个数加上c:B[l] += c, B[r + 1] -= c
给以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵中的所有元素加上c:S[x1, y1] += c, S[x2 + 1, y1] -= c, S[x1, y2 + 1] -= c, S[x2 + 1, y2 + 1] += c
