链接:HDU - 5536 Chip Factory
题意:
给出 n ( 3 ≤ n ≤ 1000 ) n(3\le n\le1000) n(3≤n≤1000)个非负整数 s 1 , s 2 , ?   , s n s_1,s_2,\cdots,s_n s1?,s2?,?,sn?,求最大的 ( s i + s j ) ? s k (s_i+s_j)\oplus s_k (si?+sj?)?sk?,其中 i , j , k i,j,k i,j,k互不相同且 1 ≤ i , j , k ≤ n 1\le i,j,k\le n 1≤i,j,k≤n。
分析:
由于 n n n只有 1000 1000 1000,所以我们可以暴力枚举 i , j i,j i,j,然后在除 s i , s j s_i,s_j si?,sj?以外元素构成的01字典树中找到异或最大的 s k s_k sk?。
每次都去建树肯定不行,所以就要加一个数组 n u m [ u ] num[u] num[u]来实现带删除操作的01字典树,先把 s 1 s_1 s1?~ s n s_n sn?都放入01字典树,枚举了 i , j i,j i,j就删除 s i , s j s_i,s_j si?,sj?,询问最大异或值后再将 s i , s j s_i,s_j si?,sj?恢复即可。
以下代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=1000+50;
const int max_base=31;
int n;
int ch[31*maxn][2],num[31*maxn],tot;
LL s[maxn],val[31*maxn];
void init()
{
tot=1;ch[0][0]=ch[0][1]=0;val[0]=0;num[0]=0;
}
void ins(LL x)
{
int u=0;num[u]++;for(LL i=max_base;i>=0;i--){
LL c=(x>>i)&1LL;if(!ch[u][c]){
ch[tot][0]=ch[tot][1]=0;val[tot]=0;num[tot]=0;ch[u][c]=tot++;}u=ch[u][c];num[u]++;}val[u]=x;
}
void updata(LL x,int op) //op=-1:删除x
{
//op=1:恢复之前被删除的xint u=0;num[u]+=op;for(LL i=max_base;i>=0;i--){
LL c=(x>>i)&1LL;u=ch[u][c];num[u]+=op;}
}
LL query(LL x)
{
int u=0;for(LL i=max_base;i>=0;i--){
LL c=(x>>i)&1LL;if(ch[u][c^1]&&num[ch[u][c^1]])u=ch[u][c^1];elseu=ch[u][c];}return x^val[u];
}
int main()
{
int T;scanf("%d",&T);while(T--){
init();scanf("%d",&n);for(int i=1;i<=n;i++){
scanf("%d",&s[i]);ins(s[i]);}LL ans=0;for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
LL x=s[i]+s[j];updata(s[i],-1);updata(s[j],-1);ans=max(ans,query(x));updata(s[i],1);updata(s[j],1);}}printf("%lld\n",ans);}return 0;
}