题意:
求max( (a[i] + a[j])
⊕a[k]
) (i, j, k都不相同)
思路:
这题可以暴力也可以01trie. 来说说01trie.
其实遇到异或求最大最小啊啥的都可以想01trie是否可做.
那么这个题肯定就是枚举两个和,然后跑01trie了.
关键是怎么解决下标不同的问题,这里解决办法是增加一个del函数,删除以某个前缀为数的个数.
即:num[]保存的是到该节点,以该前缀 的数的个数有多少,我们-1就相当于把这个数删除了.
具体见代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int maxn=1e5+10;
typedef long long ll;
int a[maxn];
int n;
int trie[maxn][3];
int num[maxn];
int now;
void init()
{
now = 1;
memset(trie[0],0,sizeof trie[0]);
return ;
}
void insert(int x)//插入
{
int d = 0;
for(int i = 31;i >= 0;--i)
{
int tmp = (x >> i) & 1;//傻逼错误啊 = =
if(!trie[d][tmp])
{
num[now] = 0;
memset(trie[now],0,sizeof trie[now]);
trie[d][tmp] = now++;
}
d = trie[d][tmp];
num[d]++;
}
return ;
}
void del(int x)//删除操作
{
int d = 0;
for(int i = 31;i >= 0;--i)
{
int tmp = (x >> i) & 1;
d = trie[d][tmp];
num[d]--;//前缀个数-1即可
}
return ;
}
int find(int x)//匹配
{
int res = 0,d = 0;
for(int i = 31;i >= 0;--i)
{
int tmp = (x >> i) & 1;
if(trie[d][tmp^1] && num[trie[d][tmp^1]])
{
res |= (1 << i);
d = trie[d][tmp^1];
}
else
d = trie[d][tmp];
}
return res;
}
int main(){
int _;
cin>>_;
while(_--)
{
scanf("%d",&n);
init();
for(int i = 1;i <= n;++i)
{
scanf("%d",&a[i]);
insert(a[i]);
}
int ans = 0;
for(int i = 1;i <= n;++i)
{
del(a[i]);
for(int j = i + 1;j <= n;++j)
{
del(a[j]);
int s= a[i]+a[j];
ans = max(ans,find(s));
insert(a[j]);
}
insert(a[i]);
}
printf("%d\n",ans);
}
return 0;
}