策略游戏
题目来源
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。
可以分为以下几种情况讨论:
- A m i n ≥ 0 A_{min}\geq 0 Amin≥0 且 B m i n ≥ 0 \ B_{min}\geq 0 Bmin≥0, a n s = A m a x B m i n ans=A_{max}B_{min} ans=AmaxBmin
- A m i n ≥ 0 A_{min}\geq 0 Amin≥0 且 B m a x ≤ 0 \ B_{max}\leq 0 Bmax≤0, a n s = A m i n B m i n ans=A_{min}B_{min} ans=AminBmin
- A m a x ≤ 0 A_{max}\leq 0 Amax≤0 且 B m i n ≥ 0 \ B_{min}\geq 0 Bmin≥0, a n s = A m a x B m a x ans=A_{max}B_{max} ans=AmaxBmax
- A m a x ≤ 0 A_{max}\leq 0 Amax≤0 且 B m a x ≤ 0 \ B_{max}\leq 0 Bmax≤0, a n s = A m i n B m a x ans=A_{min}B_{max} ans=AminBmax
- A m i n ≥ 0 A_{min}\geq 0 Amin≥0, a n s = A m i n B m i n ans=A_{min}B_{min} ans=AminBmin
- A m a x ≤ 0 A_{max}\leq 0 Amax≤0, a n s = A m a x B m a x ans=A_{max}B_{max} ans=AmaxBmax
- B m i n ≥ 0 B_{min}\geq 0 Bmin≥0, a n s = A m a x B m i n ans=A_{max}B_{min} ans=AmaxBmin
- B m a x ≤ 0 B_{max}\leq 0 Bmax≤0, a n s = A m i n B m a x ans=A_{min}B_{max} ans=AminBmax
- 否则:
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;
}