【洛谷P2216】[HAOI2007]理想的正方形
理想的正方形
【题目描述】
一个a*b的矩阵,从中取一个n*n的子矩阵,使所选矩阵中的最大数与最小数的差最小。
思路:
二维的滑动窗口
对于每行:用一个单调队列维护,算出每个长度为n的区间的最大值和最小值,分别存在两个数组fmin和fmax中,fmax[i][j]表示第i行区间[j,j+n-1]的最大值。
对于每列:用一个单调队列维护,算出fmax和fmin数组中纵列每个长度为n的区间的最大值和最小值,分别存在两个数组ffmin和ffmax中,
ffmax[i][j]表示以(i,j)为左上端点的大小为n*n的矩阵中的最大值。
扫一遍ffmax[1~a-n+1][1~b-n+1]和ffmin[1~a-n+1][1~b-n+1]的差,得出ans。
单调队列原理:
以维护最大值为例:
对于每个新加入区间的值,显而易见的是:对于向右移动的“窗口”,即当前长度为n的区间中,若存在data[q[i]]比data[q[j]]大且q[i]>q[j](q[i]表示队列中的第i个元素的编号,data[i]表示编号为i的元素的值),则可以保证q[j]在以后的区间取最大值时是不会产生影响的,我们便可以将q[j]删除,从而得到更加优秀的时间复杂度,所以,当一个新的值入队时,便可以将在其前面入队且值比它小的元素删除。 我们便可以发现可以用一个单调队列维护。 当然,对于不在当前区间内的“老”元素,要把它从队列中删除。
贴C++代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a,b,n;
int g[][],fmin[][],fmax[][],ffmin[][],ffmax[][],queue[],head,tail,i,j,ans=0x7fffffff;
int main()
{
scanf("%d%d%d",&a,&b,&n);
for(i=;i<=a;i++)
for(j=;j<=b;j++)
scanf("%d",&g[i][j]);
for(i=;i<=a;i++) //枚举每行 单调递减求区间最大值
{
head=;tail=;
memset(queue,,sizeof(queue));
for(j=;j<n;j++)
{
while(tail>&&g[i][queue[tail]]<g[i][j]) tail--;
queue[++tail]=j;
}
for(j=n;j<=b;j++)
{
while(tail>=head&&g[i][queue[tail]]<g[i][j]) tail--;
queue[++tail]=j;
if(queue[head]<j-n+) head++;
fmax[i][j-n+]=g[i][queue[head]];
}
}
for(i=;i<=a;i++) //枚举每行 单调递增求区间最小值
{
head=;tail=;
memset(queue,,sizeof(queue));
for(j=;j<n;j++)
{
while(tail>&&g[i][queue[tail]]>g[i][j]) tail--;
queue[++tail]=j;
}
for(j=n;j<=b;j++)
{
while(tail>=head&&g[i][queue[tail]]>g[i][j]) tail--;
queue[++tail]=j;
if(queue[head]<j-n+) head++;
fmin[i][j-n+]=g[i][queue[head]];
}
}
for(i=;i<=b-n+;i++) //枚举每列 单调递减求区间最大值
{
head=;tail=;
memset(queue,,sizeof(queue));
for(j=;j<n;j++)
{
while(tail>&&fmax[queue[tail]][i]<fmax[j][i]) tail--;
queue[++tail]=j;
}
for(j=n;j<=a;j++)
{
while(tail>=head&&fmax[queue[tail]][i]<fmax[j][i]) tail--;
queue[++tail]=j;
if(queue[head]<j-n+) head++;
ffmax[j-n+][i]=fmax[queue[head]][i];
}
}
for(i=;i<=b-n+;i++) //枚举每列 单调递增求区间最小值
{
head=;tail=;
memset(queue,,sizeof(queue));
for(j=;j<n;j++)
{
while(tail>&&fmin[queue[tail]][i]>fmin[j][i]) tail--;
queue[++tail]=j;
}
for(j=n;j<=a;j++)
{
while(tail>=head&&fmin[queue[tail]][i]>fmin[j][i]) tail--;
queue[++tail]=j;
if(queue[head]<j-n+) head++;
ffmin[j-n+][i]=fmin[queue[head]][i];
}
}
for(i=;i<=a-n+;i++)
for(j=;j<=b-n+;j++)
ans=min(ans,ffmax[i][j]-ffmin[i][j]);
printf("%d\n",ans);
return ;
}
【洛谷P2216】[HAOI2007]理想的正方形的更多相关文章
- 洛谷 P2216 [HAOI2007]理想的正方形
P2216 [HAOI2007]理想的正方形 题目描述 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入输出格式 输入格式: 第一 ...
- 洛谷P2216: [HAOI2007]理想的正方形 单调队列优化DP
洛谷P2216 )逼着自己写DP 题意: 给定一个带有数字的矩阵,找出一个大小为n*n的矩阵,这个矩阵中最大值减最小值最小. 思路: 先处理出每一行每个格子到前面n个格子中的最大值和最小值.然后对每一 ...
- 洛谷 P2216 [HAOI2007]理想的正方形 || 二维RMQ的单调队列
题目 这个题的算法核心就是求出以i,j为左上角,边长为n的矩阵中最小值和最大值.最小和最大值的求法类似. 单调队列做法: 以最小值为例: q1[i][j]表示第i行上,从j列开始的n列的最小值.$q1 ...
- 洛谷P2216 HAOI2007 理想的正方形 (单调队列)
题目就是要求在n*m的矩形中找出一个k*k的正方形(理想正方形),使得这个正方形内最值之差最小(就是要维护最大值和最小值),显然我们可以用单调队列维护. 但是二维平面上单调队列怎么用? 我们先对行处理 ...
- 【DP】【单调队列】洛谷 P2216 [HAOI2007]理想的正方形 题解
算是单调队列的复习吧,不是很难 题目描述 有一个$a\times b$的整数组成的矩阵,现请你从中找出一个$n\times n$的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入 ...
- [洛谷P2216][HAOI2007]理想的正方形
题目大意:有一个$a\times b$的矩阵,求一个$n\times n$的矩阵,使该区域中的极差最小. 题解:二维$ST$表,每一个点试一下是不是左上角就行了 卡点:1.用了一份考试时候写的二维$S ...
- 洛谷 P2216 [HAOI2007]理想正方形
洛谷 巨说这是一道单调队列好题,但是我并不是用单调队列做的诶. 如果往最暴力的方向去想,肯定是\(n^3\)的\(dp\)了. \(f[i][j][k]\)代表当前正方形的左上角定点是\((i,j)\ ...
- BZOJ1047或洛谷2216 [HAOI2007]理想的正方形
BZOJ原题链接 洛谷原题链接 显然可以用数据结构或\(ST\)表或单调队列来维护最值. 这里采用单调队列来维护. 先用单调队列维护每一行的最大值和最小值,区间长为正方形长度. 再用单调队列维护之前维 ...
- 洛谷 2216 [HAOI2007]理想的正方形
题目戳这里 一句话题意 给你一个a×b的矩形,求一个n×n的子矩阵,矩阵里面的最大值和最小值之差最小. Solution 这个题目许多大佬都是单调队列,但是我不是很会,只好用了比较傻逼的方法: 首先我 ...
- P2216 [HAOI2007]理想的正方形 (单调队列)
题目链接:P2216 [HAOI2007]理想的正方形 题目描述 有一个 \(a\times b\)的整数组成的矩阵,现请你从中找出一个 \(n\times n\)的正方形区域,使得该区域所有数中的最 ...
随机推荐
- TOJ 2119 Tangled in Cables
描述 You are the owner of SmallCableCo and have purchased the franchise rights for a small town. Unfor ...
- 【Linux】Linux下使用Docker快速部署Oracle数据库
安装最新Docker wget -qO- https://get.docker.com/ | sh` 安装 docker-compose sudo curl -L https://github.com ...
- 使用awstat分析Nginx的访问日志
在我的上一篇文章<使用 Nginx 提升网站访问速度>中介绍了 Nginx 这个 HTTP 服务器以及如何通过它来加速网站的访问速度.在实际的网站运营中,我们经常需要了解到网站的访问情况, ...
- Maven工程红色感叹号,且工程无红叉错误
很可能是jar包不对,可以将maven库里的jar包删除,从 http://mvnrepository.com/ 根据jar包版本号下载到本地maven库,并在pom.xml里引入jar依赖 这次ja ...
- 深入理解JavaScript系列(30):设计模式之外观模式
介绍 外观模式(Facade)为子系统中的一组接口提供了一个一致的界面,此模块定义了一个高层接口,这个接口值得这一子系统更加容易使用. 正文 外观模式不仅简化类中的接口,而且对接口与调用者也进行了解耦 ...
- jsp的动作标签
常用的标签: 1. forward 请求转发 [基本不使用] <==> request.getRequestDispatcher(url).forward(request,respon ...
- sp_addlinkedserver创建远程服务器查询
远程服务器查询可以分两步完成: 1.建立连接服务器 exec sp_addlinkedserver @server='Test_Server', --被访问的服务器别名 @srvproduct='', ...
- python的返回值
1.返回值的作用 函数并非总是直接显示输出,相反,它可以处理一些数据,并返回一个或一组值.函数返回的值被称为返回值.在函数中,可使用return语句将值返回到调用函数的代码行.返回值让你能够将程序的大 ...
- ACM-线段树
http://blog.csdn.net/libin56842/article/details/8530197 基础可以看上面这篇文章 风格: maxn是题目给的最大区间,而节点数要开4倍,确切的说… ...
- 软件测试技术lab2——Selenium上机实验
Selenium上机实验说明 1.安装SeleniumIDE插件 2.学会使用SeleniumIDE录制脚本和导出脚本 3.访问http://121.193.130.195:8080/使用学号登录系统 ...