#include <iostream>
const int N = 1e5 + 5;
int n,m,q;
int A[N],B[N];
struct Tree{
struct Node{
int max,min,negmax,posmin,l,r;
bool is[3];
}tree[N * 4];
void build(int node,int l,int r,int a[]){
tree[node].l = l;
tree[node].r = r;
if (l == r){
tree[node].negmax = a[l] < 0 ? a[l] : 0xc0c0c0c0;
tree[node].posmin = a[l] >= 0 ? a[l] : 0x3f3f3f3f;
tree[node].min = a[l];
tree[node].max = a[l];
tree[node].is[0] = (a[l] >= 0);
tree[node].is[1] = !tree[node].is[0];
tree[node].is[2] = false;
return;
}
int mid = (l + r) / 2;
build(node * 2,l,mid,a);
build(node * 2 + 1,mid + 1,r,a);
tree[node].max = std::max(tree[node * 2].max,tree[node * 2 + 1].max);
tree[node].min = std::min(tree[node * 2].min,tree[node * 2 + 1].min);
tree[node].negmax = std::max(tree[node * 2].negmax,tree[node * 2 + 1].negmax);
tree[node].posmin = std::min(tree[node * 2].posmin,tree[node * 2 + 1].posmin);
tree[node].is[0] = tree[node * 2].is[0] && tree[node * 2 + 1].is[0];
tree[node].is[1] = tree[node * 2].is[1] && tree[node * 2 + 1].is[1];
tree[node].is[2] = !tree[node].is[0] && !tree[node].is[1];
}
int query_max(int node,int l,int r){
if (tree[node].l > r || tree[node].r < l) return 0xc0c0c0c0;
if (tree[node].l >= l && tree[node].r <= r) return tree[node].max;
return std::max(query_max(node * 2,l,r),query_max(node * 2 + 1,l,r));
}
int query_negmax(int node,int l,int r){
if (tree[node].l > r || tree[node].r < l) return 0xc0c0c0c0;
if (tree[node].l >= l && tree[node].r <= r) return tree[node].negmax;
return std::max(query_negmax(node * 2,l,r),query_negmax(node * 2 + 1,l,r));
}
int query_min(int node,int l,int r){
if (tree[node].l > r || tree[node].r < l) return 0x3f3f3f3f;
if (tree[node].l >= l && tree[node].r <= r) return tree[node].min;
return std::min(query_min(node * 2,l,r),query_min(node * 2 + 1,l,r));
}
int query_posmin(int node,int l,int r){
if (tree[node].l > r || tree[node].r < l) return 0x3f3f3f3f;
if (tree[node].l >= l && tree[node].r <= r) return tree[node].posmin;
return std::min(query_posmin(node * 2,l,r),query_posmin(node * 2 + 1,l,r));
}
bool query_sign(int node,int l,int r,int dx){
if (dx == 2) return !query_sign(node,l,r,0) && !query_sign(node,l,r,1);
if (tree[node].l > r || tree[node].r < l) return false;
if (tree[node].l >= l && tree[node].r <= r) return tree[node].is[dx];
return query_sign(node * 2,l,r,dx) && query_sign(node * 2 + 1,l,r,dx);
}
}treeA,treeB;
int main(){
std::cin.tie(0)->sync_with_stdio(0);
std::cin >> n >> m >> q;
for (int i = 1;i <= n;i++) std::cin >> A[i];
for (int i = 1;i <= m;i++) std::cin >> B[i];
treeB.build(1,1,m,B);
treeA.build(1,1,n,A);
while (q--){
int l1,r1,l2,r2;
std::cin >> l1 >> r1 >> l2 >> r2;
if (treeB.query_sign(1,l2,r2,0)) std::cout << treeB.query_min(1,l2,r2) * treeA.query_max(1,l1,r1) << '\n';
else if (treeB.query_sign(1,l2,r2,1)){
if (treeA.query_sign(1,l1,r1,0)) std::cout << treeB.query_min(1,l2,r2) * treeA.query_min(1,l1,r1) << '\n';
else std::cout << treeB.query_max(1,l2,r2) * treeA.query_min(1,l1,r1) << '\n';
}
else std::cout << std::max(treeB.query_min(1,l2,r2) * treeA.query_posmin(1,l1,r1),treeB.query_max(1,l2,r2) * treeA.query_negmax(1,l1,r1)) << '\n';
}
return 0;
}