解法一:暴力解法
每次询问都遍历小矩阵求和,时间复杂度为O(n * m * q),会超时。
解法二:前缀和
与一维前缀和类似,两步走:
第一步:预处理出一个前缀和数组
用dp[i][j]表示从[0][0]位置到[i][j]位置所有元素的和,则有:dp[i][j] = dp[i][j - 1] + dp[i - 1][j] - dp[i - 1][j - 1] + matrix[i][j]
,遍历矩阵一遍,可以得到一个完整的前缀和数组
第二步:使用前缀和数组
得到前缀和数组后,可以以O(1)时间得到[x1][y1]到[x2][y2]的元素和:
为了便于处理边界情况,将matrix与dp的行和列分别扩充1。
考虑到数据的范围,将dp存储的数据类型设置为 long long类型
#include <iostream> #include <vector> using namespace std; typedef long long ll; int main() { int n = 0, m = 0, q = 0; cin >> n >> m >> q; vector<vector<int>> matrix(n + 1, vector<int>(m + 1)); //输入数据 for(int i = 1; i < n + 1; ++i) { for (int j = 1; j < m + 1; ++j) { cin >> matrix[i][j]; } } vector<vector<ll>> dp(n + 1, vector<ll>(m + 1)); //预处理前缀和矩阵 for(int i = 1; i < n + 1; ++i) { for (int j = 1; j < m + 1; ++j) { dp[i][j] = dp[i][j - 1] + dp[i - 1][j] - dp[i - 1][j - 1] + matrix[i][j]; } } int x1 = 0, y1 = 0, x2 = 0, y2 = 0; //使用前缀和矩阵 while(q--) { cin >> x1 >> y1 >> x2 >> y2; cout << dp[x2][y2] - dp[x2][y1 - 1] - dp[x1 - 1][y2] + dp[x1 - 1][y1 - 1] << endl; } return 0; }