【洛谷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\)的正方形区域,使得该区域所有数中的最 ...
随机推荐
- GitHub+Hexo+gulp搭建博客网站
一.前期准备 1.注册GitHub账号. 不做说明 2.创建仓库 创建一个新的仓库来放置我们的文件. 3.下载安装Node.js https://nodejs.org/en/ 两个版本,选择右边那 ...
- [转]how to use both JDK 7 and JDK 8 in one build
Note: This article is original from https://gist.github.com/aslakknutsen/9648594 JDK 8 Released Most ...
- unity读取json文件
首先填表 [escel转json]注意,粘贴表之后,需要把最后的空行删掉 http://www.bejson.com/json/col2json/ [json格式化] http://www.bejso ...
- SpringBoot | 第三十三章:Spring web Servcies集成和使用
前言 最近有个单位内网系统需要对接统一门户,进行单点登录和待办事项对接功能.一般上政府系统都会要求做统一登录功能,这个没啥问题,反正业务系统都是做单点登录的,改下shiro相关类就好了.看了接入方案, ...
- Windows phone 8.1应用集成cortana语音命令
微软推出小娜已经有一段时间了,最近恰好在研究其用法,就随便写点记录一下自己的心得. 在研究时参考了@王博_Nick的博客:http://www.cnblogs.com/sonic1abc/p/3868 ...
- (转)vs2010 vs2013等vs中如何统计整个项目的代码行数
在一个大工程中有很多的源文件和头文件,我如何快速统计总行数? ------解决方案-------------------- b*[^:b#/]+.*$ ^b*[^:b#/]+.*$ ctrl + sh ...
- ACM-线段树区间更新+离散化
区间更新与单点更新最大的不同就在于Lazy思想: http://blog.sina.com.cn/s/blog_a2dce6b30101l8bi.html 可以看这篇文章,讲得比较清楚 在具体使用上, ...
- Flask插件---flask_script与flask_migrate
import app from flask_script import Manager from flask_migrate import Migrate,MigrateCommand my_app ...
- 微信小程序--阻止冒泡事件
微信小程序事件的使用方式 在组件中绑定一个事件处理函数. 如bindtap,当用户点击该组件的时候会在该页面对应的Page中找到相应的事件处理函数. <view id="tapTest ...
- Linux漏洞分析入门笔记-CVE_2018_6323_整型溢出
操作系统 Ubuntu 16.04 /32 位 调试器 IDA pro 7.0 漏洞软件 binutils-2.29.1 0x00: 漏洞描述 1.什么是整数溢出: 在计算机中,整数分 ...