前缀和(Python实现)

代码:

n, m = map(int, input().split())
a = list(map(int, input().split()))
prefix = [0] * (n + 2)
for i in range(n):
    prefix[i + 1] = prefix[i] + a[i]  # 求前缀和
# print(prefix)
for i in range(m):
    l, r = map(int, input().split())
    print(prefix[r] - prefix[l - 1])  # 求部分和

总结:

最开始没把这道题放在眼里,也不知道要用前缀和算法去做。直接用切片索引出来,结果时间超限。

后来去网上查了资料才知道前缀和这种算法:

前缀和是一种重要的预处理,能大大降低查询的时间复杂度。

咱们的代码先初始化一个数组,然后遍历数组求前缀和,最后在索引,就可以很快地求出来其中一段的和

### Python前缀和算法的概念及实现 #### 一、前缀和的基本概念 前缀和是一种高效的算法技术,主要用于优化区间求和问题。其核心思想是预先计算数组的部分和,以便在后续查询中能够快速获取任意区间的总和[^2]。 对于长度为 \( n \) 的数组 `arr`,定义一个新数组 `prefix_sum`,其中第 \( i \) 项表示从索引 0 到 \( i-1 \) 所有元素的累积和: \[ \text{prefix\_sum}[i] = \sum_{j=0}^{i-1} \text{arr}[j], \quad (1 \leq i \leq n+1) \] 这样,在需要计算某一段子数组 `[l, r]` 的和时,可以通过如下公式快速得出结果: \[ \text{Sum}(l, r) = \text{prefix\_sum}[r+1] - \text{prefix\_sum}[l] \] 这种方法的时间复杂度为预处理阶段 \( O(n) \),每次查询时间为 \( O(1) \)[^3]。 --- #### 二、Python 实现前缀和 以下是基于上述理论的一维前缀和的具体实现: ```python class PrefixSum: def __init__(self, nums): self.nums = nums self.prefix_sum = [0] * (len(nums) + 1) for i in range(len(nums)): self.prefix_sum[i + 1] = self.prefix_sum[i] + nums[i] def query(self, l, r): """返回[l, r]闭区间上的和""" return self.prefix_sum[r + 1] - self.prefix_sum[l] # 测试代码 if __name__ == "__main__": arr = [1, 2, 3, 4, 5] ps = PrefixSum(arr) # 查询不同区间的和 print(ps.query(1, 3)) # 输出: 9 (即 2 + 3 + 4) print(ps.query(0, 4)) # 输出: 15 (即整个数组之和) ``` 此代码实现了类 `PrefixSum` 来封装前缀和逻辑,并提供了一个便捷的方法来执行区间查询[^3]。 --- #### 三、二维前缀和简介及其 Python 实现 除了在一维数据上应用外,前缀和也可以扩展到二维矩阵中。假设有一个大小为 \( m \times n \) 的矩阵 `matrix`,可以构建一个辅助矩阵 `prefix_matrix`,满足以下条件: \[ \text{prefix\_matrix}[i][j] = \text{matrix}[i-1][j-1] + \text{prefix\_matrix}[i-1][j] + \text{prefix\_matrix}[i][j-1] - \text{prefix\_matrix}[i-1][j-1] \] 利用该结构,可迅速获得任何矩形区域 `(x1,y1)` 至 `(x2,y2)` 的和。 下面是对应的 Python 实现: ```python def build_prefix_matrix(matrix): rows, cols = len(matrix), len(matrix[0]) if matrix else 0 prefix_matrix = [[0] * (cols + 1) for _ in range(rows + 1)] for i in range(1, rows + 1): for j in range(1, cols + 1): prefix_matrix[i][j] = ( matrix[i - 1][j - 1] + prefix_matrix[i - 1][j] + prefix_matrix[i][j - 1] - prefix_matrix[i - 1][j - 1] ) return prefix_matrix def sum_region(prefix_matrix, x1, y1, x2, y2): return ( prefix_matrix[x2 + 1][y2 + 1] - prefix_matrix[x1][y2 + 1] - prefix_matrix[x2 + 1][y1] + prefix_matrix[x1][y1] ) # 测试代码 if __name__ == "__main__": matrix = [ [3, 0, 1, 4, 2], [5, 6, 3, 2, 1], [1, 2, 0, 1, 5], [4, 1, 0, 1, 7], [1, 0, 3, 0, 5] ] pm = build_prefix_matrix(matrix) result = sum_region(pm, 2, 1, 4, 3) print(result) # 输出应为8(对应于指定区域内的数值相加的结果) ``` 这段程序展示了如何创建并使用二维前缀和表来进行特定区域内值的汇总运算。 --- #### 四、总结 前缀和作为一种基础却强大的工具,极大地提升了针对连续序列或网格范围内求解效率的能力。无论是简单的一维列表还是复杂的多维度表格,都可以借助这一技巧显著减少重复劳动量,提高整体性能表现^。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值