菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
476
0

poj3764 The xor-longest Path

原创
05/13 14:22
阅读数 11664

TRIE树的经典应用:最大XOR问题

要求一个数与一堆数之中的最大XOR值

我们把一堆数建立一个trie树(按照二进制),那么最大XOR就是从trie顶开始,每一步都试图逆着这个数走,即可求得。

求一堆数中的最大xor呢?

就是每次insert前ask一下,更新答案。

那么本题呢?

考虑选定一个根,那么xor(i, j) = xor(root, i) ^ xor(root, j)

因为a ^ a = 0, a ^ 0 = a。

对于i, j来说,lca以上的路径会被抵消掉。

这样就是求max(xor(root, i), xor(root, j))了。

这样我们就按照开头所述方法来处理xor(root, i)即可。

  1 #include <cstdio>
  2 #include <cstring>
  3 
  4 typedef long long LL;
  5 
  6 const int N = 1000010;
  7 
  8 int n;
  9 
 10 inline void max(LL &a, LL b) {
 11     if(a < b) a = b;
 12     return;
 13 }
 14 
 15 struct Trie {
 16     int s[N][2], top;
 17     inline void clear() {
 18         memset(s, 0, sizeof(s));
 19         top = 1;
 20         return;
 21     }
 22     inline void insert(LL k) {
 23         int p = 0;
 24         for(int i = 31; i >= 0; i--) {
 25             int f = (k >> i) & 1;
 26             if(!s[p][f]) {
 27                 s[p][f] = ++top;
 28             }
 29             p = s[p][f];
 30         }
 31         return;
 32     }
 33     inline LL maxor(LL k) {
 34         LL ans = 0;int p = 0;
 35         for(int i = 31; i >= 0; i--) {
 36             int f = !((k >> i) & 1);
 37             if(s[p][f]) {
 38                 p = s[p][f];
 39                 ans = (ans << 1) | 1;
 40             }
 41             else {
 42                 p = s[p][f ^ 1];
 43                 ans = ans << 1;
 44             }
 45         }
 46         return ans;
 47     }
 48 }trie;
 49 
 50 struct Edge {
 51     int v, nex;
 52     LL len;
 53 }edge[N]; int top;
 54 int e[N];
 55 LL val[N];
 56 bool vis[N];
 57 
 58 inline void add(int x, int y, LL z) {
 59     ++top;
 60     edge[top].v = y;
 61     edge[top].len = z;
 62     edge[top].nex = e[x];
 63     e[x] = top;
 64     return;
 65 }
 66 
 67 void DFS(int k, int now) {
 68     vis[k] = 1;
 69     val[k] = now;
 70     for(int i = e[k]; i; i = edge[i].nex) {
 71         int ed = edge[i].v;
 72         if(vis[ed]) continue;
 73         DFS(ed, now ^ edge[i].len);
 74     }
 75     return;
 76 }
 77 
 78 int main() {
 79     int x, y;
 80     LL z;
 81     while(scanf("%d", &n) != EOF) {
 82         trie.clear();
 83         top = 0;
 84         memset(e, 0, sizeof(e));
 85         memset(vis, 0, sizeof(vis));
 86 
 87         for(int i = 1; i < n; i++) {
 88             scanf("%d%d%lld", &x, &y, &z);
 89             x++;
 90             y++;
 91             add(x, y, z);
 92             add(y, x, z);
 93         }
 94         DFS(1, 0);
 95 
 96         LL ans = -1;
 97         for(int i = 1; i <= n; i++) {
 98             max(ans, trie.maxor(val[i]));
 99             trie.insert(val[i]);
100         }
101         printf("%lld\n", ans);
102     }
103 
104 
105     return 0;
106 }
AC代码

 

发表评论

0/200
476 点赞
0 评论
收藏
为你推荐 换一批