HAOI2007理想的正方形
先像滑动窗口一样处理出每一行的mx mn
然后再一列一列来
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
const int N=1000+50,M=1e6+50,inf=0x3f3f3f3f,P=19650827;
int a,b,n,k,ans=inf,mp[N][N],mxh[N][N],mnh[N][N],mx[N][N],mn[N][N];
template <class t>void rd(t &x){
x=0;int w=0;char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
x=w?-x:x;
}
int main(){
freopen("in2.txt","r",stdin);
rd(a),rd(b),rd(n);
for(int i=1;i<=a;++i)
for(int j=1;j<=b;++j) rd(mp[i][j]);
int l1,l2,r1,r2,q1[N],q2[N];
for(int h=1;h<=a;++h){
l1=l2=1,r1=r2=0;
memset(q1,0,sizeof(q1));memset(q2,0,sizeof(q2));
for(int i=1;i<=b;++i){
while(l1<=r1&&mp[h][i]<mp[h][q1[r1]]) --r1;
while(l2<=r2&&mp[h][i]>mp[h][q2[r2]]) --r2;
while(l1<=r1&&q1[l1]<=i-n) ++l1;
while(l2<=r2&&q2[l2]<=i-n) ++l2;
q1[++r1]=i,q2[++r2]=i;
if(l1<=r1&&i>=n) mnh[h][i]=mp[h][q1[l1]];
if(l2<=r2&&i>=n) mxh[h][i]=mp[h][q2[l2]];
}
}
for(int l=n;l<=b;++l){
l1=l2=1,r1=r2=0;
memset(q1,0,sizeof(q1));memset(q2,0,sizeof(q2));
for(int i=1;i<=a;++i){
while(l1<=r1&&mnh[i][l]<mnh[q1[r1]][l]) --r1;
while(l2<=r2&&mxh[i][l]>mxh[q2[r2]][l]) --r2;
while(l1<=r1&&q1[l1]<=i-n) ++l1;
while(l2<=r2&&q2[l2]<=i-n) ++l2;
q1[++r1]=i,q2[++r2]=i;
if(l1<=r1) mn[i][l]=mnh[q1[l1]][l];
if(l2<=r2) mx[i][l]=mxh[q2[l2]][l];
}
}
for(int i=n;i<=a;++i)
for(int j=n;j<=b;++j){
ans=Min(ans,mx[i][j]-mn[i][j]);
if(!ans) break;
}
printf("%d",ans);
return 0;
}