• G


    G - Vitya and Strange Lesson

    CodeForces - 842D

    题意:给你一个数组,让数组里面的值都异或一下x,并构成一个新的数组,求这个数组的mex

    mex的含义:不在数组中的最小正整数。

    思路:

    异或的交换律

    1.首先我们知道,异或x之后得到的数组将其再异或y值得到的数组,其实就是原数组异或(x^y)的结果。所以这里我们没有必要将原数组进行变化。

    异或的唯一性即 a^b=c 如果b,c确定则a就确定

    2.我们将原数组中不存在的数入树。那么对于每一个查询temp,其实就相当于我们在树上找一个值,使得这个值亦或temp最小。(如果此处不懂,请看最后面)

    3.找出异或最小值即可

    **那么这个数的范围怎么确定呢?**题中所有数据的范围都在0~3e5之间,即二进制第25位之前的全为0,

    所以数组中的数与x异或后的数也都满足第二进制第25位之前的全为0,那么所求的mex的二进制的第25位之前也全为0,a^b=c b c满足这样,所以a的进制的第25位之前也全为0,

    即要求原数组中不存在的数的范围最下为2^25即可(这样的1~25位的的二进制所有情况全部枚举,答案肯定是与其中一个异或)

    #include<iostream>
    #include<string.h>
    #include<string>
    #include<stdio.h>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int maxn=10000010;
    const int maxval=524288;
    int ans[40];
    int book[maxval];
    struct Node{
        int net[2];
        Node()
        {
            clear();
        }
        void clear()
        {
          net[0]=net[1]=-1;
        }
    }node[maxn];
    int top;
    void clear_tree(int &top)//清空树
    {
        for(int i=0;i<=top;++i)
            node[i].clear();
        top=0;
    }
    int Getbit(int &val,int k)//val的第k位是多少
    {
        if(val&(1<<(k-1)))
            return 1;
        return 0;
    }
    void Becomebit(int &val,int k,int BitVal)//将val的第k位变为BitVal
    {
        if(BitVal)
            val=val|(1<<(k-1));
        else
            val=val&(~(1<<(k-1)));
    }
    void insert_node(int &val)//将val的二进制位从高到低插入进字典树内
    {
        int now=0;
        for(int i=32;i;--i)
        {
            if(node[now].net[Getbit(val,i)]==-1)
                node[now].net[Getbit(val,i)]=++top;
            now=node[now].net[Getbit(val,i)];
        }
    }
    int dfs(int now,int bit,int k)//根据当前节点和位数返回下一个节点  并且记下选的位数
    {
        if(~node[now].net[bit])
        {
            ans[k]=bit;
            return node[now].net[bit];
        }
        ans[k]=bit?0:1;
        return node[now].net[bit?0:1];
    }
    int Solve(int &val)//x的值不能改变
    {
        int now=0;
        for(int i=32;i;--i)
        {
          now=dfs(now,Getbit(val,i),i);//this?
        }
        int res;
        for(int i=32;i;--i)
          Becomebit(res,i,ans[i]);
        return res;
    }
    int main()
    {
        int x,n,m;
        scanf("%d %d",&n,&m);
        memset(book,0,sizeof(book));
        for(int i=0;i<n;++i)
        {
            int mid;
            scanf("%d",&mid);
            book[mid]=1;
        }
        x=0;
        for(int i=0;i<=maxval;++i)
            if(!book[i])
               insert_node(i);//this?
        while(m--)
        {
            int mid;
            scanf("%d",&mid);
            x^=mid;
            printf("%d
    ",x^Solve(x));
        }
    }
    
    

    参考博客 https://blog.csdn.net/mengxiang000000/article/details/77718605

    为什么与原数组异或x后的数组的mex不在原数组中的数与x异或的最小值

    假设现在数组a与x异或得到数组c 那么因为异或的唯一性,不在数组c的值构成的集合即为不在数组a的值与x异或构成的集合,(因为在数组a的值与x异或一定在数组c中)
    在这里插入图片描述

  • 相关阅读:
    java-String类
    多线程的细节
    java-多线程的练习----妖,等待唤醒,代码重构,lock到condition
    javascript函数的声明和调用
    表单
    java-多线程的入门_进阶总结
    uboot命令
    u-boot移植 III
    u-boot移植 II
    汇编词典
  • 原文地址:https://www.cnblogs.com/dchnzlh/p/10427311.html
Copyright © 2020-2023  润新知