[ARC135C] XOR to All 题解
题意
给定 \(N\) 个非负整数 \(A_1, A_2, A_N\),定义每次操作如下:
-
选取一个数 \(x \in \{A_!, A_2, \cdots, A_N\}\)。
-
对于所有的 \(1 \le i \le N\),进行 \(A_i \leftarrow A_i \oplus x\)。
你可以进行若干次操作(可以不进行操作),最大化 \(\sum\limits_{i = 1}^{N}A_i\)。
(\(1 \le N \le 3 \times 10^5\))
题解
首先,设初始序列为 \(A\),进行过任意次操作后的序列为 \(B\)。
对于一次操作,设我们这次选取的数为 \(B_i\),我们考察本次操作对其他整数(\(i \neq j\))的影响。
由于在这次操作前可能会进行其他操作,所以 \(B_i\) 和 \(B_j\) 实际上可以表达为 \(A_i \oplus x\) 和 \(A_j \oplus x\),那么我们完成操作后,有
\[B_j \leftarrow B_i \oplus B_j = (A_i \oplus x) \oplus (A_j \oplus x) = A_i \oplus A_j
\]
所以我们可以得出结论:在多次操作的过程中,最后一次操作会将之前的所有操作的影响撤销。也就是说,我们最多只需要操作一次即可。
下面我们讨论如何操作使得最终的和最大,考虑按二进制位考虑当前操作对总和的影响,所以我们可以预处理出二进制下每一位原序列中为 \(1\) 的数的个数,然后遍历序列,计算出选取当前数对答案的影响即可。
总复杂度 \(\mathcal{O}(N \log A)\),可以通过本题。
Code
#include <bits/stdc++.h>
typedef long long valueType;
typedef std::vector<valueType> ValueVector;
constexpr valueType MAXB = 31;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
valueType N;
std::cin >> N;
ValueVector A(N);
for (auto &iter: A)
std::cin >> iter;
ValueVector B(MAXB, 0);
for (auto const &iter: A) {
for (valueType i = 0; i < MAXB; ++i) {
if (iter & (1 << i))
--B[i];
else
++B[i];
}
}
valueType const base = std::accumulate(A.begin(), A.end(), (valueType) 0);
valueType ans = base;
for (auto const &iter: A) {
valueType sum = 0;
for (valueType i = 0; i < MAXB; ++i)
if (iter & (1 << i))
sum += B[i] * (1 << i);
ans = std::max(ans, base + sum);
}
std::cout << ans << std::endl;
return 0;
}