前缀和与差分

class NumArray {
int[] pre;
public NumArray(int[] nums) {
pre = new int[nums.length + 1];
for (int i = 0; i < nums.length; i++) pre[i + 1] = pre[i] + nums[i];
}
public int sumRange(int left, int right) {
return pre[right + 1] - pre[left];
}
}方法1:二维前缀和
325.和等于 k 的最长子数组长度
方法1:前缀和+Hash
方法1:前缀和
另,下面的是官方的解,说不上来哪里不一样,官方解执行了上面代码的前一种case,即将前部分的1都变成0 后部分的0都变成1 形如00000111这样的结果
方法2:朴素版DP
方法3:空间压缩DP
方法4:LIS+二分
一些名词
最长上升子序列($LIS$):
Longest Increasing Subsequence最长连续序列($LCS$):
Longest Consecutive Sequence最长连续递增序列($LCIS$):
Longest Continuous Increasing Subsequence最长公共子序列($LCS$):
Longest Common Subsequence
子串与子序列区别:子串不可跳跃,子序列可以跳跃,如 “AC”是“ABCDEFG”的子序列,而不是子串。 而“ABC”则是其子串
模板题是300题
TLE
差分数组
定义
对于一个长度大小为n的数组arr[n] 我们可以建立他的差分数组f[n]。其中f[i] = arr[i] - arr[i-1]。 例如 f[2] = arr[2] - arr[1]。
性质
(1) 可通过差分数组计算arr[i]的值: arr[i] = f[i] + f[i-1] + ... + f[0] 或 arr[i] = f[i] + arr[i-1] (2) 计算数组每一项的前缀和: 这里简单解释一下: 如果要求sum2 则sum2 = arr[0] + arr[1] + arr[2] 而每个arr[i] = f[i] + f[i-1] + ... + f[0] 故 sum2的求解中 f[0]出现3次 f[1]出现2次 f[2] 1次 故sum[2] = 3 * f[0] + 2 * f[1] + 1 * f[2]
用途
(1) 区间快速加减操作: 假如现在对数列中区间[L,R]上的数加上x,我们通过性质(1)知道,第一个受影响的差分数组中的元素为f[L], 即令f[L]+=x,那么后面数列元素在计算过程中都会加上x;最后一个受影响的差分数组中的元素为f[R], 所以令f[R+1]-=x,即可保证不会影响到R以后数列元素的计算。这样我们不必对区间内每一个数进行处理, 只需处理两个差分后的数即可。 (2) 询问区间和 求区间[l, r]的和即为 sum[R] - sum[L-1]
差分
差分是一种和前缀和相对的策略,可以当做是求和的逆运算。
这种策略的定义是令 $ b_i=\begin{cases} a_i-a_{i-1},\quad i\in [2,n]\ 1, \quad i=1 \end{cases} $
简单性质:
$a_i$的值是$b_i$的前缀和,即 $ a_i= \sum_{i=1}^n b_i $
计算 的前缀和 $ sum= \sum_{i=1}^n a_i =\sum_{i=1}^n\sum_{j=1}^i b_i =\sum_{i=1}^n (n-i+1)b_i $
它可以维护多次对序列的一个区间加上一个数,并在最后询问某一位的数或是多次询问某一位的数。注意修改操作一定要在查询操作之前。
差分
差分数组模板题
方法1:前缀和
方法1:前缀和+数学
选出一个奇数的前缀和一个偶数的前缀和,相减一定得到一个奇数,多少个奇数 * 多少个偶数 = 方案数
加上单独拉拉出来的奇数的前缀和的数量
另一种写法
1674. 使数组互补的最少操作数
差分
2121题的简化版本
方法1:前缀和+排序
另外一种写法
方法2:前缀和+快排
方法1:前缀和
本题类似926
另,不用可以统计前缀和
Reference
Last updated