差分
差分
差分与前缀和互为逆运算。对于一个普通数组a[ ],通过构造差分数组b[ ]可以使得a[i] = b[1]+b[2]+....+b[i]。
我们发现a[ ]数组是b[ ]数组的前缀和,而b[ ]数组就是a[ ]数组的差分。通过b[ ]数组求a[ ]数组就是求前缀和的过程,其时间复杂度为O(n)。
如何构造差分数组呢?
朴素公式:b[n] = a[n] - a[n - 1]
insert函数:也就是下面作用里讲到的,只不过在这里我们假设数组a[]全部为0,那么b[]也全为0。在此基础上调用insert(i,i,a[i]),实际就是在b[i] + a[i]、b[i + 1] - a[i]去构造数组。就相当于在数组a[ ]的区间[i,i]加a[i],说明这种做法是正确的。
PS:这里有点绕不能理解就用朴素公式,但是注意这里你理解了,接下来的二维差分就能用insert函数构造差分数组。
void insert(int l,int r,int c)
{
b[l] += c;
b[r + 1] -=c;
}
作用:如果现在我们要对数组a[ ]的[l,r]项都加上c,如果我们暴力扫一遍时间复杂度为O(n),但是通过差分可以做到O(1)时间复杂度。具体操作是在b[l] + c,那么a[l]...a[n]都会加上c。接着在b[r + 1] - c,那么a[r + 1]...a[n]就会不受加c的影响。
797 差分
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 100010;
int n,m;
int a[N],b[N];
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]);
b[i] = a[i] - a[i - 1];
while(m--)
{
int l, r, c;
scanf("%d%d%d",&l,&r,&c);
insert(l, r, c);//区间l-r加c的预处理
}
for (int i = 1; i <= n; i ++ ) b[i] += b[i - 1];//构造前缀和
for (int i = 1; i <= n; i ++ ) printf("%d ",b[i]);
return 0;
}
/*
6 3
1 2 2 1 2 1
1 3 1
3 5 1
1 6 1
3 4 5 3 4 2
*/
798 差分矩阵
二维差分
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1010;
int n,m,q;
int a[N][N],b[N][N];
//核心
void insert(int i1,int j1,int i2,int j2,int c)
{
b[i1][j1] += c;
b[i1][j2 + 1] -= c;
b[i2 + 1][j1] -= c;
b[i2 + 1][j2 + 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;
}
/*
3 4 3
1 2 2 1
3 2 2 1
1 1 1 1
1 1 2 2 1
1 3 2 3 2
3 1 3 4 1
2 3 4 1
4 3 4 1
2 2 2 2
*/