Description
In an edge-weighted tree, the xor-length of a path p is defined as the xor sum of the weights of edges on p:
(you ren kan ti ma? xian ran mei you. na wo jiu bu tie tu le.)
⊕ is the xor operator.
We say a path the xor-longest path if it has the largest xor-length. Given an edge-weighted tree with n nodes, can you find the xor-longest path?
Input
The input contains several test cases. The first line of each test case contains an integer n(1<=n<=100000), The following n-1 lines each contains three integers u(0 <= u < n),v(0 <= v < n),w(0 <= w < 2^31), which means there is an edge between node u and v of length w.
Output
For each test case output the xor-length of the xor-longest path.
Sample Input
4
0 1 3
1 2 4
1 3 6
Sample Output
7
题意
给出 1 棵树,询问树链上的最大连续异或和。
题解
利用异或和的性质可以得出求出dis(前缀异或和)后可以用神奇的性质求解答案(……)。这里用了指针和数组两种方法写的trie树。
代码1
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 400010;
int n, num, ans, tot, dis[N], head[N];
struct Trie {
int child[2];
void newnode() {
child[0] = 0, child[1] = 0;
}
} trie[N << 3];
struct Edge {
int v, next, w;
} edge[N << 3];
void add(int u, int v, int w) {
num ++;
edge[num].v = v;
edge[num].w = w;
edge[num].next = head[u];
head[u] = num;
}
void insert(int now) {
int root = 0, p;
for(int i = 30; i >= 0; i --) {
if(now & (1 << i)) p = 1;
else p = 0;
if(! trie[root].child[p]) {
trie[root].child[p] = ++ tot;
trie[tot].newnode();
}
root = trie[root].child[p];
}
}
void dfs(int u, int f, int w) {
dis[u] = w;
for(int i = head[u]; i; i = edge[i].next) {
int v = edge[i].v;
if(f == v) continue;
dfs(v, u, w^edge[i].w);
}
}
int query(int now) {
int p, ans = 0, root = 0;
for(int i = 30; i >= 0; i --) {
if(now & (1 << i)) p = 0;
else p = 1;
if(trie[root].child[p]) {
ans |= (1 << i);
root = trie[root].child[p];
}
else root = trie[root].child[! p];
}
return ans;
}
void clear() {
trie[0].newnode();
ans = -1, num = 0, tot = 0;
memset(dis, 0, sizeof(dis));
memset(trie, 0, sizeof(trie));
memset(head, 0, sizeof(head));
}
int main() {
while(scanf("%d", &n) != EOF){
clear();
for(register int i = 1; i < n; i ++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
add(u, v, w);
add(v, u, w);
}
dfs(0, -1, 0);
for(register int i = 0; i < n; i ++) {
ans = max(ans, query(dis[i]));
insert(dis[i]);
}
printf("%d\n", ans);
}
return 0;
}
代码2
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1000010;
int n, num, ans = 0, dis[N], head[N << 3];
struct Trie {
Trie *child[2];
} pool[N << 3], *tail = pool, *root;
struct Edge {
int v, next, w;
} edge[N << 3];
Trie *newtrie() {
Trie *node = ++ tail;
node -> child[0] = NULL, node -> child[1] = NULL;
return node;
}
void add(int u, int v, int w) {
num ++;
edge[num].v = v;
edge[num].w = w;
edge[num].next = head[u];
head[u] = num;
}
void insert(int now) {
Trie *node = root;
int p;
for(int i = 30; i >= 0; i --) {
if(now & (1 << i)) p = 1;
else p = 0;
if(node -> child[p] == NULL)
node -> child[p] = newtrie();
node = node -> child[p];
}
}
void dfs(int u, int f, int w) {
dis[u] = w;
for(int i = head[u]; i; i = edge[i].next) {
int v = edge[i].v;
if(f == v) continue;
dfs(v, u, w^edge[i].w);
}
}
int query(int now) {
Trie *node = root;
int ans = 0, p;
for(int i = 30; i >= 0; i --) {
if(now & (1 << i)) p = 0;
else p = 1;
if(node -> child[p] != NULL) {
ans |= (1 << i);
node = node -> child[p];
}
else if(node -> child[p ^ 1] != NULL)
node = node -> child[p ^ 1];
else return 0;
}
return ans;
}
void clear() {
delete tail;
delete root;
ans = 0, num = 0;
memset(dis, 0, sizeof(dis));
memset(head, 0, sizeof(head));
}
int main() {
while(scanf("%d", &n) != EOF){
clear();
root = newtrie();
for(register int i = 1; i < n; i ++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
add(u, v, w);
add(v, u, w);
}
dfs(0, -1, 0);
for(register int i = 0; i < n; i ++) {
ans = max(ans, query(dis[i]));
insert(dis[i]);
}
printf("%d\n", ans);
}
return 0;
}