AcWing 798. 差分矩阵

差分是与前缀和互逆的,所以可以用前缀和的公式推差分的公式

\[c[i][j]=a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1] \]

矩阵加减可以由定义分析,也可以换个思路 \(a[x][y]= \sum_{i=1}^{x} \sum_{j=1}^{y} c[i][j]\)
\(c[x][y]+1\) 等于把 以 \((x,y)\) 为左上角 \((n,m)\) 为右下角的矩阵中的 \(a[i][j]\) 都加上 \(1\).
由此推更快。

Code:

#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<bitset>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;
typedef long long LL;
typedef unsigned long long ULL;

const int N=1024;

int n,m,q;
LL a[N][N],c[N][N];

int main()
{
//	freopen("1.in","r",stdin);
	int i,j;
	int x1,y1,x2,y2;
	LL z;
	scanf("%d%d%d",&n,&m,&q);
	for(i=1;i<=n;i++) 
		for(j=1;j<=m;j++) 
			scanf("%lld",&a[i][j]);
	
	for(i=1;i<=n;i++) 
		for(j=1;j<=m;j++) 
			c[i][j]=a[i][j]+a[i-1][j-1]-a[i-1][j]-a[i][j-1];
	
	while(q--) {
		scanf("%d%d%d%d%lld",&x1,&y1,&x2,&y2,&z);
		c[x1][y1]+=z;
		c[x1][y2+1]-=z;
		c[x2+1][y1]-=z;
		c[x2+1][y2+1]+=z;
	}
	memset(a,0,sizeof a);
	for(i=1;i<=n;i++) 
		for(j=1;j<=m;j++) 
			a[i][j]=a[i-1][j]+a[i][j-1]-a[i-1][j-1]+c[i][j];
	
	for(i=1;i<=n;i++,printf("\n")) 
		for(j=1;j<=m;j++) 
			printf("%lld ",a[i][j]);
	return 0; 
}
posted @ 2020-11-28 21:06  cjlworld  阅读(112)  评论(0编辑  收藏  举报