题目描述
有一个 \(a \times b\) 的整数组成的矩阵,现请你从中找出一个 \(n \times n\) 的正方形区域,使得该区域所有数中的最大值和最小值的差最小。
输入格式
第一行为 \(3\) 个整数,分别表示 \(a,b,n\) 的值。
第二行至第 \(a+1\) 行每行为 \(b\) 个非负整数,表示矩阵中相应位置上的数。每行相邻两数之间用一空格分隔。
输出格式
仅一个整数,为 \(a \times b\) 矩阵中所有“ \(n \times n\) 正方形区域中的最大整数和最小整数的差值”的最小值。
样例 #1
样例输入 #1
5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
样例输出 #1
1
提示
问题规模。
矩阵中的所有数都不超过 \(1,000,000,000\)。
\(20\%\) 的数据 \(2 \le a,b \le 100,n \le a,n \le b,n \le 10\)。
\(100\%\) 的数据 \(2 \le a,b \le 1000,n \le a,n \le b,n \le 100\)。
浅浅谈一下
就是要找 \(n\times n\) 大小的矩阵
我们进行以下两种操作
- 每行扫一次单调队列,得出来的矩阵为长度为 \(n\),宽度为 \(1\) 的链
- 扫完之后每列扫一次单调队列,得出来的矩阵长度为 \(n\),宽度为 \(n\) 的矩阵
没了
至于为什么是蓝题,你自己看看代码量把
\(\mathcal{Code}\)
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e3 + 7;
int n, m, k, a[MAXN][MAXN];
int h_x[MAXN][MAXN], h_n[MAXN][MAXN], maxx[MAXN][MAXN], minn[MAXN][MAXN], ans = 1e9 + 7;
int main () {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> m >> k;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cin >> a[i][j];
for (int i = 1; i <= n; i++) {
deque<int> Q;//最大值
for (int j = 1; j <= m; j++) {
while (!Q.empty() && Q.front() < j - k + 1) Q.pop_front();
while (!Q.empty() && a[i][Q.back()] <= a[i][j]) Q.pop_back();
Q.push_back(j);
if (j >= k) h_x[i][j - k + 1] = Q.front();
}
Q.clear();//最小值
for (int j = 1; j <= m; j++) {
while (!Q.empty() && Q.front() < j - k + 1) Q.pop_front();
while (!Q.empty() && a[i][Q.back()] >= a[i][j]) Q.pop_back();
Q.push_back(j);
if (j >= k) h_n[i][j - k + 1] = Q.front();
}
}
for (int j = 1; j <= m - k + 1; j++) {
deque<int> Q;//最大值
for (int i = 1; i <= n; i++) {
while (!Q.empty() && Q.front() < i - k + 1) Q.pop_front();
while (!Q.empty() && a[Q.back()][h_x[Q.back()][j]] <= a[i][h_x[i][j]]) Q.pop_back();
Q.push_back(i);
if (i >= k) maxx[i - k + 1][j] = Q.front();
}
Q.clear();//最小值
for (int i = 1; i <= n; i++) {
while (!Q.empty() && Q.front() < i - k + 1) Q.pop_front();
while (!Q.empty() && a[Q.back()][h_n[Q.back()][j]] >= a[i][h_n[i][j]]) Q.pop_back();
Q.push_back(i);
if (i >= k) minn[i - k + 1][j] = Q.front();
}
}
for (int i = 1; i <= n - k + 1; i++)
for (int j = 1; j <= m - k + 1; j++)
ans = min(ans, a[maxx[i][j]][h_x[maxx[i][j]][j]] - a[minn[i][j]][h_n[minn[i][j]][j]]);
cout << ans << endl;
return 0;
}
完结撒花✿✿ヽ(°▽°)ノ✿