题目链接: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 ;
}

BZOJ 1047 二维单调队列的更多相关文章

  1. bzoj1047-理想的正方形(二维单调队列)

    题意: 给一个矩阵,给出行列和每个数,再给出一个N,求出所有N*N的子矩阵中最大值最小值之差的最小值解析: 暴力枚举肯定不行,这题可以用二维单调队列做,把同一行的连续N个点缩成一个点保存最大最小值预处 ...

  2. 【二维单调队列】BZOJ1047-[HAOI2007]理想的正方形

    [题目大意] 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. [思路] 裸的二维单调队列.二维单调队列的思路其实很简单: (1)对于每 ...

  3. [BZOJ1047][HAOI2007]理想的正方形 二维单调队列

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1047 我们对每矩阵的一列维护一个大小为$n$的单调队列,队中元素为矩阵中元素.然后扫描每一 ...

  4. bzoj1047 [HAOI2007]理想的正方形——二维单调队列

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1047 就是先对行做一遍单调队列,再对那个结果按列做一遍单调队列即可. 代码如下: #incl ...

  5. [luoguP2216] [HAOI2007]理想的正方形(二维单调队列)

    传送门 1.先弄个单调队列求出每一行的区间为n的最大值最小值. 2.然后再搞个单调队列求1所求出的结果的区间为n的最大值最小值 3.最后扫一遍就行 懒得画图,自己体会吧. ——代码 #include ...

  6. bzoj 2216: Lightning Conductor 单调队列优化dp

    题目大意 已知一个长度为\(n\)的序列\(a_1,a_2,...,a_n\)对于每个\(1\leq i\leq n\),找到最小的非负整数\(p\)满足: 对于任意的\(j\), \(a_j \le ...

  7. BZOJ 1855 股票交易(单调队列优化DP)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1855 题意:最近lxhgww又迷上了投资股票, 通过一段时间的观察和学习,他总结出了股票 ...

  8. BZOJ 2424 订货(贪心+单调队列)

    怎么题解都是用费用流做的啊...用单调队列多优美啊. 题意:某公司估计市场在第i个月对某产品的需求量为Ui,已知在第i月该产品的订货单价为di,上个月月底未销完的单位产品要付存贮费用m,假定第一月月初 ...

  9. BZOJ 1012 线段树||单调队列

    非常裸的线段树  || 单调队列: 假设一个节点在队列中既没有时间优势(早点入队)也没有值优势(值更大),那么显然不管在如何的情况下都不会被选为最大值. 既然它仅仅在末尾选.那么自然能够满足以上的条件 ...

随机推荐

  1. Java学习过程中的总结的小知识点(长期更新)

    Java学习过程中的总结的小知识点 (主要是自己不会的知识和容易搞错的东西) 计算某个程序运行的时间 long stime=System.currentTimeMillis(); copy3(file ...

  2. web app开发利器 - iscroll4 解决方案

    存在即是道理,iscroll会诞生,主要是因为无论是在iphone.ipod.android 或是更早前的移动webkit都没有提供一种原生的方式来支持在一个固定高度的容器内滚动内容, 这个不幸的规则 ...

  3. Red5 1.0.0RC1 集成到tomcat6.0.35中运行&部署新的red5项目到tomcat中

    1.下载red5-war-1.0-RC1.zip 解压之得到 ROOT.war 文件. 2.处理tomcat. 下载apache-tomcat-6.0.35-windows-x86.zip包,解压到你 ...

  4. Redhat6.4下安装Oracle10g

    Oracle10g_Redhat6.4 安装指南 文档说明 本文借鉴<Redhat_Linux_6.4下Oracle_10g安装配置手册><Redhat 6.4 安装 Oracle1 ...

  5. javac -encoding utf8 in linux

    由于另外负责编码的同事用的是utf-8,我用的默认的编码格式gbk,在提交代码时,为了迁就他,我打算把格式用工具转成utf-8. 转化成果后,然后在make一下,发现javac -encoding u ...

  6. matlab绘图基础

    matlab绘制条形图并分组显示: a =[1 2 3] b =[4 5 6] >> d=[a;b] d = 1 2 3 4 5 6 >> bar(d,'group') 修改横 ...

  7. [MySQL]MySQL之权限管理

    一.MySQL权限简介 关于mysql的权限简单的理解就是mysql允许你做你全力以内的事情,不可以越界.比如只允许你执行select操作,那么你就不能执行update操作.只允许你从某台机器上连接m ...

  8. Python使用TuShare将股票数据保存到Oracle数据

    TuShare是个获取股票数据的模块包,我们进行分析,需要将股票数据保存到本地,避免每次都从网上获取,由于本机装有ORCALE,以ORACLE为例介绍如何保存股票数据到本地. 一.大致思路:我们先获取 ...

  9. SQL中循环和条件语句

    .if语句使用示例: declare @a int begin print @a end else begin print 'no' end .while语句使用示例: declare @i int ...

  10. <css系列>之css--float总结

    一.float的历史     float的设计初衷是实现文字环绕效果. 如下图,对图片添加float,文字实现环绕效果. 二.float特性     1.包裹性,表现:收缩.坚挺.隔绝.具有包裹性的属 ...