1. 程式人生 > >Codeforces 888G Xor-MST - 分治 - 貪心 - Trie

Codeforces 888G Xor-MST - 分治 - 貪心 - Trie

order tro spa 集合 AD content names fine print

題目傳送門

  這是一條通往vjudge的高速公路

  這是一條通往Codeforces的高速公路

題目大意

  給定一個$n$階完全圖,每個點有一個權值$a_{i}$,邊$(i, j)$的權值是$(a_{i}\ xor\ a_{j})$。一個生成樹的權值是各邊的權值和。問最小生成樹的權值。  

  設值域為$[0, 2^{k})$。

  當$k = 1$的時候,顯然將點權為0的點之間互相連邊,點權為1的點之間互相連邊,中間隨便連一條。

  當$k = x\ (x > 1)$的時候,將這些點按照二進制的第$k$位分成兩個集合。因為這兩集合中間的點互相連邊,邊權的第$k$位會被消掉,於是變成了$k = x - 1$的子問題。

  假如得到了它們的最優解,那麽我只需要在兩個連通塊之間添加一條邊權最小的邊就行了。

  考慮怎麽找這樣一條邊。

  我可以把其中一個集合中數插入Trie樹,然後拿另一集合中的點的點權在Trie樹中查最小異或和。

Code

  1 /**
  2  * Codeforces
  3  * Problem#888G
  4  * Accepted
  5  * Time: 327ms
  6  * Memory: 49772k
  7  */
  8 #include <bits/stdc++.h>
  9 #ifndef WIN32
 10 #define
Auto "%lld" 11 #else 12 #define Auto "%I64d" 13 #endif 14 using namespace std; 15 typedef bool boolean; 16 17 #define ll long long 18 19 typedef class TrieNode { 20 public: 21 TrieNode* ch[2]; 22 23 TrieNode():ch({NULL, NULL}) { } 24 }TireNode;
25 26 TrieNode pool[6000000]; 27 TrieNode* top = pool; 28 29 TrieNode* newnode() { 30 top->ch[0] = top->ch[1] = NULL; 31 return top++; 32 } 33 34 typedef class Trie { 35 public: 36 TrieNode* rt; 37 38 Trie() { 39 top = pool; 40 rt = newnode(); 41 } 42 43 void insert(int x, int dep) { 44 int temp = 1 << dep, d; 45 TrieNode *p = rt; 46 while (temp) { 47 d = (temp & x) ? (1) : (0); 48 if (!p->ch[d]) 49 p->ch[d] = newnode(); 50 p = p->ch[d], temp = temp >> 1; 51 } 52 } 53 54 int query(int x, int dep) { 55 int temp = 1 << dep, rt = 0, d; 56 TrieNode *p = this->rt; 57 while (temp) { 58 d = (temp & x) ? (1) : (0); 59 if (p->ch[d]) 60 p = p->ch[d]; 61 else 62 p = p->ch[d ^ 1], rt |= temp; 63 temp = temp >> 1; 64 } 65 return rt; 66 } 67 }Trie; 68 69 int n; 70 int *ar; 71 Trie t; 72 73 inline void init() { 74 scanf("%d", &n); 75 ar = new int[(n + 1)]; 76 for (int i = 1; i <= n; i++) 77 scanf("%d", ar + i); 78 } 79 80 ll dividing(int dep, int l, int r) { 81 if (!dep) return ar[l] ^ ar[r]; 82 int tl = l, tr = r, mid, temp = 1 << dep, mincost = 1 << 30; 83 while (tl <= tr) { 84 mid = (tl + tr) >> 1; 85 if (ar[mid] & temp) 86 tr = mid - 1; 87 else 88 tl = mid + 1; 89 } 90 if (tr == l - 1 || tr == r) 91 return dividing(dep - 1, l, r); 92 t = Trie(); 93 for (int i = l; i <= tr; i++) 94 t.insert(ar[i], dep); 95 for (int i = tr + 1; i <= r; i++) 96 mincost = min(mincost, t.query(ar[i], dep)); 97 return mincost + dividing(dep - 1, l, tr) + dividing(dep - 1, tr + 1, r); 98 } 99 100 inline void solve() { 101 sort(ar + 1, ar + n + 1); 102 printf(Auto"\n", dividing(29, 1, n)); 103 } 104 105 int main() { 106 init(); 107 solve(); 108 return 0; 109 }

Codeforces 888G Xor-MST - 分治 - 貪心 - Trie