一维的差分序列
题目:https://www.acwing.com/activity/content/problem/content/831/
首先暴力解法就是每次询问的时候进行循环遍历进行相加。原理很简单,可以直接看代码。
暴力解法:
#include<iostream>
using namespace std;
const int N=1e5+10;
int n,m;
int a[N];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
while(m--)
{
int l,r,c;
scanf("%d%d%d",&l,&r,&c);
cin>>l>>r>>c;
for(int i=l;i<=r;i++)
{
a[i]+=c;
}
}
for(int i=1;i<=n;i++)
{
printf("%d ",a[i]);
}
return 0;
}
为了降低时间复杂度,可以采用差分法来解决。
构造两个整数数组a,b来分别存储原整数序列,存储原整数序列的差分项。
这句话有点难以理解,意思就是a里面存放的是正常题目给的东西,而b存放的是a的差分,a也就成为了b的前缀和。
举个例子方便理解:
......
也就是说,就是利用这个公式来初始化b数组的。
接下来细说具体是如何使用a,b来解决具体问题的
题目要求在(L、R)这个区间中的数字都加上整数C,那我们只需要给b[L]加上C这样会使得a[L]~a[n]中的数都加上C,因为我们要是的是区间中的加C,所以还要减去多加的a[R]后面的!也就是给b[R+1]减去C。
利用差分法解决:
#include<iostream>
using namespace std;
const int N=1e5+10;
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()
{
cin>>n>>m;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
//初始化b
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);
}
//已经通过b来完成了加减操作
//将b变成其前缀和数组即可
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;
}
接下来是二维的差分矩阵,先看题目
https://www.acwing.com/activity/content/problem/content/832/
解决方法比较类似之前二维前缀和矩阵的解决办法https://blog.csdn.net/qq_63055790/article/details/135567640
也是定义两个整数矩阵a和b,b矩阵是存放差分矩阵的。
然后类似于一维的,控制差分矩阵b来控制对于a与c的相加即可,具体如图所示
减去相应多加的c即可,道理都一样。
最后将b转为前缀和矩阵的时候与之前前缀和矩阵初始化是一样的。
#include<iostream>
using namespace std;
const int N=1010;
int n,m,q;
int a[N][N],b[N][N];
void insert(int x1,int y1,int x2,int y2,int c)
{
b[x1][y1]+=c;
b[x2+1][y1]-=c;
b[x1][y2+1]-=c;
b[x2+1][y2+1]+=c;
}
int main()
{
cin>>n>>m>>q;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
//初始化差分矩阵b
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;
cin>>x1>>y1>>x2>>y2>>c;
insert(x1,y1,x2,y2,c);
}
//将b矩阵转为前缀和矩阵输出
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++)
cout<<b[i][j]<<" ";
cout<<endl;
}
return 0;
}