#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define x first
#define y second
using namespace std;
const int N=100010;
typedef long long LL;
typedef pair<int,bool> PIB;
int n,m,T;
PIB a[N],b[N];
struct Tree1
{
int l,r;
int minn;
int maxn;
int t;
}tr1[N*4];
struct Tree2
{
int l,r;
int minn;
int maxn;
int t;
}tr2[N*4];
void pushup1(int u)
{
tr1[u].minn=min(tr1[u<<1].minn,tr1[u<<1|1].minn);
tr1[u].maxn=max(tr1[u<<1].maxn,tr1[u<<1|1].maxn);
if(tr1[u<<1].t!=tr1[u<<1|1].t) tr1[u].t=0;
else tr1[u].t=tr1[u<<1].t;
}
void build1(int u,int l,int r)
{
if(l==r)
{
tr1[u].l=l; tr1[u].r=r; tr1[u].minn=a[r].x; tr1[u].maxn=a[r].x;
if(a[r].y==true) tr1[u].t=2;
else tr1[u].t=1;
}
else
{
tr1[u].l=l;tr1[u].r=r;
int mid=(l+r)>>1;
build1(u<<1,l,mid);
build1(u<<1|1,mid+1,r);
pushup1(u);
}
}
void pushup2(int u)
{
tr2[u].minn=min(tr2[u<<1].minn,tr2[u<<1|1].minn);
tr2[u].maxn=max(tr2[u<<1].maxn,tr2[u<<1|1].maxn);
if(tr2[u<<1].t!=tr2[u<<1|1].t) tr2[u].t=0;
else tr2[u].t=tr2[u<<1].t;
}
void build2(int u,int l,int r)
{
if(l==r)
{
tr2[u].l=l; tr2[u].r=r; tr2[u].minn=b[r].x; tr2[u].maxn=b[r].x;
if(b[r].y) tr2[u].t=2;
else tr2[u].t=1;
}
else
{
tr2[u].l=l;tr2[u].r=r;
int mid=(l+r)>>1;
build2(u<<1,l,mid);
build2(u<<1|1,mid+1,r);
pushup2(u);
}
}
int ask1(int u,int l,int r)
{
if(tr1[u].l>=l&&tr1[u].r<=r) return tr1[u].t;
int num=100;
int mid=(tr1[u].l+tr1[u].r)>>1;
if(mid>=l) num=ask1(u<<1,l,r);
if(mid<r)
{
if(num+ask1(u<<1|1,l,r)==3) num=0;
num=min(num,ask1(u<<1|1,l,r));
}
return num;
}
int ask2(int u,int l,int r)
{
if(tr2[u].l>=l&&tr2[u].r<=r) return tr2[u].t;
int num=100;
int mid=(tr2[u].l+tr2[u].r)>>1;
if(mid>=l) num=ask2(u<<1,l,r);
if(mid<r)
{
if(num+ask2(u<<1|1,l,r)==3) num=0;
num=min(num,ask2(u<<1|1,l,r));
}
return num;
}
int querymin1(int u,int l,int r)
{
if(tr1[u].l>=l&&tr1[u].r<=r) return tr1[u].minn;
int num=1e9;
int mid=(tr1[u].l+tr1[u].r)>>1;
if(mid>=l) num=querymin1(u<<1,l,r);
else num=min(num,querymin1(u<<1|1,l,r));
return num;
}
int querymin2(int u,int l,int r)
{
if(tr2[u].l>=l&&tr2[u].r<=r) return tr2[u].minn;
int num=1e9;
int mid=(tr2[u].l+tr2[u].r)>>1;
if(mid>=l) num=querymin2(u<<1,l,r);
else num=min(num,querymin2(u<<1|1,l,r));
return num;
}
int querymax1(int u,int l,int r)
{
if(tr1[u].l>=l&&tr1[u].r<=r) return tr1[u].maxn;
int num=-1e9;
int mid=(tr1[u].l+tr1[u].r)>>1;
if(mid>=l) num=querymax1(u<<1,l,r);
else num=max(num,querymax1(u<<1|1,l,r));
return num;
}
int querymax2(int u,int l,int r)
{
if(tr2[u].l>=l&&tr2[u].r<=r) return tr2[u].minn;
int num=-1e9;
int mid=(tr2[u].l+tr2[u].r)>>1;
if(mid>=l) num=querymax2(u<<1,l,r);
else num=max(num,querymax2(u<<1|1,l,r));
return num;
}
int main()
{
scanf("%d%d%d",&n,&m,&T);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].x);
if(a[i].x>=0) a[i].y=true;
else a[i].y=false;
}
build1(1,1,n);
for(int i=1;i<=m;i++)
{
scanf("%d",&b[i].x);
if(b[i].x>=0) b[i].y=true;
else b[i].y=false;
}
build2(1,1,m);
while(T--)
{
int l1,l2,r1,r2;
scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
int ans1=ask1(1,l1,r1);
int ans2=ask2(1,l2,r2);
if(ans1==0&&ans2==0)
{
LL maxn=-1e9;
for(int i=l1;i<=r1;i++)
{
LL minn=1e9;
for(int j=l2;j<=r2;j++) minn=min(minn,(LL)a[i].x*b[j].x);
maxn=max(maxn,minn);
}
printf("%lld\n",maxn);
continue;
}
else if(ans2==1)
{
printf("%lld\n",(LL)querymin1(1,l1,r1)*querymax2(1,l2,r2));
continue;
}
else if(ans2==2)
{
printf("%lld\n",(LL)querymax1(1,l1,r1)*querymin2(1,l2,r2));
continue;
}
else if(ans1==1)
{
printf("%lld\n",(LL)querymax1(1,l1,r1)*querymax2(1,l2,r2));
continue;
}
else if(ans1==2)
{
printf("%lld\n",(LL)querymin1(1,l1,r1)*querymin2(1,l2,r2));
continue;
}
}
return 0;
}