hdu4825---Xor Sum(Trie + 贪心)

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

Source

2014年百度之星程序设计大赛 - 资格赛

Recommend

liuyiding | We have carefully selected several similar problems for you: 5235 5234 5233 5232 5231

把n个数化成二进制,然后建立Trie树

接下来贪心遍历这棵树就行

/*************************************************************************
    > File Name: hdu4825.cpp
    > Author: ALex
    > Mail: [email protected]
    > Created Time: 2015年05月25日 星期一 14时36分41秒
 ************************************************************************/

#include <functional>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <stack>
#include <map>
#include <bitset>
#include <set>
#include <vector>

using namespace std;

const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const double eps = 1e-15;
typedef long long LL;
typedef pair <int, int> PLL;

int bit[40];
static const int MaxNode = 3200010;
class Trie {
    public:
        void init();
        int newnode();
        void insert(int bit[], int w);
        int getNum(int bit[], int w);
    private:
        int next[MaxNode][2];
        int end[MaxNode];
        int L, root;
}trie;

int Trie :: newnode() {
    next[L][0] = next[L][1] = -1;
    ++L;
    return L - 1;
}

void Trie :: init() {
    L = 0;
    root = newnode();
}

void Trie :: insert(int bit[], int w) {
    int now = root;
    for (int i = 31; i >= 0; --i) {
        if (next[now][bit[i]] == -1) {
            next[now][bit[i]] = newnode();
        }
        now = next[now][bit[i]];
    }
    end[now] = w;
}

int Trie :: getNum(int bit[], int w) {
    int now = root;
    for (int i = 31; i >= 0; --i) {
        if (next[now][bit[i] ^ 1] == -1) {
            now = next[now][bit[i]];
        }
        else {
            now = next[now][bit[i] ^ 1];
        }
    }
    return end[now];
};

void calc(int num) {
    int cnt = 0;
    while (num) {
        bit[cnt++] = num % 2;
        num >>= 1;
    }
    for (int i = cnt; i <= 31; ++i) {
        bit[i] = 0;
    }
}

int main() {
    int t, icase = 1;
    scanf("%d", &t);
    while (t--) {
        int n, m, w;
        scanf("%d%d", &n, &m);
        trie.init();
        for (int i = 1; i <= n; ++i) {
            scanf("%d", &w);
            calc(w);
            trie.insert(bit, w);
        }
        printf("Case #%d:\n", icase++);
        for (int i = 1; i <= m; ++i) {
            scanf("%d", &w);
            calc(w);
            printf("%d\n", trie.getNum(bit, w));
        }
    }
    return 0;
}
时间: 2024-08-30 11:56:21

hdu4825---Xor Sum(Trie + 贪心)的相关文章

hdu 4825 Xor Sum(trie+贪心)

hdu 4825 Xor Sum(trie+贪心) 刚刚补了前天的CF的D题再做这题感觉轻松了许多.简直一个模子啊...跑树上异或x最大值.贪心地让某位的值与x对应位的值不同即可. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 #define CLR(a,b) memset((a)

HDU--4825 Xor Sum (字典树)

题目链接:HDU--4825 Xor Sum mmp sb字典树因为数组开的不够大一直wa 不是报的 re!!! 找了一下午bug 草 把每个数转化成二进制存字典树里面 然后尽量取与x这个位置上不相同的 先来一个最原始的代码写的跟屎一样的 #include<iostream> #include<cstring> #include<algorithm> #include<string.h> #include<stdio.h> #include<

hdu 4828 Xor Sum (trie 树模板题,经典应用)

hdu 4825 题目链接 题意:给定n个数,然后给出m个询问,每组询问一个数x,问n中的数y使得x和y的异或和最大. 思路:字典树..把每个数转化成二进制,注意补全前导0,使得所有数都有相同的位数. 如果想要异或和最大,那么每一位尽可能都是1. 所以做法是,先构建字典树,然后每次find的时候,尽可能按照和当前寻找的数的位相反的位的方向走(如果有的话) 比如当前位是1,那我就往0的方向走. 需要注意的是,多组数据,每次要重新初始化一遍. 做法是 在struct 中重新 root = new N

hdu 4285 Xor Sum trie树

Xor Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others) Problem Description Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问,每次询问中包含一个正整数 S ,之后 Zeus 需要在集合当中找出一个正整数 K ,使得 K

HDU4825 Xor Sum(贪心+Trie树)

今天本来想写一个可持久化Trie树,发现这道题一直没做就补上了. 其实思路很简单,假如说两个数,和同一个数异或,很显然,由于进制,高位上的一个1可以大于低位上所有1,所以即使后面的情况再糟糕,也比取后面好的值高(其实就是1000比0111大) 所以可以建一个01线段树,从高往低插入一个数,比较时取反即可^_^ 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace st

HDU4825 Xor Sum

题意 给定一个集合后, 求一组查询中每个数和集合中任一元素异或的最大值. 题解 异或的规律是这样的 1 ^ 1 = 0, 0 ^ 0 = 0, 1 ^ 0 = 1, 0 ^ 1 = 1, 而最大值即是代表了, 在 靠前的位置 上有 尽量多的 1 . 因此, 对于答案来说, 等价于 在 靠前的位置 上有 尽量与查询数值对应位不相同的数字 这类题目可以用 01Trie 在 O(1) 的时间内完成对 一个查询 的求解. 具体思路: 对于一个数字, 首先取反(也可以不取反, 只不过后续判断条件会有稍微变

Xor Sum(字典树加贪心)

Xor Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others) Total Submission(s): 457    Accepted Submission(s): 231 Problem Description Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeu

HDU 4825 Xor Sum(经典01字典树+贪心)

Xor Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others) Total Submission(s): 1555    Accepted Submission(s): 657 Problem Description Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Ze

Xor Sum 01字典树 hdu4825

Xor Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)Total Submission(s): 4119    Accepted Submission(s): 1796 Problem Description Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Ze