1 条题解
-
0
自动搬运
来自洛谷,原作者为

dbxxx
多刷题,少整那些没用的搬运于
2025-08-24 22:42:47,当前版本为作者最后更新于2022-10-31 01:27:03,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
本文中 A 和 B 分别代表小 L 和小 Q,而原题中的 , 两个数组在本题中分别用 和 表示。
矩阵这个描述就是障眼法。翻译一下题目:
A 在 中选择一个 ,然后 B 在 中选择一个 ,分数是 ,A 想让分数尽可能大,B 想让分数尽可能小。求分数。
肯定先思考 B 再思考 A,因为 A 会思考 B 的思考。
B 的行为就是对于 ,找到一个 中的 ,使得 最小。
具体地:
- 时,B 会选择最小的 ;
- 时,B 会选择最大的 。
那么 A 的行为是什么呢?还是按照正负分类讨论:
如果 A 这次想让 ,那么 B 会选择最小的 。如果这个 ,那么 A 一定会选最大的 ;如果这个 ,那么 A 一定会选最小的非负数 (别忘了当前制约条件 )。
如果 A 这次想让 ,那么 B 会选择最大的 。如果这个 ,那么 A 一定会选最大的负数 ;如果这个 ,那么 A 一定会选最小的 。
因此 A 的行为只有四种:选择最大的 ;最小的 ,最大的负数 ,最小的非负数 。
分别讨论 A 选择四种行为时 B 的选择,答案取最大值即可。
然后就变成了静态区间最值的板子。使用 6 个 ST 表分别存储以下信息:
- 的区间最大值;
- 的区间最小值;
- 的负数区间最大值;
- 具体是把所有满足 的 全部替换为 代表这个位置不存在数,至于为何是 请读者自己思考。
- 的非负数区间最小值;
- 具体是把所有满足 的 全部替换为 代表这个位置不存在数。
- 的区间最大值;
- 的区间最小值。
时间复杂度 。
/* * @Author: crab-in-the-northeast * @Date: 2022-10-30 22:49:26 * @Last Modified by: crab-in-the-northeast * @Last Modified time: 2022-10-30 23:15:25 */ #include <bits/stdc++.h> #define int long long inline int read() { int x = 0; bool f = true; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = false; for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0'; return f ? x : (~(x - 1)); } inline int max(int a, int b) { return a > b ? a : b; } inline bool gmx(int &a, int b) { return b > a ? a = b, true : false; } inline int min(int a, int b) { return a < b ? a : b; } const int maxn = (int)1e5 + 5; const int maxm = (int)1e5 + 5; const int mlgn = 25; const int mlgm = 25; int amx[maxn][mlgn], amn[maxn][mlgn], afx[maxn][mlgn], azn[maxn][mlgn]; int bmx[maxm][mlgm], bmn[maxm][mlgm]; // 6 个 ST 表 // amx:a 的区间最大值,amn:a 的区间最小值,afx:a 的负数区间最大值,azn:a 的非负数区间最小值。 // bmx:b 的区间最大值,bmn:b 的区间最小值。 int lg[maxn]; const int maxinf = LONG_LONG_MAX, mininf = LONG_LONG_MIN; signed main() { int n = read(), m = read(), q = read(); for (int i = 1; i <= n; ++i) { int x = read(); amx[i][0] = amn[i][0] = x; afx[i][0] = (x < 0 ? x : mininf); azn[i][0] = (x >= 0 ? x : maxinf); } for (int i = 1; i <= m; ++i) { int x = read(); bmx[i][0] = bmn[i][0] = x; } for (int i = 2; i <= max(n, m); ++i) lg[i] = lg[i >> 1] + 1; for (int j = 1; j <= lg[n]; ++j) { for (int i = 1; i + (1 << j) - 1 <= n; ++i) { int p = i + (1 << (j - 1)); amx[i][j] = max(amx[i][j - 1], amx[p][j - 1]); afx[i][j] = max(afx[i][j - 1], afx[p][j - 1]); amn[i][j] = min(amn[i][j - 1], amn[p][j - 1]); azn[i][j] = min(azn[i][j - 1], azn[p][j - 1]); } } for (int j = 1; j <= lg[m]; ++j) { for (int i = 1; i + (1 << j) - 1 <= m; ++i) { int p = i + (1 << (j - 1)); bmx[i][j] = max(bmx[i][j - 1], bmx[p][j - 1]); bmn[i][j] = min(bmn[i][j - 1], bmn[p][j - 1]); } } while (q--) { int la = read(), ra = read(), lb = read(), rb = read(); int sa = lg[ra - la + 1], sb = lg[rb - lb + 1]; int pa = ra - (1 << sa) + 1, pb = rb - (1 << sb) + 1; int amax = max(amx[la][sa], amx[pa][sa]); int amin = min(amn[la][sa], amn[pa][sa]); int afmx = max(afx[la][sa], afx[pa][sa]); int azmn = min(azn[la][sa], azn[pa][sa]); int bmax = max(bmx[lb][sb], bmx[pb][sb]); int bmin = min(bmn[lb][sb], bmn[pb][sb]); int ans = mininf; gmx(ans, amax * (amax >= 0 ? bmin : bmax)); gmx(ans, amin * (amin >= 0 ? bmin : bmax)); if (afmx != mininf) gmx(ans, afmx * (afmx >= 0 ? bmin : bmax)); if (azmn != maxinf) gmx(ans, azmn * (azmn >= 0 ? bmin : bmax)); printf("%lld\n", ans); } return 0; }如果觉得这篇题解写得好,请不要忘记点赞,谢谢!
- 1
信息
- ID
- 3175
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者