差分讲解

差分应用到解决题目中,主要是区间修改的问题。

如果让你给区间[l,r]中的每一个数都加上x,一般情况下会直接暴力循环将每一个数都加上x。

就像这样:

1 void update(int l,int r,int x)
2 {
3     for(int i=l;i<=r;i++)
4     {
5         a[i]+=x;
6     }
7 }

但是如果l-r非常大的话,这样做很明显时间复杂度很高,而差分则可以解决这个问题。

首先看一下前缀和的概念,前缀和是前 i 个数的和,就有了前缀和数组presum[maxn],前缀和数组中的每一个元素都存储了对应数组a[maxn]中前 i 个数的和,也就是presum[i]=presum[i-1]+a[i](前i-1个数的和加上当前数)。

差分可以说是和前缀和操作相反的,差分需要一个差分数组d[maxn],差分数组储存的是相邻元素的差,即d[i]=a[i] -a[i-1]。

举个例子:比如数组a={1,2,3,4,5,6},那么前缀和数组是presum={1,3,6,10,15,21},差分数组d={1,1,1,1,1}(少一个)。

构造差分数组的代码:(a数组是编号1-n的数组)

1 void makediff(int n)
2 {
3     for(int i=2;i<=n;i++)
4     {
5         d[i]=a[i]-a[i-1];
6     }
7 }

进行区间修改操作,只需要在l和r这两个端点处对差分数组进行修改,假如在区间[l,r],中每个数都加上x。

那么将d[l]加上x,将d[r+1]减去x,因为是相邻的差,所以数a[r+1]-a[r]是差分数组d[r+1]的值,a[r+1]没变,而a[r]变了,所以..就这样。

看代码:

1 void update(int l,int r,int x)
2 {
3     d[l]+=x;
4     d[r+1]-=x;
5     return ;
6 }

 要得到一个数a[i],需要推出这个数。

从第1个数依托差分数组得到每一个a[i],或者直接到要查询的数就停也可以。

代码如下:

1 int getnum(int pos)
2 {
3     for(int i=1;i<=n;i++)
4     {
5         a[i]=a[i-1]+d[i];
6     }
7     return a[pos];
8 }

 

posted on 2020-04-11 19:20  轻描淡写ぃ  阅读(322)  评论(0编辑  收藏  举报

导航