// 1604:理想的正方形.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <deque>
#include <algorithm>
using namespace std;
/*
https://loj.ac/p/10182
http://ybt.ssoier.cn:8088/problem_show.php?pid=1604
原题来自:HAOI 2007
有一个 a×b
的整数组成的矩阵,现请你从中找出一个 n×n
的正方形区域,使得该区域所有数中的最大值和最小值的差最小。
【输入】
第一行为三个整数,分别表示 a,b,n
的值;
第二行至第 a+1
行每行为 b
个非负整数,表示矩阵中相应位置上的数。
【输出】
输出仅一个整数,为 a×b
矩阵中所有「n×n
正方形区域中的最大整数和最小整数的差值」的最小值。
【输入样例】
5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
【输出样例】
1
2≤a,b≤1000,n≤a,n≤b,n≤100,矩阵中的所有数都不超过 10^9。
*/
const int N = 1010;
long long arr[N][N];
long long minrow[N][N];
long long maxrow[N][N];
int a, b, n;
void getmin(int row) {
deque<long long> q;
for (int i = 1; i <= b; i++) {
while (!q.empty() && i - q.front() + 1 > n) q.pop_front();
while (!q.empty() && arr[row][q.back()] >= arr[row][i]) q.pop_back();
if (q.empty() || arr[row][q.front()] >= arr[row][i]) {
minrow[row][i] = arr[row][i];
}
else {
minrow[row][i] = arr[row][q.front()];
}
q.push_back(i);
}
}
void getmax(int row) {
deque<long long> q;
for (int i = 1; i <= b; i++) {
while (!q.empty() && i - q.front() + 1 > n) q.pop_front();
while (!q.empty() && arr[row][q.back()] <= arr[row][i]) q.pop_back();
if (q.empty() || arr[row][q.front()] <= arr[row][i]) {
maxrow[row][i] = arr[row][i];
}
else {
maxrow[row][i] = arr[row][q.front()];
}
q.push_back(i);
}
}
void getminCol(int col,int mincol[]) {
deque<long long> q;
for (int i = 1; i <= a; i++) {
while (!q.empty() && i - q.front() + 1 > n) q.pop_front();
while (!q.empty() && minrow[q.back()][col] >= minrow[i][col]) q.pop_back();
if (q.empty() || minrow[q.front()][col] >= minrow[i][col]) {
mincol[i] = minrow[i][col];
}
else {
mincol[i] = minrow[q.front()][col];
}
q.push_back(i);
}
}
void getmaxCol(int col, int maxcol[]) {
deque<long long> q;
for (int i = 1; i <= a; i++) {
while (!q.empty() && i - q.front() + 1 > n) q.pop_front();
while (!q.empty() && maxrow[q.back()][col] <= maxrow[i][col]) q.pop_back();
if (q.empty() || maxrow[q.front()][col] <= maxrow[i][col]) {
maxcol[i] = maxrow[i][col];
}
else {
maxcol[i] = maxrow[q.front()][col];
}
q.push_back(i);
}
}
int main()
{
cin >> a >> b >> n;
for (int i = 1; i <= a; i++) {
for (int j = 1; j <= b; j++) {
cin >> arr[i][j];
}
}
for (int i = 1; i <= a; i++) {
getmin(i);
getmax(i);
}
long long ans = 1e18;
for (int i = n; i <= b; i++) {
//对每个竖列做滑动窗口 得到最大最小值
int mincol[N]; int maxcol[N];
getminCol(i, mincol);
getmaxCol(i, maxcol);
for (int j = n; j <= a; j++) {
ans = min(ans, 1ll * maxcol[j] - mincol[j]);
}
}
cout << ans << endl;
return 0;
}
标签:arr,理想,int,1604,minrow,back,正方形,front,row
From: https://www.cnblogs.com/itdef/p/18252181