一维前缀和
对数组a[i]中前i个元素求和,记prefix_sum[i+1] = prefix_sum[i] + a[i] // prefix_sum[i]即为a[i]前缀和
计算一维前缀和
-
- prefix_sum[i+1] = prefix_sum[i] + a[i] // 前缀和数组下标从1开始
def p_sum(a,n):
"""
a为原数组,n为原数组的长度
"""
prefix_sum = [0] * (n+1) # 数组长度为n+1,数组的下标从1开始
# 将prefix_sum[0]定义为0的作用:减少对prefix_sum[0]的特判,
# 求区间[1,r]也可直接用公式计算:prefix_sum[r] - prefix_sum[0]
for i in range(n):
prefix_sum[i+1] = prefix_sum[i] + a[i]
前缀和的作用
用O(1)时间复杂度快速求出原数组中的一段区间和[l,r]:sum[l,r] = prefix_sum[r] - prefix_sum[l-1]
def main():
s = input().split()
n = int(s[0])
m = int(s[1])
s2 = input().split()
prefix_sum = [0] * (n+1)
for i in range(n):
prefix_sum[i+1] = prefix_sum[i] + int(s2[i])
while m:
s3 = input().split()
l = int(s3[0])
r = int(s3[1])
print(prefix_sum[r] - prefix_sum[l-1])
m -= 1
main()
二维前缀和
计算二维前缀和
prefix_sum[i+1][j+1] = prefix_sum[i][j+1] + prefix_sum[i+1][j] - prefix_sum[i][j]
def p_sum(arr,n.m):
"""
arr表示原数组,n表示行数,m表示列数
"""
prefix_sum = [[0] * (m+1) for _ in range(n+1)] # 生成一个前缀和矩阵,用于存放前缀和
for i in range(n):
for j in range(m):
prefix_sum[i+1][j+1] = prefix_sum[i][j+1] + prefix_sum[i+1][j] - prefix_sum[i][j]
二维前缀和计算区间[x1,y1,x2,y2]的和
sum[x1,y1,x2,y2]] = prefix_sum[x2][y2] - prefix_sum[x2][y1-1] - prefix_sum[x1-1][y2] + prefix_sum[x1-1][y2-1]
def main():
s1 = input().split()
n,m,q = int(s1[0]),int(s1[1]),int(s1[2])
prefix_sums = [[0] * (m+1) for j in range(n+1)]
for i in range(n):
line = input().split()
for j in range(m):
# 计算二维矩阵的前缀和
prefix_sums[i+1][j+1] = prefix_sums[i+1][j] + prefix_sums[i][j+1] - prefix_sums[i][j] + int(line[j])
while q:
s = input().split()
x1,y1,x2,y2 = int(s[0]),int(s[1]),int(s[2]),int(s[3])
res = prefix_sums[x2][y2] - prefix_sums[x2][y1-1] - prefix_sums[x1-1][y2] + prefix_sums[x1-1][y1-1]
q -= 1
print(res)
main()
差分
差分为前缀和的逆运算,b[i] = a[i] - a[i-1]
差分的作用
用O(1)的时间复杂度快速对区间[l,r]的所有元素加上一个值c
- 方法
def insert_c(lists,l,r,c):
"""
在差分数组中区间l-r之间插入一个数c
对差分数组求前缀和的时候,r右边的所有数由于进行了+c -c,所以插入的数不会对r右边的前缀和产生影响
:param lists: 差分数组
:param l: 区间左端点
:param r: 区间右端点
:param c: 要插入的数
:return:
"""
lists[l] += c
lists[r+1] -= c
def insert_c(lists,l,r,c):
"""
在差分数组中区间l-r之间插入一个数c
对差分数组求前缀和的时候,r右边的所有数由于进行了+c -c,所以插入的数不会对r右边的前缀和产生影响
:param lists: 差分数组
:param l: 区间左端点
:param r: 区间右端点
:param c: 要插入的数
:return:
"""
lists[l] += c
lists[r+1] -= c
def main():
s = input().split()
lists = input().split()
lists.insert(0,'0')
n,m = int(s[0]),int(s[1])
b = [0] * (n+10)
for i in range(1,n+1):
# insert的同时对r+1进行了-a[i]操作,等价于:b[i] = a[i] - a[i-1]
insert_c(b,i,i,int(lists[i]))
while m:
s1 = input().split()
l,r,c = int(s1[0]),int(s1[1]),int(s1[2])
insert_c(b,l,r,c)
m -= 1
for i in range(1,n+1):
b[i] += b[i-1]
print(b[i],end=' ')
if __name__ == '__main__':
main()