//又是一个矩阵的问题,还要,我在网上看了一个二维ST表的做法,找不到了,而且我自己只过了百分之九十的样例https://ac.nowcoder.com/acm/contest/883/F
题意:就是求满足条件的最大矩形面积,其实就是求二维的最大值最小值,满足条件就可以,我用二维ST表过了百分之九十,网上大部分都是用单调栈做的,我先找找我之前提交的代码,呜呜呜~~~
//这个是错的,哈哈哈,超了1ms再改改,天哪
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=505;
int mm[1005];
int val[maxn][maxn];
int dpmin[maxn][maxn][9][9];
int dpmax[maxn][maxn][9][9];
void initRMQ(int n,int m)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
dpmin[i][j][0][0]=dpmax[i][j][0][0]=val[i][j];
for(int ii=0;ii<=mm[n];ii++)
for(int jj=0;jj<=mm[m];jj++)
if(ii+jj)
for(int i=1;i+(1<<ii)-1<=n;i++)
for(int j=1;j+(1<<jj)-1<=m;j++)
{
if(ii)
{
dpmin[i][j][ii][jj]=min(dpmin[i][j][ii-1][jj],dpmin[i+(1<<(ii-1))][j][ii-1][jj]);
dpmax[i][j][ii][jj]=max(dpmax[i][j][ii-1][jj],dpmax[i+(1<<(ii-1))][j][ii-1][jj]);
}
else
{
dpmin[i][j][ii][jj]=min(dpmin[i][j][ii][jj-1],dpmin[i][j+(1<<(jj-1))][ii][jj-1]);
dpmax[i][j][ii][jj]=max(dpmax[i][j][ii][jj-1],dpmax[i][j+(1<<(jj-1))][ii][jj-1]);
}
}
}
int rmq1(int x1,int y1,int x2,int y2)//max
{
int k1=mm[x2-x1+1];
int k2=mm[y2-y1+1];
x2=x2-(1<<k1)+1;
y2=y2-(1<<k2)+1;
return max(max(dpmax[x1][y1][k1][k2],dpmax[x1][y2][k1][k2]),max(dpmax[x2][y1][k1][k2],dpmax[x2][y2][k1][k2]));
}
int rmq2(int x1,int y1,int x2,int y2)
{
int k1=mm[x2-x1+1];
int k2=mm[y2-y1+1];
x2=x2-(1<<k1)+1;
y2=y2-(1<<k2)+1;
return min(min(dpmin[x1][y1][k1][k2],dpmin[x1][y2][k1][k2]),min(dpmin[x2][y1][k1][k2],dpmin[x2][y2][k1][k2]));
}
int cal(int x1,int y1,int x2,int y2)
{
return rmq1(x1,y1,x2,y2)-rmq2(x1,y1,x2,y2);
}
void read(int &x)
{
char c=getchar();
x = 0;
while(c<'0'||c>'9')
c=getchar();
while(c<='9'&&c>='0')
x=x*10+c-48,c=getchar();
}
void put(int x)
{
int num=0; char c[15];
while(x)
c[++num]=(x%10)+48,x/=10;
while(num)
putchar(c[num--]);
putchar('\n');
}
int main()
{
int t,n,m;
read(t);
mm[0]=-1;
for(int i=1;i<=1005;i++)
mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1];
while(t--)
{
read(n);
read(m);
int ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
read(val[i][j]);
initRMQ(n,n);
for(int i=1;i<=n;i++)//O(n^4)一定不行,这样没想到可以过,还是看数据吧,哈哈
for(int j=1;j<=n;j++)
{
int x=j,mi1=val[i][j],mx1=val[i][j];
while(x<=n&&mx1-mi1<=m)//从(i,j)开始的在这一行上的最远距离
{
++x;
mi1=min(mi1,val[i][x]);
mx1=max(mx1,val[i][x]);
}
--x;
ans=max(ans,x-j+1);
for(int k=i+1;k<=n;k++)
{
while(x>=j&&cal(i,j,k,x)>m)
--x;
if((n-i+1)*(x-j+1)<=ans)
break;
ans=max(ans,(k-i+1)*(x-j+1));
}
}
put(ans);
}
return 0;
}