题意:给你n个数,让你在n个数中选三个,使得(a1+a2)^a3的值最大,a1!=a2!=a3(下标不等于);
解题思路:01字典树可以写,因为数据小,我们可以先把n个数建一颗字典树,然后两边for找a1+a2,扔到字典树中,但是这道题因为不能相同,所以有一个操作,每当我们扔一个a1+a2的时候,我们需要把a1和a2在树中删除,因为万一和a1能够成最大异或值,那么不合题意,在每次结束后,再把a1,a2加回来;
代码:
#include<iostream> #include<cstdio> #include<cstring> #define maxn 2005 #define ll long long using namespace std; ll val[maxn*32]; int num[maxn*32]; int trie[maxn*32][2]; int tot; int n; int t; int root; ll a[maxn]; void init() { memset(num,0,sizeof(num)); memset(val,0,sizeof(val)); memset(trie,0,sizeof(trie)); tot=0;root=0; } void get_trie(ll u) { root=0; for(int i=32;i>=0;i--) { int id=(u>>i)&1; if(!trie[root][id]) trie[root][id]=++tot; root=trie[root][id]; num[root]++; } val[root]=u; } void update(ll u,int cnt) { root=0; for(int i=32;i>=0;i--) { int id=(u>>i)&1; root=trie[root][id]; num[root]+=cnt; } } ll query(ll u) { root=0; for(int i=32;i>=0;i--) { int id=(u>>i)&1; if(id==1) { if(trie[root][0]&&num[trie[root][0]]) root=trie[root][0]; else root=trie[root][1]; } else { if(trie[root][1]&&num[trie[root][1]]) root=trie[root][1]; else root=trie[root][0]; } } return val[root]; } int main() { scanf("%d",&t); while(t--) { init(); ll ans=-1; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); get_trie(a[i]); } for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++) { update(a[i],-1);update(a[j],-1); ans=max(ans,(a[i]+a[j])^query(a[i]+a[j])); update(a[i],1);update(a[j],1); } } printf("%lld ",ans); } }