HDU

来源:互联网 发布:数组foreach c# 编辑:程序博客网 时间:2024/06/05 14:13

题意:在集合K里,每次给一个整数S,问集合K里哪个数和S异或的值最大

这个问题一开始是在不明白异或思想题目给的数据量让我知道不用数据结构写的代码都是瞎BB。。。。

求一个数在一个集合里的最大异或,首先要了解一下异或思想

异或:相同为0,不同为1

思路:可以将其处理为一位一位的,从高位置到底位置找不同,如果不同就采用,是在没有不同的那没办法,那只能相同了,从高位往低位找一遍

每一个都找,想想是不是想到了****数据结构???

没错!!!字典树!!!

字典树把所有数据都存成字典树 int类型 最大32*10万的数据量

代码直接敲吧,细节的问题打注释

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;typedef long long ll;const int maxn = 1e5 + 5;int T,n,m;ll num;struct Trie{    int tot,child[maxn * 32][2];//只有两个分支和二叉树很像    void Init(){tot = 0; memset(child,-1,sizeof(child));}//初始化    void Insert(ll x){        int temp[32] = {0} , cnt = 32;        while(x){temp[--cnt] = x & 1; x >>= 1; /*把一个正常的数字转化为一个倒叙的二进制表达形式,这一步是二进制的方法*/}        int root = 0;//根为第零层        for(int i = 0; i < 32; i++){            if(child[root][temp[i]] == -1) child[root][temp[i]] = ++tot;//如果没有就创造一个新的阶点,用一个不是0的值(这个值是编号)存储            root = child[root][temp[i]];        }    }    ll Query(ll x){        //查找前几部准备工作和插入相同        int temp[32] = {0} , cnt = 32;        while(x){temp[--cnt] = x & 1; x >>= 1; /*把一个正常的数字转化为一个倒叙的二进制表达形式,这一步是二进制的方法*/}        int root = 0;//根为第零层        ll ans = 0;        for(int i = 0; i < 32; i++){            if(child[root][temp[i]^1] != -1){//可以就插入,插入不同值                ans = ans * 2 + (temp[i]^1);                root = child[root][temp[i]^1];//继续往下走            }else{//是在没有只能委屈自己直接往下走了,真没有也没办法                ans = ans * 2 + temp[i];                root = child[root][temp[i]];            }        }        return ans;    }}trie;int main(){    //主函数已经不需要过度操作了,直接输入和输出查找完成    scanf("%d",&T);    for(int kase = 1; kase <= T; kase ++){        scanf("%d %d",&n,&m);        trie.Init();        for(int i = 1; i <= n;i++){            scanf("%lld",&num);            trie.Insert(num);        }        printf("Case #%d:\n",kase);        for(int i = 1; i <= m;i ++)        {            scanf("%lld",&num);            printf("%lld\n",trie.Query(num));        }    }    return 0;}


原创粉丝点击