http://www.lydsy.com/JudgeOnline/problem.php?id=1047
先用单调队列求出每横着n个最大值
再在里面用单调队列求出每竖着n个的最大值
这样一个位置就代表了一个n*n矩阵的最大值
同理求出最小值
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define N 1001 int num[N][N]; int mx1[N][N],mx2[N][N]; int mi1[N][N],mi2[N][N]; int q[N],pos[N],h,t; void read(int &x) { x=0; int f=1; char c=getchar(); while(!isdigit(c)) { if(c=='-') f=-1; c=getchar(); } while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } x*=f; } int main() { #ifndef ONLINE_JUDGE freopen("data.in","r",stdin); freopen("xxy.out","w",stdout); #endif int a,b,n; read(a); read(b); read(n); for(int i=1;i<=a;++i) for(int j=1;j<=b;++j) read(num[i][j]); for(int i=1;i<=a;++i) { h=t=0; for(int j=1;j<=b;++j) { while(h<t && j-pos[h]+1>n) h++; while(h<t && num[i][j]>q[t-1]) t--; q[t]=num[i][j]; pos[t++]=j; if(j>=n) mx1[i][j]=q[h]; } } for(int j=n;j<=b;++j) { h=t=0; for(int i=1;i<=a;++i) { while(h<t && i-pos[h]+1>n) h++; while(h<t && mx1[i][j]>q[t-1]) t--; q[t]=mx1[i][j]; pos[t++]=i; if(i>=n) mx2[i][j]=q[h]; } } for(int i=1;i<=a;++i) { h=t=0; for(int j=1;j<=b;++j) { while(h<t && j-pos[h]+1>n) h++; while(h<t && num[i][j]<q[t-1]) t--; q[t]=num[i][j]; pos[t++]=j; if(j>=n) mi1[i][j]=q[h]; } } for(int j=n;j<=b;++j) { h=t=0; for(int i=1;i<=a;++i) { while(h<t && i-pos[h]+1>n) h++; while(h<t && mi1[i][j]<q[t-1]) t--; q[t]=mi1[i][j]; pos[t++]=i; if(i>=n) mi2[i][j]=q[h]; } } int ans=2e9; for(int i=n;i<=a;++i) for(int j=n;j<=b;++j) ans=min(ans,mx2[i][j]-mi2[i][j]); printf("%d",ans); }