#include <bits/stdc++.h>
using namespace std;
ifstream f("struti.in");
ofstream g("struti.out");
const int Max = 1e3 + 1;
void nos()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
}
struct minim
{
bool operator () (int a, int b) const
{
return a < b;
}
};
struct maxim
{
bool operator () (int a, int b) const
{
return a > b;
}
};
int n,m,q;
int a[Max][Max];
void read()
{
f>>n>>m>>q;
int i,j;
for(i=1; i<=n; i++)
for(j=1; j<=m; j++)
f>>a[i][j];
}
int cnt;
int min_delta;
struct nod
{
int minx;
int maxx;
};
nod tree[Max][4*Max];
nod merge_nod(nod n1, nod n2)
{
nod ans;
ans.minx = min(n1.minx,n2.minx);
ans.maxx = max(n1.maxx,n2.maxx);
return ans;
}
void init_tree(int j,int where, int left, int right)
{
if(left == right)
{
tree[j][where].minx = tree[j][where].maxx = a[left][j];
return;
}
int mid = (left + right) / 2;
init_tree(j,2*where,left,mid);
init_tree(j,2*where+1,mid+1,right);
tree[j][where] = merge_nod(tree[j][2*where],tree[j][2*where+1]);
}
int ans;
int left_limit,right_limit;
void ask_min(int j, int where, int left, int right)
{
if(left_limit <= left and right <= right_limit)
{
ans = min(ans,tree[j][where].minx);
return;
}
int mid = (left + right) / 2;
if(left_limit <= mid)
ask_min(j,2*where,left,mid);
if(mid + 1 <= right_limit)
ask_min(j,2*where+1,mid + 1,right);
}
void ask_max(int j, int where, int left, int right)
{
if(left_limit <= left and right <= right_limit)
{
ans = max(ans,tree[j][where].maxx);
return;
}
int mid = (left + right) / 2;
if(left_limit <= mid)
ask_max(j,2*where,left,mid);
if(mid + 1 <= right_limit)
ask_max(j,2*where+1,mid + 1,right);
}
int go_on_row(int start_poz, int dimx, int dimy)
{
multiset < int, minim > lowest;
multiset < int, maxim > highest;
deque < int > elemente;
int i,j;
for(j=1; j<=dimy +1; ++j)
{
int new_entry_min,new_entry_max;
left_limit = start_poz;
right_limit = start_poz + dimx;
ans = INT_MAX;
ask_min(j,1,1,n);
new_entry_min = ans;
ans = 0;
ask_max(j,1,1,n);
new_entry_max = ans;
elemente.push_back(new_entry_min);
elemente.push_back(new_entry_max);
lowest.insert(new_entry_min);
highest.insert(new_entry_max);
}
for(j=dimy + 2; j<= m; ++j)
{
int current_delta = *highest.begin() - *lowest.begin();
if(current_delta == min_delta)
++cnt;
if(current_delta < min_delta)
{
min_delta = current_delta;
cnt = 1;
}
int new_entry_min,new_entry_max;
left_limit = start_poz;
right_limit = start_poz + dimx;
ans = INT_MAX;
ask_min(j,1,1,n);
new_entry_min = ans;
ans = 0;
ask_max(j,1,1,n);
new_entry_max = ans;
auto del1 = lowest.find(elemente.front());
lowest.erase(del1);
elemente.pop_front();
auto del2 = highest.find(elemente.front());
highest.erase(del2);
elemente.pop_front();
elemente.push_back(new_entry_min);
elemente.push_back(new_entry_max);
lowest.insert(new_entry_min);
highest.insert(new_entry_max);
}
int current_delta = *highest.begin() - *lowest.begin();
if(current_delta == min_delta)
++cnt;
if(current_delta < min_delta)
{
min_delta = current_delta;
cnt = 1;
}
}
void sweep(int dx, int dy)
{
int i;
for(i=1; i + dx - 1 <= n ; ++i )
go_on_row(i,dx-1,dy-1);
}
void solve()
{
for(int j=1; j<=m; j++)
init_tree(j,1,1,n);
while(q--)
{
int dx,dy;
f>>dx>>dy;
cnt = 0;
min_delta = INT_MAX;
sweep(dx,dy);
if(dx!=dy)
sweep(dy,dx);
g<<min_delta<<' '<<cnt<<'\n';
}
}
void restart()
{
}
int32_t main()
{
nos();
read();
solve();
restart();
return 0;
}