[CSP-S 2022] 策略游戏题解

策略游戏

题目来源

CSP-S 2022 T2

题目描述

见题面

解题方法

  R M Q \ RMQ  RMQ 问题。

可以从小   L \ L  L 角度出发,小   Q \ Q  Q 应对。
首先考虑建   2 \ 2  2 棵线段树 (   S T \ ST  ST 表也可以)。
存多个值: l ,   r ,   m a x ,   m i n ,   p m a x ,   p m i n ,   n m a x ,   n m i n l,\ r,\ max,\ min,\ pmax,\ pmin,\ nmax,\ nmin l, r, max, min, pmax, pmin, nmax, nmin。其中, p p p 表示非负数, n n n 表示非正数。
对于每次询问: l 1 ,   r 1 ,   l 2 ,   r 2 l_1,\ r_1,\ l_2,\ r_2 l1, r1, l2, r2
可以分为以下几种情况讨论:

  1. A m i n ≥ 0 A_{min}\geq 0 Amin0   B m i n ≥ 0 \ B_{min}\geq 0  Bmin0 a n s = A m a x B m i n ans=A_{max}B_{min} ans=AmaxBmin
  2. A m i n ≥ 0 A_{min}\geq 0 Amin0   B m a x ≤ 0 \ B_{max}\leq 0  Bmax0 a n s = A m i n B m i n ans=A_{min}B_{min} ans=AminBmin
  3. A m a x ≤ 0 A_{max}\leq 0 Amax0   B m i n ≥ 0 \ B_{min}\geq 0  Bmin0 a n s = A m a x B m a x ans=A_{max}B_{max} ans=AmaxBmax
  4. A m a x ≤ 0 A_{max}\leq 0 Amax0   B m a x ≤ 0 \ B_{max}\leq 0  Bmax0 a n s = A m i n B m a x ans=A_{min}B_{max} ans=AminBmax
  5. A m i n ≥ 0 A_{min}\geq 0 Amin0 a n s = A m i n B m i n ans=A_{min}B_{min} ans=AminBmin
  6. A m a x ≤ 0 A_{max}\leq 0 Amax0 a n s = A m a x B m a x ans=A_{max}B_{max} ans=AmaxBmax
  7. B m i n ≥ 0 B_{min}\geq 0 Bmin0 a n s = A m a x B m i n ans=A_{max}B_{min} ans=AmaxBmin
  8. B m a x ≤ 0 B_{max}\leq 0 Bmax0 a n s = A m i n B m a x ans=A_{min}B_{max} ans=AminBmax
  9. 否则: a n s 1 = A p m i n B n m i n ans_1=A_{pmin}B_{nmin} ans1=ApminBnmin
       a n s 2 = A n m a x B p m a x \qquad \ \ ans_2=A_{nmax}B_{pmax}   ans2=AnmaxBpmax
       a n s = max ⁡ ( a n s 1 ,   a n s 2 ) \qquad \ \ ans=\max(ans_1,\ ans_2)   ans=max(ans1, ans2)
