二维前缀和入门:
(我们DP来预处理,dpleft [ i ight ]left [ j ight ]表示left ( 1,1 ight )这个点与left ( i,j ight )这个点两个点分别为左上角和右下角所组成的矩阵内的数的和,转移方程:)
(dpleft [ i ight ]left [ j ight ]=dpleft [i-1 ight ]left [j ight ]+dpleft [ i ight ]left [ j-1 ight ]-dpleft [ i-1 ight ]left [ j-1 ight ]+mpleft [ i ight ]left [ j ight ]left ( mpleft [ i ight ]left [ j ight ]表示二维表格left ( i,j ight )处的值 ight ))
预处理完毕,下面来讲怎么快速的得出我们想要的任意子矩阵中的和,我们定义(left ( x_{1},y_{1} ight )为我们想要的子矩阵的左上角,left ( x_{2},y_{2} ight )为我们想要的子矩阵的右下角)
那么由图可得,(dpleft [ x_{2} ight ]left [ y_{2} ight ]-dpleft [ x_{1}-1 ight ]left [ y_{2} ight ]-dpleft [ x_{2} ight ]left [ y_{1}-1 ight ]+dpleft [ x_{1}-1 ight ]left [ y_{1}-1 ight ])
模板代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define endl ' ' 4 typedef long long ll; 5 const int maxn = 1e3+10; 6 const int inf = 0x3f3f3f3f; 7 const ll mod=1e9+7; 8 9 int dp[maxn][maxn],mp[maxn][maxn]; 10 int n,m,k; 11 int main() 12 { 13 ios::sync_with_stdio(false); 14 cin>>n>>m>>k; 15 for(int i=1;i<=n;i++) 16 for(int j=1;j<=m;j++) 17 cin>>mp[i][j]; 18 19 memset(dp,0,sizeof(dp)); 20 for(int i=1;i<=n;i++) 21 for(int j=1;j<=m;j++) 22 dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+mp[i][j]; 23 24 for(int i=1;i<=k;i++){ 25 int x1,y1,x2,y2; 26 cin>>x1>>y1>>x2>>y2; 27 int ans=dp[x2][y2]-dp[x2][y1-1]-dp[x1-1][y2]+dp[x1-1][y1-1]; 28 cout<<ans<<endl; 29 } 30 return 0; 31 }
本博客图来自于:here