题目大意:给出一个矩阵,求出一个k*k的子矩阵,使得这个矩阵中最大值和最小值的差最小,输出这个差值。
思路:利用单调队列维护每一行的数字,求出一个数字前面k个数字中的最大值和最小值,然后在列上暴力求出真个矩阵的最大值和最小值,总时间复杂度O(M*M+M*M*K)。
CODE:
#include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 1010 #define INF 0x3f3f3f3f using namespace std; struct Status{ int num,pos; Status(int _,int __):num(_),pos(__) {} }; int m,n,k; int src[MAX][MAX]; int _max[MAX][MAX],_min[MAX][MAX]; inline void Calc(int line) { deque<Status> __min,__max; for(int i = 1; i <= n; ++i) { while(!__min.empty() && i - __min.front().pos >= k) __min.pop_front(); while(!__max.empty() && i - __max.front().pos >= k) __max.pop_front(); Status now(src[line][i],i); while(!__min.empty() && now.num <= __min.back().num) __min.pop_back(); while(!__max.empty() && now.num >= __max.back().num) __max.pop_back(); __min.push_back(now); __max.push_back(now); _min[line][i] = __min.front().num; _max[line][i] = __max.front().num; } } int main() { cin >> m >> n >> k; for(int i = 1; i <= m; ++i) for(int j = 1; j <= n; ++j) scanf("%d",&src[i][j]); for(int i = 1; i <= m; ++i) Calc(i); int ans = INF; for(int i = 1; i <= m - k + 1; ++i) for(int j = k; j <= n; ++j) { int __min = INF,__max = -INF; for(int l = 0; l < k; ++l) { __min = min(__min,_min[i + l][j]); __max = max(__max,_max[i + l][j]); } ans = min(ans,__max - __min); } cout << ans << endl; return 0; }
BZOJ 1047 HAOI 2007 理想的正方形 单调队列
原文地址:http://blog.csdn.net/jiangyuze831/article/details/41310813