Vitya and Strange Lesson

Vitya and Strange Lesson

https://ac.nowcoder.com/acm/problem/112209

题意:
给你一个长度为n的数组,然后有m次询问,每次询问有一个值x,让数组的每一个值异或x后,求数组中不存在的最小非负整数。

思路:
先将数组中的元素按01trie树建立, 然后每一次查询查询相当于原数组和(当前的值和前面次数的值异或)异或。
01trie树上找答案:
如果与当前位异或为0的点不存在则输出当前结果。
如果与当前位异或为0的点为根的子树满了则往异或为1找,如果还不存在则加上该位的值再输出结果。

代码:

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

int a[33], cnt[9200005][2], ji=1;
int pa[300005], f[9200005];
ll pb[300005];

void Insert()
{
    int now=0, i=31;
    while(i>=0)
    {
        if(cnt[now][a[i]]==-1)
        {
            cnt[now][a[i]]=ji;
            ji++;
        }
        now=cnt[now][a[i]];
        i--;
    }
}

int dfs(int v,int d)
{
    if(d==31)
    {
        f[v]=1;
        return 1;
    }
    if(cnt[v][0]!=-1)
    {
        dfs(cnt[v][0],d+1);
    }
    if(cnt[v][1]!=-1)
    {
        dfs(cnt[v][1],d+1);
    }
    if(f[cnt[v][1]]&&f[cnt[v][0]])
    {
        f[v]=1;
        return 1;
    }
    return 0;
}

ll fun()
{
    ll now=0, p=0, i=31, k=(1LL<<31);
    while(i>=0)
    {
        if(a[i]==1)
        {
            if(cnt[now][1]!=-1&&f[cnt[now][1]]!=1)
            {
                now=cnt[now][1];
            }
            else if(cnt[now][1]==-1)
            {
                return p;
            }
            else if(cnt[now][0]!=-1&&f[cnt[now][0]]!=1)
            {
                p=p+k;
                now=cnt[now][0];
            }
            else if(cnt[now][0]==-1)
            {
                return p+k;
            }
        }
        else
        {
            if(cnt[now][0]!=-1&&f[cnt[now][0]]!=1)
            {
                now=cnt[now][0];
            }
            else if(cnt[now][0]==-1)
            {
                return p;
            }
            else if(cnt[now][1]!=-1&&f[cnt[now][1]]!=1)
            {
                p=p+k;
                now=cnt[now][1];
            }
            else if(cnt[now][1]==-1)
            {
                return p+k;
            }
        }
        i--;
        k=k/2;
    }
    return p;
}

int main()
{
    int n, m;
    scanf("%d%d",&n,&m);
    memset(cnt,-1,sizeof(cnt));
    for(int i=0;i<n;i++)
    {
        scanf("%d",&pa[i]);
        int x=pa[i], j=0;
        memset(a,0,sizeof(a));
        while(x)
        {
            a[j++]=x%2;
            x=x/2;
        }
        Insert();
    }
    dfs(0,-1);
    for(int i=0;i<m;i++)
    {
        scanf("%lld",&pb[i]);
        if(i!=0)
        {
            pb[i]=(pb[i]^pb[i-1]);
        }
        ll x=pb[i], j=0;
        memset(a,0,sizeof(a));
        while(x)
        {
            a[j++]=x%2;
            x=x/2;
        }
        cout << fun() << endl;
    }
    return 0;
}
全部评论

相关推荐

03-26 22:27
已编辑
中南大学 Java
点赞 评论 收藏
分享
群星之怒:1.照片可以换更好一点的,可以适量P图,带一些发型,遮住额头,最好穿的正式一点,可以适当P图。2.内容太少。建议添加的:求职意向(随着投递岗位动态更改);项目经历(内容太少了建议添加一些说明,技术栈:用到了什么技术,还有你是怎么实现的,比如如何确保数据传输稳定的,角色注册用到了什么技术等等。)项目经历是大头,没有实习是硬伤,如果项目经理不突出的话基本很难过简历筛。3.有些内容不必要,比如自我评价,校内实践。如果实践和工作无关千万别写,不如多丰富丰富项目。4.排版建议:建议排版是先基础信息,然后教育背景(要突出和工作相关的课程),然后专业技能(一定要简短,不要长篇大论,写你会什么,会的程度就可以),然后是项目经历(一定要详细,占整个简历一定要超过一半,甚至超过百分之70都可以)。最后如果有一部分空白的话可以填补上校内获得的专业相关的奖项,没有就写点校园经历和自我评价。5.技术一定要够硬,禁得住拷打。还有作息尽量保证正常,不要太焦虑。我24双非本科还是非科班,秋招春招各找了一段实习结果都没有转正,当时都想噶了,最后6月份在校的尾巴也找到一份工作干到现在,找工作有时很看运气的不要急着自我否定。 加油
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务