zoukankan      html  css  js  c++  java
  • HDU 4825 Trie树 异或树!

    Xor Sum

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)
    Total Submission(s): 2403    Accepted Submission(s): 1041


    Problem Description
    Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问,每次询问中包含一个正整数 S ,之后 Zeus 需要在集合当中找出一个正整数 K ,使得 K 与 S 的异或结果最大。Prometheus 为了让 Zeus 看到人类的伟大,随即同意 Zeus 可以向人类求助。你能证明人类的智慧么?
     
    Input
    输入包含若干组测试数据,每组测试数据包含若干行。
    输入的第一行是一个整数T(T < 10),表示共有T组数据。
    每组数据的第一行输入两个正整数N,M(<1=N,M<=100000),接下来一行,包含N个正整数,代表 Zeus 的获得的集合,之后M行,每行一个正整数S,代表 Prometheus 询问的正整数。所有正整数均不超过2^32。
     
    Output
    对于每组数据,首先需要输出单独一行”Case #?:”,其中问号处应填入当前的数据组数,组数从1开始计算。
    对于每个询问,输出一个正整数K,使得K与S异或值最大。
     
    Sample Input
    2 3 2 3 4 5 1 5 4 1 4 6 5 6 3
     
    Sample Output
    Case #1: 4 3 Case #2: 4
     先声明自己智障的看错输出的结果,以为输出最大的异或后的值,谁知道与哪个数异或后的值最大,就输出那个数,尴尬还以为样例错了。。。
    字典树这样玩真的好酷炫,我是看了用字典树才想到怎么写惭愧,这样真的好巧妙,利用了字典树前缀和的思想在O(len)的时间就能算出结果!
    将每个数按二进制33位不够得话高位补零,从高到低位存入字典树中,其实就是一颗只含01的字典树。
    之所以由高到低是由于高位决定数的大小(贪心思想),对于读入的每个数也按33位在树上匹配,在满足条件的情况下尽可能的选择与bit不相同的位置走,
    这样答案就会最大,最后输出ans^num就是原来的数!
    可能动态键树释放内存的操作时间挺慢的跑700+ms,我看静态数组都是200左右
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define LL long long
     4 
     5 struct node
     6 {
     7     node *child[2];
     8     node(){child[0]=child[1]=NULL;}
     9 };
    10 node *root;
    11 void Clear(node *p)
    12 {
    13     if(p==NULL) return;
    14     for(int i=0;i<2;++i){
    15         if(p->child[i]!=NULL) Clear(p->child[i]);
    16     }
    17     delete p;
    18 }
    19 void add(LL num)
    20 {
    21    node *p=root;
    22    int i,bit;
    23    for(i=32;i>=0;--i){
    24       bit=(num&((LL)1<<i))?1:0;
    25       if(p->child[bit]==NULL)
    26         p->child[bit]=new node();
    27       p=p->child[bit];
    28    }
    29 }
    30 LL solve(LL num)
    31 {
    32  node *p=root;
    33  int i,bit[2];  LL ans=0;
    34  for(i=32;i>=0;--i){
    35     bit[0]=(num&((LL)1<<i))?1:0;
    36     if(p->child[bit[0]^1]!=NULL){
    37         p=p->child[bit[0]^1];
    38         bit[1]=1;
    39     }
    40     else {p=p->child[bit[0]];bit[1]=0;}
    41     if(bit[1]) ans+=((LL)1<<i);
    42  }
    43  return ans;
    44 }
    45 int main()
    46 {
    47     int T,N,M,i,j,k=0;
    48     LL n;
    49     cin>>T;
    50     while(T--){root=new node();
    51         cin>>N>>M;
    52         for(i=1;i<=N;++i){
    53             scanf("%lld",&n);
    54             add(n);
    55         }printf("Case #%d:
    ",++k);
    56         for(i=1;i<=M;++i){
    57             scanf("%lld",&n);
    58             printf("%lld
    ",n^solve(n));
    59         }
    60         Clear(root);
    61     }
    62     return 0;
    63 }
  • 相关阅读:
    一种想法
    识别link_text
    识别name
    识别id
    文件的读写
    条件和循环
    网站测试-功能测试小结
    拷贝
    #团队博客作业1-小组成员介绍
    软件测试基础-Homework1
  • 原文地址:https://www.cnblogs.com/zzqc/p/7219905.html
Copyright © 2011-2022 走看看