题意:给你n个数(n<=1e3), 求max( (a[i] + a[j]) ^ a[k] ) (i, j, k都不相同)
思路:先将n个数建立01Trie,然后枚举i,j,从01Trie中删除a[i]和a[j],然后去查询与(a[i]+a[j])异或的最大值,查询完后再插回去。
另外,删除操作是这样实现的,我们每个节点记录一个值。
val
插入时对所有经过节点的值加1,删除就将对应节点的val值减1。
在树上匹配的时候就只走那些val值为正的节点。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1e3+5;
const int maxnode = 1e5+5;
int a[maxn], n;
int sz, ch[maxnode][2], val[maxnode];
void init()
{
sz = 1;
memset(ch[0], 0, sizeof(ch[0]));
}
void Insert(int x)
{
int u = 0;
for(int i = 31; i >= 0; i--)
{
int idx = (x>>i)&1;
if(!ch[u][idx])
{
memset(ch[sz], 0, sizeof(ch[sz]));
val[sz] = 0;
ch[u][idx] = sz++;
}
u = ch[u][idx];
val[u]++;
}
}
void Delete(int x)
{
int u = 0;
for(int i = 31; i >= 0; i--)
{
int idx = (x>>i)&1;
u = ch[u][idx];
val[u]--;
}
}
int Match(int x)
{
int ans = 0, u = 0;
for(int i = 31; i >= 0; i--)
{
int idx = (x>>i)&1;
if(ch[u][idx^1] && val[ch[u][idx^1]])
{
ans |= (1<<i);
u = ch[u][idx^1];
}
else u = ch[u][idx];
}
return ans;
}
int main(void)
{
int t;
cin >> t;
while(t--)
{
init();
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]), Insert(a[i]);
int ans = (a[1]+a[2])^a[3];
for(int i = 1; i <= n; i++)
{
Delete(a[i]);
for(int j = i+1; j <= n; j++)
{
Delete(a[j]);
ans = max(ans, Match(a[i]+a[j]));
Insert(a[j]);
}
Insert(a[i]);
}
printf("%d\n", ans);
}
return 0;
}