理想的正方形

  【题目描述】

  一个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]理想的正方形的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

    题目大意:有一个$a\times b$的矩阵,求一个$n\times n$的矩阵,使该区域中的极差最小. 题解:二维$ST$表,每一个点试一下是不是左上角就行了 卡点:1.用了一份考试时候写的二维$S ...

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

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

  8. BZOJ1047或洛谷2216 [HAOI2007]理想的正方形

    BZOJ原题链接 洛谷原题链接 显然可以用数据结构或\(ST\)表或单调队列来维护最值. 这里采用单调队列来维护. 先用单调队列维护每一行的最大值和最小值,区间长为正方形长度. 再用单调队列维护之前维 ...

  9. 洛谷 2216 [HAOI2007]理想的正方形

    题目戳这里 一句话题意 给你一个a×b的矩形,求一个n×n的子矩阵,矩阵里面的最大值和最小值之差最小. Solution 这个题目许多大佬都是单调队列,但是我不是很会,只好用了比较傻逼的方法: 首先我 ...

  10. P2216 [HAOI2007]理想的正方形 (单调队列)

    题目链接:P2216 [HAOI2007]理想的正方形 题目描述 有一个 \(a\times b\)的整数组成的矩阵,现请你从中找出一个 \(n\times n\)的正方形区域,使得该区域所有数中的最 ...

随机推荐

  1. Oracle 系统常用命令

    1.基本口令 1.1.show user                               作用:显示当前连接用户 1.2.conn 用户名/密码                       ...

  2. ClouderManger搭建大数据集群时ERROR 2003 (HY000): Can't connect to MySQL server on 'ubuntucmbigdata1' (111)的问题解决(图文详解)

    问题详情 相关问题的场景,是在我下面的这篇博客里 Cloudera Manager安装之利用parcels方式(在线或离线)安装3或4节点集群(包含最新稳定版本或指定版本的安装)(添加服务)(Ubun ...

  3. TOJ 1258 Very Simple Counting

    Description Let f(n) be the number of factors of integer n. Your task is to count the number of i(1 ...

  4. nginx反向代理使用网址速度变慢

    最近公司网址加载静态文件的速度总是跟不上于是试着用带端口的ip来访问, 发现速度快不少于是将nginx的代理修改为ip的如: location / { proxy_pass http://localh ...

  5. 2、Angular2 Directive

    1.Attribute directives 2.directive的理解

  6. .Net下Redis使用注意事项

    .Net下Redis使用注意事项 注:Redis的安装方法和桌面端工具很多,不在本文讨论范围内. 一:不结合适用场景的技术都是耍流氓,Redis主要适用场景: 简单字符串缓存 简单队列 简单发布订阅 ...

  7. SpringBoot ------ 使用AOP处理请求

    一.AOP统一处理请求日志 1.spring的两大核心:AOP ,  IOC 2.面向对象OOP关注的是将需求功能垂直,划分为不同的,并且相对独立的,   会封装成良好的类,并且类有属于自己的行为. ...

  8. Android开发ListView嵌套ImageView实现单选按钮

    做Android开发两年的时间,技术稍稍有一些提升,刚好把自己实现的功能写出来,记录一下,如果能帮助到同行的其他人,我也算是做了件好事,哈哈!!废话不多说,先上个图. 先上一段代码: if (last ...

  9. java自动生成jar包工具

    jar -cfe Main.jar com.xjq.test.Main com/xjq/test/Main.class jar -cmef manifest.mf com.xjq.test.Main ...

  10. android的MVP模式

    MVP简介 相信大家对MVC都是比较熟悉了:M-Model-模型.V-View-视图.C-Controller-控制器,MVP作为MVC的演化版本,那么类似的MVP所对应的意义:M-Model-模型. ...