没看过一维ST表的可以移步
https://www.cnblogs.com/tldr/p/11261351.html
二维ST表的思路参考一维,每次维护一个step*step的一个正方形
因此 洛谷P2216理想的正方形是一个很好的二维ST表
一般来说,二维ST表询问的是某一个状态,这样可以用一个二维数组存下,否则就需要三维数组了,内存和时间消耗特别大
#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<b;i++)
#define FOR2(i,a,b) for(int i=a;i<=b;i++)
#define sync ios::sync_with_stdio(false);cin.tie(0)
#define ll long long
#define INF 0x3f3f3f3f;
#define MAXN 1000100
#define MOD 10007
#define sf(a,b) read(a),read(b)
using namespace std;
int a,b,k,arr[1100][1100],dpmax[1100][1100],dpmin[1100][1100];
int main()
{//AC
cin>>a>>b>>k;int logk=log2(k);
//read
FOR2(i,1,a)
FOR2(j,1,b)scanf("%d",&arr[i][j]),dpmin[i][j]=dpmax[i][j]=arr[i][j];
//process
for(int h=1;h<=logk;h++)
for(int i=1;i+(1<<h)-1<=a;i++)
for(int j=1;j+(1<<h)-1<=b;j++)
{
dpmax[i][j]=max(dpmax[i][j],max(dpmax[i+(1<<h-1)][j],max(dpmax[i+(1<<h-1)][j+(1<<h-1)],dpmax[i][j+(1<<h-1)])));
dpmin[i][j]=min(dpmin[i][j],min(dpmin[i+(1<<h-1)][j],min(dpmin[i+(1<<h-1)][j+(1<<h-1)],dpmin[i][j+(1<<h-1)])));
}
//query
int res=INF;
for(int i=1;i<=a-k+1;i++)
for(int j=1;j<=b-k+1;j++)
{
int maxx=max(dpmax[i][j],max(dpmax[i+k-(1<<logk)][j],max(dpmax[i+k-(1<<logk)][j+k-(1<<logk)],dpmax[i][j+k-(1<<logk)])));
int minn=min(dpmin[i][j],min(dpmin[i+k-(1<<logk)][j],min(dpmin[i+k-(1<<logk)][j+k-(1<<logk)],dpmin[i][j+k-(1<<logk)])));
res=min(res,maxx-minn);
}
cout<<res<<endl;
return 0;
}