• HDU4825 Xor Sum(字典树解决最大异或问题)


    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

    题意:

    给出n个数a[],然后给出m个问题Y,求a[]里面的X,有X xor Y最大。

    字典树的作用之一----最大异或:

    如果找一个数的最大异或,当然需要从高位到低位(已转化为二进制),尽可能不同。

    •  那么我们从高位到低位表示一个数X,并且存入字典树中,结尾节点记录X(不同的数结尾肯定不同)。
    •  对于询问,从高位到地位先尽可能从兄弟边走。

    这可Trie树高度为32,复杂度在接受范围内。

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn=3000010;
    inline int read()
    {
        int res=0;char x=getchar();while(x<'0'||x>'9') x=getchar();
        while(x>='0'&&x<='9'){ res=res*10+x-'0';x=getchar();}return res;
    }
    int q_pow(int a,int x){ int res=1;while(x){ if(x&1) res*=a; x>>=1; a=a*a;} return res; }
    struct TREE
    {
        int ch[maxn][2],cnt,num[maxn];
        void init() { memset(ch,0,sizeof(ch));cnt=0;}
        void insert(int s[],int val)
        {
            int Now=0;
            for(int i=31;i>=0;i--){
                if(!ch[Now][s[i]]) ch[Now][s[i]]=++cnt;
                Now=ch[Now][s[i]];
            }   num[Now]=val;
        }
        int query(int s[])
        {
            int Now=0;
            for(int i=31;i>=0;i--){
                if(ch[Now][s[i]^1]) Now=ch[Now][s[i]^1];
                else Now=ch[Now][s[i]];
            }   return num[Now];
        }
    }Tree;
    int main()
    {
        int T,n,m,x,tx,a[32],Case=0;
        scanf("%d",&T);
        while(T--){
            printf("Case #%d:
    ",++Case);
            scanf("%d%d",&n,&m);
            Tree.init();
            for(int i=1;i<=n;i++){
                 scanf("%d",&x);tx=x;
                 for(int j=0;j<=31;j++) {
                     a[j]=x%2; x>>=1;
                 } Tree.insert(a,tx);
            }
            for(int i=1;i<=m;i++) {
                 scanf("%d",&x);
                 for(int j=0;j<=31;j++) {
                     a[j]=x%2; x>>=1;
                 } printf("%d
    ",Tree.query(a));
            } 
        }return 0;
    }

    兄弟题目:Find MaxXorSum ,这个题求最大异或结果。

    所以不需要记录来自于那个数字,记录下和即可。

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn=1300010;
    inline int read()
    {
        int res=0;char x=getchar();while(x<'0'||x>'9') x=getchar();
        while(x>='0'&&x<='9'){ res=res*10+x-'0';x=getchar();}return res;
    }
    int q_pow(int a,int x){ int res=1;while(x){ if(x&1) res*=a; x>>=1; a=a*a;} return res; }
    struct TREE
    {
        int ch[maxn][2],cnt;
        void init() { memset(ch,0,sizeof(ch));cnt=0;}
        void insert(int s[])
        {
            int Now=0;
            for(int i=30;i>=0;i--){
                if(!ch[Now][s[i]]) ch[Now][s[i]]=++cnt;
                Now=ch[Now][s[i]];
            }
        }
        int query(int s[])
        {
            int Now=0,res=0;
            for(int i=30;i>=0;i--){
                if(ch[Now][s[i]^1]) Now=ch[Now][s[i]^1],res+=q_pow(2,i);
                else if(ch[Now][s[i]]) Now=ch[Now][s[i]];
                else break;
            } return res;
        }
    }Tree;
    int main()
    {
        int T,n,i,j,a[100010],b[40],tmp,ans;
        scanf("%d",&T);
        while(T--){
            Tree.init();  ans=0; scanf("%d",&n);
            for(i=1;i<=n;i++){
                 scanf("%d",&a[i]);  tmp=a[i];
                 for(j=0;j<=30;j++) {
                     b[j]=tmp%2; tmp>>=1;
                 } Tree.insert(b);
            }
            for(i=1;i<=n;i++) {
                 for(j=0;j<=30;j++) {
                        b[j]=a[i]%2; a[i]>>=1;
                 }  ans=max(ans,Tree.query(b));
            } printf("%d
    ",ans);
        }return 0;
    }
  • 相关阅读:
    TSQL(3)批处理
    TSQL(5)操作数据行
    如何设计数据库(1)?
    搜索引擎处理查询
    如何进行shell脚本正确性测试
    机房收费系统用户级别查询
    PageRank算法
    链接分析算法之:SALSA算法
    机器学习排序
    倒排索引搜索引擎的基石
  • 原文地址:https://www.cnblogs.com/hua-dong/p/8244839.html
Copyright © 2020-2023  润新知