hdu5536 Chip Factory xor,字典树

hdu5536 Chip Factory   xor,字典树

Chip Factory

Time Limit: 18000/9000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 280    Accepted Submission(s): 158

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

看到异或就应该想到字典树。。。

注意用siz来处理删除,而不要直接删除结点。

#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define MS0(a) memset(a,0,sizeof(a))

using namespace std;

typedef long long ll;
const int maxn=1000100;
const int INF=(1<<29);
const double EPS=0.000000001;
const double Pi=acos(-1.0);

struct Trie
{
    int ch[2];
    int siz;
    void debug()
    {
        printf("lch=%2d rch=%2d siz=%2d\n",ch[1],ch[0],siz);
    }
};Trie tr[maxn];int p;int rt;
int n,a[maxn];

int newnode()
{
    tr[++p].siz=0;
    tr[p].ch[0]=tr[p].ch[1]=-1;
    return p;
}

void Init()
{
    rt=0;
    tr[rt].ch[0]=tr[rt].ch[1]=-1;
    tr[rt].siz=0;
    p=0;
}

void Insert(int t)
{
    int k=rt;
    tr[k].siz++;
    int c;
    for(int i=30;i>=0;i--){
        if(t&(1<<i)) c=1;
        else c=0;
        if(tr[k].ch[c]==-1) tr[k].ch[c]=newnode();
        k=tr[k].ch[c];
        tr[k].siz++;
    }
}

void Delete(int t)
{
    int k=rt;
    tr[k].siz--;
    int c;
    for(int i=30;i>=0;i--){
        if(t&(1<<i)) c=1;
        else c=0;
        k=tr[k].ch[c];
        tr[k].siz--;
    }
}

int query(int t)
{
    int k=rt;
    int res=0;
    for(int i=30;i>=0;i--){
        if(t&(1<<i)){
            if(tr[k].ch[0]==-1||tr[tr[k].ch[0]].siz==0){
                k=tr[k].ch[1];
            }
            else{
                k=tr[k].ch[0];
                res|=(1<<i);
            }
        }
        else{
            if(tr[k].ch[1]==-1||tr[tr[k].ch[1]].siz==0){
                k=tr[k].ch[0];
            }
            else{
                k=tr[k].ch[1];
                res|=(1<<i);
            }
        }
    }
    return res;
}

