UPC-9264 Chip Factory(01字典树)
题目描述
John is a manager of a CPU chip factory, the factory produces lots of chips everyday. To manage large amounts of products, every processor has a serial number. More specifically, the factory produces n chips today, the i-th chip
produced this day has a serial number si.
At the end of the day, he packages all the chips produced this day, and send it to wholesalers. More specially, he writes a checksum number on the package, this checksum is defined as below:
which i, j, k are three different integers between 1 and n. And is symbol of bitwise XOR.
Can you help John calculate the checksum number of today?
输入
The first line of input contains an integer T indicating the total number of test cases.
The first line of each test case is an integer n, indicating the number of chips produced today. The next line has n integers s1 , s2 ,…, sn , separated with single space, indicating serial number of each chip.
1≤T≤1000
3≤n≤1000
0≤s i≤109
There are at most 10 testcases with n > 100
输出
For each test case, please output an integer indicating the checksum number in a line.
样例输入
2
3
1 2 3
3
100 200 300
样例输出
6
400
题意: 给序列A,找到i,j,k使得序列中(Ai+Aj)^Ak最大。i≠j≠k
题解: 关于异或值最大的问题容易想到01字典树,问题在于三种数不能重复用,那么两层for暴力枚举Ai+Aj,使其异或01字典树上的Ak,记录一个最大值即可,不能重复用的情况,每次枚举到第i个和第j个值时,在字典树上删除这两个值,那么k就不会查询到和两者相同的位置了。删除后注意要加回字典树上
#include<bits/stdc++.h>
#define LL long long
#define M(a,b) memset(a,b,sizeof a)
#define pb(x) push_back(x)
using namespace std;
const int maxn=1e3+7;
int tre[maxn<<5][2];
int cnt[maxn<<5];
int tot;
void insert(LL a,int rt,int add)
{
for(int i=31; i>=0; i--)
{
int x=(a>>i)&1;
if(!tre[rt][x])
{
tre[rt][x]=++tot;
M(tre[tre[rt][x]],0);
}
rt=tre[rt][x];
cnt[rt]+=add;
}
}
LL finds(LL a,int rt)
{
LL ans=0;
for(int i=31;i>=0;i--)
{
ans<<=1;
int x=(a>>i)&1;
if(tre[rt][!x]&&cnt[tre[rt][!x]])rt=tre[rt][!x],ans|=1;
else rt=tre[rt][x];
}
return ans;
}
int t,n;
LL a[1080];
int main()
{
scanf("%d",&t);
while(t--)
{
LL ans=0;
tot=0;
int rt=++tot;
M(tre[rt],0);
M(cnt,0);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
insert(a[i],rt,1);
}
for(int i=1;i<n;i++)
{
insert(a[i],rt,-1);
for(int j=i+1;j<=n;j++)
{
insert(a[j],rt,-1);
ans=max(ans,finds(a[i]+a[j],rt));
insert(a[j],rt,1);
}
insert(a[i],rt,1);
}
printf("%lld\n",ans);
}
}