#include <fstream>
#include <iostream>
#include <iterator>
#include <deque>
#include <limits>
#include <algorithm>
#include <string>
#include <sstream>
#include <cstring>
#define MAXN 1024
using namespace std;
short mat[MAXN][MAXN];
short matMin[MAXN][MAXN];
short matMax[MAXN][MAXN];
struct MinMaxDiff
{
MinMaxDiff() :
Diff(numeric_limits<short>::max()),
Count(0)
{}
short Diff;
int Count;
};
struct Entry
{
Entry() :
Value(0),
Position(0)
{}
Entry(short v, short p) :
Value(v),
Position(p)
{}
short Value;
short Position;
};
template <const int Rows, const int Columns, short (&Mat)[Rows][Columns]>
struct IterMat
{
IterMat(short r, short c) :
Row(r),
Column(c)
{}
short& operator* ()
{
return Mat[Row][Column];
}
IterMat& operator++ ()
{
++Row;
return *this;
}
private:
short Row;
short Column;
};
struct EntryValuesLess
{
EntryValuesLess()
{}
inline bool operator () (const Entry lhs, short value) const
{
return lhs.Value <= value;
}
};
struct EntryValuesGreater
{
EntryValuesGreater()
{}
inline bool operator () (const Entry lhs, short value) const
{
return lhs.Value >= value;
}
};
template <class Comparator>
inline static void PopBackElements(deque<Entry>& deq, short value)
{
const Comparator comp;
while (!deq.empty() && comp(deq.back(), value))
{
deq.pop_back();
}
}
template<typename FirstIterType, typename SecondIterType>
static void GetMinMaxFromSequence(const short seq[], int n, int k, FirstIterType& itOutMin, SecondIterType& itOutMax)
{
deque<Entry> deqMin;
deque<Entry> deqMax;
for (int i=0; i<k; ++i)
{
PopBackElements<EntryValuesGreater>(deqMin, seq[i]);
deqMin.push_back(Entry(seq[i], i));
PopBackElements<EntryValuesLess>(deqMax, seq[i]);
deqMax.push_back(Entry(seq[i], i));
}
*itOutMin = deqMin.front().Value;
++itOutMin;
*itOutMax = deqMax.front().Value;
++itOutMax;
for (int i=k; i<n; ++i)
{
PopBackElements<EntryValuesGreater>(deqMin, seq[i]);
deqMin.push_back(Entry(seq[i], i));
if (deqMin.front().Position <= i-k)
{
deqMin.pop_front();
}
*itOutMin = deqMin.front().Value;
++itOutMin;
PopBackElements<EntryValuesLess>(deqMax, seq[i]);
deqMax.push_back(Entry(seq[i], i));
if (deqMax.front().Position <= i-k)
{
deqMax.pop_front();
}
*itOutMax = deqMax.front().Value;
++itOutMax;
}
}
static void PopulateMinMaxArray(int m, int n, int k)
{
for (int i=0; i<m; ++i)
{
IterMat<MAXN, MAXN, matMin> itMin(0, i);
IterMat<MAXN, MAXN, matMax> itMax(0, i);
GetMinMaxFromSequence(mat[i], n, k, itMin, itMax);
}
}
inline static void SetMinMaxDiff(MinMaxDiff& diffMinMax, const short diff)
{
if (diff < diffMinMax.Diff)
{
diffMinMax.Diff = diff;
diffMinMax.Count = 1;
}
else if (diff == diffMinMax.Diff)
{
++diffMinMax.Count;
}
}
static void GetMinMaxMinDiffForSequence(const short seqMin[], const short seqMax[], const int n, const int k, MinMaxDiff& diffMinMax)
{
deque<Entry> deqMin;
deque<Entry> deqMax;
for (int i=0; i<k; ++i)
{
PopBackElements<EntryValuesGreater>(deqMin, seqMin[i]);
deqMin.push_back(Entry(seqMin[i], i));
PopBackElements<EntryValuesLess>(deqMax, seqMax[i]);
deqMax.push_back(Entry(seqMax[i], i));
}
SetMinMaxDiff(diffMinMax, deqMax.front().Value - deqMin.front().Value);
for (int i=k; i<n; ++i)
{
PopBackElements<EntryValuesGreater>(deqMin, seqMin[i]);
deqMin.push_back(Entry(seqMin[i], i));
if (deqMin.front().Position <= i-k)
{
deqMin.pop_front();
}
PopBackElements<EntryValuesLess>(deqMax, seqMax[i]);
deqMax.push_back(Entry(seqMax[i], i));
if (deqMax.front().Position <= i-k)
{
deqMax.pop_front();
}
SetMinMaxDiff(diffMinMax, deqMax.front().Value - deqMin.front().Value);
}
}
static void GetMinMaxMinDiff(const int m, const int n, const int k, MinMaxDiff& diffMinMax)
{
for (int i=0; i<m; ++i)
{
GetMinMaxMinDiffForSequence(matMin[i], matMax[i], n, k, diffMinMax);
}
}
template<int M, int N>
static void PrintMatrix(const short (&mat)[N][M], int m, int n)
{
ostream_iterator<short> itOut(cout, " ");
for (int i=0; i<m; ++i)
{
copy(mat[i], mat[i] + n, itOut);
cout << endl;
}
cout << endl;
}
template<int M, int N>
static void ClearMatrix(short (&mat)[N][M], int m, int n)
{
for (int i=0; i<m; ++i)
{
memset(mat, 0, n*sizeof(short));
}
}
static short GetNumber(char buf[], int& i)
{
short num = 0;
for (; buf[i] >= '0' && buf[i] <= '9'; ++i)
{
num = num * 10 + (buf[i] - '0');
}
++i;
return num;
}
char buffer[5 * MAXN];
int main()
{
int m, n, p;
int DX, DY;
fstream fin("struti.in", fstream::in);
fstream fout("struti.out", fstream::out);
fin >> m >> n >> p;
//cout << m << " " << n << " " << p << "\n";
fin.getline(buffer, 5 * MAXN);
for (int i=0; i<m; ++i)
{
fin.getline(buffer, 5 * MAXN);
int index = 0;
for (int j=0; j<n; ++j)
{
//cout << "Buffer = " << buffer << endl;
mat[i][j] = GetNumber(buffer, index);
//fin >> mat[i][j];
//cout << mat[i][j] << " ";
}
//cout << "\n";
}
for (int i=0; i<p; ++i)
{
fin >> DX >> DY;
//cout << DX << " " << DY << "\n";
if (DX < DY)
{
swap(DX, DY);
}
MinMaxDiff diffMinMax;
PopulateMinMaxArray(m, n, DX);
GetMinMaxMinDiff(n - DX + 1, m, DY, diffMinMax);
//PrintMatrix(matMin, n - DX + 1, m);
//PrintMatrix(matMax, n - DX + 1, m);
if (DX != DY)
{
//ClearMatrix(matMin, m, n);
//ClearMatrix(matMax, m, n);
PopulateMinMaxArray(m, n, DY);
GetMinMaxMinDiff(n - DY + 1, m, DX, diffMinMax);
//PrintMatrix(matMin, n - DY + 1, m);
//PrintMatrix(matMax, n - DY + 1, m);
}
//ClearMatrix(matMin, m, n);
//ClearMatrix(matMax, m, n);
//cout << "Here\n";
fout << diffMinMax.Diff << " " << diffMinMax.Count << "\n";
}
return 0;
}