Codeforces 842 D Vitya and Strange Lesson

Codeforces 842 D Vitya and Strange Lesson

Today at the lesson Vitya learned a very interesting function — mex. Mex of a sequence of numbers is the minimum non-negative number that is not present in the sequence as element. For example, mex([4,33,0,1,1,5])=2 and mex([1,2,3])=0.

Vitya quickly understood all tasks of the teacher, but can you do the same?

You are given an array consisting of n non-negative integers, and m queries. Each query is characterized by one number x and consists of the following consecutive steps:

Perform the bitwise addition operation modulo 2 (xor) of each array element with the number x.
Find mex of the resulting array.
Note that after each query the array changes.
Input
First line contains two integer numbers n and m (1 ≤ n, m ≤ 3·105) — number of elements in array and number of queries.

Next line contains n integer numbers ai (0 ≤ ai ≤ 3·105) — elements of then array.

Each of next m lines contains query — one integer number x (0 ≤ x ≤ 3·105).

Output
For each query print the answer on a separate line.
题意:给你一段数字,有q个操作,每次对整段数字全部元素进行xor
并输出当前这段数字的mex的值

心得:一开始没有想明白要用字典树,当前想到一个做法就是假设是
每次操作只改变一个数字的值,那就可以用树状数组做,单点修改,
然后二分找第一个满足i<sum[i]即可,可惜是修改一整串。

搜了题解看到01字典树突然有点明白了,假设答案的范围是xxxxxx=ans
(6位二进制内),那么一定存在一个数sco,使得 sco xor num=ans,
此时sco也是在6位二进制内。从0(ans-1)每个数都不是答案,说明这
些值xor上num应该会出现在原数组上,而ans必然不会出现。所以在答案
在6位数字的情况下,我们只需要把这些原数组上的值去掉即可。然后在剩
下的数当中,寻找与num xor的最小值即可,同理,这个题目数据二进制
在20位的情况下就可以成立了。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<map>
#define IOS ios::sync_with_stdio(0),cin.tie(0)
#define sf(a) scanf("%d",&a)
#define dg(a) cout<<"#a"<<" "<<a<<endl
#define pi acos(double(-1))
const int mod=1e9+7;
using namespace std;
const int N=6e6+10;
typedef long long ll;
int l[N],r[N];
int id;
bool tags[N];
void inst(int num)
{
    int cur=0;
    for(int i=19;i>=0;i--)
    {
        int bits=(1<<i)&num;
        if(bits)
        {
            if(!r[cur])
            {
                r[cur]=++id;
            }
            cur=r[cur];
        }
        else
        {
            if(!l[cur])
            {
                l[cur]=++id;
            }
            cur=l[cur];
        }
    }
}
int findmin(int num)
{
    int cur=0;
    int ans=0;
    for(int i=19;i>=0;i--)
    {
        int bits=(1<<i)&num;
        if(bits)
        {
            if(r[cur])
            {
                cur=r[cur];
            }
            else
            {
                ans+=(1<<i);
                cur=l[cur];
            }
        }
        else
        {
            if(l[cur])
            {
                cur=l[cur];
            }
            else
            {
                ans+=(1<<i);
                cur=r[cur];
            }
        }
    }
    return ans;
}
int main()
{
    IOS;
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        int num;
        cin>>num;
        tags[num]=true;
    }
    for(int i=0;i<=(1<<19);i++)
    {
        if(!tags[i])
        {
            inst(i);
        }
    }
    int cur=0;
    while(m--)
    {
        int num;
        cin>>num;
        cur^=num;
        cout<<findmin(cur)<<endl;
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值