ARC100E Or Plus Max 题解

原题传送门

题目描述

有一个长度为 \(2^N\) 的整数序列 \(A_0,\ A_1,\ ...,\ A_{2^N-1}\)。(注意下标从 \(0\) 开始)
对于所有满足 \(1\leq K\leq 2^N-1\) 的整数 \(K\),请解决以下问题:

  • \(i,j\) 为整数,满足 \(0\leq i<j\leq 2^N-1\),且 \((i\ \text{or}\ j)\leq K\),求 \(A_i+A_j\) 的最大值。这里 \(\mathrm{or}\) 表示按位或运算。
    \(1 \le n \le 18, 1 \le A_i \le 10^9\)

思路

考虑对于每个 \(k\) 计算出其答案。显然对于 \(k\),其答案为 \(\max\limits_{t = 1}^k\max\limits_{i \,\mathrm{or}\, j = t, i \neq j} A_i + A_j\)
我们可以把每个 \(i\) 看作一个集合,那么显然我们有 \(i \ \mathrm{or} \ j = k \Rightarrow i \subseteq k \land j \subseteq k\)\(i \ \mathrm{or} \ j \le k \Leftrightarrow i \subseteq k \land j \subseteq k\)
因此对于每一个 \(k\),答案可以化为 \(\max\limits_{t = 1}^k\left(\max\limits_{i \subseteq t} A_i + \max\limits_{j \subseteq t, i \neq j} A_j\right)\)。正确性显然。
考虑高维前缀和(SOSDP)。我们只需要维护最大值和非严格的第二大值即可。

#include <bits/stdc++.h>
#define endl '\n'
#define int long long
const int inf = 2e9;
const int N = 20;
int n, h[1 << N];
struct node {
  int mx, se;
  node operator+(const node y) const {
    node ret;
    if (mx >= y.mx) ret.mx = mx, ret.se = std::max(se, y.mx);
    if (mx < y.mx) ret.mx = y.mx, ret.se = std::max(mx, y.se);
    return ret;
  }
} a[1 << N];
int ans = -inf;
signed main() {
  std::cin.tie(nullptr)->sync_with_stdio(false);
  std::cin >> n;
  for (int i = 0; i < (1 << n); i++)
    std::cin >> h[i], a[i].mx = h[i], a[i].se = -inf;
  for (int k = 0; k < n; k++)
    for (int i = 0; i < (1 << n); i++)
      (i & (1 << k)) && (a[i] = a[i] + a[i ^ (1 << k)], 1);
  for (int i = 1; i < (1 << n); i++) {
    ans = std::max(ans, a[i].mx + a[i].se);
    std::cout << ans << endl;
  }
  return 0;
}
posted @ 2025-08-25 13:48  Terminal_P  阅读(8)  评论(0)    收藏  举报