#include <cstdio>
using namespace std;
const int N = 100005;
typedef long long ll;
struct Result {
ll maxpos, minpos, maxneg, minneg;
bool pos, neg, zero;
};
ll max(ll a, ll b) {
return a > b ? a : b;
}
ll min(ll a, ll b) {
return a < b ? a : b;
}
Result operator + (const Result & a, const Result & b) {
Result c;
c.pos = c.neg = false;
if (a.pos) {
if (c.pos) {
c.maxpos = max(c.maxpos, a.maxpos);
c.minpos = min(c.minpos, a.minpos);
} else {
c.maxpos = a.maxpos;
c.minpos = a.minpos;
c.pos = true;
}
}
if (b.pos) {
if (c.pos) {
c.maxpos = max(c.maxpos, b.maxpos);
c.minpos = min(c.minpos, b.minpos);
} else {
c.maxpos = b.maxpos;
c.minpos = b.minpos;
c.pos = true;
}
}
if (a.neg) {
if (c.neg) {
c.maxneg = max(c.maxneg, a.maxneg);
c.minneg = min(c.minneg, a.minneg);
} else {
c.maxneg = a.maxneg;
c.minneg = a.minneg;
c.neg = true;
}
}
if (b.neg) {
if (c.neg) {
c.maxneg = max(c.maxneg, b.maxneg);
c.minneg = min(c.minneg, b.minneg);
} else {
c.maxneg = b.maxneg;
c.minneg = b.minneg;
c.neg = true;
}
}
c.zero = a.zero || b.zero;
return c;
}
ll operator * (const Result & a, const Result & b) {
ll ans = -0x7fffffffffffffff - 1;
if (a.zero || b.zero) {
ans = 0;
}
if (a.pos) {
if (b.neg) {
ans = max(ans, a.minpos * b.minneg);
} else if (b.pos) {
ans = max(ans, a.maxpos * b.minpos);
}
}
if (a.neg) {
if (b.pos) {
ans = max(ans, a.maxneg * b.maxpos);
} else if (b.neg) {
ans = max(ans, a.minneg * b.maxneg);
}
}
return ans;
}
struct SegmentTree {
ll a[N];
struct Node {
int l, r;
Result w;
} node[4 * N];
void build(int p, int l, int r) {
node[p].l = l;
node[p].r = r;
if (l == r) {
if (a[l] == 0) {
node[p].w.pos = false;
node[p].w.neg = false;
node[p].w.zero = true;
} else if (a[l] > 0) {
node[p].w.pos = true;
node[p].w.neg = false;
node[p].w.zero = false;
node[p].w.maxpos = node[p].w.minpos = a[l];
} else {
node[p].w.pos = false;
node[p].w.neg = true;
node[p].w.zero = false;
node[p].w.maxneg = node[p].w.minneg = a[l];
}
} else {
int mid = (l + r) / 2;
build(2 * p, l, mid);
build(2 * p + 1, mid + 1, r);
node[p].w = node[2 * p].w + node[2 * p + 1].w;
}
}
Result query(int p, int l, int r) {
if (l <= node[p].l && node[p].r <= r) {
return node[p].w;
} else {
int mid = (node[p].l + node[p].r) / 2;
if (r <= mid) {
return query(2 * p, l, r);
} else if (mid + 1 <= l) {
return query(2 * p + 1, l, r);
} else {
return query(2 * p, l, r) + query(2 * p + 1, l, r);
}
}
}
} seg1, seg2;
int main() {
int n, m, q;
scanf("%d %d %d", &n, &m, &q);
for (int i = 1; i <= n; i++) {
scanf("%lld", &seg1.a[i]);
}
for (int i = 1; i <= m; i++) {
scanf("%lld", &seg2.a[i]);
}
seg1.build(1, 1, n);
seg2.build(1, 1, n);
for (int l1, r1, l2, r2; q != 0; q--) {
scanf("%d %d %d %d", &l1, &r1, &l2, &r2);
printf("%lld\n", seg1.query(1, l1, r1) * seg2.query(1, l2, r2));
}
return 0;
}