题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1047

题意:见中文题面

思路:该题是求二维的子矩阵的最大值与最小值的差值尽量小。所以可以考虑求出每个子矩阵的最大值和最小值。考虑一维求子段的最小值/最大值的思路。滑动窗口+单调队列。 转换成二维。设minNum[i][j]表示右下角为(i,j)的子矩阵的最小值。先对矩阵每一行用一维的做法求出每一行的子段的最小值,然后同样的方法求列的最值。注意在求列的子段最小值时比较的元素不是原矩阵的元素而是用行求的结果来比较。 具体看代码吧。

#define _CRT_SECURE_NO_DEPRECATE
#include<stdio.h>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<queue>
#include<math.h>
#include<time.h>
#include<vector>
#include<iostream>
#include<string>
using namespace std;
typedef long long int LL;
const int MAXN = + ;
const int INF = 0x3f3f3f3f;
int n, m, k, num[MAXN][MAXN], minNum[MAXN][MAXN], maxNum[MAXN][MAXN];
void solve(int type, int seg[][MAXN]){
deque<pair<int, int> > deq;
for (int i = ; i <= n; i++){ //求行子段的最值。
deq.clear();
for (int j = ; j <= m; j++){
while (!deq.empty() && j - deq.front().second >= k){ deq.pop_front(); }
if (type){
while (!deq.empty() && deq.back().first < num[i][j]){ deq.pop_back(); }
}
else{
while (!deq.empty() && deq.back().first > num[i][j]){ deq.pop_back(); }
}
deq.push_back(make_pair(num[i][j], j));
seg[i][j] = deq.front().first;
}
}
for (int j = ; j <= m; j++){ //求列的最值
deq.clear();
for (int i = ; i <= n; i++){
while (!deq.empty() && i - deq.front().second >= k){ deq.pop_front(); }
if (type){
while (!deq.empty() && deq.back().first < seg[i][j]){ deq.pop_back(); }
}
else{
while (!deq.empty() && deq.back().first > seg[i][j]){ deq.pop_back(); }
}
deq.push_back(make_pair(seg[i][j], i));
seg[i][j] = deq.front().first;
}
}
}
int main(){
//#ifdef kirito
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
//#endif
// int start = clock();
while (~scanf("%d%d%d", &n, &m, &k)){
for (int i = ; i <= n; i++){
for (int j = ; j <= m; j++){
scanf("%d", &num[i][j]);
}
}
int ans = INF;
solve(, minNum); solve(, maxNum);
////Debug
//printf("minNum Segment:\n");
//for (int i = 1; i <= n; i++){
// for (int j = 1; j <= m; j++){
// printf("%d ", minNum[i][j]);
// }
// printf("\n");
//}
//printf("maxNum Segment:\n");
//for (int i = 1; i <= n; i++){
// for (int j = 1; j <= m; j++){
// printf("%d ", maxNum[i][j]);
// }
// printf("\n");
//}
for (int i = k; i <= n; i++){
for (int j = k; j <= m; j++){
ans = min(ans, maxNum[i][j] - minNum[i][j]);
}
}
printf("%d\n", ans);
}
//#ifdef LOCAL_TIME
// cout << "[Finished in " << clock() - start << " ms]" << endl;
//#endif
return ;
}

最新文章

  1. 使用dd命令备份Linux分区
  2. RMAN备份与恢复之初入茅庐
  3. SQL Server 2008 FILESTREAM特性管理文件
  4. sqlserver错误&quot;试图扩大物理文件时,MODIFY FILE 遇到操作系统错误 112(磁盘空间不足。)。&quot;处理
  5. Java多线程中易混淆的概念
  6. java线程的等待、通知机制【读书笔记】
  7. 华为防火墙USG5500-企业双ISP出口
  8. SharePoint 查找字段内部名称的小方法
  9. Thunk
  10. 常用js方法整理(个人)
  11. volatile 与 JVM 指令重排序
  12. Linux目录/usr结构说明
  13. Windows IIS 使用批处理脚本自动安装与卸载
  14. javascript中的值如何传递到django下的views.py中或者数据库中?
  15. 如何利用jquery来给input添加或删除disabled属性
  16. Hexo站点之域名配置【2】
  17. 关于ArcGIS Server修改数据源是否对切片服务有影响
  18. IO模型与select,poll,epoll
  19. Android ProgressBar具体解释以及自己定义
  20. python16_day35【算法】

热门文章

  1. 【学习笔记】C语言之词法规则
  2. iOS小知识:计算字符串长度(如果有表情,表情的长度为1)
  3. java 初始化顺序
  4. EBS中加载FORM使用的JavaBean的JAR包
  5. js中typeof和instanceof
  6. js时间Date对象介绍及解决getTime转换为8点的问题
  7. 没有我的A协
  8. mybatis调用存储过程 无参、带有输入输出参数,输出游标类型的 存储
  9. 安装两个tomcat
  10. 【纯css】响应式图片列表