知识点:单调队列
难度:5
单调队列的练习题,原先我们练习的都是一维序列上面的单调队列,这里是二维的,具体的方法就是我们先对每一行用单调队列,储存在两个数组里面,一个存最大值,一个存最小值,然后我们对每一列的元素求单调队列,从左到右,从上到下,再分别储存在两个数组里面,这样得到的的数据就是,以那个元素为右下角的矩形(正方形)的最大最小值了,重点是这个要想明白,这个题就好做了
#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
int main() {
int n, m, d;
cin >> n >> m >> d;
int a[N][N];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) cin >> a[i][j];
}
int b[N][N], c[N][N];
for (int i = 1; i <= n; i++) {
deque<int> q1, q2;
for (int j = 1; j <= m; j++) {
if (!q1.empty() && q1.front() + d == j) q1.pop_front();
if (!q2.empty() && q2.front() + d == j) q2.pop_front();
while (!q1.empty() && a[i][j] >= a[i][q1.back()]) q1.pop_back();
while (!q2.empty() && a[i][j] <= a[i][q2.back()]) q2.pop_back();
q1.push_back(j);
q2.push_back(j);
b[i][j] = a[i][q1.front()];
c[i][j] = a[i][q2.front()];
}
}
int e[N][N], f[N][N];
for (int i = 1; i <= m; i++) {
deque<int> q1, q2;
for (int j = 1; j <= n; j++) {
if (!q1.empty() && q1.front() + d == j) q1.pop_front();
if (!q2.empty() && q2.front() + d == j) q2.pop_front();
while (!q1.empty() && b[j][i] >= b[q1.back()][i]) q1.pop_back();
while (!q2.empty() && c[j][i] <= c[q2.back()][i]) q2.pop_back();
q1.push_back(j);
q2.push_back(j);
e[j][i] = b[q1.front()][i];
f[j][i] = c[q2.front()][i];
}
}
int ans = 1e9;
for (int i = d; i <= n; i++) {
for (int j = d; j <= m; j++) ans = min(ans, e[i][j] - f[i][j]);
}
cout << ans;
return 0;
}