首页 > 其他分享 >HDU−4825 XorSum

HDU−4825 XorSum

时间:2023-07-27 14:22:40浏览次数:31  
标签:HDU Zeus 正整数 int 4825 tree trie 异或 XorSum

01trie树

定义:将整数转化为二进制再插入 trie 树,通常是从高位到低位插入trie。

使用场景:寻找与异或相关的结果

题目背景:

Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问,每次询问中包含一个正整数 S ,之后 Zeus 需要在集合当中找出一个正整数 K ,使得 K 与 S 的异或结果最大。Prometheus 为了让 Zeus 看到人类的伟大,随即同意 Zeus 可以向人类求助。你能证明人类的智慧么?

输入:

输入包含若干组测试数据,每组测试数据包含若干行。
输入的第一行是一个整数T(T < 10),表示共有T组数据。
每组数据的第一行输入两个正整数N,M(<1=N,M<=100000),接下来一行,包含N个正整数,代表 Zeus 的获得的集合,之后M行,每行一个正整数S,代表 Prometheus 询问的正整数。所有正整数均不超过2^32。

输出:

对于每组数据,首先需要输出单独一行”Case #?:”,其中问号处应填入当前的数据组数,组数从1开始计算。
对于每个询问,输出一个正整数K,使得K与S异或值最大。

样例:
输入:
2
3 2
3 4 5
1
5
4 1
4 6 5 6
3

输出:
Case #1:
4
3
Case #2:
4


题目大意:

对于每一个 s 在 n 个数中找一个,使得与其异或值最大。

步骤:

1.将n个整数,转化成二进制,从高位到低位插入 trie 树

2.对于询问的整数 s ,从高位开始与trie树中的结点比对:若 s[i] = 0 ,则尝试走 trie 中值为 1 的结点,反之尝试走 trie 中值为 0 的结点。(这样异或值最大)

这样说可能会有些抽象。

举一个例子: n 个数中第一个是 29 ,就先把它化成 2 进制,也就是 11101 ,注意前面要加零凑够 32 位数于是我们得到了一棵树(此处省略前面的零, 1 为右节点, 0 为左节点):

这时第二个数是 24 ,我们发现它的一部分与 29 相同,就只需要补齐其他的节点了,这个图里,两个数都可以找到:

像这样我们把 n 个数都映射到 trie 树上下一步肯定有对应的数。这题正好是异或操作,我们只需要把每一个 s 从高位到低位寻找树上的点(高位为 1 肯定更大),因为异或值当前位为 1 ,两个异或的数的这一位肯定不同,所以对于 s 的每一位,如果为 1 去 0 (左节点)否则反之,当然没有期望的数就只能走相反的一边了。

Code:

#include<bits/stdc++.h>
using namespace std;
int tree[3300000][2];
int tot,n,q,t,now;
int xx[100001];

void insert(int x){
    int u=0;
    for(int i=31;i>=0;i--){
        int k=(x>>i)&1;
        if(!tree[u][k]){
            tree[u][k]=++tot;
        }
        u=tree[u][k];
    }
    return;
} 

int search(int x){
    long long ans=0;
    int u=0;
    for(int i=31;i>=0;i--){
        int k=(x>>i)&1;
        if(tree[u][k^1]){
            ans+=(k^1)<<i;
            u=tree[u][k^1];
        }
        else{
            ans+=k<<i;
            u=tree[u][k];
        }
    }
    return ans;
}

void ans(){
    for(int i=1;i<=n;i++){
        int x;
        cin>>x;
        insert(x);
    }    
    for(int i=1;i<=q;i++){
        cin>>xx[i];    
    }
    cout<<"Case #"<<now<<":"<<endl;
    for(int i=1;i<=q;i++){
        cout<<search(xx[i])<<endl;
    }
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>t;
    now=0;
    while(t--){
        now++;
        memset(tree,0,sizeof(tree));
        tot=0;
        cin>>n>>q;
        ans();
    }
    return 0;
}

注意要点(坑):

1. 2的32次方 已经超出了 int 的范围;
2. 这题时间卡得很紧,读入不能直接 cin 要么加 ios 要么写 scanf。

标签:HDU,Zeus,正整数,int,4825,tree,trie,异或,XorSum
From: https://www.cnblogs.com/wangwenhan/p/17584800.html

