#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int NMAX = 305;
const int QMAX = 20005;
int N,NrQ;
int Matrix[NMAX][NMAX];
int sol[QMAX];
struct Vertice
{
int x,y;
bool operator()(Vertice A,Vertice B)
{
return Matrix[A.x][A.y]>Matrix[B.x][B.y];
}
};
struct Query
{
int x1,x2,y1,y2,ind;
bool operator()(Query A,Query B)
{
return sol[A.ind]>sol[B.ind];
}
};
Vertice V[NMAX*NMAX];
Query Q[QMAX];
int root[NMAX*NMAX];
int dx[]= {-1,1,0,0};
int dy[]= {0,0,-1,1};
int B[NMAX][NMAX];
int find(int x)
{
if(root[x]!=x) root[x]=find(root[x]);
return root[x];
}
void unite(int x,int y)
{
root[y]=x;
}
void unite_4d(int x,int y)
{
int i;
for(i=0; i<4; i++)
if(B[x+dx[i]][y+dy[i]]) unite(find(B[x][y]),find(B[x+dx[i]][y+dy[i]]));
}
int main()
{
int i,j,k,a,b,cnt;
freopen("matrice2.in","r",stdin);
freopen("matrice2.out","w",stdout);
scanf("%d%d",&N,&NrQ);
for(i=1; i<=N; i++)
for(j=1; j<=N; j++)
{
scanf("%d",&Matrix[i][j]);
V[(i-1)*N+j].x=i;
V[(i-1)*N+j].y=j;
}
for(i=1; i<=NrQ; i++)
{
scanf("%d%d%d%d",&Q[i].x1,&Q[i].y1,&Q[i].x2,&Q[i].y2);
Q[i].ind=i;
}
sort(V+1,V+N*N+1,Vertice());
for(k=(1<<20); k; k>>=1)
{
sort(Q+1,Q+NrQ+1,Query());
memset(B,0,sizeof(B));
for(i=1; i<=N*N; i++)
root[i]=i;
for(i=1,j=1,cnt=0; j<=NrQ; j++)
{
for(; (i<=N*N) && (Matrix[V[i].x][V[i].y] >= sol[Q[j].ind]+k); i++)
{
B[V[i].x][V[i].y]=++cnt;
unite_4d(V[i].x,V[i].y);
}
a=find(B[Q[j].x1][Q[j].y1]);
b=find(B[Q[j].x2][Q[j].y2]);
if(a && b && a==b) sol[Q[j].ind]+=k;
}
}
for(i=1; i<=NrQ; i++)
printf("%d\n",sol[i]);
return 0;
}