社区讨论
求条 WA on 4 8 19
P8818[CSP-S 2022] 策略游戏参与者 1已保存回复 0
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mhj3gf3w
- 此快照首次捕获于
- 2025/11/03 20:06 4 个月前
- 此快照最后确认于
- 2025/11/03 20:06 4 个月前
注:subtask #1 通过偷窥数据发现是把负数输出成0
CPP#include <iostream>
#include <cstdio>
#include <algorithm>
#include <climits>
namespace noip {
typedef long long Int;
constexpr Int MAX_N = 100000;
constexpr Int MAX_M = 100000;
constexpr Int MAX_LOG_N = 18;
constexpr Int MAX_LOG_M = 18;
constexpr Int MG = LLONG_MAX; // 美观作用
Int n, m, q, a[MAX_N+1], b[MAX_M+1];
Int LOG[MAX_N+1];
Int mia[MAX_N+1][MAX_LOG_N+1], maa[MAX_N+1][MAX_LOG_N+1];
Int miaz[MAX_N+1][MAX_LOG_N+1], maaf[MAX_N+1][MAX_LOG_N+1]; // 正数最小和负数最大
Int mib[MAX_M+1][MAX_LOG_M+1], mab[MAX_M+1][MAX_LOG_M+1];
Int l1, r1, l2, r2, len, ans, ac;
void init() {
LOG[1] = 0; for (Int i = 2; i <= n; i++) LOG[i] = LOG[i/2] + 1;
for (Int i = 1, e = 0; i <= n; i++) {
mia[i][e] = a[i];
maa[i][e] = a[i];
miaz[i][e] = a[i] <= 0 ? MG : a[i];
maaf[i][e] = a[i] > 0 ? -MG : a[i];
}
for (Int e = 1; e <= LOG[n]; e++)
for (Int i = n; i >= 1; i--)
if (i+(1<<(e-1)) <= n) {
mia[i][e] = std::min(mia[i][e-1], mia[i+(1<<(e-1))][e-1]);
maa[i][e] = std::max(maa[i][e-1], maa[i+(1<<(e-1))][e-1]);
miaz[i][e] = std::min(miaz[i][e-1], miaz[i+(1<<(e-1))][e-1]);
maaf[i][e] = std::max(maaf[i][e-1], maaf[i+(1<<(e-1))][e-1]);
}
else {
mia[i][e] = mia[i][e-1];
maa[i][e] = maa[i][e-1];
miaz[i][e] = miaz[i][e-1];
maaf[i][e] = maaf[i][e-1];
}
for (Int i = 1, e = 0; i <= m; i++) {
mib[i][e] = b[i];
mab[i][e] = b[i];
}
for (Int e = 1; e <= LOG[m]; e++)
for (Int i = m; i >= 1; i--)
if (i+(1<<(e-1)) <= m) {
mib[i][e] = std::min(mib[i][e-1], mib[i+(1<<(e-1))][e-1]);
mab[i][e] = std::max(mab[i][e-1], mab[i+(1<<(e-1))][e-1]);
}
else {
mib[i][e] = mib[i][e-1];
mab[i][e] = mab[i][e-1];
}
}
Int ask(Int f[100001][19], Int L, Int R, Int t) {
len = R-L+1;
if (t == 1)
return std::max(f[L][LOG[len]], f[R-(1<<LOG[len])+1][LOG[len]]);
else
return std::min(f[L][LOG[len]], f[R-(1<<LOG[len])+1][LOG[len]]);
}
Int bc(Int ac) {
if (ac > 0) return noip::ask(mib, l2, r2, 2LL);
else if (ac <= 0) return noip::ask(mab, l2, r2, 1LL);
}
void main() {
//freopen("input.in", "r", stdin);
//freopen("output.out", "w", stdout);
std::cin >> n >> m >> q;
for (Int i = 1; i <= n; i++) std::cin >> a[i];
for (Int i = 1; i <= m; i++) std::cin >> b[i];
noip::init();
while (q--) {
std::cin >> l1 >> r1 >> l2 >> r2;
// 对于 L 来说,自己被资本做局,只能让差异最小化
// 由于 L 看得到 Q 的候选范围,故只需要尝试
// 最大,最小,非正数最大,正数最小
// 去模拟 Q 的回答,然后取一个 max 即可
// 对于 Q 来说,自己只要根据 L 选的来选就可以
// 如果 L 选了正数,那么自己选值最小的数
// 如果 L 选了非正数,那么自己选值最大的数
// 对于 A 建立 min负值 max负值 min正值 和 max正值 的 st表
// 对于 B 建立 min值 和 max值 的 st表
ac = noip::ask(mia, l1, r1, 2LL);
ans = std::max(-MG, ac*noip::bc(ac));
ac = noip::ask(maa, l1, r1, 1LL);
ans = std::max(ans, ac*noip::bc(ac));
ac = noip::ask(miaz, l1, r1, 2LL);
if (ac != MG) ans = std::max(ans, ac*noip::bc(ac));
ac = noip::ask(maaf, l1, r1, 1LL);
if (ac != -MG) ans = std::max(ans, ac*noip::bc(ac));
std::cout << ans << std::endl;
}
}
} int main() {
noip::main();
return 0;
}
回复
共 0 条回复,欢迎继续交流。
正在加载回复...