RT,大致思路是维护区间最大值 (mx) 、最小值 (mn) 、最大非正数 (nmx) 、最小非负数 (nmn) 、是否全非正 (eg) 、是否全非负 (neg) 。
MnZn打线段树的次数不多,不知道哪里写挂了qwq
#include <iostream>
#include <cstdlib>
#define MAXN 100007
#define INF 0x3f3f3f3f
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define RE register
using namespace std;
typedef long long ll;
int n, m, q, lt1, rt1, lt2, rt2;
ll a[MAXN], b[MAXN];
struct node {
int l, r; ll mx, mn, nmx, nmn; bool eg, neg;
node() {l = 0, r = 0, mx = -INF, mn = INF, nmx = -INF, nmn = INF, eg = false, neg = false; }
}sA[MAXN << 2], sB[MAXN << 2];
inline void update(node* T, int d) {
T[d].mx = max(T[(d << 1)].mx, T[((d << 1) | 1)].mx); T[d].mn = min(T[(d << 1)].mn, T[((d << 1) | 1)].mn);
T[d].nmx = max(T[(d << 1)].nmx, T[((d << 1) | 1)].nmx); T[d].nmn = min(T[(d << 1)].nmn, T[((d << 1) | 1)].nmn);
T[d].eg = T[(d << 1)].eg && T[((d << 1) | 1)].eg; T[d].neg = T[(d << 1)].neg && T[((d << 1) | 1)].neg;
return ;
}
inline void build(ll* ar, node* T, int lp, int rp, int d) {
T[d].l = lp, T[d].r = rp;
if(lp == rp) {
T[d].mx = T[d].mn = ar[lp];
if(ar[lp] <= 0) { T[d].nmx = ar[lp]; T[d].eg = true; }
if(ar[lp] >= 0) { T[d].nmn = ar[lp]; T[d].neg = true; }
return ;
}
int mid = (lp + rp) >> 1;
build(ar, T, lp, mid, (d << 1));
build(ar, T, mid + 1, rp, (d << 1) | 1);
update(T, d);
return ;
}
inline ll akm(node* T, int lp, int rp, int d) {
if(lp <= T[d].l && T[d].r <= rp) return T[d].mx;
int mid = (T[d].l + T[d].r) >> 1;
int fs = -INF;
if(lp <= mid) fs = max(fs, akm(T, lp, rp, (d << 1)));
if(rp > mid) fs = max(fs, akm(T, lp, rp, ((d << 1) | 1)));
return fs;
}
inline ll akn(node* T, int lp, int rp, int d) {
if(lp <= T[d].l && T[d].r <= rp) return T[d].mn;
int mid = (T[d].l + T[d].r) >> 1;
int fs = INF;
if(lp <= mid) fs = min(fs, akn(T, lp, rp, (d << 1)));
if(rp > mid) fs = min(fs, akn(T, lp, rp, ((d << 1) | 1)));
return fs;
}
inline ll aknm(node* T, int lp, int rp, int d) {
if(lp <= T[d].l && T[d].r <= rp) return T[d].nmx;
int mid = (T[d].l + T[d].r) >> 1;
int fs = -INF;
if(lp <= mid) fs = max(fs, aknm(T, lp, rp, (d << 1)));
if(rp > mid) fs = max(fs, aknm(T, lp, rp, ((d << 1) | 1)));
return fs;
}
inline ll aknn(node* T, int lp, int rp, int d) {
if(lp <= T[d].l && T[d].r <= rp) return T[d].nmn;
int mid = (T[d].l + T[d].r) >> 1;
int fs = INF;
if(lp <= mid) fs = min(fs, aknn(T, lp, rp, (d << 1)));
if(rp > mid) fs = min(fs, aknn(T, lp, rp, ((d << 1) | 1)));
return fs;
}
inline bool aeg(node* T, int lp, int rp, int d) {
if(lp > rp) return false;
if(lp <= T[d].l && T[d].r <= rp) return T[d].eg;
int mid = (T[d].l + T[d].r) >> 1;
bool fs = true;
if(lp <= mid) fs = fs && aeg(T, lp, rp, (d << 1));
if(!fs) return false;
if(rp > mid) fs = fs && aeg(T, lp, rp, ((d << 1) | 1));
return fs;
}
inline bool aneg(node* T, int lp, int rp, int d) {
if(lp > rp) return false;
if(lp <= T[d].l && T[d].r <= rp) return T[d].neg;
int mid = (T[d].l + T[d].r) >> 1;
bool fs = true;
if(lp <= mid) fs = fs && aneg(T, lp, rp, (d << 1));
if(!fs) return false;
if(rp > mid) fs = fs && aneg(T, lp, rp, ((d << 1) | 1));
return fs;
}
int main() {
freopen("game3.in", "r", stdin);
freopen("game3.out", "w", stdout);
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n >> m >> q;
for(RE int i = 1; i <= n; i++) cin >> a[i];
for(RE int i = 1; i <= m; i++) cin >> b[i];
build(a, sA, 1, n, 1); build(b, sB, 1, m, 1);
for(RE int i = 1; i <= q; i++) {
cin >> lt1 >> rt1 >> lt2 >> rt2;
if(aeg(sA, lt1, rt1, 1)) {
ll tm = akm(sB, lt2, rt2, 1);
if(aeg(sB, lt2, rt2, 1)) cout << 1LL * tm * akn(sA, lt1, rt1, 1) << endl;
else cout << 1LL * tm * akm(sA, lt1, rt1, 1) << endl;
}
else if(aneg(sA, lt1, rt1, 1)) {
ll tm = akn(sB, lt2, rt2, 1);
if(aneg(sB, lt2, rt2, 1)) cout << 1LL * tm * akm(sA, lt1, rt1, 1) << endl;
else cout << 1LL * tm * akn(sA, lt1, rt1, 1) << endl;
}
else {
if(aneg(sB, lt2, rt2, 1)) cout << 1LL * akm(sA, lt1, rt1, 1) * akn(sB, lt2, rt2, 1) << endl;
else if(aeg(sB, lt2, rt2, 1)) cout << 1LL * akn(sA, lt1, rt1, 1) * akm(sB, lt2, rt2, 1) << endl;
else {
ll an_0 = 1LL * akn(sB, lt2, rt2, 1) * aknn(sA, lt1, rt1, 1), an_1 = 1LL * akm(sB, lt2, rt2, 1) * aknm(sA, lt1, rt1, 1);
cout << max(an_0, an_1) << endl;
}
}
}
return 0;
}