文章目录
前缀和&差分 详解、总结及例题
前缀和
用于解决区间累加及查询问题。
通俗易懂解读传送门:
点击此处 (参考文章及图片来源,特别是前缀和部分很清楚)
一维前缀和
第一步:预处理(求前缀和数组)
假设原数组为 a[] , 定义一个 sum[] 数组,sum[i] 代表 a 数组中前 i 个数的和。即:
s
u
m
[
i
]
=
s
u
m
[
i
−
1
]
+
a
[
i
]
sum[i] = sum[i - 1] + a[i]
sum[i]=sum[i−1]+a[i]
时间复杂度为 O(n) 。注意,a[0] = 0 , 前缀和从索引为1的数组开始,防止越界。
第二步:查询操作
假设需要查询 [l,r] 的和,只需计算:
a
n
s
=
s
u
m
[
r
]
−
s
u
m
[
l
−
1
]
ans = sum[ r ] - sum[l -1]
ans=sum[r]−sum[l−1]
时间复杂度为 O(1) 。
例题
点击此处 洛谷P3131:[USACO16JAN]Subsequences Summing to Sevens S
二维前缀和
第一步:预处理(求前缀和数组)
假设原数组为 a[ ][ ] , 如下图所示,定义一个 sum[ ][ ] 数组,右下角坐标为 (i , j) 的前缀和为
s
u
m
[
i
]
[
j
]
=
s
u
m
[
i
−
1
]
[
j
]
+
s
u
m
[
i
]
[
j
−
1
]
−
s
u
m
[
i
]
[
j
]
+
a
[
i
]
[
j
]
sum[i] [j] = sum[ i - 1] [j] + sum[i] [j - 1] - sum[ i ] [ j ] + a[i] [j]
sum[i][j]=sum[i−1][j]+sum[i][j−1]−sum[i][j]+a[i][j]
注意:数组先初始化为0,前缀和计算从s[ 1 ] [ 1 ] 开始,防止越界。
第二步:查询操作
以(x1,y1)为左上角,(x2,y2)为右下角的子矩阵,查询其和的公式为:
a
n
s
=
s
u
m
[
x
2
]
[
y
2
]
−
s
u
m
[
x
1
−
1
]
[
y
2
]
−
s
u
m
[
x
2
]
[
y
1
−
2
]
+
s
u
m
[
x
1
−
1
]
[
y
1
−
1
]
ans = sum[x_2][y_2] - sum[x_1 - 1][y_2] - sum[x_2][y_1-2] + sum[x_1-1][y_1-1]
ans=sum[x2][y2]−sum[x1−1][y2]−sum[x2][y1−2]+sum[x1−1][y1−1]
例题
点击此处 洛谷P2280 [HNOI2003]激光炸弹
差分
前缀和的逆运算,用于对数组进行快速多次的批量运算。
一维差分
通俗易懂解读传送门:
点击此处(参考视频,特别是差分部分)
第一步:预处理(求差分数组)
假设原数组为 a[ ] , 先求出它的差分数组,时间复杂度O(n)
d
[
i
]
=
a
[
i
]
−
a
[
i
−
1
]
d[ i ] = a[ i ] - a[i - 1]
d[i]=a[i]−a[i−1]
第二步:差分数组批量运算
对[l , r] 区间加 v , 只需进行以下操作:
d
[
l
]
+
=
v
;
d
[
r
+
1
]
−
=
v
d[l] += v; d[r + 1] -=v
d[l]+=v;d[r+1]−=v
注意:假设原数组区间长度为 n , 需要对[1 , n]加v,此时差分数组应开大一些,防止越界。
第三步:对差分数组做前缀和
对 d[ ] 数组做一次前缀和,即可求出原数组。
例题
点击此处 洛谷P4552 [Poetize6] IncDec Sequence
二维差分
第一步:预处理(求差分数组)
假设原数组为 a[ ][ ] ,先求差分数组为 d[ ][ ] ,时间复杂度为O(n),操作如下:
d
[
i
]
[
j
]
=
a
[
i
]
[
j
]
−
a
[
i
−
1
]
[
j
]
−
a
[
i
]
[
j
−
1
]
+
a
[
i
−
1
]
[
j
−
1
]
d[i][j] = a[i][j] - a[i-1][j] - a[i][j-1]+a[i-1][j-1]
d[i][j]=a[i][j]−a[i−1][j]−a[i][j−1]+a[i−1][j−1]
第二步:差分数组批量运算
现在要将 (x1,y1) 到 (x2,y2) 这一矩阵里的数全部加 v ,进行如下操作即可,时间复杂度为O(n) 。
d
[
x
1
]
[
y
1
]
+
=
v
;
d
[
x
2
+
1
]
[
y
1
]
−
=
v
d[x_1][y_1] += v;d[x_2 + 1][y_1] -= v
d[x1][y1]+=v;d[x2+1][y1]−=v
d [ x 1 ] [ y 2 + 1 ] − = v ; d [ x 1 − 1 ] [ y 1 − 1 ] + = v d[x_1][y_2+1]-=v;d[x_1-1][y_1-1]+=v d[x1][y2+1]−=v;d[x1−1][y1−1]+=v
第三步:对差分数组做前缀和
对二维差分数组做前缀和,步骤同上二位前缀和。
例题
点击此处 洛谷P3397 地毯
简便方法
对于一二维差分数组,其实我们并不需要求出差分数组,直接假设差分数组为0就好,最后再将原数组加上差分数组就好,相当于加上改变的量。