• 【算法竞赛进阶指南】字典树 The XOR Largest Pair


    题目链接

    题意

    给出 N 个数字,任意选择两个数字进行异或运算,求结果最大值。

    思路

    我们对于每个数字求与其异或得到的最大值,求这 N 个最大值的最大值。

    把每个数字看做一个长度为 32 的二进制串,将其翻转,更新到 trie 中。

    对于每个二进制串 (S),遍历其值 (S_i)
    在 trie 中每次都尝试向下访问与 (S_i) 相反的字符。
    如果能向下访问那么向下访问,当前数字增加 (1LL<<(31-i)) ( 字符下标从 0 开始),
    否则向下访问与当前字符相同的节点。

    代码

    #include<bits/stdc++.h>
    typedef long long ll;
    using namespace std;
    const ll N=2e6+10;
    
    ll arr[N];
    int tot=1,trie[N][2];
    ll s[N];
    void insert()
    {
    	ll p=1;
    	for(ll i=0;i<32;i++){
    		ll now=s[i];
    		if(!trie[p][now]){
    			trie[p][now]=++tot;
    		}
    		p=trie[p][now];
    	}
    }
    
    ll solve()
    {
    	ll rel=0,p=1,cnt=31;
    	for(ll i=0;i<32;i++,cnt--){
    		ll now=1^s[i];
    		if(trie[p][now]){
    			rel+=(1LL<<cnt);
    		}else{
    			now=s[i];
    		}
    		p=trie[p][now];
    	}	
    	return rel;
    }
    
    int main()
    {
    	ll n,rel=0;
    	scanf("%lld",&n);
    	for(ll i=1;i<=n;i++){
    		scanf("%lld",&arr[i]);
    		for(ll j=0;j<32;j++){
    			s[31-j]=(arr[i]&(1LL<<j))?1:0;
    		}
    		insert();
    		rel=max(rel,solve());
    	}
    	printf("%lld
    ",rel);
    	return 0;
    }
    
  • 相关阅读:
    牛客练习赛51
    [HZOI 2016] 偏序(CDQ套CDQ)
    AtCoder Beginner Contest 140
    [国家集训队] 拉拉队排练
    [CF91B] Queue
    [AT3867] Digit Sum 2
    [TJOI2007] 路标设置
    [HNOI2001] 求正整数
    [十二省联考2019] 异或粽子
    [SDOI2013] 直径
  • 原文地址:https://www.cnblogs.com/valk3/p/13917929.html
Copyright © 2020-2023  润新知