fork download
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. const int limN = 2e5 + 5;
  5. const int MAX_NODES = 12500005;
  6. const long long INF = 4e18;
  7.  
  8. int child[MAX_NODES][2];
  9. int c1[MAX_NODES], c2[MAX_NODES];
  10. int id1[MAX_NODES], id2[MAX_NODES];
  11. int nnode = 0;
  12.  
  13. inline int new_node() {
  14. int u = ++nnode;
  15. child[u][0] = child[u][1] = 0;
  16. c1[u] = c2[u] = id1[u] = id2[u] = 0;
  17. return u;
  18. }
  19.  
  20. inline void add(int u, int c, int id) {
  21. if (!c1[u]) {
  22. c1[u] = c;
  23. id1[u] = id;
  24. }
  25. else if (c1[u] != c && !c2[u]) {
  26. c2[u] = c;
  27. id2[u] = id;
  28. }
  29. }
  30.  
  31. inline bool check(int u, int c) {
  32. if (!u) return false;
  33. if (c1[u] != c) return true;
  34. return c2[u] != 0;
  35. }
  36.  
  37. inline int other(int u, int c) {
  38. if (c1[u] != c) return id1[u];
  39. return id2[u];
  40. }
  41.  
  42. inline void insert(int root, long long val, int c, int id) {
  43. int u = root;
  44. add(u, c, id);
  45. for (int i = 30; i >= 0; --i) {
  46. int bit = (val >> i) & 1;
  47. if (!child[u][bit])
  48. child[u][bit] = new_node();
  49.  
  50. u = child[u][bit];
  51. add(u, c, id);
  52. }
  53. }
  54.  
  55. inline int get(int root, long long val, int c) {
  56. int u = root;
  57. for (int i = 30; i >= 0; --i) {
  58. int bit = (val >> i) & 1;
  59.  
  60. int x = child[u][bit];
  61. if (x && check(x, c)) u = x;
  62. else u = child[u][!bit];
  63. }
  64. return other(u, c);
  65. }
  66.  
  67. struct DSU {
  68. vector<int> lab;
  69. DSU(int n) : lab(n + 1, -1) {}
  70.  
  71. int find(int u) {
  72. return lab[u] < 0 ? u : lab[u] = find(lab[u]);
  73. }
  74.  
  75. bool unite(int u, int v) {
  76. u = find(u); v = find(v);
  77. if (u == v) return false;
  78. if (lab[u] > lab[v]) swap(u, v);
  79. lab[u] += lab[v]; lab[v] = u;
  80. return true;
  81. }
  82. };
  83.  
  84. struct Edge {
  85. long long w;
  86. int u, v;
  87. };
  88.  
  89. int n, comp[limN];
  90. long long a[limN], b[limN], k;
  91. Edge best[limN];
  92.  
  93. void solve() {
  94. cin >> n >> k;
  95. for (int i = 1; i <= n; ++i) {
  96. cin >> a[i];
  97. b[i] = a[i] + k;
  98. }
  99.  
  100. DSU dsu(n);
  101. long long ans = 0;
  102. int numcomp = n;
  103.  
  104. vector<Edge> tmp;
  105. tmp.reserve(n);
  106.  
  107. while (numcomp > 1) {
  108. nnode = 0;
  109. int A = new_node(), B = new_node();
  110.  
  111. for (int i = 1; i <= n; ++i) {
  112. comp[i] = dsu.find(i);
  113. insert(A, a[i], comp[i], i);
  114. insert(B, b[i], comp[i], i);
  115. best[i] = {INF, -1, -1};
  116. }
  117.  
  118. for (int i = 1; i <= n; ++i) {
  119. int c = comp[i];
  120.  
  121. int v1 = get(B, a[i], c);
  122. long long w1 = a[i] ^ b[v1];
  123. if (w1 < best[c].w)
  124. best[c] = {w1, i, v1};
  125.  
  126. int v2 = get(A, b[i], c);
  127. long long w2 = b[i] ^ a[v2];
  128. if (w2 < best[c].w)
  129. best[c] = {w2, i, v2};
  130. }
  131.  
  132. tmp.clear();
  133. for (int i = 1; i <= n; ++i) {
  134. if (comp[i] == i && best[i].w != INF) {
  135. tmp.push_back(best[i]);
  136. }
  137. }
  138.  
  139. bool ok = false;
  140. for (const Edge &it : tmp) {
  141. if (dsu.unite(it.u, it.v)) {
  142. ans += it.w;
  143. --numcomp;
  144. ok = true;
  145. }
  146. }
  147.  
  148. if (!ok) break;
  149. }
  150.  
  151. cout << ans << "\n";
  152. }
  153.  
  154. int main() {
  155. ios::sync_with_stdio(false), cin.tie(nullptr);
  156.  
  157. solve();
  158. return 0;
  159. }
  160.  
Success #stdin #stdout 0s 5320KB
stdin
Standard input is empty
stdout
0