zoukankan      html  css  js  c++  java
  • HDU 4285

    Xor Sum

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

    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

    题目大意:

    给出 t 组数据,对于每组数据,输入 n q 表示n 个数和q 个询问,接下来输入n个数,然后再输出q个数,对于每个询问,输出 n 个数中与 该数异或值最大的数。

    解题思路:

    01字典树模板题,建树以后直接插入查询即可。

    Code:

    #pragma GCC optimize(2)
    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <cstring>
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    const int N = 1e5 + 50;
    int tot = 1;
    ll val[N * 32], ch[N * 32][2];
    void init()
    {
    	memset(ch, 0, sizeof ch);
    	memset(val, 0, sizeof val);
    	tot = 1;
    }
    void insert(ll x)//插入的过程
    {
    	int u = 0;
    	for (int i = 31; i >= 0; i --)
    	{
    		int v = (x >> i) & 1;//从大到小依次按位&1
    		if (!ch[u][v])//如果这个节点没有被访问过则插入新节点
    		{
    			ch[tot][0] = ch[tot][1] = 0;//下一个节点初始化
    			ch[u][v] = tot++;//当前的u v(0或1)指向下一个节点
    			val[tot] = 0;//因为没到最底层节点,所以 = 0
    		}
    		u = ch[u][v];//类似于指针,指向下一个编号
    	}
    	val[u] = x;
    }
    ll query(ll x)
    {
    	int u = 0;
    	for (int i = 31; i >= 0; i --)
    	{
    		int v = (x >> i) & 1;
    		if (ch[u][v ^ 1])  u = ch[u][v ^ 1];//每次去找和v不一样的,使异或值最大
    		else  u = ch[u][v];
    	}
    	return val[u];
    }
    int main()
    {
    	ios::sync_with_stdio(false);
    	int t, k = 1;
    	cin >> t;
    	while (t--)
    	{
    		cout << "Case #" << k++ << ':' << endl;
    		init();
    		int n, q;
    		cin >> n >> q;
    		for (int i = 1; i <= n; i ++)
    		{
    			int s;
    			cin >> s;
    			insert(s);
    		}
    		while (q--)
    		{
    			ll s;
    			cin >> s;
    			cout << query(s) << endl;
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    [转]VC++中操作XML(MFC、SDK)
    VC解析XML--使用CMarkup类解析XML
    C++基础--完善Socket C/S ,实现客户端,服务器端断开重连
    socket编程的select模型
    libevent源码分析
    socket异步编程--libevent的使用
    Win32编程点滴3
    Win32编程点滴5
    thrift之TTransport层的堵塞的套接字I/O传输类TSocket
    Thrift之代码生成器Compiler原理及源码详细解析1
  • 原文地址:https://www.cnblogs.com/Hayasaka/p/14294167.html
Copyright © 2011-2022 走看看