zoukankan      html  css  js  c++  java
  • hdu4825 字典树 + 贪心

    题意:
          给你n个数,然后给你m组询问,每组询问给你一个数,输出n个数中与该数亦或
    的最大的那个数,输出的是被亦或的那个数,不是亦或后的结果。


    思路:
          我用的是字典树+贪心,首先我们可以把前n个数拆成2进制,然后补全前导0,

    我是补成了34位,然后把他存在字典树中,对于每个询问,把他变成二进制,然后补全前导0,然后在把每一位都取反,在字典树上查找,查找的时候用贪心的思想,因为前面的是高位,所以相等就走相等的,不行再走不相等的那个,反正都是34位,怎么走都有路,一直找到最后,在某一位上如果当前这一位一样了,那么sum += 当前这一位的权值(2^**),然后return sum,输出的时候不能直接输出sum求的是被异或的那个值,所以输出 sum ^ num,根据的是 a ^ b ^ a = b,还有一点要注意的就是一开始超时了,后来把 %2 改成 &1就400+ ms AC了.


    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    
    typedef struct Tree
    {
        Tree *next[2];
    }Tree;
    
    Tree root;
    
    void Buid_Tree(char *str)
    {
        int len = 34;
        Tree *p = &root ,*q;
        for(int i = 0 ;i < len ;i ++)
        {
           int id = str[i] - '0';
           if(p -> next[id] == NULL)
           {
               q = (Tree *) malloc(sizeof(root));
               for(int j = 0 ;j < 2 ;j ++)
               q -> next[j] = NULL;
               p ->next[id] = q;
               p = p -> next[id];
           }
           else p = p -> next[id];
         }
    }
    
    __int64 Find(char *str)
    {
        int len = 34;
        Tree *p = &root;
        __int64 K = 2;
        K <<= 32;
        __int64 sum = 0;
        for(int i = 0 ;i < len ;i ++)
        {
            int id = str[i] - '0';
            if(p -> next[id] == NULL)
            p = p -> next[id ^ 1];
            else
            {
                p = p -> next[id];
                sum += K;
            }
            K = K / 2;
        }
        return sum;
    }
    
    void get_str(char *str ,__int64 num)
    {
        int t = 34;
        str[t] = '';
        while(num)
        {
           str[--t] = (num & 1) + '0';
           num >>= 1;
        }
        for(int i = t - 1 ;i >= 0 ;i --)
        str[i] = '0';
    }
    
    int main ()
    {
        int i ,t ,n ,m ,cas = 1;
        __int64 num;
        char str[50];
        scanf("%d" ,&t);
        while(t--)
        {
            scanf("%d %d" ,&n ,&m);
            root.next[0] = root.next[1] = NULL;
            while(n--)
            {
                scanf("%I64d" ,&num);
                get_str(str ,num);
                Buid_Tree(str);
            }
            printf("Case #%d:
    " ,cas ++);
            while(m--)
            {
               scanf("%I64d" ,&num);
               get_str(str ,num);
               for(i = 0 ;i < 34 ;i ++)
               if(str[i] == '1') str[i] = '0';
               else str[i] = '1';
               printf("%I64d
    " ,Find(str) ^ num);
            }
        }
        return 0;
    }
    
    
    
    
    
    
    
    
    
    

  • 相关阅读:
    Java注释中的@deprecated与源代码中的@Deprecated
    android KE or NE分析
    Android手机中UID、PID作用及区别
    mtk刷机错误汇总
    区分Integer.getInteger和Integer.valueOf、Integer.parseInt() 的使用方法
    :>/dev/null 2>&1 的作用
    android 小技巧
    转:Eclipse自动补全功能轻松设置
    android开发常用地址
    转:大数据 2016 landscape
  • 原文地址:https://www.cnblogs.com/csnd/p/12062982.html
Copyright © 2011-2022 走看看