题目描述

有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小。

输入输出格式

输入格式:

第一行为3个整数,分别表示a,b,n的值

第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每行相邻两数之间用一空格分隔。

输出格式:

仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值。

输入输出样例

输入样例#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)矩阵中的所有数都不超过1,000,000,000

(2)20%的数据2<=a,b<=100,n<=a,n<=b,n<=10

(3)100%的数据2<=a,b<=1000,n<=a,n<=b,n<=100

题意:

给定一个a*b的矩阵,找一个n*n的正方形,使得正方形里最大值和最小值之差最小。

思路:

我们可以预处理出每一个n*n的正方形的最大最小值分别是多少,然后暴力跑一遍找到最小值就可以了。

先处理横着的,用单调队列来维护。刚开始一直写不对,因为队列中应该存的是位置的下标而不是直接存值,因为head++的时候比较的是下标的距离,而我刚开始直接比较了tail和head也就是队列里的元素个数。

然后按照同样的方法,在行处理好的基础上处理列。

发现写单调队列的套路就是。比如我们要建一个存最大值的,那我们应该比较队尾和当前值的关系。

如果队尾比当前值小就要一直tail--

然后删去不满足区间约束的队头的值。

然后每次取的应该是队头的元素。

 #include <iostream>
#include <set>
#include <cmath>
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define inf 0x7f7f7f7f const int maxn = ;
int a, b, n;
LL grid[maxn][maxn];
LL row_big[maxn][maxn], col_big[maxn][maxn], row_small[maxn][maxn], col_small[maxn][maxn];
LL que_big[maxn], que_small[maxn]; int main()
{
scanf("%d%d%d", &a, &b, &n);
for(int i = ; i <= a; i++){
for(int j = ; j <= b; j++){
scanf("%lld", &grid[i][j]);
row_big[i][j] = col_big[i][j] = -;
row_small[i][j] = col_small[i][j] = LLONG_MAX;
}
} //cout<<endl;
int tail_b = , tail_s = , head_b = , head_s = ;
for(int i = ; i <= a; i++){
tail_b = tail_s = ;
head_b = head_s = ;
for(int j = ; j <= b; j++){
//row_big[i][j] = max(que_big[tail_b], grid[i][j]);
//cout<<row_big[i][j]<<" ";
while(grid[i][que_big[tail_b]] <= grid[i][j] && head_b <= tail_b){
tail_b--;
}
que_big[++tail_b] = j;
while(j - que_big[head_b] >= n){
head_b++;
}
row_big[i][j] = grid[i][que_big[head_b]]; //row_small[i][j] = min(que_small[tail_s], grid[i][j]);
while(grid[i][que_small[tail_s]] >= grid[i][j] && head_s <= tail_s){
tail_s--;
}
que_small[++tail_s] = j;
while(j - que_small[head_s] >= n){
head_s++;
}
row_small[i][j] = grid[i][que_small[head_s]];
}
//cout<<endl;
} /*cout<<endl;
for(int i = 1; i <= a; i++){
for(int j = n; j <= b; j++){
cout<<row_big[i][j]<<" ";
}
cout<<endl;
}*/ for(int j = ; j <= b; j++){
tail_b = tail_s = ;
head_b = head_s = ;
for(int i = ; i <= a; i++){
//col_big[i][j] = max(que_big[tail_b], row_big[i][j]);
while(row_big[que_big[tail_b]][j] <= row_big[i][j] && head_b <= tail_b){
tail_b--;
}
que_big[++tail_b] = i;
while(i - que_big[head_b] >= n){
head_b++;
}
col_big[i][j] = row_big[que_big[head_b]][j]; //col_small[i][j] = min(que_small[tail_s], row_small[i][j]);
while(row_small[que_small[tail_s]][j] >= row_small[i][j] && head_s <= tail_s){
tail_s--;
}
que_small[++tail_s] = i;
while(i - que_small[head_s] >= n){
head_s++;
}
col_small[i][j] = row_small[que_small[head_s]][j];
}
} /*cout<<endl;
for(int i = n ;i <= a; i++){
for(int j = n; j <= b; j++){
cout<<col_big[i][j]<<" ";
}
cout<<endl;
}*/ LL ans = LLONG_MAX;
for(int i = n; i <= a; i++){
for(int j = n; j <= b; j++){
ans = min(ans, col_big[i][j] - col_small[i][j]);
}
}
printf("%lld\n", ans);
return ;
}

