算法学习1 前缀和与差分

一 前缀和是什么?

 顾名思义,就是数组里面,以原数组的和作为另一个数组元素的数组。

二 有何益裨?

求数组某个元素内,某一块区域内数据的和,并将他们的时间复杂度由O(n)降低到O(1)。

三 如何使用?

前缀和分为一维前缀和和二维前缀和

有如下几种情况:

设有A[9],成员为{1,2,3,4,5,6,7,8,9};

那么前缀和设为S[9],元素有{1,3,6,10,15,21,28,36,45};

公式如下:

一维前缀和:

S[ i ] - S[ i - 1 ]  =  A[ i ];所以S[ i ] = A[ i ] + S[ i - 1 ];

(  注意!这也是为什么前缀和与差分数组要从1而不是0开始的原因,因为“ 第一步 ”的空窗期要用A[0]和S[0]去填补。)

二维前缀和:

 

 

 

S[ i ][ j ] = S[ i - 1 ][ j ] + S[ i ][ j - 1] - S[ i - 1 ][ j - 1] + A[ i ][ j ];

 

 

 

OK,前缀和到此结束。


 

一 差分是什么?

(请注意 ,前缀和与差分的x轴与y轴,和我们平时接触的数学x轴y轴不一样,在这里横为y轴,纵为x轴。)

普遍来说,差分就是前缀和的逆运算。为什么呢?因为你看,前缀和的求值是“依靠原数组的数去求数组在不同位置上的和,并将此坐标作为前缀和数组的下标。”

而我理解的差分是“将原数组作为一个前缀和数组,然后通过逆运算列出每一步参与求和的元素,将这些元素与下标一一对应,便是差分数组了。”

 

二 差分用途与裨益?

差分既然作为每一步的求和元素,其实在求和过程的每一步重复(加上前元素总和和现元素)都是一个“迭代”的过程,我们可以利用这个特性去反过来“伪造”出一个在“任意范围”里添加了“任意元素”的前缀和数组“A”。

 

三 差分的使用方法?

差分大致可分为两步,

第一步:拆分析构;第二步:变量重组。

设有原数组Q[9],设立影子数组B[9];

一维差分:

B[ i ] = Q[ i ] - Q[ i - 1];

 

 

 在Q[ l ] 到Q[ r ]的范围里加上一个常数c;

B[ l ] += c;B[ r + 1 ] -= c;(加一再减去的作用是为了让c完整的覆盖整个{ l ~ r}范围)

最后,伪造原数组:B[ i ] += B[ i - 1]。

二维差分:

内容大致大同小异,唯一不同的就是线性变成了矩阵。

 

 

 构造insert函数,以便我们逆求前缀和数组:

1 void insert(int x1,int y1,int x2,int y2,int c)
2 {     //对b数组执行插入操作,等价于对a数组中的(x1,y1)到(x2,y2)之间的元素都加上了c
3     b[x1][y1] += c;
4     b[x2 + 1][y1] -= c;
5     b[x1][y2 + 1] -= c;
6     b[x2 + 1][y2 + 1] += c;
7 }

 把A[ i ][ t ]数组拆分进去的方法:

void insert ( i , t , i , t , A[ i ][ t ] ) ;

或者是直接构造法:

b[i][j] = a[i][j] − a[i − 1][j] − a[i][j − 1] + a[i −1 ][j − 1]

 

 

 

之后都是如法炮制,把需要修改的参数值放入insert函数中。

posted @ 2023-03-22 18:26  王博涵  阅读(31)  评论(0编辑  收藏  举报