#include <bits/stdc++.h>
using namespace std;
ifstream fin("matrice2.in");
ofstream fout("matrice2.out");
class Forest {
private:
vector<int> height, father, ans, ind;
vector<set<int>> qry;
void merge(int x, int y, int val) {
if (qry[ind[x]].size() > qry[ind[y]].size()) {
for (int it : qry[ind[y]])
if (qry[ind[x]].find(it) == qry[ind[x]].end())
qry[ind[x]].insert(it);
else {
ans[it] = val;
qry[ind[x]].erase(it);
}
}
else {
for (int it : qry[ind[x]])
if (qry[ind[y]].find(it) == qry[ind[y]].end())
qry[ind[y]].insert(it);
else {
ans[it] = val;
qry[ind[y]].erase(it);
}
ind[x] = ind[y];
}
}
public:
Forest(int n, int q) :
height(n + 1), father(n + 1),
ans(q), ind(n + 1), qry(n + 1) {
for (int i = 1; i <= n; i++)
ind[i] = i;
}
int find(int x) {
int root = x;
while (father[root])
root = father[root];
int aux;
while (father[x]) {
aux = father[x];
father[x] = root;
x = aux;
}
return root;
}
void unite(int x, int y, int val) {
int rootX = find(x);
int rootY = find(y);
if (rootX == rootY)
return;
if (height[rootX] < height[rootY]) {
merge(rootY, rootX, val);
father[rootX] = rootY;
}
else {
merge(rootX, rootY, val);
father[rootY] = rootX;
if (height[rootX] == height[rootY])
height[rootX]++;
}
}
void addQuery(int x, int y) {
static int id = 0;
qry[x].insert(id);
qry[y].insert(id);
id++;
}
vector<int> solve() {
return ans;
}
};
int main() {
int n, q; fin >> n >> q;
vector<vector<int>> mat(n + 1, vector<int>(n + 1));
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
fin >> mat[i][j];
auto id = [&](int x, int y) {
return (x - 1) * n + y;
};
auto in = [&](int x, int y) {
return 1 <= x && x <= n
&& 1 <= y && y <= n;
};
Forest dsu(n * n, q);
for (int i = 0; i < q; i++) {
int x1, y1, x2, y2; fin >> x1 >> y1 >> x2 >> y2;
dsu.addQuery(id(x1, y1), id(x2, y2));
}
vector<tuple<int, int, int>> cells;
cells.reserve(n * n);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
cells.emplace_back(mat[i][j], i, j);
sort(cells.rbegin(), cells.rend());
const int addLin[] = {-1, 0, 1, 0};
const int addCol[] = {0, 1, 0, -1};
for (auto cell : cells) {
int x1, y1, val; tie(val, x1, y1) = cell;
for (int i = 0; i < 4; i++) {
int x2 = x1 + addLin[i];
int y2 = y1 + addCol[i];
if (in(x2, y2) && mat[x2][y2] >= mat[x1][y1])
dsu.unite(id(x1, y1), id(x2, y2), val);
}
}
auto ans = dsu.solve();
for (int i = 0; i < q; i++)
fout << ans[i] << '\n';
fout.close();
return 0;
}