首先预处理出pre_xmax[i][j],表示第i横行,第j~j+N-1竖列a[i][j]的最大值;预处理出pre_xmin,意义与前边相反。
接着处理pre_max[i][j]表示第i横行,第j~j+N-1竖列pre_xmax[i][j]的最大值;预处理出pre_min,意义与前边相反。
处理完后,pre_max[i][j]实际上是a[i~i+N-1][j~j+N-1]里的最大值,pre_min类似,以i,j为左上角。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1005;
int A,B,N,a[MAXN][MAXN];
int pre_xmin[MAXN][MAXN],pre_xmax[MAXN][MAXN];
int pre_min[MAXN][MAXN],pre_max[MAXN][MAXN];
struct data{int id,num;}q[MAXN];
char c;
void scan(int &x)
{
for(c=getchar();c<'0'||c>'9';c=getchar());
for(x=0;c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
}
void prexmax(int x)
{
int L=1,R=0,i;
q[1]=((data){0,0});
for(i=B;i>=1;i--)
{
while(L<=R&&q[L].id-i>=N) L++;
while(L<=R&&a[x][i]>=q[R].num) R--;
q[++R]=((data){i,a[x][i]});
pre_xmax[x][i]=q[L].num;
}
}
void prexmin(int x)
{
int L=1,R=0,i;
q[1]=((data){0,0});
for(i=B;i>=1;i--)
{
while(L<=R&&q[L].id-i>=N) L++;
while(L<=R&&a[x][i]<=q[R].num) R--;
q[++R]=((data){i,a[x][i]});
pre_xmin[x][i]=q[L].num;
}
}
void premax(int x)
{
int L=1,R=0,i;
q[1]=((data){0,0});
for(i=A;i>=1;i--)
{
while(L<=R&&q[L].id-i>=N) L++;
while(L<=R&&pre_xmax[i][x]>=q[R].num) R--;
q[++R]=((data){i,pre_xmax[i][x]});
pre_max[i][x]=q[L].num;
}
}
void premin(int x)
{
int L=1,R=0,i;
q[1]=((data){0,0});
for(i=A;i>=1;i--)
{
while(L<=R&&q[L].id-i>=N) L++;
while(L<=R&&pre_xmin[i][x]<=q[R].num) R--;
q[++R]=((data){i,pre_xmin[i][x]});
pre_min[i][x]=q[L].num;
}
}
int main()
{
int i,j;
scan(A);scan(B);scan(N);
for(i=1;i<=A;i++)
for(j=1;j<=B;j++)
scan(a[i][j]);
for(i=1;i<=A;i++)
{
prexmax(i);
prexmin(i);
}
for(i=1;i<=B;i++)
{
premax(i);
premin(i);
}
int ans=0x3f3f3f3f;
for(i=1;i<=A-N+1;i++)
for(j=1;j<=B-N+1;j++)
ans=min(ans,pre_max[i][j]-pre_min[i][j]);
cout<<ans;
return 0;
}