前言😇
今天分享一下学到的基础算法前缀和。 首先了解一下前缀和的基础概念 😄 有一个序列,序列内包含很多数a1、a2、a3、a4、a5、a6、a7 a1的前缀和就是a1 a2的前缀和就是a1+a2 a3的前缀和就是a1+a2+a3 … 此时可以定义一个序列bn专门用于存放关于an的前缀和 b1、b2、b3、b4、b5、b6、b7… 使得:
b1=a1 b2=a1+a2 b3=a1+a2+a3 …
这样就得到了一个关于a序列的前缀和序列,在进行一些运算的时候可以大大的降低时间复杂度。 写题的时候步骤就是
- (1)确定前缀和序列
- (2)使用位置关系对前缀和序列进行查询,得到想要的结果
具体如何用听我细细道来
一维前缀和😈
问题描述
输入一个长度为n的整数序列。 接下来再输入m个询问,每个询问输入一对l, r。 对于每个询问,输出原序列中从第l个数到第r个数的和。 输入格式 第一行包含两个整数n和m。 第二行包含n个整数,表示整数数列。 接下来m行,每行包含两个整数l和r,表示一个询问的区间范围。 输出格式 共m行,每行输出一个询问的结果。 数据范围 1≤l≤r≤n, 1≤n,m≤100000, ?1000≤数列中元素的值≤1000 输入样例: 5 3 2 1 3 6 4 1 2 1 3 2 4 输出样例: 3 6 10
问题分析
对于一维前缀和直接构造前缀和序列即可,然后打印l与r位置的前缀和元素之差。 可以将所有的结果先添加到一个序列中,在输入所有操作之后一块打印。
代码实现
老规矩先上运行结果:
'''
import sys
n,m=sys.stdin.readline().strip().split()
n,m=int(n),int(m)
nls=[]
ans=[]
ls=[int(x) for x in sys.stdin.readline().strip().split()]
for i in range(m):
l,r=sys.stdin.readline().strip().split()
l,r=int(l),int(r)
sum=0
for i in range(l-1,r):
sum+=ls[i]
ans.append(sum)
print(ans)
'''
'''
先将数据处理一下,然后在进行计算的时候就是进行查询
显然进行查询要方便的多。
'''
import sys
n,m=sys.stdin.readline().strip().split()
n,m=int(n),int(m)
ls=[int(x) for x in sys.stdin.readline().strip().split()]
als=[]
ans=[]
als.append(0)
ans.append(0)
als.append(ls[0])
for j in range(1,n):
als.append(als[len(als)-1]+ls[j])
for i in range(m):
l,r=sys.stdin.readline().strip().split()
r,l=int(r),int(l)
ans.append(als[r]-als[l-1])
for i in range(1,m+1):
print(ans[i])
二维前缀和👿
问题描述
输入一个n行m列的整数矩阵,再输入q个询问,每个询问包含四个整数x1, y1, x2, y2,表示一个子矩阵的左上角坐标和右下角坐标。 对于每个询问输出子矩阵中所有数的和。 输入格式 第一行包含三个整数n,m,q。 接下来n行,每行包含m个整数,表示整数矩阵。 接下来q行,每行包含四个整数x1, y1, x2, y2,表示一组询问。 输出格式 共q行,每行输出一个询问的结果。 数据范围 1≤n,m≤1000, 1≤q≤200000, 1≤x1≤x2≤n, 1≤y1≤y2≤m, ?1000≤矩阵内元素的值≤1000 输入样例: 3 4 3 1 7 2 4 3 6 2 8 2 1 2 3 1 1 2 2 2 1 3 4 1 3 3 4 输出样例: 17 27 21
问题分析
应准备一个矩阵,一个用于存放以(1,1)与(x1,y1)矩阵中的元素和 在进行求取面积内元素和的时候,使用矩阵元素之间的关系。 此时面临两个问题(可以配合图片进行理解): 对于以下图片中均是左边代表原始矩阵,右边代表和矩阵
一、矩阵求求和 对应颜色矩阵的框所有数的和求出来后放进对应颜色的位置 由于矩阵叠加,所以我们在进行求和的时候应先加然后再减去叠加的部分故可得: b33=a33+b32+b23-b22 二、矩阵求差 (这也是最终面临的问题) 由于矩阵叠加,所以我们在进行求差的时候应先减去矩阵周围的矩阵和,然后加上重复减去的部分: 故可得下标为a22与a33围成的矩阵所有元素和为:b22-33=b33-b31+b13+b11 这里进行求解的时候可能面临坐标交换,a22-a33围成的矩阵,与a32-a23围成的是一个矩阵 所以我们不妨将ax1y1中的下标均换成最小的便于计算。(也就是说转换成x1<x2,y1<y2) 然后以最小的坐标与最大的坐标为界,减去所求矩阵周围的矩阵
代码实现
老规矩先上运行结果:
import sys
ans=[]
amatrix=[]
bmatrix=[]
n,m,q=sys.stdin.readline().strip().split()
n,m,q=int(n),int(m),int(q)
for i in range(n+1):
bmatrix.append([0]*(m+1))
for i in range(n):
amatrix.append([int(x) for x in sys.stdin.readline().strip().split()])
i=1
while i<=n:
j=1
while j<=m:
bmatrix[i][j]=amatrix[i-1][j-1]+bmatrix[i][j-1]+bmatrix[i-1][j]-bmatrix[i-1][j-1]
j+=1
i+=1
qm=[]
for i in range(q):
qm.append([int(x) for x in sys.stdin.readline().strip().split()])
i=0
while i<q:
if qm[i][0]>qm[i][2]:
qm[i][0],qm[i][2]=qm[i][2],qm[i][0]
if qm[i][1]>qm[i][3]:
qm[i][1],qm[i][3]=qm[i][3],qm[i][1]
ans.append(bmatrix[qm[i][2]][qm[i][3]]-bmatrix[qm[i][0]-1][qm[i][3]]-bmatrix[qm[i][2]][qm[i][1]-1]+bmatrix[qm[i][0]-1][qm[i][1]-1])
i+=1
print(ans)
????????💯
???? ? ???? ????
|