登录以参加训练计划
前缀和
前缀和是一种重要的算法思想,在很多场景中都有广泛应用。
定义
对于一个给定的数组 arr,它的前缀和数组 prefixSum 中的第 i 个元素,是原数组 arr 中从第一个元素到当前位置的所有元素之和 。即 prefixSum[i] = arr[0] + arr[1] + ... + arr[i],其中 prefixSum[0] = arr[0]。
比如,对于数组 arr = [1, 2, 3, 4] ,它的前缀和数组 prefixSum 计算过程如下:
prefixSum[0] = arr[0] = 1;
prefixSum[1] = arr[0] + arr[1] = 1 + 2 = 3;
prefixSum[2] = arr[0] + arr[1] + arr[2] = 1 + 2 + 3 = 6;
prefixSum[3] = arr[0] + arr[1] + arr[2] + arr[3] = 1 + 2 + 3 + 4 = 10 。
最终得到前缀和数组 prefixSum = [1, 3, 6, 10] 。
####计算方式 在代码实现中,通常可以通过一次遍历原数组来计算前缀和数组。
int n;
cin>>n;
int a[n+1],sum[n+1];
for(int i=1;i<=n;i++){
cin>>a[i];
sum[i]=sum[i-1]+a[i];
}
常见用途
快速计算子数组的和:如果需要计算原数组中从索引 left 到索引 right(left <= right)的子数组的和,根据前缀和的性质,结果就是 prefixSum[right] - (prefixSum[left - 1] if left > 0 else 0) 。比如在上述数组 arr 中,要计算子数组 [2, 3] 的和,left = 1,right = 2 ,那么 prefixSum[2] - prefixSum[0] = 6 - 1 = 5 。这样通过预处理得到前缀和数组,就可以在 O(1) 的时间复杂度内完成子数组和的计算,而如果不使用前缀和,每次计算子数组和都需要遍历子数组,时间复杂度是 O(n)(n 为子数组长度) 。
区间统计问题:
在一些统计区间内满足特定条件的元素个数等问题中,前缀和也能发挥作用。比如给定一个数组和若干个区间,需要统计每个区间内大于某个阈值的元素个数,通过前缀和可以优化计算过程。
动态规划中的应用:#####
在某些动态规划问题中,前缀和可以帮助优化状态转移方程的计算,减少重复计算,提高算法效率。例如在一些求最大子数组和相关的动态规划问题中就会用到前缀和的思想。
差分数组的基础概念
差分数组并不是简单的相邻元素之差,而是用来表示原数组中每个位置与其前一位置的增量变化。对于一个长度为 的数组 ,其对应的差分数组 的定义如下:
- (第一个元素保持不变)
- 对于 ,
但是,当我们使用差分数组进行区间更新时,我们并不直接计算相邻元素的差值,而是利用差分数组的特性来进行高效的区间操作。
区间更新与差分数组
假设我们有一个数组 和一个差分数组 ,并且我们想要对 中从索引 到 (包括两端)的每个元素都增加一个值 。我们可以只在差分数组 上做两个修改:
- :表示从 开始增加 。
- :表示到 结束后不再增加 。
然后,通过对差分数组 求前缀和,我们可以恢复原始数组 更新后的状态。
例子
原始数组
构建差分数组
根据上述规则,差分数组 可以初始化为: 这里 ,而 对于 。
进行区间更新
假设我们要将 中索引 1 到 3(即第二个到第四个元素)的值各增加 2。我们只需在差分数组 上做以下两步:
更新后的差分数组变为:
恢复原始数组
为了得到更新后的 ,我们需要对差分数组 求前缀和: $ A'[3] = D[0] + D[1] + D[2] + D[3] = 1 + 3 + 1 + 1 = 6 $ $ A'[4] = D[0] + D[1] + D[2] + D[3] + D[4] = 1 + 3 + 1 + 1 - 1 = 5 $
因此,更新后的数组 是:
总结
在这个例子中,我们展示了如何使用差分数组高效地执行区间更新。关键点在于,我们只需要在差分数组的两端进行修改,然后通过求前缀和就可以恢复更新后的原数组。这种方法特别适用于需要频繁进行区间更新的情况,因为它避免了对每个元素逐一进行修改,从而大大提高了效率。
- 参加人数
- 4
- 创建人