rt,代码中注释有标出,53 行和 65 行的值一变,分数就变了。
但理论上如果绝对值大于 109,都是可以正常查询的,因为线段树只放了初始的 a,b 数组。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e5 + 10;
const int M = N << 2;
int n, m, q;
ll a[N], b[N];
struct sgt{
ll mx[M], mn[M];
#define ls(o) (o << 1)
#define rs(o) (o << 1 | 1)
void init(){
for(int i=0;i<M;i++){
mx[i] = -2147483647;
mn[i] = 2147483647;
}
}
void build(int o, int l, int r, ll *a){
if(l == r){
mx[o] = mn[o] = a[l];
return ;
}
int mid = (l + r) >> 1;
build(ls(o), l, mid, a);
build(rs(o), mid + 1, r, a);
mn[o] = min(mn[ls(o)], mn[rs(o)]);
mx[o] = max(mx[ls(o)], mx[rs(o)]);
}
void update(int o, int l, int r, int p, ll v){
if(l == r){
mn[o] = mx[o] = v;
return ;
}
int mid = (l + r) >> 1;
if(p <= mid)
update(ls(o), l, mid, p, v);
else
update(rs(o), mid + 1, r, p, v);
mn[o] = min(mn[ls(o)], mn[rs(o)]);
mx[o] = max(mx[ls(o)], mx[rs(o)]);
}
ll query_max(int o, int l, int r, int s, int t){
if(l >= s && r <= t)
return mx[o];
int mid = (l + r) >> 1;
ll res = -2147483647;//53 行
if(s <= mid)
res = max(res, query_max(ls(o), l, mid, s, t));
if(t > mid)
res = max(res, query_max(rs(o), mid + 1, r, s, t));
return res;
}
ll query_min(int o, int l, int r, int s, int t){
if(l >= s && r <= t)
return mn[o];
int mid = (l + r) >> 1;
ll res = 2147483647;//65 行
if(s <= mid)
res = min(res, query_min(ls(o), l, mid, s, t));
if(t > mid)
res = min(res, query_min(rs(o), mid + 1, r, s, t));
return res;
}
} A, B, Az, Af;
int main(){
// freopen("game.in", "r", stdin);
// freopen("game.out", "w", stdout);
scanf("%d%d%d", &n, &m, &q);
Az.init(), Af.init();
for(int i=1;i<=n;i++){
scanf("%lld", &a[i]);
if(a[i] >= 0)
Az.update(1, 1, n, i, a[i]);
else
Af.update(1, 1, n, i, a[i]);
}
for(int i=1;i<=m;i++)
scanf("%lld", &b[i]);
A.build(1, 1, n, a);
B.build(1, 1, m, b);
while(q--){
int l1, r1, l2, r2;
scanf("%d%d%d%d", &l1, &r1, &l2, &r2);
ll mx1 = A.query_max(1, 1, n, l1, r1), mx2 = B.query_max(1, 1, m, l2, r2);
ll mn1 = A.query_min(1, 1, n, l1, r1), mn2 = B.query_min(1, 1, m, l2, r2);
if(mn2 >= 0){//第二个人只能取到非负数
if(mx1 >= 0)
printf("%lld\n", mx1 * mn2);
else
printf("%lld\n", mx1 * mx2);
continue;
}
if(mx2 < 0){//第二个人只能取到负数
if(mn1 < 0)
printf("%lld\n", mn1 * mx2);
else
printf("%lld\n", mn1 * mn2);
continue;
//若 mn1 为正,则无论如何都是负,因此选最小使得得分最大
//若 mn1 为负,mn1 越小,结果越大(负负得正),因此还是选最小
}
if(mx2 >= 0 && mn2 <= 0){//第二个人可以取到正、负数
ll x = Az.query_min(1, 1, n, l1, r1);//最小正数,第二个人最小数
if(!x){//有 0 肯定先取 0
printf("0\n");
continue;
}
//要么取最小的正数,否则取最大的负数
ll y = Af.query_max(1, 1, n, l1, r1);//最大负数,第二个人最大数
printf("%lld\n", max(x * mn2, y * mx2));//第一个人先取,所以输出较大值
}
}
return 0;
}