[ARC135C] XOR to All 题解

题意

给定 \(N\) 个非负整数 \(A_1, A_2, A_N\),定义每次操作如下:

  1. 选取一个数 \(x \in \{A_!, A_2, \cdots, A_N\}\)

  2. 对于所有的 \(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;
}
posted @ 2023-09-28 08:17  User-Unauthorized  阅读(8)  评论(0编辑  收藏  举报