前缀和与差分互为逆运算
一、一维前缀和
- 设有序列,则该序列的前缀和
- 作用:快速求出到之间所有数的和:
二、二维前缀和
- 设有矩阵,则该矩阵前缀和
- 前缀和的数学意义:与所形成的矩形内部所有数的和,按照这个思路公式就很容易推啦
- 作用:求出与所形成的矩形内部所有数的和:
注意:前缀和的均为0,因为需要考虑边界情况
三、一维差分
- 设有序列,构造,使得
- 方法:使
tips:其实不需要考虑构造,因为差分数列就相当于在原数列全是0的基础上,在这个点加上对应数
{
for (int i = 1; i <= n; i++) //初始化
{
scanf("%d", &a[i]); //读入
insert(i, i, a[i]); //构造差分
}
insert(l, r, c); //在l到r间加上常数c
}
void intsert(int l, int r, int c)
{
b[l] += c;
b[r + 1] -= c;
}
- 作用:使a的子数列区间[l,r]上的所有数+C,只需要将,
输出修改后的数列:
for (int i = 1; i <= n; i++)
{
b[i] += b[i-1]; //参考一维前缀和
printf("%d ", b[i]);
}
四、二维差分
- 作用:使矩阵中的某一小块矩形同时加上某个常数,只需要将
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
scanf("%d", &a[i][j]); //读入
insert(i, j ,i ,j, a[i][j]); //构造差分
}
}
insert(x1, y1, x2, y2, c); //在(x1,y1)到(x2,y2)间的矩阵中每位加上常数c
}
void intsert(int x1, int y1, int x2, int y2, int c)
{
b[x1][y1] += c;
b[x2+1][y1] -= c;
b[x1][y2+1] -= c;
b[x2+1][y2+1] += c;
}
输出修改后的数列:
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]; //参考二维前缀和
printf("%d", b[i][j]);
}
printf("\n");
}
五、配套练习
AcWing795https://www.acwing.com/problem/content/797/Acwing796https://www.acwing.com/problem/content/798/AcWing797https://www.acwing.com/problem/content/799/Acwing798https://www.acwing.com/problem/content/800/