小蓝有一棵树,树中包含 N 个节点编号为 0 , 1 , 2 ,……, N 一 1 ,其中每个结点上都有一个整数。他可以从树中任意选择两个不直接相连的结点 a 、 b 并获得分数,其中表示按位异或操作。
请问小蓝可以获得的最大分数是多少 ?
输入格式:
输入的第一行包含一个整数 N, 表示有 N 个结点。
第二行包含 N 个整数, ,…… ,, 相邻整数之间使用一个空格分隔。
第三行包含 N 个整数, ,…… ,, 相邻整数之间使用一个空格分隔,其中第i个整数表示i的父结点编号, 表示结点i没有父结点。
输出格式:
输出一行包含一个整数表示答案。
样例
Example
输入:
5
1 0 5 3 4
-1 0 1 0 1
输出:
7
思路
两个节点(数)的异或最大值,容易想到0-1字典树。但是题目要求两个节点不能相连,因此将每个节点相邻的节点记录下来,并在查询当前节点时先将相邻节点删掉,计算完后再添加回去。
答案
Java
import java.util.*;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
static final class Trie {
static final int BITS = 31;
static int[][] tree = new int[N * BITS][2];
static int[] cnt = new int[N * BITS];
static int total = 1;
void insert(int x) {
int u = 1;
for (int i = BITS; i >= 0; i--) {
int bit = (x >> i) & 1;
if (tree[u][bit] == 0) {
tree[u][bit] = ++total;
}
u = tree[u][bit];
cnt[u]++;
}
}
void remove(int x) {
int u = 1;
for (int i = BITS; i >= 0; i--) {
int bit = (x >> i) & 1;
u = tree[u][bit];
cnt[u]--;
}
}
int queryMaxXor(int x) {
int u = 1, res = 0;
for (int i = BITS; i >= 0; i--) {
int bit = (x >> i) & 1;
if (tree[u][bit ^ 1] != 0 && cnt[tree[u][bit ^ 1]] > 0) {
res |= (1 << i);
u = tree[u][bit ^ 1];
} else {
u = tree[u][bit];
}
}
return res;
}
}
static int N = (int) (1e5 + 10);
static int n;
static int[] x = new int[N];
static int f;
static List<Integer>[] neighbors = new List[N];
static Trie root = new Trie();
static int ans;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
for (int i = 0; i < n; i++) {
neighbors[i] = new ArrayList<>();
}
for (int i = 0; i < n; i++) {
x[i] = scan.nextInt();
root.insert(x[i]);
}
for (int i = 0; i < n; i++) {
f = scan.nextInt();
if (f != -1) {
neighbors[i].add(f);
neighbors[f].add(i);
}
}
scan.close();
for (int i = 0; i < n; i++) {
for (Integer j : neighbors[i]) {
root.remove(x[j]);
}
ans = Math.max(ans, root.queryMaxXor(x[i]));
for (Integer j : neighbors[i]) {
root.insert(x[j]);
}
}
System.out.println(ans);
}
}