HDU.5536.Chip Factory(01字典树)
思路: 字典树 暴力。
考虑:求枚举 ,因为 等价所以我们可以假设
然后对于 ,我们用一个 字典树维护查询。
需要注意的是:先删除 ,再查询,然后再将 插入还原,继续下一个查询。
对于删除我们动态维护一个 数组记录该结点出现的次数,对于查询我们用一个 数组维护从该根到该节点的路径的异或和 。
时间复杂度:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e3+5,M=3e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
struct Trie{
int son[M][2],sz[M],cnt,val[M];
void init(){cnt=0,mst(son[0]);}
void ins(int x){ //插入.
int p=0;
for(int i=30;~i;i--){
int &s=son[p][x>>i&1];
if(!s) s=++cnt,mst(son[cnt]),sz[cnt]=val[cnt]=0;
p=s,sz[p]++;
}
val[p]=x;
}
void del(int x){ //删除.
int p=0;
for(int i=30;~i;i--){
int s=x>>i&1;
p=son[p][s];
--sz[p];
}
}
int que(int x){ //查询.
int p=0;
for(int i=30;~i;i--){
int s=x>>i&1;
if(son[p][!s]&&sz[son[p][!s]]) p=son[p][!s];
else p=son[p][s];
}
return x^val[p];
}
}T;
int t,n,a[N],ans;
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);T.init();ans=0;//初始化
for(int i=1;i<=n;i++) scanf("%d",&a[i]),T.ins(a[i]);
for(int i=1;i<n;i++){ //先删除,查询再插入.
T.del(a[i]);
for(int j=i+1;j<=n;j++){
T.del(a[j]);
ans=max(ans,T.que(a[i]+a[j]));
T.ins(a[j]);
}
T.ins(a[i]);
}
printf("%d\n",ans);
}
return 0;
}