acwing算法基础之基础算法--差分算法

1 知识点

已知原数组 a 1 , a 2 , ⋯   , a n a_1,a_2,\cdots,a_n a1,a2,,an
获得其差分数组 b 1 , b 2 , ⋯   , b n b_1,b_2,\cdots,b_n b1,b2,,bn
b 1 = a 1 b_1=a_1 b1=a1
b 2 = a 2 − a 1 b_2=a_2-a_1 b2=a2a1
b i = a i − a i − 1 b_i=a_i-a_{i-1} bi=aiai1

此时,数组a是数组b的前缀和数组。

作用:快速处理多个如下这类操作,
对原数组a中的[l,r]区间的数都加上val。
此操作等价于 b l + = v a l , b r + 1 − = v a l b_l+=val,b_{r+1}-=val bl+=val,br+1=val

差分并不需要构造差分数组 b b b。只需要利用上述性质,在区间[i,i]加上 a i a_i ai即可。

二维情况下,对 ( x 1 , y 1 ) , ( x 2 , y 2 ) (x_1,y_1),(x_2,y_2) (x1,y1),(x2,y2)表示的矩阵加上val,等价于
d [ x 1 ] [ y 1 ] + = c d[x_1][y_1] += c d[x1][y1]+=c
d [ x 1 ] [ y 2 + 1 ] − = c d[x_1][y_2+1] -=c d[x1][y2+1]=c
d [ x 2 + 1 ] [ y 1 ] − = c d[x_2+1][y1] -= c d[x2+1][y1]=c
d [ x 2 + 1 ] [ y 2 + 1 ] + = c d[x_2+1][y_2+1] + =c d[x2+1][y2+1]+=c

初始化,取 ( x 1 , y 1 ) (x_1,y_1) (x1,y1) ( i , j ) (i,j) (i,j) ( x 2 , y 2 ) (x_2,y_2) (x2,y2) ( i , j ) (i,j) (i,j)

2 模板

//一维情况
//原数组nums,第0位没有含义,从第1位开始存储
int n = nums.size();
vector<int> d(n+10,0);
for (int i = 1; i <= n; ++i) {
	d[i] += nums[i];
	d[i+1] -= nums[i];
}

//在原数组的[l,r]区间中加上c,注意l和r都是从1开始编号的
d[l] += c;
d[r+1] -= c;

//多次操作之后的原数组如下所示
for (int i = 1; i <= n; ++i) {
	d[i] += d[i-1];
}
//二维情况
//原数组a
//差分数组d
void insert(vector<vector<int>> &d, int x1, int y1, int x2, int y2, int c) {
    d[x1][y1] += c;
    d[x1][y2+1] -= c;
    d[x2+1][y1] -= c;
    d[x2+1][y2+1] += c;
    return;
}

int n = a.size(), m = a[0].size();
vector<vector<int>> d(n+10,vector<int>(m+10,0));
for (int i = 1; i <= n; ++i) {
	for (int j = 1; j <= m; ++j) {
		insert(d, i, j, i, j, a[i][j]);
	}
}

//子矩阵(x1,y1) (x2,y2)加上c
insert(d, x1, y1, x2, y2, c);

//输出最终数组a
//相当于求矩阵的前缀和
for (int i = 1; i <= n; ++i) {
	for (int j = 1; j <= m; ++j) {
		a[i][j] = a[i-1][j] + a[i][j-1] - a[i-1][j-1] + b[i][j];
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YMWM_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值