遇到区间求和先问自己3个问题,如果都能回答,那前缀和就被你拿捏了~
第一个问题:前缀和是个啥?
顾名思义,前缀和就是前缀的元素求和,一个区间的总数和sum(a[l:r])
第二个问题:为什么要学前缀和?
因为它就像一个火箭,装上它的程序速度直接起飞!时间复杂度从O(n*m)降到O(n)。
第三个问题:那前缀和怎么学习呢?
很简单,先理解原理,再背背模板,最后刷题巩固就掌握了。(╹ڡ╹ )
#线性DP-前缀和模板
for i in range(1,n):
dp[i]=dp[i-1]+a[i]
print(dp[r]-dp[l-1])
'''
参数说明:
n个数,区间左端点l,区间右端点r,
权值列表a,前缀和列表dp
测试样例:
n 1 2 3
a= [0, 7, 5, 6]
dp=[0, 7, 12, 18]
'''
10 3
7 5 6 4 2 5 0 8 5 3
1 5
2 6
3 7
24
22
17
解决这种问题一般有两种方法:暴力枚举和动态规划。
建议先写一版暴力枚举,能过一半的测试案例。
然后再写动态规划版的代码,过所有的测试案例,得满分。
1、输入:先输入题目里的一堆参数 n ,m ,a ,l , r。
2、计算:再构建前缀和列表dp,计算出所有的前缀和保存起来。
3、输出:最后输出两个区间端点对应的前缀和之差。
#暴力枚举-大学里的树木要维护
n,m=map(int,input().split())
a=list(map(int,input().split()))
for i in range(m):
l,r=map(int,input().split())
print(sum(a[l-1:r]))
#线性DP-大学里的树木要维护
n,m=map(int,input().split()) #n棵树 m个区间
a=[0]+list(map(int,input().split())) #维护开销
dp=[0 for i in range(n+1)] #前缀和列表
for i in range(1,n+1): #遍历1~n
dp[i]=dp[i-1]+a[i] #计算前缀和
for i in range(m): #m次询问
l,r=map(int,input().split()) #区间左右
print(dp[r]-dp[l-1]) #两和作差
print(dp)
'''
样例输入:
10 3
7 5 6 4 2 5 0 8 5 3
1 5
2 6
3 7
测试样例:
n 1 2 3 4 5 6 7 8 9 10
a= [0, 7, 5, 6, 4, 2, 5, 0, 8, 5, 3 ]
dp=[0, 7, 12, 18, 22, 24, 29, 29, 37, 42, 45]
'''
读码上万行,下键如有神,撸起袖子加油干!