int main()
{
    freopen("in.txt","r",stdin);
    int T;cin>>T;
    while(T--){
        scanf("%d",&n);
        Init();
        REP(i,1,n) scanf("%d",&a[i]),Insert(a[i]);
        int ans=0;
        REP(i,1,n){
            REP(j,i+1,n){
                Delete(a[i]);Delete(a[j]);
                int tmp=query(a[i]+a[j]);
                ans=max(ans,tmp);
                Insert(a[i]);Insert(a[j]);
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

时间: 2024-10-25 22:22:40

hdu5536 Chip Factory xor,字典树的相关文章

HDU 5536 Chip Factory(字典树)

题目戳这 题意:给你n个数,从中选出三个数a,b,c,然后(a+b)^c,这个式子的值是最大的. 思路:如果来三个for循环,果断TLE,所以想到了字典树,就是先把所有的数字都插进去,在查询的时候就先把确定了的那两个数字删掉,然后在字典树中求出异或的最大值,得到结果后,再把两个数字插回去. P.S.一开始我的数组开到了45*10^5+10,然后他给我TLE,然后当我把数组开到10^5+10的时候,A了···········,居然是数组爆我时间了,我勒个擦. #include<stdio.h>

ACM学习历程—HDU 5536 Chip Factory(xor &amp;&amp; 字典树)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5536 题目大意是给了一个序列,求(si+sj)^sk的最大值. 首先n有1000,暴力理论上是不行的. 此外题目中说大数据只有10组,小数据最多n只有100.(那么c*n^2的复杂度应该差不多) 于是可以考虑枚举i和j,然后匹配k. 于是可以先把所有s[k]全部存进一个字典树, 然后枚举s[i]和s[j],由于i.j.k互不相等,于是先从字典树里面删掉s[i]和s[j],然后对s[i]+s[j]这个

ACM学习历程—POJ 3764 The xor-longest Path(xor &amp;&amp; 字典树 &amp;&amp; 贪心)

题目链接:http://poj.org/problem?id=3764 题目大意是在树上求一条路径,使得xor和最大. 由于是在树上,所以两个结点之间应有唯一路径. 而xor(u, v) = xor(0, u)^xor(0, v). 所以如果预处理出0结点到所有结点的xor路径和,问题就转换成了求n个数中取出两个数,使得xor最大. 这个之前用字典树处理过类似问题. 代码: #include <iostream> #include <cstdio> #include <cst

[HDU5536] Chip Factory

传送门:>Here< 题意:给出一个长度为N的序列,求$Max\{ (a_i + a_j) ⊕ a_k \}$ (i,j,k均不相同)  ($N \leq 1000$) 解题思路 既然$O(n^3)$不行,就考虑$O(n^2)$的做法. 网上说得很对,凡是和xor有关的80%都是Trie…… 将所有数的二进制建立Trie树,枚举$i,j$——此时在trie树中删去$a_i, a_j$,然后用上一篇文章的方法求得最大的异或. 那么这道题的关键问题就在于如何删去$a_i, a_j$?每次重新建树显

[SCU 4494] 双剑合并 (xor字典树)

SCU - 4494 给定两个序列,问从两个序列中各取一个值的异或和最大为多少 把 A序列中的数字看成一个二进制的 01串,然后存到 Trie树里 然后将 B序列的数字同样看成一个 01串,然后在 Trie树上从高位到低位贪心地查找 如果B序列中查找的 01串当前位为 0,则找 Trie树上为 1的子儿子 否则就只能走为 0的右儿子,反之亦然,然后往下走 时间复杂度 O(N) #include <cstdio> #include <iostream> #include <cs

Chip Factory(HDU5536 + 暴力 || 01字典树)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5536 题目: 题意: 对于给定的n个数,求出三个下标不同的数使得(si+sj)^sk最大. 思路: 由于时间给了9s,所以可以暴力过.不过还可以用01字典树艹过去,不过注意字典树里面存si查询(sj+sk),不要存(si+sj)查询sk,不然会T. 暴力代码实现如下: 1 #include <set> 2 #include <map> 3 #include <deque>

hdu 5536 Chip Factory 字典树+bitset 铜牌题

Chip Factory Time Limit: 18000/9000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 1842    Accepted Submission(s): 833 Problem Description John is a manager of a CPU chip factory, the factory produces lots of chip

HDU 5536 Chip Factory 字典树+贪心

给你n个数,a1....an,求(ai+aj)^ak最大的值,i不等于j不等于k 思路:先建字典树,暴力i,j每次删除他们,然后贪心找k,再恢复i,j,每次和答案取较大的,就是答案,有关异或的貌似很多都用字典树,也是醉了 /*Problem : 5536 ( Chip Factory ) Judge Status : Accepted RunId : 15506230 Language : G++ Author : qianbi08*/ #include<iostream> #include&

Chip Factory HDU - 5536 字典树(删除节点|增加节点)

题意: t组样例,对于每一组样例第一行输入一个n,下面在输入n个数 你需要从这n个数里面找出来三个数(设为x,y,z),找出来(x+y)^z(同样也可以(y+z)^1)的最大值 (“^”代表异或操作,即“相同为0,不同为1”) 题解: 这一道题和Xor Sum HDU - 4825很相似 因为异或运算的特性,我们最后要求最大值,那我们就对这n个数的二进制形式建一颗字典树.然后就暴力枚举是哪两个数相加,然后在字典树中把这两个数删掉.然后在处理完的字典树中查找那个能使结果尽可能大的第三个数(至于怎么