前缀和&差分
前缀和子矩阵:
#include <iostream> using namespace std; const int N = 1010; int a[N][N],s[N][N]; int main() { int n,m,k; cin>>n>>m>>k; for(int i = 1;i<=n;i++) for(int j = 1;j<=m;j++) { cin>>a[i][j]; s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + a[i][j]; } while(k--) { int x1,y1,x2,y2; cin>>x1>>y1>>x2>>y2; int t = s[x2][y2] - s[x1-1][y2] - s[x2][y1-1] + s[x1-1][y1-1]; cout<<t<<endl; } return 0; }
s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + a[i][j];
差分:
#include <iostream> using namespace std; const int N = 100010; int a[N],b[N]; void insert(int l, int r, int c) { b[l] += c; b[r+1] -= c; } int main() { int n,m; cin>>n>>m; for(int i = 1;i<=n;i++) cin>>a[i]; for(int i = 1;i<=n;i++) insert(i, i, a[i]); while(m--) { int l,r,c; cin>>l>>r>>c; insert(l, r, c); } for (int i = 1; i<=n; i++) a[i] = a[i-1] + b[i]; for(int i = 1;i<n;i++) cout<<a[i]<<" "; cout<<a[n]<<endl; return 0; }
构造差分数组:a[i] = b[1] + b[2] + ... + b[i];
那么如何通过已知的a数组来得出b数组呢?通过insert(i,i,a[i]); b[l] += c; b[r+1] -= c;
可以模拟一下,比如
b[1] = b[1] + a[1] = a[1]; b[2] = -a[1];
b[2] = b[2] + a[2] = -a[1] + a[2];---> a[2] = a[1] + b[2] = b[1] + b[2] ; b[3] = -a[2];
b[3] = -a[2] + a[3]; ---> a[3] = a[2] + b[3] = b[1] + b[2] + b[3] ;b[4] = -a[3];
非常巧妙。
由a数组得到差分数组b之后,就可以通过前缀和,a[n] = a[n-1] + b[n];来输出a[n]即可。
同理二维差分矩阵,可以类似于从一维差分和前缀和子矩阵两种结合起来得到:
#include <iostream> using namespace std; const int N = 1010; int a[N][N],b[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,k; cin>>n>>m>>k; 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(k--) { 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++) a[i][j] = a[i-1][j]+a[i][j-1] - a[i-1][j-1] + b[i][j]; for(int i = 1;i<=n;i++){ for(int j = 1;j<=m;j++) cout<<a[i][j]<<" "; cout<<endl; } return 0; }
同样可以模拟一下:
b[1][1] = a[1][1];b[1][2] = -a[1][1] = -b[1][1], b[2][1] = -b[1][1];b[2][2] = a[1][1] = b[1][1];
b[1][2] = -b[1][1] + a[1][2], --->a[1][2] = b[1][1] + b[1][2], b[2][2] = -a[1][2]...
b[2][1] = -b[1][1] + a[2][1],--->a[2][1] = b[1][1] + b[2][1], b[2][2] = -a[2][1]...
b[2][2] = -a[1][2] - a[2][1] + b[1][1] + a[2][2],--->a[2][2] = a[1][2] + a[2][1] - b[1][1] = b[1][1] + b[1][2] + b[1][1] + b[2][1] - b[1][1] + b[2][2] = b[1][1] + b[1][2] + b[2][1] + b[2][2];
可以看到这样就可以得到a数组是b数组的前缀二维子矩阵和了。