题意:求max( (a[i] + a[j]) ^ a[k] ) (i, j, k都不相同)
01字典树。
思路:建一个字典树直接找,每次先删除a[i],a[j]然后找出剩下的与a[i]+a[j]的最大异或和,然后然把a[i],a[j]插回去
亦或和最大值,trie基本操作。
#include <iostream>
#include <cstdio>
#include <cstring>
#define mem(x,v) memset(x,v,sizeof(x))
#define go(i,a,b) for (int i = a; i <= b; i++)
#define og(i,a,b) for (int i = a; i >= b; i--)
using namespace std;
typedef long long LL;
const double EPS = 1e-10;
const int INF = 0x3f3f3f3f;
const int N = 1e4+10;
int Ac[N*32][2];
int Num[N*32],cnt;
LL End[N*32];
LL a[N];
void Insert(LL z){
int now = 0;
og(i,32,0){
int id = (z & (1ll << i))?1:0;
if (!Ac[now][id]) Ac[now][id] = ++cnt;
now = Ac[now][id];
Num[now]++;
}
End[now] = z;
}
void Delete(LL z){
int now = 0;
og(i,32,0){
int id = (z & (1ll<<i))?1:0;
now = Ac[now][id];
Num[now]--;
}
}
LL Query(LL z){
int now = 0;
og(i,32,0){
int id = (z & (1ll << i))? 0:1;
if (!Ac[now][id] || !Num[Ac[now][id]]) id ^= 1;
now = Ac[now][id];
}
return End[now]^z;
}
int main(){
int T; cin>>T;
while(T--){
int n; scanf("%d",&n);
LL ans = 0;
mem(Num,0);
mem(End,0);
mem(Ac,0);
cnt = 0;
go(i,1,n) scanf("%lld",&a[i]),Insert(a[i]);
go(i,1,n){
go(j,i+1,n){
LL x = a[i] + a[j];
Delete(a[i]); Delete(a[j]);
ans = max(ans,Query(x));
Insert(a[i]); Insert(a[j]);
}
}
printf("%lld\n",ans);
}
return 0;
}