CSP-S 2022 策略游戏

RMQ,贪心

因为 \(-10^9 \leq A_i, B_i \leq 10^9\),而且要相乘,所以我们需要分类讨论。

\(\max_1, \min_1\) 表示正整数的最大值、最小值,\(\max_2, \min_2\) 表示负整数的最大值、最小值。

分类讨论,则

A 选 B 选
\(\max_1 A, \min_1 A\) \(\min_1 B, \min_2 B\)
\(\max_2 A, \min_2 A\) \(\max_1 B, \max_2 B\)

B 选中优先选择第一个,如果不存在考虑第二个。思考后可得 \(0\) 在这里既要算作正整数,也要算作负整数。

为了让代码更简单,可以把这四个值记录下来,分别记作 \(X_i, Y_i\)\(4 \times 4\) 枚举一遍,则答案为 \(\max \min {X_i \times Y_j}\)。注意,不存在的情况不能计算。

使用线段树实现或 ST 表实现,时间复杂度都为 \(O(n \log n)\)。(考虑到 \(n, m, q\) 上限相同)

#include <bits/stdc++.h>

typedef long long LL;
const int N = 100005, inf = 2e9;

struct Info {
  int l, r;
  int pmax, pmin; // 正数
  int qmax, qmin; // 负数
};

int A[N], B[N];

struct SegmentTree {
  Info t[N * 4];
  bool ini;
  void init(int x) {
    ini = x;
  }
#define lson p * 2
#define rson p * 2 + 1
  void pushup(int p) {
    t[p].pmax = std::max(t[lson].pmax, t[rson].pmax);
    t[p].pmin = std::min(t[lson].pmin, t[rson].pmin);
    t[p].qmax = std::max(t[lson].qmax, t[rson].qmax);
    t[p].qmin = std::min(t[lson].qmin, t[rson].qmin);
  }
  void build(int p, int l, int r) {
    t[p].l = l, t[p].r = r;
    if (l == r) {
      int x = ini ? A[l] : B[l];
      if (x >= 0) {
        t[p].pmax = x, t[p].pmin = x;
        t[p].qmax = -inf, t[p].qmin = inf;
      }
      if (x <= 0) {
        t[p].pmax = -inf, t[p].pmin = inf;
        t[p].qmax = x, t[p].qmin = x;
      }
      return;
    }
    int mid = (l + r) / 2;
    build(lson, l, mid);
    build(rson, mid + 1, r);
    pushup(p);
  }
  int queryPmax(int p, int l, int r) {
    if (l <= t[p].l && r >= t[p].r) return t[p].pmax;
    int mid = (t[p].l + t[p].r) / 2;
    int ans = -inf;
    if (l <= mid) ans = std::max(ans, queryPmax(lson, l, r));
    if (r > mid) ans = std::max(ans, queryPmax(rson, l, r));
    return ans;
  }
  int queryPmin(int p, int l, int r) {
    if (l <= t[p].l && r >= t[p].r) return t[p].pmin;
    int mid = (t[p].l + t[p].r) / 2;
    int ans = inf;
    if (l <= mid) ans = std::min(ans, queryPmin(lson, l, r));
    if (r > mid) ans = std::min(ans, queryPmin(rson, l, r));
    return ans;
  }
  int queryQmax(int p, int l, int r) {
    if (l <= t[p].l && r >= t[p].r) return t[p].qmax;
    int mid = (t[p].l + t[p].r) / 2;
    int ans = -inf;
    if (l <= mid) ans = std::max(ans, queryQmax(lson, l, r));
    if (r > mid) ans = std::max(ans, queryQmax(rson, l, r));
    return ans;
  }
  int queryQmin(int p, int l, int r) {
    if (l <= t[p].l && r >= t[p].r) return t[p].qmin;
    int mid = (t[p].l + t[p].r) / 2;
    int ans = inf;
    if (l <= mid) ans = std::min(ans, queryQmin(lson, l, r));
    if (r > mid) ans = std::min(ans, queryQmin(rson, l, r));
    return ans;
  }
#undef lson
#undef rson
} seg1, seg2;

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  int n, m, q;
  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];
  seg1.init(1);
  seg2.init(0);
  seg1.build(1, 1, n);
  seg2.build(1, 1, m);
  for (int i = 1; i <= q; i++) {
    int l1, r1, l2, r2;
    std::cin >> l1 >> r1 >> l2 >> r2;
    int X[4], Y[4];
    X[0] = seg1.queryPmax(1, l1, r1);
    X[1] = seg1.queryPmin(1, l1, r1);
    X[2] = seg1.queryQmax(1, l1, r1);
    X[3] = seg1.queryQmin(1, l1, r1);
    Y[0] = seg2.queryPmax(1, l2, r2);
    Y[1] = seg2.queryPmin(1, l2, r2);
    Y[2] = seg2.queryQmax(1, l2, r2);
    Y[3] = seg2.queryQmin(1, l2, r2);
    LL ans = -1e18;
    for (int i = 0; i < 4; i++) {
      if (X[i] == inf || X[i] == -inf)
        continue;
      LL res = 1e18;
      for (int j = 0; j < 4; j++) {
        if (Y[j] == inf || Y[j] == -inf)
          continue;
        res = std::min(res, 1ll * X[i] * Y[j]);
      }
      ans = std::max(ans, res);
    }
    std::cout << ans << '\n';
  }
  return 0;
}
posted @ 2024-10-04 15:30  Unino  阅读(49)  评论(0)    收藏  举报