Solution - P8818 [CSP-S 2022] 策略游戏
校内模拟赛 T2,恭喜 lijunxi2026 拿下首 A。
赛时被 Hack 在了 #19,但是因为有 100pts 了就没有去管它,后来才调出来。
思路
首先注意小 Q。因为他选择时 \(x\) 已经确定,那么直接选可能造成最小分数的一个即可。
那么注意小 P,显然他的任务是让他选择的 \(x\) 可能造成的最小值最大。(其实是因为我做过类似的题 qwq)
首先想到的是维护两个最小值,然后看到 \(-10^9 \le |a_i|,|b_i| \le 10^9\) 的时候被打脸了。
然后想到维护两个最值,四个 ST 表。然后样例 2 的第三个询问被打脸了。
于是手模样例 2,发现选择是 \((-1, 2)\)。于是想到额外维护 \(a\) 最小的非负数与最大的负数,然后把这一堆东西取最大就行了。
于是,没了。
代码
#include <bits/stdc++.h>
#define rint register int
#define rllong register long long
#define llong long long
#define N 100005
using namespace std;
int Log2[N];
int st1a[N][20], st1b[N][20], st1d[N][20], st1e[N][20], st2a[N][20], st2b[N][20];
int n, m, q;
inline void prework(){
for(rint i = 2; i <= max(n, m); ++i)
Log2[i] = Log2[i>>1]+1;
for(rint t = 1; t <= 19; ++t)
for(rint i = 1; i <= n; ++i){
if(i+(1<<t-1) > n) continue;
st1a[i][t] = min(st1a[i][t-1], st1a[i+(1<<t-1)][t-1]);
st1b[i][t] = max(st1b[i][t-1], st1b[i+(1<<t-1)][t-1]);
st1d[i][t] = min(st1d[i][t-1], st1d[i+(1<<t-1)][t-1]);
st1e[i][t] = max(st1e[i][t-1], st1e[i+(1<<t-1)][t-1]);
}
for(rint t = 1; t <= 19; ++t)
for(rint i = 1; i <= m; ++i){
if(i+(1<<t-1) > m) continue;
st2a[i][t] = min(st2a[i][t-1], st2a[i+(1<<t-1)][t-1]);
st2b[i][t] = max(st2b[i][t-1], st2b[i+(1<<t-1)][t-1]);
}
}
#define len (r-l+1)
inline int query1a(rint l, rint r){return min(st1a[l][Log2[len]], st1a[r-(1<<Log2[len])+1][Log2[len]]);} // min
inline int query1b(rint l, rint r){return max(st1b[l][Log2[len]], st1b[r-(1<<Log2[len])+1][Log2[len]]);} // max
inline int query1d(rint l, rint r){return min(st1d[l][Log2[len]], st1d[r-(1<<Log2[len])+1][Log2[len]]);} // min
inline int query1e(rint l, rint r){return max(st1e[l][Log2[len]], st1e[r-(1<<Log2[len])+1][Log2[len]]);} // max
inline int query2a(rint l, rint r){return min(st2a[l][Log2[len]], st2a[r-(1<<Log2[len])+1][Log2[len]]);} // min
inline int query2b(rint l, rint r){return max(st2b[l][Log2[len]], st2b[r-(1<<Log2[len])+1][Log2[len]]);} // max
int main(){
scanf("%d %d %d", &n, &m, &q);
for(rint i = 1; i <= n; ++i){
rint x;
scanf("%d", &x);
if (x >= 0) st1a[i][0] = x, st1b[i][0] = -1e9-9;
else st1b[i][0] = x, st1a[i][0] = 1e9+9;
st1d[i][0] = st1e[i][0] = x;
}
for(rint i = 1; i <= m; ++i)
scanf("%d", &st2a[i][0]), st2b[i][0] = st2a[i][0];
prework();
while(q--){
rint l1, r1, l2, r2;
scanf("%d %d %d %d", &l1, &r1, &l2, &r2);
rllong val = -1e18-3;
rllong val1 = 1ll*query1a(l1, r1)*(query1a(l1, r1)>=0 ? query2a(l2, r2) : query2b(l2, r2));
rllong val2 = 1ll*query1b(l1, r1)*(query1b(l1, r1)>=0 ? query2a(l2, r2) : query2b(l2, r2));
rllong val4 = 1ll*query1d(l1, r1)*(query1d(l1, r1)>=0 ? query2a(l2, r2) : query2b(l2, r2));
rllong val5 = 1ll*query1e(l1, r1)*(query1e(l1, r1)>=0 ? query2a(l2, r2) : query2b(l2, r2));
if(query1a(l1, r1) < +1e9) val = max(val, val1);
if(query1b(l1, r1) > -1e9) val = max(val, val2);
val = max(val, max(val4, val5));
printf("%lld\n", val);
}
return 0;
}
注意
- 十年 OI 一场空,不开________见祖宗
- 务必分清 \(n, m\),我在这里被 Hack 了两个小时……