单调队列的基本应用。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 1050 #define inf 2000000000 using namespace std; int n,m,a,map[maxn][maxn],m1[maxn][maxn][3],m2[maxn][maxn][3],q1[maxn],q2[maxn],l1,r1,l2,r2,ans=inf; void get_m1() { for (int i=1;i<=n;i++) { l1=l2=1;r1=r2=0; for (int j=m;j>=1;j--) { while ((l1<=r1) && (q1[l1]>=j+a)) l1++; while ((l2<=r2) && (q2[l2]>=j+a)) l2++; while ((l1<=r1) && (map[i][j]>map[i][q1[r1]])) r1--; while ((l2<=r2) && (map[i][j]<map[i][q2[r2]])) r2--; q1[++r1]=j;q2[++r2]=j; m1[i][j][1]=map[i][q1[l1]];m1[i][j][2]=map[i][q2[l2]]; } } } void get_m2() { for (int i=1;i<=m;i++) { l1=l2=1;r1=r2=0; for (int j=n;j>=1;j--) { while ((l1<=r1) && (q1[l1]>=j+a)) l1++; while ((l2<=r2) && (q2[l2]>=j+a)) l2++; while ((l1<=r1) && (m1[j][i][1]>m1[q1[r1]][i][1])) r1--; while ((l2<=r2) && (m1[j][i][2]<m1[q2[r2]][i][2])) r2--; q1[++r1]=j;q2[++r2]=j; m2[j][i][1]=m1[q1[l1]][i][1];m2[j][i][2]=m1[q2[l2]][i][2]; } } } int main() { scanf("%d%d%d",&n,&m,&a); for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) scanf("%d",&map[i][j]); get_m1(); get_m2(); for (int i=1;i<=n-a+1;i++) for (int j=1;j<=m-a+1;j++) ans=min(ans,m2[i][j][1]-m2[i][j][2]); printf("%d\n",ans); return 0; }