洛谷P2216 理想的正方形的更多相关文章

  1. 洛谷P2216 理想的正方形(单调队列)

    洛谷P2216 理想的正方形 题目链接 思路: 直接暴力显然不可行,可以发现每一个矩形向右边扩展时是一列一列增加,于是可以想到单调队列,用数组来维护当前每列的最大值.因为行也有限制,所以还要用一个单调 ...

  2. 洛谷 [P2216] 理想的正方形

    二维单调队列 先横向跑一边单调队列,记录下每一行长度为n的区间的最值 在纵向跑一边单调队列,得出结果 注意,mi要初始化为一个足够大的数 #include <iostream> #incl ...

  3. 洛谷P2216: [HAOI2007]理想的正方形 单调队列优化DP

    洛谷P2216 )逼着自己写DP 题意: 给定一个带有数字的矩阵,找出一个大小为n*n的矩阵,这个矩阵中最大值减最小值最小. 思路: 先处理出每一行每个格子到前面n个格子中的最大值和最小值.然后对每一 ...

  4. 洛谷 P2216 [HAOI2007]理想正方形

    洛谷 巨说这是一道单调队列好题,但是我并不是用单调队列做的诶. 如果往最暴力的方向去想,肯定是\(n^3\)的\(dp\)了. \(f[i][j][k]\)代表当前正方形的左上角定点是\((i,j)\ ...

  5. 洛谷 P2216 [HAOI2007]理想的正方形

    P2216 [HAOI2007]理想的正方形 题目描述 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入输出格式 输入格式: 第一 ...

  6. 【洛谷P2216】[HAOI2007]理想的正方形

    理想的正方形 [题目描述] 一个a*b的矩阵,从中取一个n*n的子矩阵,使所选矩阵中的最大数与最小数的差最小. 思路: 二维的滑动窗口 对于每行:用一个单调队列维护,算出每个长度为n的区间的最大值和最 ...

  7. 洛谷 P2216 [HAOI2007]理想的正方形 || 二维RMQ的单调队列

    题目 这个题的算法核心就是求出以i,j为左上角,边长为n的矩阵中最小值和最大值.最小和最大值的求法类似. 单调队列做法: 以最小值为例: q1[i][j]表示第i行上,从j列开始的n列的最小值.$q1 ...

  8. 洛谷P2216 HAOI2007 理想的正方形 (单调队列)

    题目就是要求在n*m的矩形中找出一个k*k的正方形(理想正方形),使得这个正方形内最值之差最小(就是要维护最大值和最小值),显然我们可以用单调队列维护. 但是二维平面上单调队列怎么用? 我们先对行处理 ...

  9. 【DP】【单调队列】洛谷 P2216 [HAOI2007]理想的正方形 题解

        算是单调队列的复习吧,不是很难 题目描述 有一个$a\times b$的整数组成的矩阵,现请你从中找出一个$n\times n$的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入 ...

随机推荐

  1. python2和3的区别,怎么样做到轻松切换2和3

    以下是菜鸟教程列举的.这些零散的改变需要注意. 下面这些东西可能平时的程序根本没用到,或者稍加注意就可以了.但2和3最主要的区别是,掌握编码. 编码在所有程序中无处不在,处理不好,要么乱码,要么编码解 ...

  2. selenium 单浏览器模式

    如果需要无限制的任意实例化,而不是把实例化后的对象传给另一个函数.方法处理.就需要控制单浏览器,不然每次实例化弹出来一个新浏览器,很占内存 #coding=utf8 from selenium.web ...

  3. 手机APP支付--整合支付宝支付控件

    长话短说,本文根据支付宝官方说明文档,简单总结下,并且说明下开发过程碰到的问题以及该如何解决. 整合步骤: 1 登录商家服务网站,下载开发包,地址:https://b.alipay.com/order ...

  4. VS2013 编译&使用 stlport

    1. 下载stlport.   下载地址:http://sourceforge.net/projects/stlport/ 2. 解压到一个目录下面, 我的是解压到D:\project_kuku\pr ...

  5. 浅谈PostgreSQL的索引

    1. 索引的特性 1.1 加快条件的检索的特性 当表数据量越来越大时查询速度会下降,在表的条件字段上使用索引,快速定位到可能满足条件的记录,不需要遍历所有记录. create table t(id i ...

  6. Explaining Delegates in C# - Part 2 (Events 1)

    In my previous post, I spoke about a few very basic and simple reasons of using delegates - primaril ...

  7. Ansible Playbook 使用变量

    如何在 Playbook 中定义并使用变量: vars: - user: "test" # 定义变量 tasks: - name: create user user: name=& ...

  8. Hadoop核心架构HDFS+MapReduce+Hbase+Hive内部机理详解

    转自:http://blog.csdn.net/iamdll/article/details/20998035 分类: 分布式 2014-03-11 10:31 156人阅读 评论(0) 收藏 举报 ...

  9. Linux centos 下 eclipse 打开文件时关闭

    原文地址:http://processors.wiki.ti.com/index.php/Linux_Host_Support#cairo-misc.c:380:_cairo_operator_bou ...

  10. phpStorm中使用xdebug断点调试php代码

    配置好xdebug,也能使得phpstorm像java哪像跑断点调试,爽的一笔!!! 下载xdebug并配置 [XDebug] zend_extension=php_xdebug-2.4.0rc3-5 ...