[luogu2216 HAOI2007] 理想的正方形 (2dST表 or 单调队列)
题目描述
有一个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 单调队列)的更多相关文章
- [bzoj1047][HAOI2007]理想的正方形_动态规划_单调队列
理想的正方形 bzoj-1047 HAOI-2007 题目大意:有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 注释:$2\le a, ...
- [luoguP2216] [HAOI2007]理想的正方形(二维单调队列)
传送门 1.先弄个单调队列求出每一行的区间为n的最大值最小值. 2.然后再搞个单调队列求1所求出的结果的区间为n的最大值最小值 3.最后扫一遍就行 懒得画图,自己体会吧. ——代码 #include ...
- [HAOI2007]理想的正方形 st表 || 单调队列
~~~题面~~~ 题解: 因为数据范围不大,而且题目要求的是正方形,所以这道题有2种解法. 1,st表. 这种解法暴力好写好理解,但是较慢.我们设st[i][j][k]表示以(i, j)为左端点,向下 ...
- luogu2216 [HAOI2007]理想的正方形
先对于每一行中长度为 n 的列用单调队列搞出它们的最小/大值,再将这些长度为 n 的列想象成点再对行跑一遍 #include <iostream> #include <cstring ...
- [Bzoj1047][HAOI2007]理想的正方形(ST表)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1047 题目虽然有一个n的限制,但求二维区间最值首先想到的还是RMQ,但是如果按照往常RM ...
- 【BZOJ1047】[HAOI2007]理想的正方形 (倍增ST表)
[HAOI2007]理想的正方形 题目描述 有一个\(a*b\)的整数组成的矩阵,现请你从中找出一个\(n*n\)的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入输出格式 输入格式: ...
- 【BZOJ1047】[HAOI2007]理想的正方形
[BZOJ1047][HAOI2007]理想的正方形 题面 bzoj 洛谷 题解 二维\(st\)表,代码是以前的 #include<iostream> #include<cstdi ...
- [Luogu 2216] [HAOI2007]理想的正方形
[Luogu 2216] [HAOI2007]理想的正方形 题目描述 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入输出格式 输 ...
- BZOJ1047: [HAOI2007]理想的正方形 [单调队列]
1047: [HAOI2007]理想的正方形 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2857 Solved: 1560[Submit][St ...
随机推荐
- Python - 字符串模板的安全替换(safe_substitute) 具体解释
字符串模板的安全替换(safe_substitute) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/27057339 ...
- 歌乐电子一道非常easy的笔试题目居然搞错了!!!
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMjI0NzQ2Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...
- 【LeetCode OJ 136】Single Number
题目链接:https://leetcode.com/problems/single-number/ 题目:Given an array of integers, every element appea ...
- iOS 块的简单理解
占位 自己主动转载器那小子,你转完了没? 转完了,我开写了哈! Block,就两个事儿,一个是引用,一个是实例,除了实现处.其他地方都是引用. 以此思路.再继续看看引用和实现的定义方式吧. 參考官方文 ...
- Reset and Clear Recent Items and Frequent Places in Windows 10
https://www.tenforums.com/tutorials/3476-reset-clear-recent-items-frequent-places-windows-10-a.html ...
- 字符流、字节流、二进制及其在HTTP协议传输
一.二进制.字节.字符流概念 字(Byte)节是长度单位.位(bit)也是长度单位.计算机通信和存储的时候都是以010101这样的二进制数据为基础的二进制数有两个特点:它由两个基本字符0,1组成,二进 ...
- Wannafly挑战赛25 C 期望操作数 数学
题目 题意:给你你一个数x和一个数q,x<=q,每一次可以等概率把x变成[x,q]中任意一个数,问变成q的步数的期望,输出对998244353取模,多组询问 题解:首先肯定的是,可以预处理,因为 ...
- vue开发的项目中遇到的警告,报错,配置项目文件等合集(长期更新)
1. Vue组件里面data()里面没有return时触发错误:Vue components Cannot read property '__ob__' of undefined 这个警告不解决会触发 ...
- All Metro Apps on Windows 8.1 Do Not Work
所有的Metro Apps不能够正常打开,表现为打开后自动最小化到任务栏,并且不能恢复正常状态.在Event Viewer\Application中相应的错误信息为: Activation of ap ...
- video相关简单的api
video 关键api 1. video.pause() 2. video.play() 3. video.webkitRequestFullScreen() //全屏 4. video.curren ...