Description
今天小W用了1s不到的时候完成了这样一个题:
在给定的N个整数 A_1,A_2,…,A_N中选出两个进行异或运算,得到的结果最大是多少?
正当他志得意满时,L老师亮出了另一个题:
给你1000个数字a1到a1000,从其中选出三个数字ai,aj,ak
(1<=i,j,k<=1000,且i,j,k互不相同)
满足(ai+aj)xor ak的值最大
小W顿时迷茫了.........
Input
第一行给出数字N,接下来N行,每行一个数字
Output
如题
Sample Input
4
1
2
3
4
Sample Output
7
HINT
(1+2)xor4=7
sol:先将所有数字加入Trie,然后枚举前两个数字i和j,将其和拿到Trie里和第三个数字k进行异或运算。注意,三个数要各不相同,因此我们到Trie里做异或前,要从Trie里删掉i和j,异或结束后,再把i和j加回去。删除时,将i和j的各结点出现的次数-1,插入时,将i和j的各结点出现的次数+1。
代码如下:
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 int a[2005],ch[35*1005][2],val[35*1005]; 5 int tol; 6 7 void insert(ll x,ll p) 8 { 9 int u=0; 10 for(int i=31;i>=0;i--) 11 { 12 int v=(x>>i)&1; 13 if(!ch[u][v]) 14 ch[u][v]=tol++; 15 u=ch[u][v]; 16 val[u]+=p; 17 } 18 } 19 20 ll query(ll x) 21 { 22 int u=0; 23 ll ans=0; 24 for(int i=31;i>=0;i--) 25 { 26 int v=(x>>i)&1; 27 if(val[ch[u][v^1]]) 28 u=ch[u][v^1],ans=ans<<1|1; 29 else 30 u=ch[u][v],ans=ans<<1; 31 } 32 return ans; 33 } 34 35 int main() 36 { 37 int T; 38 scanf("%d",&T);//T组数据 39 while(T--) 40 { 41 tol=1; 42 int n; 43 scanf("%d",&n);//每组n个数 44 for(int i=0;i<=n*32;i++) //建立整个TRIE 45 ch[i][0]=ch[i][1]=val[i]=0; 46 for(int i=1;i<=n;i++) //将每个数字加入到TRIE中 47 { 48 scanf("%d",&a[i]); 49 insert(a[i],1);//插入,将每个结点出现的次数增加1 50 } 51 ll maxx=0; 52 for(int i=1;i<=n;i++)//枚举第一个数 53 { 54 for(int j=i+1;j<=n;j++)//枚举第二个数 55 { 56 insert(a[i],-1); //删除A[i],a[j] 57 insert(a[j],-1);//删除操作等于使用插入操作,将结点出现的次数-1 58 maxx=max(maxx,query(a[i]+a[j])); 59 //用a[i]+a[j]去异或Trie里的数,取最大值 60 //因为不能为a[i]和a[j]本身,所以先删掉这两个数,异或完后再加回来 61 insert(a[j],1); 62 insert(a[i],1); 63 } 64 } 65 printf("%lld\n",maxx); 66 } 67 return 0; 68 }