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;
}

浙公网安备 33010602011771号