代码实现
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 7;
const int INF = 1e18;
int n, m, T;
int a[N], b[N];
struct SEGTREE { int l, r, pmax, nmax, pmin, nmin, mx, mn; } treea[N * 4], treeb[N * 4];
inline int read()
{
	register int sum = 0, w = 1; register char ch = getchar();
	while (ch < '0' or ch > '9') { if (ch == '-') w = -1; ch = getchar(); }
	while (ch >= '0' and ch <= '9') { sum = sum * 10 + ch - '0'; ch = getchar(); }
	return sum * w;
}
void build_a(int u, int l, int r)
{
	treea[u].l = l, treea[u].r = r;
	if (l == r) {
		treea[u].mx = treea[u].mn = a[l];
		if (a[l] > 0) {
			treea[u].pmax = treea[u].pmin = a[l];
			treea[u].nmax = -INF; treea[u].nmin = INF;
		}
		else if (a[l] < 0) {
			treea[u].pmax = -INF; treea[u].pmin = INF;
			treea[u].nmax = treea[u].nmin = a[l];
		}
		else if (a[l] == 0)
			treea[u].pmax = treea[u].pmin = treea[u].nmax = treea[u].nmin = 0;
		return;
	}
	int mid = l + r >> 1;
	build_a(u * 2, l, mid), build_a(u * 2 + 1, mid + 1, r);
	treea[u].pmax = max(treea[u * 2].pmax, treea[u * 2 + 1].pmax);
	treea[u].pmin = min(treea[u * 2].pmin, treea[u * 2 + 1].pmin);
	treea[u].nmax = max(treea[u * 2].nmax, treea[u * 2 + 1].nmax);
	treea[u].nmin = min(treea[u * 2].nmin, treea[u * 2 + 1].nmin);
	treea[u].mx = max(treea[u * 2].mx, treea[u * 2 + 1].mx);
	treea[u].mn = min(treea[u * 2].mn, treea[u * 2 + 1].mn);
}
void build_b(int u, int l, int r)
{
	treeb[u].l = l, treeb[u].r = r;
	if (l == r) {
		treeb[u].mx = treeb[u].mn = b[l];
		if (b[l] > 0) {
			treeb[u].pmax = treeb[u].pmin = b[l];
			treeb[u].nmax = -INF; treeb[u].nmin = INF;
		}
		else if (b[l] < 0) {
			treeb[u].pmax = -INF; treeb[u].pmin = INF;
			treeb[u].nmax = treeb[u].nmin = b[l];
		}
		else if (!b[l])
			treeb[u].pmax = treeb[u].pmin = treeb[u].nmax = treeb[u].nmin = 0;
		return;
	}
	int mid = l + r >> 1;
	build_b(u * 2, l, mid), build_b(u * 2 + 1, mid + 1, r);
	treeb[u].pmax = max(treeb[u * 2].pmax, treeb[u * 2 + 1].pmax);
	treeb[u].pmin = min(treeb[u * 2].pmin, treeb[u * 2 + 1].pmin);
	treeb[u].nmax = max(treeb[u * 2].nmax, treeb[u * 2 + 1].nmax);
	treeb[u].nmin = min(treeb[u * 2].nmin, treeb[u * 2 + 1].nmin);
	treeb[u].mx = max(treeb[u * 2].mx, treeb[u * 2 + 1].mx);
	treeb[u].mn = min(treeb[u * 2].mn, treeb[u * 2 + 1].mn);
}
int query_a_max(int u, int l, int r)
{
	if (treea[u].l >= l and treea[u].r <= r) return treea[u].mx;
	int mid = treea[u].l + treea[u].r >> 1, MAX = -1e18;
	if (l <= mid) MAX = max(MAX, query_a_max(u * 2, l, r));
	if (r > mid) MAX = max(MAX, query_a_max(u * 2 + 1, l, r));
	return MAX;
}
int query_a_min(int u, int l, int r)
{
	if (treea[u].l >= l and treea[u].r <= r) return treea[u].mn;
	int mid = treea[u].l + treea[u].r >> 1, MIN = 1e18;
	if (l <= mid) MIN = min(MIN, query_a_min(u * 2, l, r));
	if (r > mid) MIN = min(MIN, query_a_min(u * 2 + 1, l, r));
	return MIN;
}
int query_b_max(int u, int l, int r)
{
	if (treeb[u].l >= l and treeb[u].r <= r) return treeb[u].mx;
	int mid = treeb[u].l + treeb[u].r >> 1, MAX = -1e18;
	if (l <= mid) MAX = max(MAX, query_b_max(u * 2, l, r));
	if (r > mid) MAX = max(MAX, query_b_max(u * 2 + 1, l, r));
	return MAX;
}
int query_b_min(int u, int l, int r)
{
	if (treeb[u].l >= l and treeb[u].r <= r) return treeb[u].mn;
	int mid = treeb[u].l + treeb[u].r >> 1, MIN = 1e18;
	if (l <= mid) MIN = min(MIN, query_b_min(u * 2, l, r));
	if (r > mid) MIN = min(MIN, query_b_min(u * 2 + 1, l, r));
	return MIN;
}
int query_a_pmin(int u, int l, int r)
{
	if (treea[u].l >= l and treea[u].r <= r) return treea[u].pmin;
	int mid = treea[u].l + treea[u].r >> 1, MIN = 1e18;
	if (l <= mid) MIN = min(MIN, query_a_pmin(u * 2, l, r));
	if (r > mid) MIN = min(MIN, query_a_pmin(u * 2 + 1, l, r));
	return MIN;
}
int query_a_nmax(int u, int l, int r)
{
	if (treea[u].l >= l and treea[u].r <= r) return treea[u].nmax;
	int mid = treea[u].l + treea[u].r >> 1, MAX = -1e18;
	if (l <= mid) MAX = max(MAX, query_a_nmax(u * 2, l, r));
	if (r > mid) MAX = max(MAX, query_a_nmax(u * 2 + 1, l, r));
	return MAX;
}
int query_b_pmax(int u, int l, int r)
{
	if (treeb[u].l >= l and treeb[u].r <= r) return treeb[u].pmax;
	int mid = treeb[u].l + treeb[u].r >> 1, MAX = -1e18;
	if (l <= mid) MAX = max(MAX, query_b_pmax(u * 2, l, r));
	if (r > mid) MAX = max(MAX, query_b_pmax(u * 2 + 1, l, r));
	return MAX;
}
int query_b_nmin(int u, int l, int r)
{
	if (treeb[u].l >= l and treeb[u].r <= r) return treeb[u].nmin;
	int mid = treeb[u].l + treeb[u].r >> 1, MIN = 1e18;
	if (l <= mid) MIN = min(MIN, query_b_nmin(u * 2, l, r));
	if (r > mid) MIN = min(MIN, query_b_nmin(u * 2 + 1, l, r));
	return MIN;
}
signed main()
{
	n = read(), m = read(), T = read();
	for (int i = 1; i <= n; i++) a[i] = read();
	for (int i = 1; i <= m; i++) b[i] = read();
	build_a(1, 1, n);
	build_b(1, 1, m);
	while (T--) {
		int l1 = read(), r1 = read(), l2 = read(), r2 = read();
		if (query_a_min(1, l1, r1) >= 0 and query_b_min(1, l2, r2) >= 0) {
			int ans = query_a_max(1, l1, r1) * query_b_min(1, l2, r2);
			printf("%lld\n", ans);
			continue;
		}
		else if (query_a_max(1, l1, r1) <= 0 and query_b_max(1, l2, r2) <= 0) {
			int ans = query_a_min(1, l1, r1) * query_b_max(1, l2, r2);
			printf("%lld\n", ans);
			continue;
		}
		else if (query_a_min(1, l1, r1) >= 0 and query_b_max(1, l2, r2) <= 0) {
			int ans = query_a_min(1, l1, r1) * query_b_min(1, l2, r2);
			printf("%lld\n", ans);
			continue;
		}
		else if (query_a_max(1, l1, r1) <= 0 and query_b_min(1, l2, r2) >= 0) {
			int ans = query_a_max(1, l1, r1) * query_b_max(1, l2, r2);
			printf("%lld\n", ans);
			continue;
		}
		else if (query_b_min(1, l2, r2) >= 0) {
			int ans = query_a_max(1, l1, r1) * query_b_min(1, l2, r2);
			printf("%lld\n", ans);
			continue;
		}
		else if (query_b_max(1, l2, r2) <= 0) {
			int ans = query_a_min(1, l1, r1) * query_b_max(1, l2, r2);
			printf("%lld\n", ans);
			continue;
		}
		else if (query_a_min(1, l1, r1) >= 0) {
			int ans = query_a_min(1, l1, r1) * query_b_min(1, l2, r2);
			printf("%lld\n", ans);
			continue;
		}
		else if (query_a_max(1, l1, r1) <= 0) {
			int ans = query_a_max(1, l1, r1) * query_b_max(1, l2, r2);
			printf("%lld\n", ans);
			continue;
		}
		else {
			int ans1 = query_a_pmin(1, l1, r1) * query_b_nmin(1, l2, r2);
			int ans2 = query_a_nmax(1, l1, r1) * query_b_pmax(1, l2, r2);
			printf("%lld\n", max(ans1, ans2));
		}
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值