给N个数,找出(a[i]+a[j])^a[k]的最大值,其中i,j,k,为不同的数。
用01字典树求解。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+3;
int arr[maxn],cnt;
struct Node
{
int a[2],sum;//a数组当前值存的是0还是1,sum当前节点下挂着几个子节点。
}tri[maxn*100];
void Insert(int x)
{
int u=0;
for(int i=31;i>=0;--i)//将要插入数转化为二进制,插入字典树
{
int t=(x>>i)&1;
if(!tri[u].a[t])
tri[u].a[t]=++cnt;//如果当前节点不存在,加上;cnt:当前节点数
u=tri[u].a[t];
++tri[u].sum;
}
}
void Delete(int x)//在字典树中删除某一个01串
{
int u=0;
for(int i=31;i>=0;--i)
{
int t=(x>>i)&1;
u=tri[u].a[t];
--tri[u].sum;
}
}
int query(int x)//查询异或和的最大
{
int u=0,ans=0;
for(int i=31;i>=0;--i)
{
int t=(x>>i)&1,rev=tri[u].a[!t],cur=tri[u].a[t];//从高位开始,找字典树中是否存在与当前数相反的二进制位数
if(rev&&tri[rev].sum>0)
u=rev,ans|=(1<<i);
else
u=cur;//否则,往下顺着找相反二进制位数
}
return ans;
}
int main()
{
int T,n;
scanf("%d",&T);
while(T--)
{
cnt=0;
memset(tri,0,sizeof(tri));
scanf("%d",&n);
for(int i=0;i<n;++i)
scanf("%d",&arr[i]),Insert(arr[i]);
int ans=0;
for(int i=0;i<n;++i)
{
Delete(arr[i]);//为了保证i,j,k各不相同
for(int j=i+1;j<n;++j)
{
Delete(arr[j]);
ans=max(ans,query(arr[i]+arr[j]));
Insert(arr[j]);
}
Insert(arr[i]);
}
printf("%d\n",ans);
}
return 0;
}