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 as well as some bit (, ). Partition the subarray into two sets and , where contains all elements with bit set, and contains other elements. We will be assuming that is the first different bit; that is, all elements in the subarray have the same bits for all bits greater than .
Because is the first different bit and because the array is sorted, contains some prefix of the subarray and contains some suffix. That is to say, and for some .
Lemma: In a minimum xor spanning tree, there is exactly 1 edge between an element in and an element in .
Proof: By definition, a spanning tree must connect all vertices, which implies the existence of at least 1 edge between and . Assume there is two edges between and , with endpoints and respectively, where and . The tree is constructed in one of the following ways, where solid lines represent edges and dashed lines represent paths.
Without loss of generality, disconnect . The spanning tree becomes disconnected, with either or in the component that does not contain and . It is always more optimal to connect this node to the corresponding edge node. That is, if is not in the same component as , then an edge between and will always be better than one between and .
By definition, and share a bit , so the xor of their values does not contain bit , whereas always contains . Note that this implies that it is always better to connect to ; however, this configuration may not be optimal. The proof is analogous if instead is disconnected.
Thus, the divide and conquer algorithm will proceed as follows: We will partition the subarray into and . This step takes time. Note that if either or is empty (if all numbers in the range contain or if none of them contain ), we immediately recurse with the same subarray and as the bit. Next, we will choose an element from and an element with a minimum pairwise xor, and add this to the answer. Lastly, recursively run the algorithm on and with bit .
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 be the length of the array, and let be the value of an arbitrary element. There are levels of recursion, each containing exactly elements. Furthermore, each insertion/query in the trie takes time, since we have to traverse at most the number of distinct bits in . Combining this information, the total time complexity is .
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!