0
点赞
收藏
分享

微信扫一扫

差分(一维)

Alex富贵 2022-02-16 阅读 77

文章目录


前言

前段时间学习了一维前缀和,一维前缀和可以对数组进行整合操作,今天学习一维差分,一维差分就可以对数组进行区域性加减操作了。


一、差分是什么?

差分与前缀和在算法中往往对应存在,它是一种策略
令b [i]=a[i] −a[i-1]  ,即相邻两数的差。

————————————————

二、差分是性质

差分数组可以通过前缀和得到原数组(⭐)

二、一维差分讲解

引入

一个由5个数字组成的数组arr[5]={1,3,7,5,2}
对其进行3次操作
:在[2,4] +5
在[1,3] +2
在[0,2] -3
最后询问1次:arr[]={ }

arr[5]
1 3 7 5 2

如果我们按部就班的进行操作

arr[5]
1   3  7    5  2
1   3  12  10  7
1   5  14  12  7
-2  2  11  12  7

一步一步求最终会得到结过arr[5]={-2,2,11,12,7}
但如果数据很大,这样的解法空间复杂度完全会超出时限,
所以我们引进差分。
先求出差分数组d[i]= arr[i]− arr[i-1] // i>0
d[0]=arr[0]

差分表示的是相邻两数的差(原因)
所以当我们对第n项进行改动时,从第n项以后的
所有数都将会受到相应的影响 。
(可以想象多米诺骨牌,一发而动全身)
  
  
如果对第L项进行改动,对第R+1项进行相反的改动,
那么改动的空间只是[L,R](手指推倒第L张多米诺骨牌从L
以后的多米诺骨牌挨个倒地,为牵扯到第R+1张牌时手指支撑
是其没有倒下,所以倒下的即改动的只有[L,R])

这样就好理解了。
这个操作我们称为:差分标记

进行完 差分标记就可以得到所有操作改变后的差分数组,根据这个差分数组,可以用差分的性质对其还原得到所有操作改变后的原数组。

我们将差分标记用到题目中:
首先由arr【】数组确定了的差分数组d【】
再进行±操作

 d【2+5    d【5-5   //对d【5】-5操作可有可无,越界了

影响的是第2项到第5项(也可以说后面的整个数组,所以对d【5】的操作可有可无)
此时

d    1  2  9   -2  -3    //差分的性质--还原原数组
arr  1  3  12  10   7

剩下的操作几乎相同,就不再讲解

代码操作

代码如下(示例):

#include<iostream>
using namespace std;
int d[6]={0};  //初始化差分数组d,d[6]比
               //arr[5]大1防止d[R+1]+-v越界
               //也可替换为d[5]={0}
void add(int L,int R,int v)
{
	d[L]+=v;
	d[R+1]-=v;
}
int main()
{
	int arr[5]={1,3,7,5,2};
	add(2,4,5);
	add(1,3,2);
	add(0,2,-3);
	for(int i=1;i<5;i++)
		d[i]+=d[i-1];
	for(int i=0;i<5;i++)
	{
		arr[i]+=d[i];
		cout<< arr[i] <<" ";
	}
	return 0;
}

总结

一维差分也比较简单,想清楚差分数组和差分标记就可以了,可以想想多米诺骨牌有助于理解。

举报

相关推荐

0 条评论