#include<stdio.h>
#include<algorithm>
#include<cstring>
#define maxn 305
#define maxq 20005
using namespace std;
struct query{int Sx,Sy,Dx,Dy,sol,ind;} q[maxq];
struct elem{int x,y;} e[maxn*maxn];
int n,m,nr=1;
int a[maxn][maxn],used[maxn][maxn],father[maxn*maxn];
int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
void read()
{
int u=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
scanf("%d",&a[i][j]),e[++u].x=i,e[u].y=j;
u=0;
for(int i=1;i<=m;i++)
u++,scanf("%d%d%d%d",&q[u].Sx,&q[u].Sy,&q[u].Dx,&q[u].Dy),q[u].sol=0,q[u].ind=i;
}
bool cmpE(const elem &e1,const elem &e2){
return a[e1.x][e1.y]>a[e2.x][e2.y];
}
bool cmpQ(const query &q1,const query &q2){
return q1.sol>q2.sol;
}
bool cmpSOL(const query &q1,const query &q2){
return q1.ind<q2.ind;
}
int search(int k)
{
if(father[k]==k) return k;
father[k]=search(father[k]);
return father[k];
}
void solve()
{
int step,i,j,nx,ny,r1,r2;
sort(e+1,e+n*n+1,cmpE);
for(step=(1<<20);step;step>>=1,nr++)
{
for(i=1;i<=n*n;i++) father[i]=i; j=1;
for(i=1;i<=m;i++)
{
for(;j<=n*n && a[e[j].x][e[j].y]>=q[i].sol+step;j++)
{
used[e[j].x][e[j].y]=nr;
for(int k=0;k<4;k++)
{
nx=e[j].x+dx[k]; ny=e[j].y+dy[k];
if(nx<1 || ny<1 || nx>n || ny>n || used[nx][ny]!=nr) continue;
r1=search(n*(e[j].x-1)+e[j].y); r2=search(n*(nx-1)+ny);
if(r1!=r2) father[r1]=r2;
}
}
if(search(n*(q[i].Sx-1)+q[i].Sy)==search(n*(q[i].Dx-1)+q[i].Dy))
q[i].sol+=step;
}
sort(q+1,q+m+1,cmpQ);
}
sort(q+1,q+m+1,cmpSOL);
}
void print()
{
for(int i=1;i<=m;i++)
printf("%d\n",q[i].sol);
}
int main()
{
freopen("matrice2.in","r",stdin);
freopen("matrice2.out","w",stdout);
read();
solve();
print();
fclose(stdin);
fclose(stdout);
return 0;
}