两者之间的关系: a[n] = b[1]+b[2]+b[3]+……b[n];
a[n]是前缀和;
b[n]是差分;
tip : 两个数组本没有时时联动关系,对某一数组操作以后需要通过手动操作同步
考虑更新
在题目中,前缀和 就是 根据a[n] 构造一个 其前n项和 a[n] ;
差分 是 构造一个b[n] 让a[n] 是他的前n项和 ;
前缀和n
一维
类似数列
S[i] = a[1] + a[2] + ... a[i];a[l] + ... + a[r] = S[r] - S[l - 1];//最最重要的是思想for(int i=1;i<=n;i++)S[i] = S[i-1]+a[i];//每个i都有其对应的前缀和
二维
S[i, j] = 第i行j列格子左上部分所有元素的和;
以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵的和为:
S[x2, y2] - S[x1 - 1, y2] - S[x2, y1 - 1] + S[x1 - 1, y1 - 1];
for(int i=1;i<=n;i++)
for(int i=1;i<=m;i++)
{
s[i][j] = s[i-1][j]+s[i][j-1]-s[i-1][j-1];
}
差分
一维
给区间[l, r]中的每个数加上c:B[l] += c, B[r + 1] -= c
void insert(int l,int r,int c)
{
b[l]+=c;
b[r+1]-=c;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) insert(i,i,a[i]);
while (m -- )
{
int l,r,c;
scanf("%d%d%d",&l,&r,&c);
insert(l,r,c);
}
int sum=0;
for(int i=1;i<=n;i++)
{
sum+=b[i];
a[i]=sum;
//b[i]+=b[i-1];
}
for(int i=1;i<=n;i++) printf("%d ",a[i]);
return 0;
}
二维
给以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵中的所有元素加上c:
S[x1, y1] += c, S[x2 + 1, y1] -= c, S[x1, y2 + 1] -= c, S[x2 + 1, y2]+=c ;
void insert(int x1,int y1,int x2,int y2,int c)
{
b[x1][y1] += c;
b[x1][y2+1] -= c;
b[x2+1][y1] -= c;
b[x2+1][y2+1] += c;
}
int main()
{
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) scanf("%d",&a[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) insert(i,j,i,j,a[i][j]);
while(q--)
{
int x1,y1,x2,y2,c;
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&c);
insert(x1,y1,x2,y2,c);
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1];
//上面就很巧妙
for (int i = 1; i <= n; i ++ )
{
for (int j = 1; j <= m; j ++ ) printf("%d ", b[i][j]);
puts("");
}
return 0;
}
