UPC-9264 Chip Factory(01字典树)

孤人 提交于 2020-04-02 14:15:57

题目描述
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);
    }
}

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!