相关文章

  • HDU 暑假多校 2023 第三场
    目录写在前面731073047311写在最后写在前面补题地址:https://acm.hdu.edu.cn/listproblem.php?vol=64,题号7300~7311。坐牢场。老东西怎么还在圈里混啊(恼以下按个人向难度排序,标题为题库中题号。7310模拟这个过程。缩放至\(Z\%\)即将原来的某个像素覆盖的范围\((x-1,y-1......
  • HDU4738 Caocao's Bridges
    \(HDU4738\)\(Caocao\)'\(s\)\(Bridges\)一、题目描述曹操在长江上建立了一些点,点之间有一些边连着。如果这些点构成的无向图变成了连通图,那么曹操就无敌了。刘备为了防止曹操变得无敌,就打算去摧毁连接曹操的点的桥。但是诸葛亮把所有炸弹都带走了,只留下一枚给刘备。所以刘......
  • hdu6089 Rikka with Terrorist
    \(n\timesm\)网格图,给一个指定的点集\(S\),\(q\)次询问(\(n,m,q,|S|\le10^5\)),给定一个点\((x,y)\),问有多少个目标点\((x',y')\)满足\[\not\exist(x_0,y_0)\inS:x_0\in[\min(x',x),\max(x',x)],y_0\in[\min(y',y),\max(y',y)]\]图都是......
  • HDU 暑假多校 2023 第一场
    目录写在前面72837279727672757284写在最后写在前面补题地址:HDUOJ题库第63页,题号7275~7286。以下题号以题库中题号为准。题目选补,按照个人认为题目难度排序,因为我是菜狗。打这场看到马娘题目直接整个人兴奋,于是推了3h推不出来滚粗了。以为是手玩题没想到是正统博弈论呃......
  • 线段树hdu-4027
    Smiling&Weeping ----姑娘,倘若,我双手合十的愿望里有你呢ProblemDescriptionAlotofbattleshipsofevilarearrangedinalinebeforethebattle.Ourcommanderdecidestouseoursecretweapontoeliminatethebattleships.Ea......
  • HDU 5492 Find a path 题解
    Description在矩阵中,找一条到从\((1,1)\)到\((n,m)\)(只能向上,右走)的路径,使路径上方差最小。输出方差平方乘\(n+m-1\)的结果。对于所有数据,\(1\leqn,m,A_{i,j}\leq30\)。Solution设路径上的数为\(A_{1},A_{2},A_{3},\cdots,A_{n+m-1}\),\(\overline{A}\)为其平均数,则答......
  • hdu 2177 取(2堆)石子游戏 (博弈)
    题意:有两堆石子,两人轮流取石子,轮到某人时,有两种取法,要么从两堆石子中同时取出一定数量的石子,要么只从一堆中取任意数量的石子,不能不取。不能取的人判为输。普通思想:对于博弈问题,首先想到的就是sg函数。所以我们先从小到大的看局面。可以得出,对于每一种状态(x,y)x,y为石子堆。要么(x,y)本身......
  • HDU 1595 find the longest of the shortest
    题意:对于题目给定的一个图,问去掉起点到终点的最短路径上的某一条边之后起点到终点的最短距离里的最大值。思路:先计算原图的最短路径,保存最短路径。枚举最短路径每一条边,删掉该边,然后计算最短路径,保留最大的那个即可。实现:先用一个spfa求得最短路径,用一个路径数组保存路径。然后枚举......
  • hdu 1142 A Walk Through the Forest
    WA了好多次了,大概是一直没搞清题意。题意:对边<a,b>,如果a到终点的距离小于b到终点的距离,那么b就可以到a,但是a就不能到b了,所以经过这样的一种筛选的方法之后,我们要在这样的图里寻找能从起点走到终点的路径的总数。思路:先算出每一点到终点的最小距离;然后dfs记忆化搜索路径总数。#incl......
  • hdu 1150 Machine Schedule
    二部图问题:每个任务的两种模式对应一条边,那么最大的匹配数就是最多的任务不用改变模式的任务数。相当于求最小点覆盖,而最小点覆盖=最大匹配数 代码:#include<stdio.h>#include<string.h>#include<algorithm>#include<iostream>usingnamespacestd;#defineMAXN110intuN,......