前缀和&差分
前提:数组从下标1开始存,下标为0的位置初始化为0
前缀和
前缀和数组和储存数据的数组长度一样
一般用来对数组预处理,多用于求区间和
一维
第i个位置储存前i个数之和
sum[i]=a[1]+a[2]+...+a[i]
sum[i]=sum[i-1]+a[i]
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]+a[i];
}
- 计算从位置
a[l]到a[r]的区间元素之和:sum[r]-sum[l-1]
二维
sum[i][j]表示以mat[1][1]为左上角,mat[i][j]为右下角的子矩阵的所有元素之和
sum[1][1]=mat[1][1];
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
//容斥原理
sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+mat[i][j];
}
}
- 计算以
mat[x1][y1]为左上角,mat[x2][y2]为右下角的矩阵中所有元素之和:sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1]
差分
差分是前缀和的逆运算
多用于实现区间修改
一维
- 先求原数组
a[]的差分数组diff[],a[]是diff[]的前缀和数组,所以diff[i]=a[i]-a[i-1] - 要实现数组区间
a[l]到a[r]上每个数加k,等效于diff[l]+=k,diff[r+1]-=k - 通过差分数组
diff[]还原新的原数组:a[i]=a[i-1]+diff[i]
差分标记数组diff[]:初始时diff[]的值全部为0,在diff[]上进行修改操作,然后对diff[]求前缀和 得到sum[],sum[i]是a[i]的修改量,在原a[]上再加上sum[],才可得到修改后的a[]
空间优化:
求完差分数组之后求原数组,直接在差分数组的基础上,把差分数组当成原数组进行计算,不需要开额外的空间存原数组
for(int i=1;i<=n;i++){
diff[i]+=diff[i-1];
}
//最后得到的diff数组就是原数组
二维
- 先求原数组
mat[][]的差分数组diff[][],diff[i][j]=mat[i][j]-mat[i-1][j]-mat[i][j-1]+mat[i-1][j-1] - 要实现以
mat[x1][y1]为右下角,mat[x2][y2]为左上角的矩阵中所有元素都加k,等效于diff[x1][y1]+=k,diff[x1][y2+1]-=k,diff[x2+1][y1]-=k,diff[x2+1][y2+1]+=k - 通过差分数组
diff[][]还原新的原数组:mat[i][j]=mat[i-1][j]+mat[i][j-1]-mat[i-1][j-1]+diff[i][j]

浙公网安备 33010602011771号