#include <iostream>
#include <limits>
#include <vector>
#include <array>

typedef int TYPE;
TYPE inf = -1;

using namespace std;

class Segment2d
{
public:
	Segment2d();
	void set(const int y, const int x, const TYPE val);
	TYPE query(const int ys, const int ye, const int xs, const int xe);
	void init(const int h, const int w);
	void print();
private:
	TYPE query(const int ys, const int ye, const int xs, const int xe, 
		const int qys, const int qye, const int qxs, const int qxe);
	TYPE queryY(const int ys, const int ye, const int qys, 
	const int qye, const int qxs, const int qxe, const int k);
	TYPE queryX(const int xs, const int xe, const int qxs, 
	const int qxe, const int ky, const int kx);
	TYPE _get(const int i, const int j);
	void _set(const int i, const int j, const TYPE val);
	int left(const int parent);
	int right(const int parent);
	int parent(const int child);
	TYPE eval(const TYPE t1, const TYPE t2);

	int height;
	int width;

	int height2;
	int width2;
	int logwidth;
	vector<TYPE> array;
};

void Segment2d::print()
{
	for(int i = 0; i < 2 * height2 - 1; i++)
	{
		for(int j = 0; j < 2 * width2 - 1; j++)
		{
			cerr << _get(i, j) << " ";
		}
		cerr << endl;
	}
}

TYPE Segment2d::eval(const TYPE t1, const TYPE t2)
{
	if(t1 == inf) return t2;
	else if(t2 == inf) return t1;
	else return min(t1, t2);
}

TYPE Segment2d::_get(const int i, const int j)
{
	return array[(i << logwidth) + j];
}
void Segment2d::_set(const int i, const int j, const TYPE val)
{
	array[(i << logwidth) + j] = val;
}

int Segment2d::left(const int parent)
{
	return parent * 2 + 1;
}

int Segment2d::right(const int parent)
{
	return parent * 2 + 2;
}

int Segment2d::parent(const int child)
{
	return (child - 1) / 2;
}

void Segment2d::init(const int h, const int w)
{
	height = h;
	width = w;
	width2 = 1;
	logwidth = 0;
	while(width2 < width)
	{
		width2 *= 2;
		logwidth++;
	} 
	logwidth++;

	height2 = 1;
	while(height2 < height) height2 *= 2;

	fill(array.begin(), array.end(), inf);
}

Segment2d::Segment2d()
{
	array.resize(1 << 23);
}

void Segment2d::set(int y, int x, TYPE val)
{
	y += height2 - 1;
	x += width2 - 1;

	_set(y, x, val);

	vector<int> ys = {y};
	while(y > 0)
	{
		y = parent(y);
		ys.push_back(y);
	}
	vector<int> xs = {x};
	while(x > 0)
	{
		x = parent(x);
		xs.push_back(x);
	}

	for(int i = 1; i < ys.size(); i++)
	{
		const TYPE val = eval(_get(left(ys[i]), xs[0]), _get(right(ys[i]), xs[0]));
		_set(ys[i], xs[0], val);
	}

	for(int i = 0; i < ys.size(); i++)
	{
		for(int j = 1; j < xs.size(); j++)
		{
			const TYPE val = eval(_get(ys[i], left(xs[j])), _get(ys[i], right(xs[j])));
			_set(ys[i], xs[j], val);
		}
	}
}

TYPE Segment2d::query(const int qys, const int qye, const int qxs, const int qxe)
{
	return queryY(0, height2, qys, qye, qxs, qxe, 0);
}

TYPE Segment2d::queryY(const int ys, const int ye, const int qys, 
	const int qye, const int qxs, const int qxe, const int k)
{
	if(qye <= ys || ye <= qys)
	{
		return inf;	
	}
	else if(qys <= ys && ye <= qye) 
	{
		return queryX(0, width2, qxs, qxe, k, 0);
	}
	else 
	{
		const int mid_y = (ys + ye) / 2;
		return eval(queryY(ys, mid_y, qys, qye, qxs, qxe, left(k)), 
			queryY(mid_y, ye, qys, qye, qxs, qxe, right(k)));
	}
}

TYPE Segment2d::queryX(const int xs, const int xe, const int qxs, 
	const int qxe, const int ky, const int kx)
{
	if(qxe <= xs || xe <= qxs)
	{
		return inf;	
	}
	else if(qxs <= xs && xe <= qxe) 
	{
		return _get(ky, kx);
	}
	else 
	{
		const int mid_x = (xs + xe) / 2;
		return eval(queryX(xs, mid_x, qxs, qxe, ky, left(kx)), 
			queryX(mid_x, xe, qxs, qxe, ky, right(kx)));
	}
}

void test()
{
	const int height = 3;
	const int width = 3;
	Segment2d seg;
	seg.init(height, width);

	for(int i = 0; i < height; i++)
	{
		for(int j = 0; j < width; j++)
		{
			seg.set(i, j, i * 100 + j);
		}
	}
	seg.print();

	for(int i = 0; i < height; i++)
	{
		for(int j = 0; j < width; j++)
		{
			cerr << seg.query(i, i+1, j, j+1) << " ";
		}
		cerr << endl;
	}
}

int main()
{
	cin.tie(0);
	ios::sync_with_stdio(false);

	Segment2d seg;

	while(true)
	{
		int r, c, q;
		cin >> r >> c >> q;	
		if(r == 0 && c == 0 && q == 0) break;

		seg.init(r, c);

		for(int i = 0; i < r; i++)
		{
			for(int j = 0; j < c; j++)
			{
				TYPE v;
				cin >> v;
				seg.set(i, j, v);
			}
		}

		for(int i = 0; i < q; i++)
		{
			int r1, c1, r2, c2;
			cin >> r1 >> c1 >> r2 >> c2;
			cout << seg.query(r1, r2 + 1, c1, c2 + 1) << endl;
		}			
	}
}

Measured memory_bytes: 35472