题目传送门:https://www.luogu.org/problemnew/show/P2216
题意:
有一个n*m的整数组成的矩阵,现请你从中找出一个k*k的正方形区域,使得该区域所有数中的最大值和最小值的差最小。
思路:
二维st表(RMQ)。
代码:
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int f1[1010][1010][15],f2[1010][1010][15];//f1[i][j][k]表示从(i,j)到(i+2^k,j+2^k)的正方形区间最大值,f2[i][j][k]表示从(i,j)到(i+2^k,j+2^k)的正方形区间最小值
int n,m,p,ans=2147483647,t;
int RMQ(int x,int y)
{
int t1=x+p-(1<<t),t2=y+p-(1<<t);
int ma=max(f1[x][y][t],max(f1[t1][t2][t],max(f1[x][t2][t],f1[t1][y][t])));
int mi=min(f2[x][y][t],min(f2[t1][t2][t],min(f2[x][t2][t],f2[t1][y][t])));
return ma-mi;
}
int main()
{
int x;
scanf("%d %d %d",&n,&m,&p);
t=log2(p);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&x);
f1[i][j][0]=f2[i][j][0]=x;
}
int calc=log2(max(n,m));
for(int k=1;k<=calc;k++)
for(int i=1;i<=n-(1<<k)+1;i++)
for(int j=1;j<=m-(1<<k)+1;j++)
{
int r=(1<<(k-1));
f1[i][j][k]=max(f1[i][j][k-1],max(f1[i+r][j+r][k-1],max(f1[i+r][j][k-1],f1[i][j+r][k-1])));
f2[i][j][k]=min(f2[i][j][k-1],min(f2[i+r][j+r][k-1],min(f2[i+r][j][k-1],f2[i][j+r][k-1])));
}
for(int i=1;i<=n-p+1;i++)
for(int j=1;j<=m-p+1;j++)
ans=min(ans,RMQ(i,j));
printf("%d",ans);
}