上次cf做了一道二维单调队列,于是在这里也枚举右下角的点用二维单调队列,结果好像不行,,,
最后题解是直接枚举上下边界,然后从左到右单调队列扫过去记录,记录当前右边界下最远的左边界可以在哪
中间超时,加了很多优化,结果是最后在mi[i]赋初值的地方出了问题,以前一直做1e5的题目,用maxl作最大值,结果这里数值大小是1e5,maxl只有500。。。
#include<bits/stdc++.h>
#define maxl 510
using namespace std;
namespace fastIO
{
#define BUF_SIZE 100000
bool IOerror = 0;
inline char nc()
{
static char buf[BUF_SIZE];
static char *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
if(p1 == pend)
{
p1 = buf;
pend = buf + fread(buf, 1, BUF_SIZE, stdin);
if(pend == p1)
{
IOerror = 1;
return -1;
}
}
return *p1++;
}
inline bool blank(char ch) {
return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
}
inline int rd(int &x)
{
char ch;
while(blank(ch = nc()));
if(IOerror) return -1;
for(x=ch-'0';(ch=nc())>='0' && ch<='9';x=x*10+ch-'0');
return 1;
}
#undef BUF_SIZE
};
using namespace fastIO;
int n,m,ans;
int a[maxl][maxl];
int mi[maxl],mx[maxl];
int miq[maxl],mxq[maxl];
inline void prework()
{
//scanf("%d%d",&n,&m);
rd(n);rd(m);
for(register int i=1;i<=n;++i)
for(register int j=1;j<=n;++j)
//scanf("%d",&a[i][j]);
rd(a[i][j]);
}
inline int max(int a,int b)
{
if(a>b) return a;
else return b;
}
inline int min(int a,int b)
{
if(a<b) return a;
else return b;
}
inline void mainwork()
{
ans=0;
int mxh,mxt,mih,mit,l,r,len;
for(register int x1=1;x1<=n;++x1)
{
for(register int i=1;i<=n;++i)
mi[i]=1e5+10,mx[i]=0;
for(register int x2=x1;x2<=n;++x2)
{
l=1;mih=1;mit=0;mxh=1;mxt=0;len=(x2-x1+1);
for(register int i=1;i<=n;++i)
{
mi[i]=min(mi[i],a[x2][i]);
mx[i]=max(mx[i],a[x2][i]);
while(mih<=mit && mi[i]<=mi[miq[mit]])
--mit;
miq[++mit]=i;
while(mxh<=mxt && mx[i]>=mx[mxq[mxt]])
--mxt;
mxq[++mxt]=i;
while(mih<=mit && mxh<=mxt && mx[mxq[mxh]]-mi[miq[mih]]>m)
{
l=min(mxq[mxh]+1,miq[mih]+1);
while(mih<=mit && miq[mih]<l)
++mih;
while(mxh<=mxt && mxq[mxh]<l)
++mxh;
}
ans=max(ans,len*(i-l+1));
}
}
}
}
inline void print()
{
printf("%d\n",ans);
}
int main()
{
int t;
//scanf("%d",&t);
rd(t);
for(int i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}