题目描述

有一个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. Python_selenium二次封装selenium的几个方法

    Python_selenium二次封装selenium的几个方法 将常用的几个webdriver方法封装到自己写的一个类中去,此实例中是将"浏览器后退.浏览器前进.打开站点和关闭浏览器&qu ...

  2. 用python开发android应用 【转载】

    用python开发android应用 [转载] 转载自:http://www.miui.com/thread-995114-1-1.html Python是动态语言,比较简洁.Android不直接支持 ...

  3. 8 -- 深入使用Spring -- 2...1 搜索Bean类

    8.2.1 搜索Bean类 既然不再使用Spring配置文件来配置任何Bean实例,那么只能希望Spring会自动搜索某些路径下的Java类,并将这些Java类注册成Bean实例. tips:Rail ...

  4. SpringBoot(一)-- 知识点介绍

    一.简介 Spring Boot是为了简化Spring应用的创建.运行.调试.部署等而出现的,使用它可以做到专注于Spring应用的开发,而无需过多关注XML的配置.简单来说,它提供了一堆依赖打包,并 ...

  5. 嵌入式ROOTFS transplantation

    作一个嵌入式Linux rootfs,并且实现 web 服务 1. 文件系统简介 •理论上说一个嵌入式设备如果内核能够运行起来,且不需要运行用户进程的话,是不需要文件系统的,文件系统简单的说就是一种目 ...

  6. Eclipse cdt debug时‘Error while launching command: gdb.exe --version’

    1. 下载gdb,网上很多可以下载一个,解压放在mingw/bin下,由于该目录以在path制定,在CMD下,gdb -version会显示当前gdb版本信息. 2.按照该文档配置即可实现debug

  7. 理解Java的反射与内省及其区别

    java的内省机制和反射机制什么区别 内省操作只针对JavaBean,只有符合JavaBean规则的类的成员才可以采用内省API进行操作....而反射则不同,一个类的所有成员都可以进行反射操作. 内省 ...

  8. 关于RabbitMQ交换机的理解

    RabbitMQ是实现AMQP(高级消息队列协议)的消息中间件的一种,最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性.扩展性.高可用性等方面表现不俗.消息中间件主要用于组件之间的解耦,消 ...

  9. 关于bat中使用rar压缩命令

    数据库备份,导出的dmp 文件比较大,需要压缩,压缩后大小能变为原来十分之一左右吧. 写的是批处理的语句,每天调用,自动导出dmp 文件,压缩删除原文件. 首先写下路径 先将压缩软件的路径写入系统的环 ...

  10. OpenCV——识别各省份地图轮廓

    好久没有发OpenCV的博客了,最近想到了一个识别地图轮廓的方案,就写来试试.(识别中国的28个省份地图轮廓,不考虑直辖市) 首先,我的基本思路是  用最小的矩形将地图的轮廓圈出来,可以根据长方形的长 ...