二維差分(差分與字首和的下标都從1開始,避免出現越界)
題目描述:
輸入一個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
算法公式:在x1,y1,x2,y2,區間内+x就是sum[x1][y1]+=w、 sum[x2+1][y1]-=w、sum[x1][y2+1]-=w、sum[x2+1][y2+1]+=w。
圖解:
想在黃色區間内+x,則要在sum[x1][y1]+=w
但是 會影響綠色區間以及藍色區間,是以需要減掉 sum[x2+1][y1]-=w、sum[x1][y2+1]-=w。
但是黑色區間被減了兩次,是以需要加回一次,sum[x2+1][y2+1]+=w
最後再使用二維字首和即可求得答案
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
namespace IO{
inline LL read(){
LL o=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){o=o*10+c-'0';c=getchar();}
return o*f;
}
}using namespace IO;
const int N=1e3+7,base=1e9;
int sum[N][N];
void Insert(int x1,int y1,int x2,int y2,int x){//二維差分
sum[x1][y1]+=x;
sum[x2+1][y1]-=x;
sum[x1][y2+1]-=x;
sum[x2+1][y2+1]+=x;
}
int main(){
int n,m,k;
n=read(),m=read(),k=read();
for(int i=1;i<=n;i++){
for(int x,j=1;j<=m;j++){
x=read();
Insert(i,j,i,j,x);//在目前位置插入,就在目前位置的下一個位置減去貢獻
}
}
int x1,x2,y1,y2,x;
while(k--){
x1=read(),y1=read(),x2=read(),y2=read(),x=read();
Insert(x1,y1,x2,y2,x);//差分
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){//二維字首和
sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
printf("%d ",sum[i][j]);
}
printf("\n");
}
return 0;
}