#include <cstdio>
#include <algorithm>
#include <vector>
#define Nmax 305
#define Qmax 20005
#define Vmax 1000005
using namespace std;
int N,Q,a[Nmax][Nmax],pad[Nmax*Nmax],MaxVal,MinVal=Vmax,sol[Qmax],nrmijl,nrauxi,nrinter;
int dx[]={-1,0,1, 0};
int dy[]={ 0,1,0,-1};
struct middle
{
int mij,nr;
bool operator < (const middle &A) const
{
return mij<A.mij;
}
};
middle mijl[Qmax];
struct interval
{
int left,right,st,dr;
};
interval inter[Qmax],auxi[Qmax];
struct cell
{
int lin,col;
};
vector <cell> L[Vmax];
struct quer
{
int l1,c1,l2,c2,poz;
};
quer v[Qmax],bune[Qmax],rele[Qmax];
inline int Findpoz(int lin, int col)
{
return (lin-1)*N+col;
}
inline int Find(int a)
{
int rad,i=a;
while(pad[a]>0)
a=pad[a];
rad=a;
while(pad[i]>0)
{
a=pad[i];
pad[i]=rad;
i=a;
}
return rad;
}
inline void Unite(int a, int b)
{
pad[a]+=pad[b];
pad[b]=a;
}
inline void Solve()
{
int x,p=nrmijl,t,lin,col,lin1,col1,i,t1,t2,aux,nrbune,nrrele,paux;
vector <cell> ::iterator it;
for(i=1;i<=N*N;++i) pad[i]=-1;
for(x=MaxVal,nrauxi=0;x>=MinVal && p;--x)
{
for(it=L[x].begin();it!=L[x].end();++it)
{
lin=it->lin; col=it->col;
for(t=0;t<4;++t)
{
lin1=lin+dx[t]; col1=col+dy[t];
if(lin1<1 || lin1>N || col1<1 || col1>N) continue;
if(a[lin1][col1]>=x)
{
t1=Find(Findpoz(lin,col));
t2=Find(Findpoz(lin1,col1));
if(t1!=t2)
Unite(t1,t2);
}
}
}
if(x==mijl[p].mij)
{
aux=mijl[p].nr;
nrbune=nrrele=0;
for(i=inter[aux].left;i<=inter[aux].right;++i)
if(Find(Findpoz(v[i].l1,v[i].c1))!=Find(Findpoz(v[i].l2,v[i].c2)))
rele[++nrrele]=v[i];
for(i=inter[aux].left;i<=inter[aux].right;++i)
if(Find(Findpoz(v[i].l1,v[i].c1))==Find(Findpoz(v[i].l2,v[i].c2)))
{
sol[v[i].poz]=mijl[p].mij;
bune[++nrbune]=v[i];
}
paux=inter[aux].left;
for(i=1;i<=nrrele;++i)
v[paux++]=rele[i];
for(i=1;i<=nrbune;++i)
v[paux++]=bune[i];
if(nrrele)
{
++nrauxi;
auxi[nrauxi].left=inter[aux].left;
auxi[nrauxi].right=inter[aux].left+nrrele-1;
auxi[nrauxi].st=inter[aux].st;
auxi[nrauxi].dr=mijl[p].mij-1;
}
if(nrbune)
{
++nrauxi;
auxi[nrauxi].left=inter[aux].left+nrrele;
auxi[nrauxi].right=inter[aux].right;
auxi[nrauxi].st=mijl[p].mij+1;
auxi[nrauxi].dr=inter[aux].dr;
}
--p;
}
}
nrinter=nrauxi;
for(i=1;i<=nrauxi;++i)
inter[i]=auxi[i];
}
int main()
{
int i,j,gata=0;
cell w;
freopen ("matrice2.in","r",stdin);
freopen ("matrice2.out","w",stdout);
scanf("%d%d", &N,&Q);
for(i=1;i<=N;++i)
for(j=1;j<=N;++j)
{
scanf("%d", &a[i][j]);
w.lin=i; w.col=j;
L[a[i][j]].push_back(w);
MaxVal=max(MaxVal,a[i][j]);
MinVal=min(MinVal,a[i][j]);
}
for(i=1;i<=Q;++i)
{
scanf("%d%d%d%d", &v[i].l1,&v[i].c1,&v[i].l2,&v[i].c2);
v[i].poz=i;
}
nrinter=1;
inter[1].left=1; inter[1].right=Q; inter[1].st=MinVal; inter[1].dr=MaxVal;
while(!gata)
{
gata=1; nrmijl=0;
for(i=1;i<=nrinter;++i)
if(inter[i].st<=inter[i].dr)
{
gata=0;
++nrmijl;
mijl[nrmijl].mij=(inter[i].st+inter[i].dr)/2;
mijl[nrmijl].nr=i;
}
sort(mijl+1,mijl+nrmijl+1);
if(!gata)
Solve();
}
for(i=1;i<=Q;++i)
printf("%d\n", sol[i]);
return 0;
}