题目链接:Chip Factory
题目大意:给你n个数,从中选出三个数a,b,c,使得(a+b)异或c最大。
思路:先建立字典树,选出两个数,先暂时删除,然后找出与其异或的最大值。
下面是代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=1009;
int sum,coun;
struct node
{
int l,r;//左(右)节点位置
int sum_l,sum_r;//记录有多少个数是从这个节点的左(右)经过
int inq;//最终这个数是几。
} dis[100*maxn];
int a[maxn],wei[33];
void build(int x)//建立字典树
{
int now=0;
for(int i=30; i>=0; i--)
{
if(wei[i]&x)
{
if(dis[now].r==-1)
{
dis[coun].inq=dis[coun].sum_r=dis[coun].sum_l=0;
dis[coun].r=dis[coun].l=-1;
dis[now].r=coun++;
}
dis[now].sum_r++;
now=dis[now].r;
}
else
{
if(dis[now].l==-1)
{
dis[coun].inq=dis[coun].sum_r=dis[coun].sum_l=0;
dis[coun].l=dis[coun].r=-1;
dis[now].l=coun++;
}
dis[now].sum_l++;
now=dis[now].l;
}
}
dis[now].inq=x;
}
int dele(int x)//暂时删除a[i](a[j])
{
int now=0;
for(int i=30; i>=0; i--)
{
if(wei[i]&x)
{
dis[now].sum_r--;
if(dis[now].sum_r==0)//没有数从这里通过,说明只有x这个数会经过这里,返回此处的位置
{
int f=dis[now].r;
dis[now].r=-1;
return f;
}
now=dis[now].r;
}
else
{
dis[now].sum_l--;
if(dis[now].sum_l==0)
{
int f=dis[now].l;
dis[now].l=-1;
return f;
}
now=dis[now].l;
}
}
}
int match(int x)//查找与(a[i]+a[j])异或的最大值
{
int now=0;
for(int i=30; i>=0; i--)
{
if(((wei[i]&x)&&dis[now].l!=-1)||dis[now].r==-1)
now=dis[now].l;
else now=dis[now].r;
}
return dis[now].inq;
}
void restore(int x,int f)//回复a[i](a[j])这个数
{
int now=0;
for(int i=30; i>=0; i--)
{
if(wei[i]&x)
{
dis[now].sum_r++;
if(dis[now].r==-1)
{
dis[now].r=f;
return ;
}
now=dis[now].r;
}
else
{
dis[now].sum_l++;
if(dis[now].l==-1)
{
dis[now].l=f;
return ;
}
now=dis[now].l;
}
}
}
int main()
{
int t;
wei[0]=1;
for(int i=1; i<31; i++)
wei[i]=wei[i-1]*2;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
sum=0,coun=1;
dis[0].l=dis[0].r=-1;
dis[0].inq=0;
dis[0].sum_l=dis[0].sum_r=0;
for(int i=0; i<n; i++)
{
scanf("%d",&a[i]);
build(a[i]);//建立字典树
}
for(int i=0; i<n; i++)//遍历所有的情况(a[i]+a[j])
{
int x=dele(a[i]);//先删除,a[i],x代表a[i]这个节点的位置
for(int j=i+1; j<n; j++)
{
int y=dele(a[j]);//删除,a[j],y代表a[j]这个节点的位置
int f=match(a[i]+a[j]);
sum=max(sum,f^(a[i]+a[j]));
restore(a[j],y);//还原a[j],还原是有先后顺序的,一定是先还原a[j],再还原a[i]
}
restore(a[i],x);//还原a[i]
}
printf("%d\n",sum);
}
return 0;
}