[hdu 5536][2015ACM/ICPC亚洲区长春站]Chip Factory 二进制字典树

Chip Factory
Time Limit: 18000/9000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 1270 Accepted Submission(s): 580

Problem Description
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:
maxi,j,k(si+sj)⊕sk

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?

Input
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≤si≤109
There are at most 10 testcases with n>100

Output
For each test case, please output an integer indicating the checksum number in a line.

Sample Input

2
3
1 2 3
3
100 200 300

Sample Output

6
400

Source
2015ACM/ICPC亚洲区长春站-重现赛(感谢东北师大)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5536

题意:给出n(3≤n≤1000)个数字,求max(si+sj)⨁sk,而且i,j,k互不相等。

思路:在字典树上从高位贪心

代码

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int T;
int t[100005][2];
int cnt[100005];
int a[1005];
int tot;
int n;
int ans;
void init(int x)
{
    cnt[x]=0;
    t[x][0]=t[x][1]=0;
}
void add(int x,int v)
{
    int now=0;
    for(int i=30;i>=0;i--)
    {
        int p=(x&(1<<i));
        if(p) p=1;
        if(!t[now][p])
        {
            t[now][p]=++tot;
            init(tot);
        }
        now=t[now][p];
        cnt[now]+=v;
    }
}
void query(int x)
{
    int ret=0;
    int now=0;
    for(int i=30;i>=0;i--)
    {
        int p=(x&(1<<i));
        if(p) p=0;
        else p=1;
        if(!t[now][p]||cnt[t[now][p]]<=0)  p=1-p;
        else ret+=(1<<i);
        now=t[now][p];
    }
    ans=max(ans,ret);

}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        ans=0;
        scanf("%d",&n);
        tot=0;
        init(0);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            add(a[i],1);
        }
        for(int i=1;i<=n;i++)
        {
            add(a[i],-1);
            for(int j=i+1;j<=n;j++)
            {
                add(a[j],-1);
                query(a[i]+a[j]);
                add(a[j],1);
            }
            add(a[i],1);
        }
        printf("%d\n",ans);
    }

}

你可能感兴趣的:(二进制,ACM)