用 \(val\) 记录目前哪个位置还缺 \(1\)。每次枚举没有取过的数字,找到一个数 \(a[pos]\) 使 a[pos] & val
最大,表示有效位组成最大的数字 。然后取出来,并通过 val &= ~a[pos]
把 \(val\) 中对应的 \(1\) 删除(把 \(a[pos]\) 取反,原来的 \(1\) 现在都为 \(0\),然后与 \(val\) 就能删掉 \(val\) 对应的 \(1\)) 。最后把 \(a[pos]\) 交换到末尾的有效数字,实现逻辑删除 。
因为 int
有 \(31\) 位,每次删除删的是结果最大的,最多删除 \(31\) 次就能达到这个序列或的最大值 。
时间复杂度 \(O(n)\)
空间复杂度 \(O(n)\)
代码#include <bits/stdc++.h>#define ll long longusing namespace std;int a[200007];bool solve() {int n;cin >> n;for (int i = 1;i <= n;i++) cin >> a[i];int val = ~(1 << 31);for (int i = 1;i <= min(31, n);i++) {int pos = 1;for (int j = 1;j <= n - i + 1;j++) {if ((val & a[j]) > (val & a[pos])) pos = j;}cout << a[pos] << ' ';val &= ~a[pos];swap(a[n - i + 1], a[pos]);}for (int i = 1;i <= n - min(31, n);i++) cout << a[i] << ' ';cout << '\n';return true;}int main() {std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);int t = 1;cin >> t;while (t--) {if (!solve()) cout << -1 << '\n';}return 0;}
推荐阅读
- Div. 3 Codeforces Round #826 A-E
- Div. 3 Codeforces Round #828 A-F
- Div. 2 CF Round #829 题解
- Codeforces 1672 E. notepad.exe
- Div. 2 Codeforces Round #830 A-D
- Div. 2 Codeforces Round #829 A-E
- Div. 2 Codeforces Round #829 /CodeForces1754
- Div. 1/Div. 2 Codeforces Round #829 1753 A B C D 题解
- Rated for Div. 2 Educational Codeforces Round 137 A-F
- Codeforces 1682 D Circular Spanning Tree