hdu5536(01trie)
题意就是给一个集合,然后在集合里找到3个数,满足max (si+sj)⊕sk。
枚举i和j,然后把si,sj从字典树里删除,然后再在字典树里找与(si+sj)异或最大的数,取最大值,最后还要还原删除的数。删除 操作是话就是让字典树的节点额外记录一个值cnt,表示经过该节点的数次数。查询的时候,当该节点的cnt>1时才能走到该节点。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1005;
struct node
{
int val,cnt,son[2];
void reset()
{
val=cnt=son[0]=son[1]=0;
}
}tree[maxn*32];
int s[maxn],n,cnt;
void myinsert(int x)
{
int r=0,v;
for(int i=31;i>=0;i--)
{
v=(x>>i)&1;
if(!tree[r].son[v])
{
tree[++cnt].reset();
tree[r].son[v]=cnt;
}
if(r!=0)
tree[r].cnt++;
r=tree[r].son[v];
}
tree[r].val=x;
tree[r].cnt++;
}
void del(int x)
{
int r=0,v;
for(int i=31;i>=0;i--)
{
v=(x>>i)&1;
tree[tree[r].son[v]].cnt--;
r=tree[r].son[v];
}
}
void rec(int x)
{
int r=0,v;
for(int i=31;i>=0;i--)
{
v=(x>>i)&1;
tree[tree[r].son[v]].cnt++;
r=tree[r].son[v];
}
}
int query(int x)
{
int r=0,v;
for(int i=31;i>=0;i--)
{
v=(x>>i)&1;
if(tree[r].son[v^1]&&tree[tree[r].son[v^1]].cnt)
r=tree[r].son[v^1];
else
r=tree[r].son[v];
}
return tree[r].val^x;
}
int main()
{
int t,maxx;
scanf("%d",&t);
while(t--)
{
cnt=0;
maxx=-1;
tree[0].reset();
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&s[i]);
myinsert(s[i]);
}
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
{
del(s[i]);
del(s[j]);
maxx=max(maxx,query(s[i]+s[j]));
rec(s[i]);
rec(s[j]);
}
printf("%d\n",maxx);
}
return 0;
}