zoukankan      html  css  js  c++  java
  • hdu4825

    hdu4825 Xor Sum
    传送门
    给定一个集合,包含n个正整数,发起m次询问,每次询问包含一个正整数s,每次在集合中找到一个正整数k,使得s与k的异或值最大,输出正整数k。
    1<=n,m<=100000,正整数不超过(2^{32})

    暴力寻找必然超时,需要优化查找方法。
    假设询问的正整数s的二进制形式为1101011100001101011000101101010(31位),想要异或值最大,首先在集合中查找最高位异或值为1的数,也就是最高位为0的数。如果存在,则继续在这些数里寻找次高位异或值为1的数,否则就在所有数中寻找次高位异或值为1的数,以此类推,31位全部找完之后,得到的就是异或值最大时的情形。
    预处理将集合中的所有数建成一棵trie树,在线处理询问。
    每一次询问,查找的时间复杂度为(O(logn)),一共m次询问,总时间复杂度为(O(mlogn))
    以样例二为例子,集合中的数为4(100),6(110),5(101),6(110),询问的数为3(011),建立trie树,则沿着图中红色路径,异或值最大,异或的数为4。

    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<algorithm>
    #define LL long long
    using namespace std;
    
    int T,cas,n,m,son[3200010][2],number[3200010],id;
    
    void insert(int x){
    	int p=0;
    	for(int i=30;i>=0;i--){
    		int& t=son[p][(x>>i)&1];
    		if(!t) t=++id;
    		p=t;
    	}
    	number[p]=x;
    }
    
    int query(int x){
    	int p=0;
    	for(int i=30;i>=0;i--){
    		int t=son[p][!((x>>i)&1)];
    		if(t){
    			p=t;
    		}
    		else{
    			p=son[p][(x>>i)&1];
    		}
    	}
    	return number[p];
    }
    
    int main(){
    	scanf("%d",&T);
    	while(T--){
    		scanf("%d %d",&n,&m);
    		memset(son,0,sizeof(son));
    		id=0;
    		for(int i=1;i<=n;i++){
    			int x;
    			scanf("%d",&x);
    			insert(x);
    		}
    		printf("Case #%d:
    ",++cas);
    		while(m--){
    			int x;
    			scanf("%d",&x);
    			printf("%d
    ",query(x));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    LVS-三种负载均衡方式比较
    keepalived和heartbeat区别
    vmware-question
    SQL Server MYSQL 检查点的好处
    MYSQL 引擎的情况
    MYSQL 关闭服务的过程
    SQL Server 行的删除与修改-------------(未完待续P222 deep SQL Server 222 )
    SQL Server一些重要视图 1
    SQL Server 查看数据页面
    SQL Server 向堆表中插入数据的过程
  • 原文地址:https://www.cnblogs.com/fxq1304/p/12994997.html
Copyright © 2011-2022 走看看