前缀和与差分
前缀和
原数组:
a1,a2,a3, \(\cdots\) ,an前缀和数组:
si=a1+a2+ \(\cdots\) +ai,s0 = 0
① 如何求前缀和数组
Si:Si=Si-1+ai,s0 = 0② 前缀和数组的作用: 快速地求出原数组中一段数的和
一维前缀和
S[i]=S[i-1]+a[i]=a[1]+a[2]+ \(\cdots\) +a[i]
a[l]+ \(\cdots\) +a[r]=S[r]-S[l-1]
二维前缀和
S[i,j]表示a[i,j]左上角全部元素的和
S[i,j]=a[i,j]+S[i-1,j]+S[i,j-1]-S[i-1,j-1]
二位前缀和的作用: 快速求出矩阵数组中子矩阵的和
a[x1,y1](左上角) 到a[x2,y2](右下角) 的矩阵的元素之和为:
S[x2,y2]-S[x2,y1-1]-S[x1-1,y2]+S[x1-1,y1-1]
差分
差分, 即前缀和的逆运算
原数组:
a1,a2,a3, \(\cdots\) ,an构造差分数组:
b1,b2,b3, \(\cdots\) ,bn使得
ai=b1+b2+ \(\cdots\) +bi
一维差分
构造
bi=ai-ai-1,a0 = 0
b1=a1
b2=a2-a1
b3=a3-a2\(\quad\) \(\cdots\)
bn=an-an-1
由差分数组
b[]可推原数组a[]
ai=b1+b2+ \(\cdots\) +bi
操作: 对数组
a[], 区间[l,r]内所有数加c只需
b[l] += c,b[r+1] -= c
ai=b1+b2+ \(\cdots\) +bi
思想: 原数组
a[]全0, 差分数组b[]也全0给
a[1]赋值a1\(\Leftrightarrow\) 对区间[1,1]内数加a1\(\Leftrightarrow\)b1 += a1,b2 -= a1
void insert (int l,int r,int c)
{
b[l]+=c;
b[r+1]-=c;
}
初始化:
insert (i,i,a[i])
二维差分
原数组
a[i][j], 构造差分数组S[i][j]
a[i][j]表示S[i][j]左上角全部元素之和
S[i][j] + = c\(\longrightarrow\)a[i][j]右下角所有元素加c给
a[x1,y1](左上角) 到a[x2,y2](右下角) 的矩阵内所有元素加上c:
b[x1][y1] += c,b[x2+1][y1] -= c,b[x1][y2+1] -= c,b[x2+1][y2+1] += c
void insert (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;
}
初始化:
insert(i,j,i,j,a[i][j])

浙公网安备 33010602011771号