思路
观察到,面积越大,越不容易满足max-min <=line,又n比较小,所以可以枚举长度,即1-n,再二分宽度,即1-m,总体来说就是二分面积,枚举的矩形确定了,剩下的就是考虑怎么快速计算矩形里面的max-min,设c[i][j][len]为(i,j)点往下len个点的最大值(最小值),可以用单调队列快速处理出来,check里面也可以使用这个思路,此时把c[i][j][len]当成队列里的元素即可,这样就相当于求出了矩形的最大(最小)值。
import java.util.*;
import java.io.*;
public class Main
{
public static int n;
public static int m;
public static int line;
public static int c[][][],c2[][][];
public static int a[][],p[],q[];
public static boolean check(int lenth,int width){
boolean fal=false;
for(int i=1;i<=n;i++){
int hh=0,tt=-1;
int hh2=0,tt2=-1;
for(int j=1;j<=m;j++){
if(tt<hh){
p[++tt]=j;
}
else{
if(j-p[hh]+1>width) hh++;
while(hh<=tt&&c[i][j][lenth]>=c[i][p[tt]][lenth]) tt--;
p[++tt]=j;
}
if(tt2<hh2) q[++tt2]=j;
else{
if(j-q[hh2]+1>width) hh2++;
while(hh2<=tt2&&c2[i][j][lenth]<=c2[i][q[tt2]][lenth]) tt2--;
q[++tt2]=j;
}
if(j>=width&&c2[i][q[hh2]][lenth]<(int)1e6){
fal|=(c[i][p[hh]][lenth]-c2[i][q[hh2]][lenth])<=line;
}
}
}
return fal;
}
public static void main(String fas[])throws Exception
{
BufferedReader rd=new BufferedReader(new InputStreamReader(System.in));
BufferedWriter wd=new BufferedWriter(new OutputStreamWriter(System.out));
String sk[]=rd.readLine().split(" ");
n=Integer.parseInt(sk[0]);
m=Integer.parseInt(sk[1]);
c=new int [n+10][m+10][n+10];//求最大值用的.
c2=new int [n+10][m+10][n+10];//求最小值用的
a=new int [n+10][m+10];
for(int i=1;i<=n;i++){
String []tem=rd.readLine().split(" ");
for(int j=1;j<=m;j++){
a[i][j]=Integer.parseInt(tem[j-1]);
c[i][j][1]=c2[i][j][1]=a[i][j];
for(int len=2;len<=n;len++) c2[i][j][len]=(int)1e6;
}
}
line=Integer.parseInt(rd.readLine());
//预处理一下c和c2数组;
p=new int [Math.max(n+10,m+10)];
q=new int[Math.max(n+10,m+10)];
for(int len=2;len<=n;len++)
{
for(int j=1;j<=m;j++)
{
int hh=0,tt=-1;
int hh2=0,tt2=-1;
for(int i=1;i<=n;i++)
{
if(tt<hh) p[++tt]=i;
else{
if(i-p[hh]+1>len) hh++;
while(hh<=tt&&a[i][j]>=a[p[tt]][j]) tt--;
p[++tt]=i;
if(i>=len) c[i-len+1][j][len]=a[p[hh]][j];
}
if(tt2<hh2) q[++tt2]=i;
else{
if(i-q[hh2]+1>len) hh2++;
while(hh2<=tt2&&a[i][j]<=a[q[tt2]][j]) tt2--;
q[++tt2]=i;
if(i>=len) c2[i-len+1][j][len]=a[q[hh2]][j];
}
}
}
}
int mx=0;
if(line==0) mx=1;
for(int i=1;i<=n;i++){
int l=2,r=m;
int ans=-1;
while(l<=r){
int mid=(l+r)/2;
if(check(i,mid)){
ans=mid;
l=mid+1;
}
else r=mid-1;
}
if(ans!=-1) mx=Math.max(mx,i*ans);
}
System.out.println(mx);
}
}