E: Or Plus Max - AtCoder Regular Contest 100
K番目の解をanswer(K)と表すことにする。
とおくと が解。
f(x)の条件の部分をもう少し緩くしてみる。
とおくと、後者の(i, j)の集合は、前者のそれを含むので が成り立つ。更に、 のときが成り立つ。したがって以下が成り立つ。
g(x)が簡単に求まるとしてanswer(K)は
g(x)の求め方を考えてみよう。和を最大にするには、であるようなA[i]について大きい方から2個を選んで使えばいい。そのためには、単にxの部分集合を列挙しながら2値を更新していく。部分集合の列挙は計算量3Nなので間に合う。ただし、定数倍が厳しいので注意。2値の更新を雑に書いたらTLEした。あと出力が多いのでprintfを使ってもいいかも。
auto upd = [](pii &a, int x) { if (x > a.second) { a.second = x; if (a.first < a.second)swap(a.first, a.second); } }; int N; cin >> N; int M = 1 << N; vi A(M); rep(i, M) cin >> A[i]; int re = 0; FOR(S, 1, M) { pii ma(0, 0); int T = S; do { upd(ma, A[T]); T = (T - 1)&S; } while (S != T); smax(re, ma.first + ma.second); cout << re << endl; }