简单来说前缀和是指某序列的前n项和,就跟高等数学里的数列的前 n n n 项和一样。
举个例子:
B[5] = 1 2 3 4 5
A[5] = 1 3 6 10 15
那么A数组称为B数组的前缀和。很简单对吧
快速求出元素组中某段区间的和
输入一个长度为 n n n 的整数序列。
接下来再输入 m m m 个询问,每个询问输入一对 l , r l,r l,r。
对于每个询问,输出原序列中从第 l l l 个数到第 r r r 个数的和。
第一行包含两个整数 n n n 和 m m m。
第二行包含 n n n 个整数,表示整数数列。
接下来 m m m 行,每行包含两个整数 l l l 和 r r r,表示一个询问的区间范围。
共 m m m 行,每行输出一个询问的结果。
1 ≤ l ≤ r ≤ n , 1≤l≤r≤n, 1≤l≤r≤n,
1 ≤ n , m ≤ 100000 , 1≤n,m≤100000, 1≤n,m≤100000,
− 1000 ≤ 数 列 中 元 素 的 值 ≤ 1000 −1000≤数列中元素的值≤1000 −1000≤数列中元素的值≤1000
5 3
2 1 3 6 4
1 2
1 3
2 4
3
6
10
只要将前缀和数组初始化一下,然后根据询问的下标,拿两个数相减就可以了。(注意越界问题。一般从1下标开始取值和赋值)
# 前缀和模板
N = 100010
n,m=map(int,input().split())
a=[0]*N
s=[0]*N
a[1:n+1] = list(map(int,input().split()))
# 这一步是关键,初始化前缀和S
for i in range(1,n+1):
s[i] = s[i-1] + a[i]
while m:
l,r=map(int,input().split())
# 注意下标问题,为防止越界问题,一般都是从1下标开始取值和赋值
print(s[r] - s[l-1])
m -= 1
简单来说:差分可以看成前缀和的逆运算。
我们再拿上面的例子来说,只不过把A和B的位置换了一下。
例子:
A[5] = 1 3 6 10 15
B[5] = 1 2 3 4 5
那么A数组称为B数组的前缀和。和前面一样对吧,那么B数组就称为A数组的差分
其实通过上面一个例子,很容易得出差分数组B
的规律:
B[i] = A[i] - A[i-1]
当然你需要考虑下标问题,建议取值和赋值的时候是从下标1开始的,下标为0的数就初始化为0
快速使得元素组中某段区间的数加上一个常数
输入一个长度为 n n n 的整数序列
接下来输入 m m m 个操作,每个操作包含三个整数 l , r , c l,r,c l,r,c,表示将序列中 [ l , r ] [l,r] [l,r] 之间的每个数加上 c c c。
请你输出进行完所有操作后的序列。
第一行包含两个整数 n n n 和 m m m。
第二行包含 n n n 个整数,表示整数序列。
接下来 m m m 行,每行包含三个整数 l , r , c l,r,c l,r,c,表示一个操作。
共一行,包含 n n n 个整数,表示最终序列。
1 ≤ n , m ≤ 100000 , 1≤n,m≤100000 , 1≤n,m≤100000,
1 ≤ l ≤ r ≤ n , 1≤l≤r≤n, 1≤l≤r≤n,
− 1000 ≤ c ≤ 1000 , −1000≤c≤1000, −1000≤c≤1000,
− 1000 ≤ 整 数 序 列 中 元 素 的 值 ≤ 1000 −1000≤整数序列中元素的值≤1000 −1000≤整数序列中元素的值≤1000
6 3
1 2 2 1 2 1
1 3 1
3 5 1
1 6 1
3 4 5 3 4 2
这个性质要记住:
A A A 是 B B B 的前缀和数组,那么对 B B B 数组的 B [ i ] B[i] B[i] 修改,会影响到 A A A 数组中从 A [ i ] A[i] A[i] 及之后的每一个数。
理解了上面这条性质,就理解了差分,这个题目就很简单了。
我们只需要对 B [ l ] B[l] B[l] += c c c ,这样 A [ l ] A[l] A[l] 及之后的每一个数都会加上 c c c
我们再进行 B [ r + 1 ] B[r+1] B[r+1] —= c c c ,这样 A [ r + 1 ] A[r+1] A[r+1] 及之后的每一个数都会减去 c c c
这样我们就完成了对区间 [ l , r ] [l,r] [l,r] 的数加 c c c (注意越界问题。一般从1下标开始取值和赋值)
# 差分模板
N = 100010
a = [0]*N
b = [0]*N
# 对区间[l,r]的数加上常数c
def insert(l,r,c):
b[l] += c
b[r+1] -= c
n,q=map(int,input().split())
a = [0] + list(map(int,input().split()))
# 构造差分数组b
for i in range(1,n+1):
insert(i,i,a[i])
# 读入操作
while q:
l,r,c = map(int,input().split())
insert(l,r,c)
q -= 1
# 求差分数组b的前缀和即可得到数组a
for i in range(1,n+1):
b[i] += b[i-1]
# 输出结果
for j in range(1,n+1):
print(b[j],end=" ")
一维前缀和、一维差分都是很简单的,在比赛中,背下来关键步骤即可。至于二维前缀和、二维差分只不过是从一维数据变到了二维数据罢了,也就是矩阵。画个图也很容易理解。这里不再赘述了。
(ps:为了方便,一般从下标1开始取值和赋值。)