#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int a[N][N],b[N][N],s[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()
{
int n,m,q;
cin>>n>>m>>q;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>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;
cin>>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++)
s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+b[i][j];
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
cout<<s[i][j]<<" ";
cout<<endl;
}
return 0;
}
二维差分
之前以为二维前缀和全是公式,其实公式是有其实际意义的,所以也不全是死记硬背
现在回想一下那个公式,其实自己也是可以现场推导出来的,公式的意思是,s
数组表示该点及其左上角所有点的和
给定我们一个矩阵左上角的顶点和右下角的顶点,我们要求这个矩阵内的所有点的和,使用二维前缀和,假设左上角的点的坐标是
(
x
1
,
y
1
)
(x_1,y_1)
(x1,y1),右下角的坐标是
(
x
2
,
y
2
)
(x_2,y_2)
(x2,y2),画格子来进行理解即可理解该公式的实际意义
ans=s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]
,最后加上的部分是被多减了一次,所以补回来
二维差分和一维差分是一样的,还是定义一个插入函数,差分的逆运算是前缀和,对差分数组b
数组进行操作,相当于对该点右下角的所有元素都进行了该操作,所以要实现某一个矩阵内的修改,只需要对左上角和右下角的顶点进行修改,但是,会出现有一些部分多减,所以需要在最后加回来,和二维前缀和一样,用画格子来进行理解是最方便的
插入函数如下
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;
}
如何构造差分数组呢
可以首先把a
数组看成是空数组,或者说全是0
的数组,那么b
数组自然就是a
数组的差分数组了,然后调用插入函数,相当于在一个一乘一的矩阵上插入a
数组的每一个元素,插入完成之后就构建好了b
数组
上面这个比较绕,建议是多思考一下
然后就是插入元素,求b
数组的前缀和,输出前缀和,前缀和就是修改后的答案数组
原文地址:https://blog.csdn.net/L3102250566/article/details/136047668
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_68385.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!