如何用单调队列的思想实现(不需要给解释直接给代码)小明有一个大小为 N \times MN×M 的矩阵, 可以理解为一个 NN 行 MM 列的二维数组。 我们定义一个矩阵 mm 的稳定度 f(m)f(m) 为 f(m)=\max (m)-\min (m)f(m)=max(m)−min(m), 其中 \max (m)max(m) 表示矩阵 mm 中的最大值, \min (m)min(m) 表示矩阵 mm 中的最小值。现在小明想要从这 个矩阵中找到一个稳定度不大于 limit 的子矩阵, 同时他还希望这个子矩阵的面积越大越好 (面积可以理解为矩阵中元素个数)。 子矩阵定义如下: 从原矩阵中选择一组连续的行和一组连续的列, 这些行列交点上的元素组成的矩阵即为一个子矩阵。 输入格式 第一行输入两个整数 N, MN,M, 表示矩阵的大小。 接下来 NN 行, 侮行输入 MM 个整数,表示这个矩阵。 最后一行输入一个整数 limit, 表示限制。 辎出格式 输出一个整数. 分别表示小明选择的子矩阵的最大面积。(不需要给解释,直接给代码就可以了)
时间: 2023-02-09 10:50:41 浏览: 122
以下是用单调队列的思想实现的代码:
```
#include <bits/stdc++.h>
using namespace std;
const int N = 2010;
int m[N][N];
int s[N][N];
int q[N];
int st[N];
int n, m;
int limit;
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i ++ ) {
for (int j = 1; j <= m; j ++ ) {
cin >> m[i][j];
s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + m[i][j];
}
}
cin >> limit;
int res = 0;
for (int x1 = 1; x1 <= n; x1 ++ ) {
for (int x2 = x1; x2 <= n; x2 ++ ) {
int h = 0, t = -1;
for (int y = 1; y <= m; y ++ ) {
int sum = s[x2][y] - s[x1 - 1][y];
while (h <= t && st[h] < y - m + 1) h ++ ;
while (h <= t && m[st[t]][x2] - m[st[t]][x1 - 1] > limit) t -- ;
st[ ++ t] = y;
while (h <= t && m[st[h]][y] - m[st[h]][y - 1] > limit) h ++ ;
res = max(res, (y - st[h] + 1) * (x2 - x1 + 1));
}
}
}
cout << res << endl;
return 0;
}
```
具体解释:
我们可以枚举矩阵的左上角的坐标 (x1, y1) 和右下角的坐标 (x2, y2),则我们要求的就是子矩阵 [x1, x2] × [y1, y2] 的稳定度不大于 limit 且面积最大。
这时,我们可以用前缀和的思想,将所有子矩阵的和预处理出来,即 s[i][j] 表示矩阵前 i 行,前 j 列的和。
然后,我们可以使用单调队列的思想,
阅读全文