前缀和与差分
前缀和¶
- 前缀思想本质上是动态规划的一种
二维前缀和¶
//生成
vector<vector<int>>arr(mat.size()+1,vector<int>(mat[0].size()+1));
for(int i=1;i<=mat.size();i++)
{
for(int j=1;j<=mat[0].size();j++)
arr[i][j]=arr[i-1][j]+arr[i][j-1]+mat[i-1][j-1]-arr[i-1][j-1];
}
//查询
int getnum(vector<vector<int>>&arr,int x1,int y1,int x2,int y2)
{
return arr[x2+1][y2+1]-arr[x2+1][y1]-arr[x1][y2+1]+arr[x1][y1];
}
例题¶
特殊前缀和¶
例题¶
- 1862. 向下取整数对和
-
数学、划分区间(桶)
- 结合哈希表,不好想
其他前缀¶
- 前缀积
- 对于前缀积,我们可以用除法消去前 l−1 个数对结果的影响
- 如果有零不能直接除法,需要根据0进行特殊处理
- 前缀异或
- 可以再次异或消去前 l−1 个数对结果的影响
- 前缀与
- 可以对每一位取前缀,一个区间如果全部是1,那么与就是1,否则是0
例题¶
- 1352. 最后 K 个数的乘积
- 存在0的前缀积
- 1738. 找出第 K 大的异或坐标值
差分¶
- 差分数组方便修改,但是每次查询都需要遍历一遍差分数组(做一遍前缀和)来获得原数组。
- 可以快速对元素进行范围修改O(1),但是查询性能较差O(n)
- 若将al~ar之间的元素全部加上k,只有al-al-1会增大k,ar+1-ar会减小k
dif[l]+=k
dif[r+1]-=k
二维差分¶
# 生成差分
state[r1][c1] += 1
state[r1][c2 + 1] -= 1
state[r2 + 1][c1] -= 1
state[r2 + 1][c2 + 1] += 1
三维差分*¶
D[num(x1[i], y1[i], z1[i])] += d[i];
D[num(x2[i]+1,y1[i], z1[i])] -= d[i];
D[num(x1[i], y1[i], z2[i]+1)] -= d[i];
D[num(x2[i]+1,y1[i], z2[i]+1)] += d[i];
D[num(x1[i], y2[i]+1,z1[i])] -= d[i];
D[num(x2[i]+1,y2[i]+1,z1[i])] += d[i];
D[num(x1[i], y2[i]+1,z2[i]+1)] += d[i];
D[num(x2[i]+1,y2[i]+1,z2[i]+1)] -= d[i];
-
三维前缀和还原
-
分维度分别求和(二维前缀和同样可以使用这种方式)
```c++ for (int i=1; i<=A; i++) for (int j=1; j<=B; j++) for (int k=1; k<C; k++) //把x、y看成定值,累加z方向 D[num(i,j,k+1)] += D[num(i,j,k)]; for (int i=1; i<=A; i++) for (int k=1; k<=C; k++) for (int j=1; j<B; j++) //把x、z看成定值,累加y方向 D[num(i,j+1,k)] += D[num(i,j,k)]; for (int j=1; j<=B; j++) for (int k=1; k<=C; k++) for (int i=1; i<A; i++) //把y、z看成定值,累加x方向 D[num(i+1,j,k)] += D[num(i,j,k)];
```
例题¶
c++
class Solution {
public:
vector<int> corpFlightBookings(vector<vector<int>>& bookings, int n) {
vector<int>ans(n);
for(auto &a:bookings)//构建差分数组
{
ans[a[0]-1]+=a[2];
if(a[1]<n)
ans[a[1]]-=a[2];
}
for(int i=1;i<n;i++)//还原元素
{
ans[i]+=ans[i-1];
}
return ans;
}
};
```python
# 前缀还原
for i in range(1, len(state) - 1):
for j in range(1, len(state[0]) - 1):
state[i][j] += state[i][j - 1] + state[i - 1][j] - state[i - 1][j - 1]
```
-
离散化二维差分最强祝福力场