记读入的矩阵为t[a][b]。
先用单调队列维护出每一个1行n列矩阵的最大值g[i][j]=max(t[i][j]~t[i+n-1][j])。
再用单调队列维护出每一个n行n列矩阵的最大值re[i][j]=max(g[i][j]~g[i+n-1][j])
最小值同理,接着O(n^2)遍历找答案即可。
#include<cstdio>
#define fmin(_a,_b) (_a>_b?_b:_a)
#define MAXN 1005
#define MAXM 105
int a, b, m, t[MAXN][MAXN], g[MAXN][MAXN], re[2][MAXN][MAXN];
struct que{int val, beg;}q[MAXN];
void solve(int k)
{
for(int i = 1; i <= a; i++)
{
int l=1, r=0;
for(int j = 1; j <= b; j++)
{
while(l<=r&&j-q[l].beg>=m)l++;
if(!k)while(l<=r&&t[i][j]>=q[r].val)r--;
else while(l<=r&&t[i][j]<=q[r].val)r--;
q[++r]=(que){t[i][j],j};
g[i][j]=q[l].val;
}
}
for(int j = m; j <= b; j++)
{
int l=1, r=0;
for(int i = 1; i <= a; i++)
{
while(l<=r&&i-q[l].beg>=m)l++;
if(!k)while(l<=r&&g[i][j]>=q[r].val)r--;
else while(l<=r&&g[i][j]<=q[r].val)r--;
q[++r]=(que){g[i][j],i};
re[k][i][j]=q[l].val;
}
}
}
int main()
{
scanf("%d%d%d",&a,&b,&m);
for(int i = 1; i <= a; i++)
for(int j = 1; j <= b; j++)
scanf("%d",&t[i][j]);
solve(0);
solve(1);
int ans=1<<30;
for(int i = m; i <= a; i++)
for(int j = m; j <= b; j++)
ans=fmin(ans,re[0][i][j]-re[1][i][j]);
printf("%d\n",ans);
return 0;
}