题目描述

有一个ab的整数组成的矩阵,现请你从中找出一个nn的正方形区域,使得该区域所有数中的最大值和最小值的差最小。

输入输出格式

输入格式:

第一行为3个整数,分别表示a,b,n的值

第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每行相邻两数之间用一空格分隔。

输出格式:

仅一个整数,为ab矩阵中所有“nn正方形区域中的最大整数和最小整数的差值”的最小值。

输入输出样例

输入样例#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

题解

反正我一看到题就想着用ST表。。

不过后来发现还有一种更优秀的做法,那便是利用单调队列,求出一个满足一维上的最值数组

之后这个最值数组上再次利用单调队列求出二维的最值数组,便可以更优秀的时间复杂度过掉这道题(而且代码也不长)

code:(2dST表) 很好写

//By Menteur_Hxy
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#define F(i,a,b) for(register int i=(a);i<=(b);i++)
using namespace std; int rd() {
int x=0,f=1; char c=getchar();
while(!isdigit(c)) {if(c=='-') f=-f; c=getchar();}
while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
return x*f;
} const int INF=0x7fffffff;
const int MAX=1050;
int a,b,n,m;
int ma[MAX][MAX][12],mi[MAX][MAX][12]; inline int min(int a,int b) {
if(a<b) return a;
return b;
} inline int max(int a,int b) {
if(a>b) return a;
return b;
} void init() {
F(k,1,11) F(i,1,a-(1<<k)+1) F(j,1,b-(1<<k)+1)
mi[i][j][k]=min(min(mi[i][j][k-1],mi[i+(1<<(k-1))][j+(1<<(k-1))][k-1]),
min(mi[i+(1<<(k-1))][j][k-1],mi[i][j+(1<<(k-1))][k-1])),
ma[i][j][k]=max(max(ma[i][j][k-1],ma[i+(1<<(k-1))][j+(1<<(k-1))][k-1]),
max(ma[i+(1<<(k-1))][j][k-1],ma[i][j+(1<<(k-1))][k-1]));
} inline int query(int i,int j) {
int maxn=-INF,minn=INF;
minn=min(min(mi[i][j][m],mi[i+n-(1<<m)][j+n-(1<<m)][m]),
min(mi[i+n-(1<<m)][j][m],mi[i][j+n-(1<<m)][m]));
maxn=max(max(ma[i][j][m],ma[i+n-(1<<m)][j+n-(1<<m)][m]),
max(ma[i+n-(1<<m)][j][m],ma[i][j+n-(1<<m)][m]));
return maxn-minn;
} int main() {
a=rd(),b=rd(),n=rd();
F(i,1,a) F(j,1,b) ma[i][j][0]=mi[i][j][0]=rd();
init(); m=log(n)/log(2); int ans=INF;
F(i,1,a-n+1) F(j,1,b-n+1) ans=min(ans,query(i,j));
printf("%d",ans);
return 0;
}

code:(单调队列)

//By Menteur_Hxy
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#define F(i,a,b) for(register int i=(a);i<=(b);i++)
using namespace std;
int rd() {
int x=0,f=1; char c=getchar();
while(!isdigit(c)) {if(c=='-') f=-f; c=getchar();}
while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
return x*f;
}
const int N=1050,INF=0x7fffffff;
int n,m,k,ans=INF,h,H,T,t;
int da[N][N],X[N][N],x[N][N],Y[N][N],y[N][N],Q[N<<1],q[N<<1];
int main() {
n=rd(),m=rd(),k=rd();
F(i,1,n) F(j,1,m) da[i][j]=rd();
F(i,1,n) { H=T=h=t=Q[1]=q[1]=1;
F(j,2,m) {
while(T>=H and da[i][j]>=da[i][Q[T]]) T--;
while(t>=h and da[i][j]<=da[i][q[t]]) t--;
t++,T++; q[t]=Q[T]=j;
while(j-Q[H]>=k) H++;
while(j-q[h]>=k) h++;
if(j>=k) X[i][j-k+1]=da[i][Q[H]],x[i][j-k+1]=da[i][q[h]];
}
}
F(i,1,m-k+1) { H=T=t=h=Q[1]=q[1]=1;
F(j,2,n) {
while(T>=H and X[j][i]>=X[Q[T]][i]) T--;
while(t>=h and x[j][i]<=x[q[t]][i]) t--;
t++,T++; q[t]=Q[T]=j;
while(j-Q[H]>=k) H++;
while(j-q[h]>=k) h++;
if(j>=k) Y[j-k+1][i]=X[Q[H]][i],y[j-k+1][i]=x[q[h]][i],
ans=min(ans,Y[j-k+1][i]-y[j-k+1][i]);
}
}
return printf("%d",ans),0;
}

