Table of Contents

SolutionImplementation

Solution

The Official Editorial uses a solution with Boruvka's Algorithm. There is a simpler solution using divide and conquer.

Firstly, note that because there is essentially an edge between any pair of nodes, the values of the nodes themselves can be considered unordered. Thus, the answer will not change if we sort the elements.

Secondly, note that duplicate elements can be removed. This is because duplicate elements can be connected with an edge of 0 cost.

After these two steps, we have obtained a sorted array with no duplicates whose answer is the same as the original problem.

Now consider some subarray [l,r][l, r] as well as some bit bb (0lr<N0 \leq l \leq r < N, 0b<300 \leq b < 30). Partition the subarray into two sets LL and RR, where RR contains all elements with bit bb set, and LL contains other elements. We will be assuming that bb is the first different bit; that is, all elements in the subarray have the same bits for all bits greater than bb.

Because bb is the first different bit and because the array is sorted, LL contains some prefix of the subarray and RR contains some suffix. That is to say, L=A[l:m1]L = A[l:m - 1] and R=[m:r]R = [m : r] for some l<mrl < m \leq r.

Lemma: In a minimum xor spanning tree, there is exactly 1 edge between an element in LL and an element in RR.

Proof: By definition, a spanning tree must connect all vertices, which implies the existence of at least 1 edge between LL and RR. Assume there is two edges between LL and RR, with endpoints (l1,r1)(l_1, r_1) and (l2,r2)(l_2, r_2) respectively, where l1,l2Ll_1, l_2 \in L and r1,r2Rr_1, r_2 \in R. The tree is constructed in one of the following ways, where solid lines represent edges and dashed lines represent paths.

double1

double2

Without loss of generality, disconnect (l2,r2)(l_2, r_2). The spanning tree becomes disconnected, with either l2l_2 or r2r_2 in the component that does not contain l1l_1 and r1r_1. It is always more optimal to connect this node to the corresponding edge node. That is, if l2l_2 is not in the same component as l1l_1, then an edge between l1l_1 and l2l_2 will always be better than one between l2l_2 and r2r_2.

single

By definition, l1l_1 and l2l_2 share a bit bb, so the xor of their values does not contain bit bb, whereas l2 xor r2l_2 \texttt{ xor } r_2 always contains bb. Note that this implies that it is always better to connect l2l_2 to l1l_1; however, this configuration may not be optimal. The proof is analogous if instead r2r_2 is disconnected. \blacksquare

Thus, the divide and conquer algorithm will proceed as follows: We will partition the subarray into LL and RR. This step takes O(n)\mathcal{O}(n) time. Note that if either LL or RR is empty (if all numbers in the range contain bb or if none of them contain bb), we immediately recurse with the same subarray and b1b - 1 as the bit. Next, we will choose an element from LL and an element RR with a minimum pairwise xor, and add this to the answer. Lastly, recursively run the algorithm on LL and RR with bit b1b - 1.

How do we find two values such that their xor is minimized? One way to do this efficiently is with a trie. In the trie, each number is represented as a string of its binary representation, starting with the most significant digit and ending with the least. For xor queries, we can do a greedy traversal from root to leaf. When a transition exists that corresponds to the current bit of the query number, we greedily take that transition; otherwise, we are forced to take the unoptimal transition, and add the weight of that bit to the answer.

Implementation

Time Complexity: Let nn be the length of the array, and let aa be the value of an arbitrary element. There are loga30\log a \approx 30 levels of recursion, each containing exactly nn elements. Furthermore, each insertion/query in the trie takes O(loga)\mathcal{O}(\log a) time, since we have to traverse at most the number of distinct bits in aa. Combining this information, the total time complexity is O(nlog2a)\mathcal{O}(n \log^2 a).

C++

#include <bits/stdc++.h>
using namespace std;
const long long INF = 2000000011;
int N;
long long A[200005];
namespace Trie {
struct Node {

Join the USACO Forum!

Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!