#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int MAXN = 600'000;
const pair<int, int> DIR[4] = {{0, 1}, {1, 0}};
vector<vector<int>> a;
int p[MAXN], s[MAXN], t[MAXN], d[MAXN];
int n, m, q;
int to_index(int i, int j) {
return (i-1)*m+j;
}
int holvan(int u) {
return p[u] == u ? u : holvan(p[u]);
}
void unio(int u, int v, int w) {
u = holvan(u); v = holvan(v);
if (u == v) return;
if (s[u] < s[v]) swap(u, v);
s[u] += s[v];
t[v] = w;
p[v] = u;
}
int calc_depth(int u) {
if (d[u] == -1) {
if (p[u] == u) d[u] = 0;
d[u] = 1 + calc_depth(p[u]);
}
return d[u];
}
int query(int u, int v) {
int ans = 0;
while (u != v) {
if (d[u] > d[v]) swap(u, v);
ans = max(ans, t[v]);
v = p[v];
}
return ans;
}
int main() {
ios::sync_with_stdio(0); cin.tie(0);
cin >> n >> m >> q;
iota(p, p+MAXN, 0);
fill(s, s+MAXN, 1);
fill(d, d+MAXN, -1);
a.resize(n+1, vector<int>(m+1));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> a[i][j];
}
}
vector<array<int, 3>> edges;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
for (auto [dx, dy] : DIR) {
int nx = i+dx, ny = j+dy;
if (1 <= nx && nx <= n && 1 <= ny && ny <= m) {
int w = max(a[i][j], a[nx][ny]);
int p = to_index(i, j), q = to_index(nx, ny);
edges.push_back({w, p, q});
}
}
}
}
sort(edges.begin(), edges.end());
for (auto [w, u, v] : edges) {
unio(u, v, w);
}
for (int i = 1; i <= n*m; i++) {
calc_depth(i);
}
while (q--) {
int a, b, c, d; cin >> a >> b >> c >> d;
int p = to_index(a, b), q = to_index(c, d);
cout << query(p, q) << "\n";
}
return 0;
}