题目描述

有一个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. vuejs使用FormData对象,ajax上传图片文件

    我相信很多使用vuejs的朋友,都有采用ajax上传图片的需求,因为前后端分离后,我们希望都能用ajax来解决数据问题,传统的表单提交会导致提交成功后页面跳转,而使用ajax能够无刷新上传图片等文件. ...

  2. Spring quartz Job不能依赖注入,Spring整合quartz Job任务不能注入

    Spring quartz Job不能依赖注入,Spring整合quartz Job任务不能注入 Spring4整合quartz2.2.3中Job任务使用@Autowired不能注入 >> ...

  3. jenkins配置RF构建结果显示

    声明:转载请注明出处,谢谢 步骤1:安装robot framework plugin插件:系统管理-管理插件 步骤2:设置构建后操作:job-配置-构建后操作增加“Publish Robot Fram ...

  4. linux系统如何操作隐藏文件

    在linux下,以点"."开头命名的文件在系统中被视为隐藏文件.因此,如果想隐藏某个文件或目录,一种简单的办法就是把文件名命名为点开头. 对于目录backcron,可以这样操作隐藏 ...

  5. 敏感词过滤和XML的创建

    今天我慢下来啦,因为这三天没有新的课程学习内容,自己仅仅看啦一些,这让我停下来栖息片刻:说说现在的生活,简单的进行着,每天要奔波着去上课,然后回来,每天都在想怎样学习这个小知识点,大脑也在想怎样解决程 ...

  6. RabbitMQ与java、Spring结合实例详细讲解

    林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要:本文介绍了rabbitMq,提供了如何在Ubuntu下安装RabbitMQ 服务的方法. ...

  7. PHP的ISAPI和FastCGI比较

     1.CGI(通用网关接口/Common Gateway Interface)一般是可执行程序,例如EXE文件,和WEB服务器各自占据着不同的进程,而且一般一个CGI程序只能处理一个用户请求.这样,当 ...

  8. Matlab练习——素数查找

    输入数字,0结束,判断输入的数字中的素数 clc; %清空命令行窗口的数据 clear; %清除工作空间的变量 k = ; n = ; %素数的个数 zzs(k) = input('请输入正整数: ' ...

  9. thinkphp5.0 获取请求信息

    如果要获取当前的请求信息,可以使用\think\Request类,除了下文中的 $request = Request::instance(); 也可以使用助手函数 $request = request ...

  10. WP8.1开发:简单天气预报应用(转)

    今天小梦给大家分享一个简单的天气预报应用源码:调用的是百度API.整个应用都没有什么难点.只是一个简单的网络请求和json数据处理.在WP8.1有小娜的情况下,天气预报应用还有意义吗?我认为还是有点意 ...