差分矩阵

输入一个 n 行 m 列的整数矩阵,再输入 q 个操作,每个操作包含五个整数 x1,y1,x2,y2,c,其中 (x1,y1) 和 (x2,y2) 表示一个子矩阵的左上角坐标和右下角坐标。

每个操作都要将选中的子矩阵中的每个元素的值加上 c。

请你将进行完所有操作后的矩阵输出。

输入格式

第一行包含整数 n,m,q。

接下来 n 行,每行包含 m 个整数,表示整数矩阵。

接下来 q 行,每行包含 5 个整数 x1,y1,x2,y2,c,表示一个操作。

输出格式

共 n 行,每行 m 个整数,表示所有操作进行完毕后的最终矩阵。

数据范围

1≤n,m≤1000,
1≤q≤100000,
1≤x1≤x2≤n,
1≤y1≤y2≤m,
−1000≤c≤1000,
−1000≤矩阵内元素的值≤1000

输入样例:

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

 想必大家肯定了解一维差分的原理,一维差分的前缀和就是原数组,二维差分也是相同的原理,一维差分可以o(1)修改区间,而二维差分可以o(1)修改矩阵,我画了一个图,下面将根据这个图来介绍二维差分求原数组的原理

红色区域就是我们要修改的区域,假如我们要将红色区域内的所有数都加上c,那么我们就应该在整个红色区域左上方加c(默认左上角为坐标原点),那么计算整个红色区域前缀和的时候都会算上左上方的蓝色区域,但当计算红色区域以外的地方就应该取消这种影响,所以应该在两个粉色区域减去c,写一下前缀和的表达式就很容易明白了,由于我们在红色区域周围的一个点加了c,两个点减了c,所以为了保持平衡,我们还应该减去c,就是在红色区域右下方的第一个点减去c,建议大家好好理解这个地方,而刚开始加点就把矩形区域的左上方的点和右下方的点看成一个重合的点即可。细节见代码:

 

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
const int N=1003;
int s[N][N];
int main()
{
	int n,m,q;
	cin>>n>>m>>q;
	int x1,y1,x2,y2,c;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
	{
		scanf("%d",&c);
		s[i][j]+=c;
		s[i+1][j]-=c;
		s[i][j+1]-=c;
		s[i+1][j+1]+=c;
	}
	while(q--)
	{
		scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&c);
		s[x1][y1]+=c;
		s[x2+1][y1]-=c;
		s[x1][y2+1]-=c;
		s[x2+1][y2+1]+=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];
			printf("%d ",s[i][j]);
		}
		puts("");
	}
	return 0;
} 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值