题意:给出一个数列,保证每个数都不相同,让你从中找出 :两个数的和亦或上另外一个数最大的结果,输出这个亦或结果。
思路:字典树,建立四个域:
ch [u] [2]: 父节点编号为u,字符0或者1代表的那一条边连向哪个节点
sz[maxn]: 经过节点的数字有几个(方便删除)
val[maxn]: 存放在每个数的结尾处,方便查询的时候返回,表示该数本身的值
id: 给树上节点编号
root:初始化时用到的根节点
建议大家使用该模板实现字典树,灵活性强,耗内存小,实现简单方便(当然如果是大佬,最好根据实际情况采用不同的写法)
思路: n=1000,我们可以暴力枚举每两个数的和,然后在字典树中先删除这两个数,然后去树中找最大的亦或,找到之后,更新结果,再插入删掉的数,进行下一次查询。
#include<bits/stdc++.h>
using namespace std;
#define maxn 300010
#define son 2
#define inf 0x3f3f3f3f
typedef long long ll;
int ch[maxn][2];// 父节点编号为u,字符0或者1代表的那一条边连向哪个节点
int sz[maxn];//经过节点i的数字有多少个
int val[maxn];//节点i的值是多少
int a[10005];
int id,root;//编号,根
int newnode()
{
ch[id][0] = -1;
ch[id][1] = -1;
return id++;
}
void init()
{
memset(ch,-1,sizeof ch);
memset(val,0,sizeof val);
memset(a,0,sizeof a);
memset(sz,0,sizeof(sz));
id=0;
root=newnode();
}
void insert(int x)
{
bool bits[32];
int xx=x;
for(int i=0;i<32;i++) bits[i]=x&1,x>>=1;
int u=root;
for(int i=31;i>=0;i--){
if(ch[u][bits[i]]==-1) { ch[u][bits[i]]=newnode();}
u=ch[u][bits[i]];
sz[u]++;
}
val[u]=xx;
}
int find(int x)
{
bool bits[32];
for(int i=0;i<32;i++) bits[i]=x&1,x>>=1;
int u=root;
for(int i=31;i>=0;i--){
if(ch[u][!bits[i]]&&sz[ch[u][!bits[i]]]>0) u=ch[u][!bits[i]];
else if(ch[u][bits[i]]&&sz[ch[u][bits[i]]]>0) u=ch[u][bits[i]];
else return x;
}
return val[u];
}
void del(int x)
{
bool bits[32];
int xx=x;
for(int i=0;i<32;i++) bits[i]=x&1,x>>=1;
int u=root,temp;
for(int i=31;i>=0;i--)
{
u=ch[u][bits[i]];
sz[u]--;
}
}
int main()
{
int n,m,T;
scanf("%d",&T);
while(T--)
{
init();
scanf("%d",&n);
int maxx=-inf;
for(int i=1;i<=n;i++) { scanf("%d",&a[i]);insert(a[i]);}
for(int i=1;i<n;i++){
del(a[i]);
for(int j=i+1;j<=n;j++){
del(a[j]);
int ans=find(a[i]+a[j]);
ans=ans^(a[i]+a[j]);
maxx=max(maxx,ans);
insert(a[j]);
}
insert(a[i]);
}
cout<<maxx<<endl;
}
}