#include <bits/stdc++.h>
using namespace std;
int main() {
ifstream cin("matrice2.in");
ofstream cout("matrice2.out");
int n, q, di[] = {1,0,-1,0}, dj[] = {0,1,0,-1};
cin >> n >> q;
vector<int> v, ans(q), c(q);
vector<vector<int>> a(n + 1, vector<int>(n + 1));
vector<tuple<int, int, int, int>> b(q);
map<int, int> mp;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j) {
cin >> a[i][j];
mp[a[i][j]];
}
for (auto& x : b) {
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
x = tie(x1, y1, x2, y2);
}
int m = 0;
vector<int> inv = {0};
for (auto& x : mp) {
x.second = ++m;
inv.emplace_back(x.first);
}
for (int i = 1 << (31 - __builtin_clz(m)); i; i >>= 1) {
vector<vector<pair<int, int>>> d(m + 1);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
d[mp[a[i][j]]].emplace_back(i, j);
for (int j = 0; j < q; ++j)
if (ans[j] + i <= m) {
c[j] = ans[j] + i;
d[c[j]].emplace_back(0, j);
}
vector<int> p(n * n + 1), s(n * n + 1, 1);
iota(p.begin(), p.end(), 0);
function<int(int)> get = [&](int a) {
if (p[a] == a)
return a;
return p[a] = get(p[a]);
};
auto unite = [&](int a, int b) {
a = get(a), b = get(b);
if (a == b) return;
if (s[b] > s[a])
swap(a, b);
p[b] = a;
s[a] += s[b];
};
auto lin = [&](int i, int j) {return (i - 1) * n + j; };
for (int i = m; i; --i)
for (auto x : d[i]) {
if (!x.first) {
int x1, y1, x2, y2;
tie(y1, x1, y2, x2) = b[x.second];
int p1 = lin(y1, x1), p2 = lin(y2, x2);
if (get(p1) == get(p2))
ans[x.second] = c[x.second];
}
else {
int x1, y1;
tie(y1, x1) = x;
for (int k = 0; k < 4; ++k) {
int y2 = y1 + di[k], x2 = x1 + dj[k];
if (y2 && x2 && y2 <= n && x2 <= n && a[y2][x2] >= a[y1][x1])
unite(lin(y1, x1), lin(y2, x2));
}
}
}
}
for (auto x : ans)
cout << inv[x] << '\n';
}