1
0

CodeForces-888G.cpp 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. #include <algorithm>
  2. #include <array>
  3. #include <iostream>
  4. #include <limits>
  5. #include <vector>
  6. using namespace std;
  7. int main() {
  8. ios::sync_with_stdio(false);
  9. cin.tie(nullptr);
  10. int n; cin >> n;
  11. vector<int> a(n);
  12. for (int &x : a) cin >> x;
  13. sort(a.begin(), a.end()); a.erase(unique(a.begin(), a.end()), a.end());
  14. auto solve = [&](auto &&self, int left, int right, int bit) -> long long {
  15. if (right - left <= 1 || bit < 0) return 0;
  16. int middle = left;
  17. while (middle < right && ((a[middle] >> bit) & 1) == 0) ++middle;
  18. long long answer = self(self, left, middle, bit - 1) + self(self, middle, right, bit - 1);
  19. if (middle == left || middle == right) return answer;
  20. int build_l = left, build_r = middle, query_l = middle, query_r = right;
  21. if (build_r - build_l > query_r - query_l) {
  22. swap(build_l, query_l); swap(build_r, query_r);
  23. }
  24. vector<array<int, 2>> trie(1, array<int, 2>{-1, -1});
  25. trie.reserve(static_cast<size_t>(build_r - build_l) * (bit + 1) + 1);
  26. for (int i = build_l; i < build_r; ++i) {
  27. int node = 0;
  28. for (int b = bit - 1; b >= 0; --b) {
  29. int digit = (a[i] >> b) & 1;
  30. if (trie[node][digit] == -1) {
  31. trie[node][digit] = static_cast<int>(trie.size());
  32. trie.push_back({-1, -1});
  33. }
  34. node = trie[node][digit];
  35. }
  36. }
  37. int best = numeric_limits<int>::max();
  38. for (int i = query_l; i < query_r; ++i) {
  39. int node = 0, cost = 0;
  40. for (int b = bit - 1; b >= 0; --b) {
  41. int digit = (a[i] >> b) & 1;
  42. if (trie[node][digit] != -1) node = trie[node][digit];
  43. else cost |= 1 << b, node = trie[node][digit ^ 1];
  44. }
  45. best = min(best, cost);
  46. }
  47. return answer + (1LL << bit) + best;
  48. };
  49. cout << solve(solve, 0, static_cast<int>(a.size()), 29) << '\n';
  50. }