在已有的两篇题解中都是对于$ A_i $中的每一个数,做一次search,search的方法是优先往当前位置的相反方向走。
实际上,我们可以直接在字典树上进行DFS,通过两个指针一开始都指向根节点,接着优先往相反方向走,也可以解决这个问题(而且好像还更快一点?前者144ms,后者112ms)
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAX_N = 100000 * 32 + 5;
namespace Trie {
int trie[MAX_N][2], tot = 1;
bool bit[32], end[MAX_N];
void insert(int x) {
for (int i = 31; i >= 0; --i) {
bit[i] = (x & 1);
x >>= 1;
}
int p = 1;
for (int i = 0; i < 32; ++i) {
bool c = bit[i];
if (trie[p][c] == 0) trie[p][c] = ++tot;
p = trie[p][c];
}
end[p] = 1;
}
bool u[32], v[32];
LL maxAns = -1;
int uPos = 0, vPos = 0;
void dfs(int pu, int pv) {
if (uPos == 32) {
LL t = 0;
for (int i = 0; i < 32; ++i) {
t <<= 1;
t ^= (u[i] ^ v[i]);
}
// printf("t = %lld\n", t);
maxAns = max(maxAns, t);
return;
}
bool diff = false;
if (trie[pu][0] && trie[pv][1]) {
// puts("1");
diff = true;
u[uPos++] = 0; v[vPos++] = 1;
dfs(trie[pu][0], trie[pv][1]);
--uPos; --vPos;
}
if (trie[pu][1] && trie[pv][0]) {
// puts("2");
diff = true;
u[uPos++] = 1; v[vPos++] = 0;
dfs(trie[pu][1], trie[pv][0]);
--uPos; --vPos;
}
if (diff) return;
if (trie[pu][0] && trie[pv][0]) {
// puts("3");
u[uPos++] = 0; v[vPos++] = 0;
dfs(trie[pu][0], trie[pv][0]);
--uPos; --vPos;
}
if (trie[pu][1] && trie[pv][1]) {
// puts("4");
u[uPos++] = 1; v[vPos++] = 1;
dfs(trie[pu][1], trie[pv][1]);
--uPos; --vPos;
}
}
};
int n;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
int a;
scanf("%d", &a);
Trie::insert(a);
}
Trie::dfs(1, 1);
printf("%lld\n", Trie::maxAns);
return 0;
}