前缀和与差分

分类: 进阶算法 · 更新时间 2026-5-27 21:41:18

前缀和

前缀和用于快速求区间和,预处理 O(n)O(n),查询 O(1)O(1)

一维前缀和

定义 pre[i]=a[1]+a[2]++a[i]pre[i] = a[1] + a[2] + \cdots + a[i]

区间 [l,r][l, r] 的和 = pre[r]pre[l1]pre[r] - pre[l-1]

vector<int> a(n + 1), pre(n + 1);
for (int i = 1; i <= n; i++)
    pre[i] = pre[i - 1] + a[i];

// 查询 [l, r] 的和
int sum = pre[r] - pre[l - 1];

二维前缀和

定义 pre[i][j]pre[i][j] 为从 (1,1)(1,1)(i,j)(i,j) 的矩阵和。

for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++)
        pre[i][j] = pre[i - 1][j] + pre[i][j - 1] - pre[i - 1][j - 1] + a[i][j];

// 查询子矩阵 (x1,y1) 到 (x2,y2) 的和
int sum = pre[x2][y2] - pre[x1 - 1][y2] - pre[x2][y1 - 1] + pre[x1 - 1][y1 - 1];

差分

差分是前缀和的逆运算,用于快速进行区间修改。

一维差分

区间 [l,r][l, r]kk

int diff[MAXN];

// 区间 [l, r] 加 k
diff[l] += k;
diff[r + 1] -= k;

// 最后求前缀和得到最终结果
for (int i = 1; i <= n; i++)
    diff[i] += diff[i - 1];

二维差分

子矩阵 (x1,y1)(x1,y1)(x2,y2)(x2,y2)kk

diff[x1][y1] += k;
diff[x2 + 1][y1] -= k;
diff[x1][y2 + 1] -= k;
diff[x2 + 1][y2 + 1] += k;

// 最后求二维前缀和得到最终结果