{\n cin >> n >> m >> q;\n // 预处理前缀和数组\n for(int i = 1; i \u003C= n; i++)\n {\n for(int j = 1; j \u003C= m; j++)\n {\n LL a; cin >> a;\n f[i][j] = f[i][j - 1] + f[i - 1][j] - f[i - 1][j - 1] + a;\n }\n }\n \n while(q--)\n {\n int x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2;\n cout \u003C\u003C f[x2][y2] - f[x1 - 1][y2] - f[x2][y1 - 1] + f[x1 - 1][y1 - 1] \u003C\u003C endl;\n }\n
时间: 2025-03-28 20:17:06 浏览: 30
这段代码实现了一个二维矩阵的前缀和查询功能。以下是逐步解析:
### 功能概述
该程序的主要目的是对一个 `n * m` 的二维矩阵进行预处理,并支持多次询问某个矩形区域内的元素总和。
---
### 具体步骤
#### 1. **输入数据**
```cpp
cin >> n >> m >> q;
```
从标准输入读取三个整数:
- `n`: 矩阵行数;
- `m`: 矩阵列数;
- `q`: 查询次数。
---
#### 2. **构建前缀和数组**
```cpp
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
LL a; cin >> a;
f[i][j] = f[i][j - 1] + f[i - 1][j] - f[i - 1][j - 1] + a;
}
}
```
##### 前缀和的核心思想:
对于每个位置 `(i, j)`,记录从左上角 `(1, 1)` 到当前位置 `(i, j)` 所有元素的累加值。公式为:
\[ \text{f}[i][j] = \text{f}[i][j-1] + \text{f}[i-1][j] - \text{f}[i-1][j-1] + \text{a} \]
其中,
- `\text{f}[i][j-1]` 表示当前行左边部分的累计值;
- `\text{f}[i-1][j]` 表示上面所有行到第 `j` 列为止的部分累计值;
- 减去 `\text{f}[i-1][j-1]` 是为了避免重复计算交集区域。
通过这种方式可以快速计算任意子矩阵的和。
---
#### 3. **响应查询**
```cpp
while (q--) {
int x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2;
cout << f[x2][y2] - f[x1 - 1][y2] - f[x2][y1 - 1] + f[x1 - 1][y1 - 1] << endl;
}
```
每次询问给定两个坐标点 `(x1, y1)` 和 `(x2, y2)`,表示需要求出矩形范围 `[x1:x2], [y1:y2]` 内的所有元素之和。
利用前缀和的特点,可通过以下公式直接得出结果:
\[ S(x_1,y_1,x_2,y_2) = f[x_2][y_2] - f[x_1 - 1][y_2] - f[x_2][y_1 - 1] + f[x_1 - 1][y_1 - 1] \]
解释:
- \(f[x_2][y_2]\): 包含整个目标矩形及其外部多余内容。
- 减掉两块多余的外延(上下左右),即 `- f[x_1 - 1][y_2]` 和 `- f[x_2][y_1 - 1]`。
- 加回多减的一小块重叠区域,即 `+ f[x_1 - 1][y_1 - 1]`。
---
### 总结
此算法的时间复杂度主要集中在以下几个阶段:
- 构建前缀和表的时间复杂度为 \(O(n \times m)\),仅需一次遍历即可完成。
- 每次查询可在常数时间 \(O(1)\) 完成。
这种高效的方式非常适合处理频繁区间查询的问题。
---
阅读全文
相关推荐



















