二維差分
阿新 • • 發佈:2020-11-30
二維差分
我們有一個矩陣,如下圖所示:
假設我們有這麼一個矩陣:
1 2 4 3 5 1 2 4 6 3 5 9
二維字首和公式:
sum[i][j]=sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1]+arr[i][j];
差分:
如果我們要在左上角是 (x1,y1),右下角是 (x2,y2) 的矩形區間每個值都 +a,如下圖所示
在我們要的區間開始位置(x1,y1)處 +c,根據字首和的性質,那麼它影響的就是整個黃色部分,多影響了兩個藍色部分,所以在兩個藍色部分 -c 消除 +c 的影響,
而兩個藍色部分重疊的綠色部分多了個 -c 的影響,所以綠色部分 +c 消除影響。所以對應的計算方法如下:
diff[x1][y1] += c; diff[x1][y2+1] -=c; diff[x2+1][y1] -=c; diff[x2+1][y2+1] += c;
差分矩陣:
diff[i][j]=arr[i][j]-arr[i-1][j]-arr[i][j-1]+arr[i-1][j-1];
差分陣列為:
1 1 2 -1 4 -5 -1 3 1 1 1 2 -6 3 -2 -4
求區間值:
要求左上角是(x1,y1),右下角是(x2,y2)的矩形區間內的值處理出字首和後也可以O(1)時間內求出來。
我們要求紫色部分的值,我們已知的是黃色部分的值,但它多了兩個藍色部分的值,而兩個藍色部分有重疊了個綠色部分
sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-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,表示一個操作。
輸出
程式碼:
#include<bits/stdc++.h> #include<algorithm> #include<cstring> using namespace std; const int MAXN = 1e3+6; const int MAXM = 1e3+6; int a[MAXN][MAXM] = {}; int diff[MAXN][MAXM] = {}; int main() { int n,m,q; freopen("data1.txt","r",stdin); cin>>n>>m>>q; int i, j; for (i=1; i<=n; i++) { for (j=1; j<=m; j++) { cin>>a[i][j]; diff[i][j] = a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1]; } } for (i=0; i<q; i++) { int x1, y1, x2, y2, c; cin>>x1>>y1>>x2>>y2>>c; diff[x1][y1] += c; diff[x1][y2+1] -=c; diff[x2+1][y1] -=c; diff[x2+1][y2+1] += c; } for (i=1; i<=n; i++) { for (j=1; j<=m; j++) { diff[i][j] += diff[i-1][j]+diff[i][j-1]-diff[i-1][j-1]; cout<<diff[i][j]<<" "; } cout<<endl; } return 0; }