点此看题面

大致题意: 求出一个矩阵中所有\(n*n\)正方形中极差的最小值。

另一种做法

听说这题可以用单调队列去做,但是我写了一个二维\(RMQ\)

二维\(RMQ\)

\(RMQ\)相信大家都会的,而 二维\(RMQ\) 其实与普通\(RMQ\)是没什么区别的。

我们可以用\(Max_{i,j,k}\)来表示\((i,j)\sim(i+2^k,j+2^k)\)这个矩阵内的最大值,\(Min_{i,j,k}\)同理。

由于求的是一个正方形内的最大值与最小值,所以\((i,j)\sim(x,y)\)这个矩阵内的最大值就等于

\[max(Max_{i,j,Log},Max_{x-2^{Log}+1,j,Log},Max_{i,y-2^{Log}+1,Log},Max_{x-2^{Log}+1,y-2^{Log}+1,Log})
\]

其中\(Log\)表示\(log_2(x-i)\)(\(=log_2(y-j)\)),最小值同理。

那么代码就很简单了。

代码

#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define uint unsigned int
#define LL long long
#define ull unsigned long long
#define swap(x,y) (x^=y,y^=x,x^=y)
#define abs(x) ((x)<0?-(x):(x))
#define INF 1e9
#define Inc(x,y) ((x+=(y))>=MOD&&(x-=MOD))
#define ten(x) (((x)<<3)+((x)<<1))
#define N 1000
#define K 100
#define LogN 10
using namespace std;
int n,m,k,a[N+5][N+5];
class FIO
{
private:
#define Fsize 100000
#define tc() (FinNow==FinEnd&&(FinEnd=(FinNow=Fin)+fread(Fin,1,Fsize,stdin),FinNow==FinEnd)?EOF:*FinNow++)
#define pc(ch) (FoutSize<Fsize?Fout[FoutSize++]=ch:(fwrite(Fout,1,FoutSize,stdout),Fout[(FoutSize=0)++]=ch))
int f,FoutSize,OutputTop;char ch,Fin[Fsize],*FinNow,*FinEnd,Fout[Fsize],OutputStack[Fsize];
public:
FIO() {FinNow=FinEnd=Fin;}
inline void read(int &x) {x=0,f=1;while(!isdigit(ch=tc())) f=ch^'-'?1:-1;while(x=ten(x)+(ch&15),isdigit(ch=tc()));x*=f;}
inline void read_char(char &x) {while(isspace(x=tc()));}
inline void read_string(string &x) {x="";while(isspace(ch=tc()));while(x+=ch,!isspace(ch=tc())) if(!~ch) return;}
inline void write(int x) {if(!x) return (void)pc('0');if(x<0) pc('-'),x=-x;while(x) OutputStack[++OutputTop]=x%10+48,x/=10;while(OutputTop) pc(OutputStack[OutputTop]),--OutputTop;}
inline void write_char(char x) {pc(x);}
inline void write_string(string x) {register int i,len=x.length();for(i=0;i<len;++i) pc(x[i]);}
inline void end() {fwrite(Fout,1,FoutSize,stdout);}
}F;
class Class_RMQ//二维RMQ
{
private:
//写define有利于代码简洁
#define Delta (X2-X1+1)
#define Log (Log2[Delta])
#define XX (X2-(1<<Log)+1)
#define YY (Y2-(1<<Log)+1)
int Log2[K+5],Max[N+5][N+5][LogN+5],Min[N+5][N+5][LogN+5];
public:
inline void Init()//初始化
{
register int i,j,l;
for(i=1;i<=n;++i) for(j=1;j<=m;++j) F.read(Max[i][j][0]),Min[i][j][0]=Max[i][j][0];
for(i=2;i<=k;++i) Log2[i]=Log2[i>>1]+1;
for(l=1;l<LogN;++l) for(i=1;i+(1<<l)-1<=n;++i) for(j=1;j+(1<<l)-1<=m;++j)
{
Max[i][j][l]=max(max(Max[i][j][l-1],Max[i+(1<<l-1)][j][l-1]),max(Max[i][j+(1<<l-1)][l-1],Max[i+(1<<l-1)][j+(1<<l-1)][l-1])),
Min[i][j][l]=min(min(Min[i][j][l-1],Min[i+(1<<l-1)][j][l-1]),min(Min[i][j+(1<<l-1)][l-1],Min[i+(1<<l-1)][j+(1<<l-1)][l-1]));
}
}
inline int GetMax(int X1,int Y1,int X2,int Y2) {return max(max(Max[X1][Y1][Log],Max[XX][Y1][Log]),max(Max[X1][YY][Log],Max[XX][YY][Log]));}//区间最大值
inline int GetMin(int X1,int Y1,int X2,int Y2) {return min(min(Min[X1][Y1][Log],Min[XX][Y1][Log]),min(Min[X1][YY][Log],Min[XX][YY][Log]));}//区间最小值
}RMQ;
int main()
{
register int i,j,ans=INF,res;
for(F.read(n),F.read(m),F.read(k),RMQ.Init(),i=1;i<=n-k+1;++i)
for(j=1;j<=m-k+1;++j) res=RMQ.GetMax(i,j,i+k-1,j+k-1)-RMQ.GetMin(i,j,i+k-1,j+k-1),ans=min(ans,res);//枚举区间,更新ans
return F.write(ans),F.end(),0;
}

