COJ 1216 异或最大值

      这道题也是搁了很久了,这次百度之星初赛中有道题感觉很相似,还是不会……,中午看status时,看到有个牛过了这道题,于是搜了搜,发现都是说用01二叉树来解决的,我没细看他们的方法,自己研究了一下,最后AC了,因为将一个 char 当成 8 位来用,所以空间是很小的;

     我的思路可能不太一样,还有些暴力的痕迹,不过因为使用了位运算,加速比较明显:二叉树用数组来做,输入一个数时,顺带将这个数在二叉树中所经历路径用 1 来标记,然后遍历这些数一遍,对每个数,找出二叉树中已经标记的与这个数距离最远的叶结点,相当于对每个数在其他数中找到和它异或最大的那个,然后把这个异或的结果来更新 ans ,就可以找到最大的了。

# include <stdio.h>

# include <string.h>



# define R 0x7

# define S 0x3

# define N 17



char tree[0x1<<(N-2)];

int a[100005];



void set_bit(int x)

{

    tree[x>>S] |= 0x1<<(x & R);

}



void clr_bit(int x)          /* 这个函数实际上没用到,因为初始化是用memset()做的 */

{

    tree[x>>S] |= ~(0x1<<(x & R));

}



char get_bit(int x)

{

    return (char)((tree[x>>S]>>(x & R)) & 0x1);

}



int xor_max(int x)

{

    int i, k;

    

    k = 1;

    for (i = N-1; i >= 0; --i)

    {

        k <<= 1;

        if ((x>>i) & 0x1)

        {

            if (!get_bit(k)) k |= 0x1;

        }

        else

        {

            k |= 0x1;

            if (!get_bit(k)) k &= (~0x1);

        }

    }

    k -= (0x1<<N);

    

    return (k ^ x);

}



void pre_process(int x)

{

    int i;

    

    x += (0x1<<N);

    for (i = 0; i < N; ++i)

    {

        set_bit((x>>i));

    }

}



int max(int x, int y)

{

    return x>y? x:y;

}



int main()

{

    int n, i, ans;

        

    while (~scanf("%d", &n))

    {

        memset(tree, 0, sizeof(tree));    /* 这里应该相对耗时较多,本来想通过初始化节点1和2,最后发现不行,WA */

        

        for (i = 0; i < n; ++i)

        {

            scanf("%d", &a[i]);

            pre_process(a[i]);

        }

        

        ans = 0;

        for (i = 0; i < n; ++i)

        {

            ans = max(ans, xor_max(a[i]));

        }

        

        printf("%d\n", ans);

    }



    return 0;

}

.

你可能感兴趣的:(OJ)