校园网站建设简介,有限公司和公司哪个好,请说明网站建设的一般过程包括哪些,河北做it的网站文章目录 原题链接题目描述输入格式输出格式数据范围输入样例#xff1a;输出样例#xff1a; 题目分析示例代码 原题链接
796. 子矩阵的和
题目难度#xff1a;简单
题目描述
输入一个 n 行 m 列的整数矩阵#xff0c;再输入 q 个询问#xff0c;每个询问包含四个整数… 文章目录 原题链接题目描述输入格式输出格式数据范围输入样例输出样例 题目分析示例代码 原题链接
796. 子矩阵的和
题目难度简单
题目描述
输入一个 n 行 m 列的整数矩阵再输入 q 个询问每个询问包含四个整数 x 1 , y 1 , x 2 , y 2 x_1, y_1, x_2, y_2 x1,y1,x2,y2表示一个子矩阵的左上角坐标和右下角坐标。
对于每个询问输出子矩阵中所有数的和。
输入格式
第一行包含三个整数 nmq。
接下来 n 行每行包含 m 个整数表示整数矩阵。
接下来 q 行每行包含四个整数 x 1 , y 1 , x 2 , y 2 x_1, y_1, x_2, y_2 x1,y1,x2,y2表示一组询问。
输出格式
共 q 行每行输出一个询问的结果。
数据范围
1≤n,m≤1000, 1≤q≤200000, 1≤x1≤x2≤n, 1≤y1≤y2≤m, −1000≤矩阵内元素的值≤1000
输入样例
3 4 3
1 7 2 4
3 6 2 8
2 1 2 3
1 1 2 2
2 1 3 4
1 3 3 4 输出样例
17
27
21 题目分析
对于一维的前缀和就是求某一段的前缀和这道题是二维数组中的前缀和是求任意区域的数字之和
如果每一次询问都是暴力算的话复杂度其实是极高的因此同样的我们还是需要用前缀和的做法
对于这个前缀和矩阵其中的每一个数就代表了包括这个数和他左上角的所有数的和
第一个问题就是如何计算这个前缀和矩阵我们的公式是什么这里我们就可以运用一下数学中容斥原理的思想或者可以理解为图形面积的加减
例如 我们是想要计算23的数字实际上就需要用13的数字加上22的数字也就是黄色包括绿色加上蓝色包括绿色但是这样我们就把绿色加了两遍因此需要减去一个绿色的12这样我们就算除了原本23对应的数字剩下数字的和最后只需要加上23原本的数字即可
用公式表示就是 S x , y S x − 1 , y S x , y − 1 − S x − 1 , y − 1 a x , y S_{x,y}S_{x-1,y}S_{x,y-1}-S_{x-1,y-1}a_{x,y} Sx,ySx−1,ySx,y−1−Sx−1,y−1ax,y
利用这个公式就可以计算出前缀和数组了
第二个问题就是假设我们已经有了前缀和数组我们如何快速算出子矩阵的和是多少这里的数学原理是与之前一样的 我们想要计算蓝色部分的子矩阵和其实只需要用对应的前缀和矩阵的33包括黄色绿色橙色减去13包括橙色绿色减去31包括黄色绿色这里绿色被减去了两次因此我们需要再加回来一次加上11绿色即可
我们使用 ( x 1 , y 1 ) (x_1,y_1) (x1,y1)表示子矩阵左上角的坐标用 ( x 2 , y 2 ) (x_2,_y2) (x2,y2)表示右下角的坐标最终结果用公式表示就是 a n s S x 2 , y 2 − S x 2 , y 1 − 1 − S x 1 − 1 , y 2 S x 1 − 1 , y 1 − 1 ans S_{x_2,y_2}-S_{x_2,y_1-1}-S_{x_1-1,y_2}S_{x_1-1,y_1-1} ansSx2,y2−Sx2,y1−1−Sx1−1,y2Sx1−1,y1−1
这就是二维前缀和的思想
示例代码
#includeiostream
using namespace std;const int N 1010; // 数据范围int n, m, q;
int arr[N][N], pre[N][N];int main()
{cin n m q;for (int i 1; i n; i) // 数据输入{for (int j 1; j m; j){cin arr[i][j];pre[i][j] pre[i - 1][j] pre[i][j - 1] - pre[i - 1][j - 1] arr[i][j]; // 计算前缀和矩阵}}while (q--){int x1, y1, x2, y2;cin x1 y1 x2 y2;cout pre[x2][y2] - pre[x1 - 1][y2] - pre[x2][y1 - 1] pre[x1 - 1][y1 - 1] \n; // 计算子矩阵的和}return 0;
}