【洛谷2216】[HAOI2007] 理想的正方形(二维RMQ)的更多相关文章

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

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

  2. 【bzoj1047】[HAOI2007]理想的正方形 二维RMQ

    题目描述 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入 第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非 ...

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

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

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

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

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

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

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

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

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

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

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

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

  9. BZOJ1047[HAOI2007]理想的正方形——二维ST表

    题目描述 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入 第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非 ...

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

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

随机推荐

  1. 22. Generate Parentheses (recursion algorithm)

    Given n pairs of parentheses, write a function to generate all combinations of well-formed parenthes ...

  2. Exception异常处理

    1.java异常类: 都是Throwable的子类: 1.Exception(异常) :是程序本身可以处理的异常. 2.Error(错误): 是程序无法处理的错误.这些错误表示故障发生于虚拟机自身.或 ...

  3. UML——再回首

    概述     在画图的过程中,发现自己还是有好多不懂的地方,对于四大关系理解的不是特别透彻,所以画图的过程中总是"剪不断,理还乱!"再一次整理四大关系,再回首必然丰收~~~ 1.实 ...

  4. ACM-ICPC 2018 徐州赛区网络预赛 B(dp || 博弈(未完成)

    传送门 题面: In a world where ordinary people cannot reach, a boy named "Koutarou" and a girl n ...

  5. VSCode makedown增强插件

    Markdown Preview Enhanced https://shd101wyy.github.io/markdown-preview-enhanced/#/zh-cn/

  6. 才知道 Windows Live Writer Source Code plugin for SyntaxHighlighter 更新到2.0了

    这是我用 Windows Live Writer 发布的第一篇文章! 在官方网站看到 Windows Live Writer Source Code plugin for SyntaxHighligh ...

  7. Sort HDU - 5884 哈夫曼权值O(n)

    http://acm.hdu.edu.cn/showproblem.php?pid=5884 原来求一次哈夫曼可以有O(n)的做法. 具体是,用两个队列,一个保存原数组,一个保存k个节点合并的数值,然 ...

  8. CentOS 7 iptables 开放8080端口

    # 安装iptables-services [root@localhost bin]# yum install iptables-services [root@localhost bin]# /bin ...

  9. Java集合——集合框架Map接口

    1.Map接口 public interface Map<K,V>将键映射到值的对象.一个映射不能包含重复的键:每个键最多只能映射到一个值.  2.HashMap.Hashtable.Tr ...

  10. 如何在mssql中获取最新自增ID的值

    @@IDENTITY 返回最后一个插入 IDENTITY 的值,这些操作包括:INSERT, SELECT INTO,或者 bulk copy.如果在给没有 IDENTITY 列的其他表插入记录,系统 ...