早就听过用字典树求异或最大值,然而没做过。发现一碰到异或的题就GG,而且因为以前做过的一道类似的题(事实上并不类似)限制了思路,蠢啊= =。
题意:一棵带权的树,求任意两点间路径异或的最大值。
题解:设xor(a,b)是求a,b间路径的异或值,那么xor(a,b)=xor(root,a)^xor(root,b)。因为如果LCA(a,b)==root时结论显然成立,不然的话就会有重复走过的部分,但是异或有性质x^x=0,所以LCA(a,b)!=root结论依然成立。
这样题目就很简单了。对每一个xor(root,i)(0<i<n)建立trie,然后对每一个xor(root,i)在trie查询最大值就好了。
#include <vector> #include <list> #include <map> #include <set> #include <queue> #include <stack> #include <bitset> #include <algorithm> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <cstring> #define pk printf("lalala"); #define ppp(x) printf("%d\n", x) using namespace std; #define PI acos(-1.0) #define EXP exp(1.0) #define EPS 1E-6 #define clr(x,c) memset(x,c,sizeof(x)) const int KIND = 2; const int MAXN = 5000005; const int N = 100005; int cnt_node; struct node{ node* nt[KIND]; void init(){ memset(nt, 0, sizeof(nt)); } } Heap[MAXN]; node *root; int Xor[N]; inline node* new_node() { Heap[cnt_node].init(); return &Heap[cnt_node++]; } void insert(node* root, int *str) { for(int i = 0; i <= 30; ++i){ int ch = str[i]; if(root->nt[ch] == NULL) root->nt[ch] = new_node(); root = root->nt[ch]; } } int count(node* root, int *str) { int ans = 0; for(int i = 0; i <= 30; ++i){ int ch = str[i]; int need = (ch ^ 1); if(root->nt[need] == NULL) { root = root->nt[ch]; } else { root = root->nt[need]; ans += (1 << (30 - i)); } } return ans; } struct Edge { int to; int w; int next; } edge[N * 2]; int cnt_edge; int head[N]; void add_edge(int u, int v, int w) { edge[cnt_edge].to = v; edge[cnt_edge].w = w; edge[cnt_edge].next = head[u]; head[u] = cnt_edge++; } void dfs(int u, int fa, int val) { Xor[u] = val; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; int w = edge[i].w; if (v == fa) continue; dfs(v, u, val^w); } } int str[N][40]; int main() { int n; while (~scanf("%d",&n)) { clr(head, -1); cnt_edge = 0; cnt_node = 0; root = new_node(); int u, v, w; for (int i = 1; i < n; ++i) { scanf("%d%d%d",&u, &v, &w); add_edge(u, v, w); add_edge(v, u, w); } dfs(0, -1, 0); //for (int i = 0; i < n; ++i) printf("%d ", Xor[i]); printf("\n"); int ans = 0; for (int i = 0; i < n; ++i) { int idx = 0; for (int b = 30; b >= 0; --b) { str[i][idx++] = Xor[i] & (1 << b) ? 1 : 0; } //for (int j = 0; j < idx; ++j) printf("%d ", str[i][j]); printf("\n"); insert(root, str[i]); } for (int i = 0; i < n; ++i) { ans = max(ans, count(root, str[i])); } printf("%d\n", ans); } return 0; }
时间: 2024-11-06 15:18:13