所以有人知道 Subtask 2 为什么错了吗?
查看原帖
所以有人知道 Subtask 2 为什么错了吗?
363036
chlchl楼主2022/10/30 09:45

rt,线段树 85 分,带注释。

#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] = -1e18;
			mn[i] = 1e18;
		}
	}
	
	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 = -1000000001;
		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 = 1000000001;
		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;
} 

2022/10/30 09:45
加载中...