rc的矩阵用单调队列横向缩为r(c-n+1)矩阵,然后纵向缩为(r-n+1)*(c-n+1)矩阵,矩阵每一个点都代表着一个正方形的最值。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cstdio>
using namespace std;
const int maxn=2e5+5;
struct node
{
int x,y;
} idm[maxn],idn[maxn];
int vmax[maxn],vmin[maxn],lm=1,ln=1,rm=0,rn=0,mp[2001][2001],valm[2001][2001],valn[2001][2001];
#define base1(xs,j,k) \
while(lm<=rm&&vmax[rm]<=xs)rm--; \
vmax[++rm]=xs; \
idm[rm].y=k; \
idm[rm].x=j; \
#define base2(xs,j,k) \
while(ln<=rn&&vmin[rn]>=xs)rn--; \
vmin[++rn]=xs; \
idn[rn].y=k; \
idn[rn].x=j; \
#define sq(x,y,z,a) for(int i=x;i<=y;i++)for(int j=z;j<=a;j++)
#define getans() minn=min(minn,vmax[lm]-vmin[ln]);//cout<<"vmax"<<vmax[lm]<<' '<<"vmin "<<vmin[ln]<<" lm "<<idm[lm].x<<' '<<idm[lm].y<<' '<<lm<<" ln "<<idn[ln].x<<' '<<idn[ln].y<<' '<<ln<<endl;
int r,c,n,minn=0x3f3f3f3f;
void init()
{
scanf("%d%d%d",&r,&c,&n);
sq(1,r,1,c) scanf("%d",&mp[i][j]);
}
int main()
{
init();
for(int i=1; i<=r; i++)
{
lm=1,ln=1,rm=0,rn=0;
for(int j=1; j<=c; j++)
{
base1(mp[i][j],i,j);
base2(mp[i][j],i,j);
int ym=idm[lm].y;
int yn=idn[ln].y;
while(ym<=j-n) {
lm++;
ym=idm[lm].y;
}
while(yn<=j-n) {
ln++;
yn=idn[ln].y;
}
valm[i][j]=vmax[lm];
valn[i][j]=vmin[ln];
}
}
for(int i=n; i<=c; i++){
lm=1,ln=1,rm=0,rn=0;
for(int j=1; j<=r; j++)
{
// cout<<valm[j][i]<<">>>>"<<endl;
base1(valm[j][i],j,i);
base2(valn[j][i],j,i);
int xm=idm[lm].x;
int xn=idn[ln].x;
while(xm<=j-n) {
lm++;
xm=idm[lm].x;
}
while(xn<=j-n) {
ln++;
xn=idn[ln].x;
}
valm[j][i]=vmax[lm];
valn[j][i]=vmin[ln];
}
}
sq(n,r,n,c)minn=min(valm[i][j]-valn[i][j],minn);
cout << minn << endl;
return 0;
}