可以先合一维再合一维
两个方向单调队列分别搞一下即可
蒟蒻我居然想不到单调队列
#include <cstdio>
const int MAXN=1011;
const int MAXM=1011;
const int INF=1034567890;
int N, M, K;
int Map[MAXN][MAXM], Temp[MAXN][MAXM], Max[MAXN][MAXM], Min[MAXN][MAXM];
int Q[MAXN+MAXM], Head, Tail;
int main(){
scanf("%d%d%d", &N, &M, &K);
for(int i=1;i<=N;++i)
for(int j=1;j<=M;++j)
scanf("%d", &Map[i][j]);
for(int i=1;i<=N;++i){
Head=1;Tail=1;
for(int j=1;j<=M;++j){
while(Head<Tail && Map[i][Q[Tail-1]]<=Map[i][j]) --Tail;
Q[Tail++]=j;
while(Q[Head]<=j-K) ++Head;
Temp[i][j]=Map[i][Q[Head]];
}
}
for(int j=1;j<=M;++j){
Head=1;Tail=1;
for(int i=1;i<=N;++i){
while(Head<Tail && Temp[Q[Tail-1]][j]<=Temp[i][j]) --Tail;
Q[Tail++]=i;
while(Q[Head]<=i-K) ++Head;
Max[i][j]=Temp[Q[Head]][j];
}
}
for(int i=1;i<=N;++i){
Head=1;Tail=1;
for(int j=1;j<=M;++j){
while(Head<Tail && Map[i][Q[Tail-1]]>=Map[i][j]) --Tail;
Q[Tail++]=j;
while(Q[Head]<=j-K) ++Head;
Temp[i][j]=Map[i][Q[Head]];
}
}
for(int j=1;j<=M;++j){
Head=1;Tail=1;
for(int i=1;i<=N;++i){
while(Head<Tail && Temp[Q[Tail-1]][j]>=Temp[i][j]) --Tail;
Q[Tail++]=i;
while(Q[Head]<=i-K) ++Head;
Min[i][j]=Temp[Q[Head]][j];
}
}
for(int i=1;i<=N;++i)
for(int j=1;j<=M;++j)
Temp[i][j]=Max[i][j]-Min[i][j];
int ANS=INF;
for(int i=K;i<=N;++i)
for(int j=K;j<=M;++j)
if(Temp[i][j]<ANS) ANS=Temp[i][j];
printf("%d
", ANS);
return 0;
}
/*
5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
1
*/