#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define pf push_front
#define ll long long
#define ull unsigned long long
#define x first
#define y second
#define pi pair<int,int>
#define pl pair<ll,ll>
using namespace std;
ifstream fin("matrice2.in");
ofstream fout("matrice2.out");
const ll N=3e2+5,INF=1e18,MOD=666013,M=1e2+5,inf=INT_MAX;
struct edge
{
int a,b,cost;
};
int n,q;
int v[N][N],dp[N*N],par[N*N],siz[N*N];
vector<edge> edges;
int nr(int i,int j)
{
return (i-1)*n+j;
}
bool cmp(edge a,edge b)
{
return a.cost>b.cost;
}
int parent(int nod)
{
if(nod==par[nod])return nod;
return par[nod]=parent(par[nod]);
}
void dsu(int a,int b,int cost)
{
a=parent(a);
b=parent(b);
if(a!=b)
{
if(siz[a]==siz[b])siz[a]++;
if(siz[a]<siz[b])
{
siz[b]+=siz[a];
par[a]=b;
dp[a]=cost;
}
else
{
siz[a]+=siz[b];
par[b]=a;
dp[b]=cost;
}
}
}
int main()
{
fin>>n>>q;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
fin>>v[i][j];
if(i!=1)edges.pb({nr(i-1,j),nr(i,j),min(v[i][j],v[i-1][j])});
if(j!=1)edges.pb({nr(i,j-1),nr(i,j),min(v[i][j],v[i][j-1])});
}
}
sort(edges.begin(),edges.end(),cmp);
for(int i=1;i<=n*n;i++)
{
par[i]=i;
siz[i]=1;
}
for(int i=0;i<edges.size();i++)
{
int a=edges[i].a,b=edges[i].b,cost=edges[i].cost;
dsu(a,b,cost);
}
for(int i=1;i<=q;i++)
{
int x1,y1,x2,y2;
fin>>x1>>y1>>x2>>y2;
int a=nr(x1,y1),b=nr(x2,y2),ans=1e9;
while(a!=b)
{
if(siz[a]<siz[b])
{
ans=min(ans,dp[a]);
a=par[a];
}
else
{
ans=min(ans,dp[b]);
b=par[b];
}
}
fout<<ans<<'\n';
}
}