#include <iostream>
#include <fstream>
#include <queue>
using namespace std;
void buildMatrix(int **mat, int **min_max_mat, deque<int> &deq, const int &M, const int &N,
const int &x, const int &y, const bool &minim) {
for (int i = 0; i < M; ++i) {
//pe fiecare linie, voi baga intai primele x coloane in deque
deq.clear();
for (int j = 0; j < x; ++j) {
while (deq.size() > 0 && (minim ? mat[i][deq.back()] > mat[i][j] : mat[i][deq.back()] < mat[i][j])) {
deq.pop_back();
}
deq.push_back(j);
}
min_max_mat[i][x - 1] = mat[i][deq.front()];
for (int j = x; j < N; ++j) {
if (deq.front() <= j - x) {
deq.pop_front();
}
while (deq.size() > 0 && (minim ? mat[i][deq.back()] > mat[i][j] : mat[i][deq.back()] < mat[i][j])) {
deq.pop_back();
}
deq.push_back(j);
min_max_mat[i][j] = mat[i][deq.front()];
}
}
}
void solve(int **mat, const int &M, const int &N, const int &x, const int &y,
int &MIN, int &nro) {
//matricea are M linii si N coloane;
//subdreptunghiul are y linii si x coloane
deque<int> min_deq, max_deq;
int **min_mat = new int*[M];
int **max_mat = new int*[M];
for (int i = 0; i < M; ++i) {
min_mat[i] = new int[N];
max_mat[i] = new int[N];
for (int j = 0; j < N; ++j) {
min_mat[i][j] = 1 << 30;
max_mat[i][j] = 0;
}
}
buildMatrix(mat, min_mat, min_deq, M, N, x, y, 1);
buildMatrix(mat, max_mat, max_deq, M, N, x, y, 0);
int **diff_mat = new int*[M];
for (int i = 0; i < M; ++i) {
diff_mat[i] = new int[N];
for (int j = 0; j < N; ++j) {
diff_mat[i][j] = 1 << 30;
}
}
for (int j = x - 1; j < N; ++j) {
// pe fiecare coloana fac deque-urile
min_deq.clear(), max_deq.clear();
for (int i = 0; i < y; ++i) {
while (min_deq.size() > 0 && min_mat[min_deq.back()][j] > min_mat[i][j]) {
min_deq.pop_back();
}
min_deq.push_back(i);
while (max_deq.size() > 0 && max_mat[max_deq.back()][j] < max_mat[i][j]) {
max_deq.pop_back();
}
max_deq.push_back(i);
}
diff_mat[y - 1][j] = max_mat[max_deq.front()][j] - min_mat[min_deq.front()][j];
if (diff_mat[y - 1][j] < MIN) {
MIN = diff_mat[y - 1][j];
nro = 1;
} else {
if (diff_mat[y - 1][j] == MIN) {
++nro;
}
}
for (int i = y; i < M; ++i) {
if (min_deq.front() <= i - y) {
min_deq.pop_front();
}
if (max_deq.front() <= i - y) {
max_deq.pop_front();
}
while (min_deq.size() > 0 && min_mat[min_deq.back()][j] > min_mat[i][j]) {
min_deq.pop_back();
}
min_deq.push_back(i);
while (max_deq.size() > 0 && max_mat[max_deq.back()][j] < max_mat[i][j]) {
max_deq.pop_back();
}
max_deq.push_back(i);
diff_mat[i][j] = max_mat[max_deq.front()][j] - min_mat[min_deq.front()][j];
if (diff_mat[i][j] < MIN) {
MIN = diff_mat[i][j];
nro = 1;
} else {
if (diff_mat[i][j] == MIN) {
++nro;
}
}
}
}
for (int i = 0; i < M; ++i) {
delete[] min_mat[i];
delete[] max_mat[i];
}
delete[] min_mat;
delete[] max_mat;
}
int main() {
int M, N, P;
ifstream in("struti.in");
in >> M >> N >> P;
int **mat = new int*[M];
for (int i = 0; i < M; ++i) {
mat[i] = new int[N];
for (int j = 0; j < N; ++j) {
in >> mat[i][j];
}
}
ofstream out("struti.out");
for (int i = 0; i < P; ++i) {
int x, y;
in >> x >> y;
int min1 = 1 << 30, min2 = 1 << 30, nro1 = 0, nro2 = 0;
solve(mat, M, N, x, y, min1, nro1);
solve(mat, M, N, y, x, min2, nro2);
if (min1 < min2) {
out << min1 << " " << nro1 << "\n";
} else {
if (min1 == min2) {
if (x != y) {
out << min1 << " " << nro1 + nro2 << "\n";
} else {
out << min1 << " " << nro1 << "\n";
}
} else {
out << min2 << " " << nro2 << "\n";
}
}
}
in.close();
out.close();
for (int i = 0; i < M; ++i) {
delete[] mat[i];
}
delete[] mat;
return 0;
}