#include<cstdio>
#include<vector>
#include<algorithm>
#define MAXN 310
#define dim 8192
using namespace std;
int n,poz=0;
int dad[MAXN*MAXN],height[MAXN*MAXN];
char buff[dim];
struct cell{int l,c,cost;};
struct query{int x1,y1,x2,y2,position,answer;};
vector<cell> cells;
vector<query> queries,first,second;
bool cmp(cell a,cell b){
if(a.cost>b.cost)
return true;
return false;
}
bool cmp0(query a,query b){
if(a.position<b.position)
return true;
return false;
}
int number(int l,int c){
return (l-1)*n+c;
}
void initialize(){
int i;
for(i=1;i<=n*n;i++){
dad[i]=0;
height[i]=0;
}
}
int find_dad(int node){
if(dad[node]==node)
return node;
return dad[node]=find_dad(dad[node]);
}
void join(int node1,int node2){
int dad1=find_dad(node1),dad2=find_dad(node2);
if(dad1==dad2)
return;
if(height[dad1]>height[dad2])
dad[dad2]=dad1;
else
if(height[dad2]>height[dad1])
dad[dad1]=dad2;
else{
dad[dad2]=dad1;
height[dad1]++;
}
}
int check(int l,int c){
if(c<1||l<1||c>n||l>n)
return 0;
if(dad[number(l,c)]==0)
return 0;
return 1;
}
void add(int l,int c){
int node=number(l,c);
dad[node]=node;
height[node]=1;
if(check(l-1,c)==1)
join(node,number(l-1,c));
if(check(l+1,c)==1)
join(node,number(l+1,c));
if(check(l,c-1)==1)
join(node,number(l,c-1));
if(check(l,c+1)==1)
join(node,number(l,c+1));
}
void unite(){
int l1=first.size(),l2=second.size(),i=0,j=0;
queries.clear();
while(i<l1&&j<l2)
if(first[i].answer>second[j].answer){
queries.push_back(first[i]);
i++;
}
else{
queries.push_back(second[j]);
j++;
}
while(i<l1){
queries.push_back(first[i]);
i++;
}
while(j<l2){
queries.push_back(second[j]);
j++;
}
}
void read(int &numar){
numar=0;
while(buff[poz]<'0'||buff[poz]>'9'){
poz++;
if(poz==dim){
fread(buff,1,dim,stdin);
poz=0;
}
}
while(buff[poz]>='0'&&buff[poz]<='9'){
numar=numar*10+buff[poz]-'0';
poz++;
if(poz==dim){
fread(buff,1,dim,stdin);
poz=0;
}
}
}
int main(){
freopen("matrice2.in","r",stdin);
freopen("matrice2.out","w",stdout);
int m,i,q,a,b,c,bit,j,x,x1,y1,x2,y2,dad1,dad2;
fread(buff,1,dim,stdin);
read(n);
read(q);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++){
read(x);
cells.push_back({i,j,x});
}
for(i=1;i<=q;i++){
read(x1);
read(y1);
read(x2);
read(y2);
queries.push_back({x1,y1,x2,y2,i,0});
}
sort(cells.begin(),cells.end(),cmp);
for(bit=29;bit>=0;bit--){
initialize();
first.clear();
second.clear();
j=0;
for(i=0;i<q;i++){
while(j<n*n&&cells[j].cost>=queries[i].answer+(1<<bit)){
add(cells[j].l,cells[j].c);
j++;
}
dad1=find_dad(number(queries[i].x1,queries[i].y1));
dad2=find_dad(number(queries[i].x2,queries[i].y2));
if(dad1!=0&&dad1==dad2){
queries[i].answer+=(1<<bit);
first.push_back(queries[i]);
}
else
second.push_back(queries[i]);
}
unite();
}
sort(queries.begin(),queries.end(),cmp0);
for(i=0;i<q;i++)
if(queries[i].answer>0)
printf("%d\n",queries[i].answer);
else
printf("-1\n");
return 0;
}