#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <list>
#include <limits.h>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
using namespace std;
int R,C,K;
void update_max_struct(list<pair<int,int>>& l,int i,int val) {
if(l.empty())
l.push_back(make_pair(i,val));
else {
if(val<=l.back().second) {
l.push_back(make_pair(i,val));
}
else {
while(!l.empty()&&val>l.back().second) {
l.pop_back();
}
l.push_back(make_pair(i,val));
}
}
}
void update_min_struct(list<pair<int,int>>& l,int i,int val) {
if(l.empty())
l.push_back(make_pair(i,val));
else {
if(val>=l.back().second) {
l.push_back(make_pair(i,val));
}
else {
while(!l.empty()&&val<l.back().second) {
l.pop_back();
}
l.push_back(make_pair(i,val));
}
}
}
void make_h(vector<vector<int>>& grid,vector<vector<int>>& h) {
for(int i=0;i<R;++i) {
list<pair<int,int>> l1;
list<pair<int,int>> l2;
int count = 0;
int l = 0,r = 0;
while(l<C) {
if(r>=C) {
h[i][l] = count;
--count;++l;
continue;
}
if(l1.size()==0 || l2.size()==0) {
update_max_struct(l1,r,grid[i][r]);
update_min_struct(l2,r,grid[i][r]);
++count;++r;
continue;
}
int max_h = max(l1.front().second,grid[i][r]);
int min_h = min(l2.front().second,grid[i][r]);
if(abs(max_h-min_h)<=K) {
update_max_struct(l1,r,grid[i][r]);
update_min_struct(l2,r,grid[i][r]);
++r; ++count;
}
else {
h[i][l] = count;
count--;
if(l1.front().first==l)
l1.pop_front();
if(l2.front().first==l)
l2.pop_front();
++l;
}
}
}
}
void make_h1(vector<vector<int>>& grid,vector<vector<int>>& h) {
for(int i=0;i<R;++i) {
for(int j=0;j<C;++j) {
int min_h = grid[i][j],max_h = grid[i][j],count = 1;
for(int k=j+1;k<C;++k) {
min_h = min(grid[i][k],min_h);
max_h = max(grid[i][k],max_h);
if(abs(min_h-max_h)<=K)
++count;
else break;
}
h[i][j] = count;
}
}
}
int largestRectangleArea(vector<int> &height) {
int r = 0;
stack<int> st;
height.push_back(0);
for (int i = 0; i < height.size(); ++i) {
if (st.empty() || height[st.top()] < height[i]) {
st.push(i);
} else {
int cur = st.top();
st.pop();
r = max(r, height[cur] * (st.empty() ? i : (i - st.top() - 1)));
--i;
}
}
return r;
}
void helper(vector<vector<int>>& h,int& res) {
for(int j=0;j<C;++j) {
vector<int> temp(R,0);
for(int i=0;i<R;++i)
temp[i] = h[i][j];
int cur = largestRectangleArea(temp);
res = max(res,cur);
}
}
int main() {
int T;
cin >> T;
for(int t=0;t<T;++t) {
int res = 0;
cin >> R >> C >> K;
vector<vector<int>> grid(R,vector<int>(C,0));
for(int i=0;i<R;++i) {
for(int j=0;j<C;++j)
cin >> grid[i][j];
}
vector<vector<int>> h(R,vector<int>(C,0));
make_h(grid,h);
helper(h,res);
cout << "Case #" << t+1 << ":" << " " << res << endl;
}
return 0;
}