[luogu2216 HAOI2007] 理想的正方形 (2dST表 or 单调队列)的更多相关文章

  1. [bzoj1047][HAOI2007]理想的正方形_动态规划_单调队列

    理想的正方形 bzoj-1047 HAOI-2007 题目大意:有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 注释:$2\le a, ...

  2. [luoguP2216] [HAOI2007]理想的正方形(二维单调队列)

    传送门 1.先弄个单调队列求出每一行的区间为n的最大值最小值. 2.然后再搞个单调队列求1所求出的结果的区间为n的最大值最小值 3.最后扫一遍就行 懒得画图,自己体会吧. ——代码 #include ...

  3. [HAOI2007]理想的正方形 st表 || 单调队列

    ~~~题面~~~ 题解: 因为数据范围不大,而且题目要求的是正方形,所以这道题有2种解法. 1,st表. 这种解法暴力好写好理解,但是较慢.我们设st[i][j][k]表示以(i, j)为左端点,向下 ...

  4. luogu2216 [HAOI2007]理想的正方形

    先对于每一行中长度为 n 的列用单调队列搞出它们的最小/大值,再将这些长度为 n 的列想象成点再对行跑一遍 #include <iostream> #include <cstring ...

  5. [Bzoj1047][HAOI2007]理想的正方形(ST表)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1047 题目虽然有一个n的限制,但求二维区间最值首先想到的还是RMQ,但是如果按照往常RM ...

  6. 【BZOJ1047】[HAOI2007]理想的正方形 (倍增ST表)

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

  7. 【BZOJ1047】[HAOI2007]理想的正方形

    [BZOJ1047][HAOI2007]理想的正方形 题面 bzoj 洛谷 题解 二维\(st\)表,代码是以前的 #include<iostream> #include<cstdi ...

  8. [Luogu 2216] [HAOI2007]理想的正方形

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

  9. BZOJ1047: [HAOI2007]理想的正方形 [单调队列]

    1047: [HAOI2007]理想的正方形 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2857  Solved: 1560[Submit][St ...

随机推荐

  1. percona-xtradb-cluster安装部署

    Percona Xtradb Cluster 安装 Percona Xtradb Cluster 介绍 Percona XtraDB Cluster 简称:PXC,是针对MySQL 用户的高可用性和扩 ...

  2. 关于在linux下出现stdio.h文件不存在等gcc标准库不能找到的解决的方法

    首先说明一下我的系统配置:ubuntu 12.04     gcc 4.6.3 有几天没有使用ubuntu了,今天拿出来编程序,刚開始编译一个uboot1.1.6的代码.出现了stdio.h:没有那么 ...

  3. HDU 4906 Our happy ending (状压DP)

    HDU 4906 Our happy ending pid=4906" style="">题目链接 题意:给定n个数字,每一个数字能够是0-l,要选当中一些数字.然 ...

  4. javascript学习笔记(一)-廖雪峰教程

    一. 基础 1.for in,for of和forEach 遍历的是对象的属性,因为数组也是对象,其内部的元素的索引就是其属性值.用该方式遍历数组就是获取了数组中的每一个元素的索引值(从0開始). 而 ...

  5. wifi断线问题

    近期在项目中,遇到wifi常常断线现象,平台是Android平台,现象是:连接wifi后,长时间播放视频,会出现wifi断开,界面上WiFi图标显示打叉,请问有WiFi方面的行家朋友,有没有办法来检測 ...

  6. 第一个关于selenium项目

    1.创建一个简单的Python工程 在主菜单中,选择File | New Project ,并指定Python解释器版本 2.创建python类,快捷键alt+insert 3.编写打开浏览器的代码, ...

  7. 用树莓派实现RGB LED的颜色控制——C语言版本号

    用树莓派实现RGB LED的颜色控制  RGB色彩模式是工业界的一种颜色标准.是通过对红(R).绿(G).蓝(B)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,RGB即是代 表红.绿 ...

  8. Linux下开启vim高亮

    默认是不高亮的. [root@local ~]# vi ~/.vimrc 没有则新建这个文件. 或者修改 [root@local vim74]# vi /etc/vimrc 添加一行. syntax ...

  9. hdoj--1045--Fire Net(二分图)

    Fire Net Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  10. [JavaEE] Spring事务配置的五种方式

    前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识.通过这次的学习发觉Spring的事务配置只要把思路理清,还是比较好掌握的. ...