显然就是扫一下所有n*n的矩阵的最大值和最小值只差取min,单调队列横着扫一遍竖着扫一遍就好了
好好取名字,少用ctrl+C ctrl+V【因为这个我调了一年233333
#include<bits/stdc++.h>
#define MAXN 1006
using namespace std; int n,m,k;
inline int read(){
register char ch = getchar();
while(!isdigit(ch)) ch = getchar();
register int rtn = 0;
while(isdigit(ch)) rtn = rtn*10 + ch - '0' , ch = getchar();
return rtn;
}
int g[MAXN][MAXN];
int f[MAXN][MAXN],h[MAXN][MAXN];
int que[MAXN],head,tail;
int q2[MAXN],head2,tail2;
int main(){
// freopen("1.in","r",stdin);
n = read() , m = read() , k = read();
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
g[i][j] = read();
for(int j=1;j<=n;++j){
memset(que,0,sizeof que);
memset(q2,0,sizeof q2);
head = tail = 0;
head2 = tail2 = 0;
for(int i=1;i<k;++i){
while(tail>head && g[j][i]>g[j][que[tail-1]]) --tail;
que[tail++] = i;
while(tail2>head2 && g[j][i]<g[j][q2[tail2-1]]) --tail2;
q2[tail2++] = i;
}
for(int i=k;i<=m;++i){
while(tail>head && g[j][i]>g[j][que[tail-1]]) --tail;
que[tail++] = i;
while(tail>head && que[head]+k<=i) ++head;
f[j][i] = g[j][que[head]];
while(tail2>head2 && g[j][i]<g[j][q2[tail2-1]]) --tail2;
q2[tail2++] = i;
while(tail2>head2 && q2[head2]+k<=i) ++head2;
h[j][i] = g[j][q2[head2]];
}
}
int ans = 0x3f3f3f3f;
for(int j=k;j<=m;++j){
memset(que,0,sizeof que);
memset(q2,0,sizeof q2);
head = tail = head2 = tail2 = 0;
for(int i=1;i<k;++i){
while(tail>head && f[i][j] > f[que[tail-1]][j]) --tail;
que[tail++] = i;
while(tail2>head2 && h[i][j] < h[q2[tail2-1]][j]) --tail2;
q2[tail2++] = i;
}
for(int i=k;i<=n;++i){
while(tail>head && f[i][j]>f[que[tail-1]][j]) --tail;
que[tail++] = i;
while(tail>head && que[head]+k<=i) ++head;
while(tail2>head2 && h[i][j]<h[q2[tail2-1]][j]) --tail2;
q2[tail2++] = i;
while(tail2>head2 && q2[head2]+k<=i) ++head2;
ans = min(ans,f[que[head]][j]-h[q2[head2]][j]);
}
}
printf("%d",ans);
return 0;
}