基础算法模板之前缀和与差分

前缀和

规定数列{\(a_i\)}的前缀和为\(S_i\) = \(\sum{_{k = 1}^i}a_k\),常用于使用o(1)的时间计算某段区间求和

// 一维前缀和
S[i] = S[i - 1] + a[i]; //前缀和初始化,i从1开始,S[0] = 0
S[r] - s[l - 1] = a[l] + a[l + 1] + ... + a[r]; //求[l,r]区间和

// 二维前缀和
S[i][j] = S[i - 1][j] + S[i][j - 1] - S[i - 1][j - 1] + a[i][j];
// 以(x1,y1)为左上角,(x2,y2)为右下角的矩阵和
S = S[x2][y2] - S[x1 - 1][y2] - S[x2][y1 - 1] + S[x1 - 1][y1 - 1];

差分

差分与前缀和相对,很显然一个数列的差分数组的前缀和数组是原数组,差分数组经常用于使用o(1)的时间对某一段区间上的所有数加上一个数c

// 一维差分
// 差分数组的构造
for(int i = 0;i < n;i ++ ) insert(i,i,a[i]) // 将初始值均为0的差分数组各个位置上插入对应的a[i]之后,该差分数组就变成了数组a的差分数组了

// 在(l,r)区间上加上c
void insert(int l,int r,int c)
{
	b[l] += c,b[r + 1] -= c;
}

// 二维差分
// 差分数组的构造;
for(int i = 0;i < n;i ++ )
    for(int j = 0;j < m;j ++ )
        insert(i,j,i,j,a[i]);
// 在以(x1,y1)为左上角,(x2,y2)为右下角的子矩阵上的每个数上加c
void insert(int x1,int y1,int x2,int y2,int c) 
{
    b[x1][y1] += c;
    b[x1][y2 + 1] -= c;
    b[x2 + 1][y1] -= c;
    b[x2 + 1][y2 + 1] += c;
}
posted @ 2023-03-17 19:52  知凹  阅读(47)  评论(0)    收藏  举报