E - Set Meal

· · 个人记录

Description

给定 n 个数 a_im 个数 b_i。再给定 q 个关键对 (c_i, d_i)。请你找到一个非关键对 (x_i, y_i),使得 a_{x_i} + b_{y_i} 最大。求最大的 a_{x_i} + b_{y_i}

## Solution 首先将 $b$ 从大到小排序,然后统计对于每个 $a_i$ 而言,那些 $b_j$ 与它构成关键对。这里可以用 $\text {vector}$ 存储。 然后我们枚举 $a_i$,现在我们想找到一个位置 $j$,使得 $(i, j)$ 不为关键对且 $b_j$ 最大。因为我们已经将 $b$ 从大到小 排序了,所以只需要找到最小的 $j$ 即可。 又因为我们在前面统计了每个与 $i$ 有关的关键对,不妨令其为 $v_i$(这是一个 $\text {vector}$),那么实际上就是要找到最小的不在 $v_i$ 中出现的数。这本质上就是从 $1$ 开始的 $\operatorname{mex}$ 值。 我们可以直接暴力去求它。比如对于这样一个 $v_i$ 而言: $$ v_i = \{1, 2, 3, 5, 6, \dots\} $$ 可以发现这个 $v_i$ 已经从小到大排序了。其中 $v_{i, 3}$ 的值为 $3$,那么就代表 $1, 2, 3$ 一定都出现过。可是 $v_{i, 4}$ 的值并不为 $4$,也就是说在这个 $v_i$ 中 $4$ 没有出现过。因为我们是从小到大枚举的,所以 $4$ 就是这个序列的伪 $\operatorname{mex}$ 值。 因此我们首先要对每个 $v_i$ 中的元素从小到大排序,然后暴力求解即可。可以发现这样暴力计算的复杂度为 $\Theta\left(\sum \text{size of }(v_i)\right) = \Theta (q)$。 ## Code ```cpp int n, m, q, a[N]; PII b[N]; int now[N]; vector<int> v[N]; int res; signed main() { n = read(), m = read(), q = read(); fup (i, 1, n) a[i] = read(); fup (i, 1, m) b[i] = {read(), i}; sort(b + 1, b + m + 1, [&](PII x, PII y) { return x.fi > y.fi; }); fup (i, 1, m) now[b[i].se] = i; fup (i, 1, q) { int x = read(), y = read(); v[x].push_back(y); } fup (i, 1, n) { for (auto &j : v[i]) j = now[j]; sort(v[i].begin(), v[i].end()); } fup (i, 1, n) { int j = 0; for (; j < v[i].size(); ++ j ) if (v[i][j] != j + 1) break; ++ j; res = Max(res, a[i] + b[j].fi); } wel(res); return 0; } ```