#include <bits/stdc++.h>
using namespace std;
struct intrebare{
pair<int, int>from, to;
int IND;
};
class multimi_disjuncte{
public:
vector <int> root;
int n;
multimi_disjuncte(const int n = 0) : n(n) {
root = vector<int>(n + 1);
iota(begin(root), end(root), 0);
}
int tata(int x) {
return x == root[x] ? x : root[x] = tata(root[x]);
}
void unite(int x, int y) {
root[tata(x)] = tata(y);}
};
void uneste_vecini(int i, int j, int cost_minim, const vector<vector<int>>&valori, const vector<vector<int>>& coduri, multimi_disjuncte &padure) {
static array<int, 4> dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1};
for(int k = 0; k < 4; ++k) {
int ni = dx[k] + i, nj = dy[k] + j;
if(ni < 0 || nj < 0 || ni >= valori.size() || nj >= valori.size()) continue;
if(valori[ni][nj] < cost_minim) continue;
padure.unite(coduri[i][j], coduri[ni][nj]);
}
}
int main() {
ifstream cin("matrice2.in");
ofstream cout("matrice2.out");
int n, cate_intreb;
cin >> n >> cate_intreb;
vector<vector<int>>a(n, vector<int>(n)), cod(n, vector<int>(n));
for(int i = 0, id = 0; i < n; ++i)
for(int j = 0; j < n; ++j)
cin >> a[i][j], cod[i][j] = id++;
vector<intrebare>qs(cate_intreb);
for(int i = 0; i < cate_intreb; ++i) {
pair<int, int>from, to;
cin >> from.first >> from.second >> to.first >> to.second;
from.first--, from.second--, to.first--, to.second--;
qs[i] = intrebare{from, to, i};
}
vector < pair<int, int>> mat_sortata;
for(int i = 0; i < n; ++i)
for(int j = 0; j < n; ++j) mat_sortata.emplace_back(i, j);
sort(begin(mat_sortata), end(mat_sortata), [&] (const pair<int, int>&lhs, const pair<int, int>&rhs) { return a[lhs.first][lhs.second] > a[rhs.first][rhs.second];});
vector<int>cost_maxim(cate_intreb);
for(int delta = 20; delta >= 0; delta--) {
sort(begin(qs), end(qs), [&] (const intrebare &lhs, const intrebare &rhs) { return cost_maxim[lhs.IND] > cost_maxim[rhs.IND];});
multimi_disjuncte padure(n * n);
int poz = 0;
for(auto intrebari : qs) {
int cost_cerut = (1<<delta) + cost_maxim[intrebari.IND];
while(poz < mat_sortata.size() && a[mat_sortata[poz].first][mat_sortata[poz].second] >= cost_cerut) {
uneste_vecini(mat_sortata[poz].first, mat_sortata[poz].second, cost_cerut, a, cod, padure);
++poz;
}
int IDfrom = cod[intrebari.from.first][intrebari.from.second], IDto = cod[intrebari.to.first][intrebari.to.second];
if(padure.tata(IDfrom) == padure.tata(IDto))
cost_maxim[intrebari.IND] += 1<<delta;
}
}
for(int i = 0; i < cate_intreb; ++i)
cout << cost_maxim[i] << '\n';
return 0;
}