CF842D Vitya and Strange Lesson

CF842D Vitya and Strange Lesson

Description

mex 是一个序列中没有出现过的最小非负整数。

给出你一个长度为 n 的非负整数序列以及 m 个询问,每次询问先给你一个整数 x ,然后:

  • 把序列中所有数异或上 x
  • 输出序列的 mex

Solution

题目要求求mex,则只考虑每个数是否出现

于是可以想到建出Trie

考虑修改操作

如果某位异或上的数为0,显然不影响

而异或1,就是交换左右子树

#include<bits/stdc++.h>

using namespace std;

#define LL long long 

inline LL read()
{
    LL f = 1,x = 0;
    char ch;
    do
    {
        ch = getchar();
        if(ch == '-')f = -1;
    }while(ch < '0'||ch > '9');
    do
    {
        x = (x<<3) + (x<<1) + ch - '0';
        ch = getchar();
    }while(ch >= '0' && ch  <= '9');
    return f*x;
}

const int MAXN = 300000 + 10;

map<int,int>used;
int n,m;
int Trie[MAXN * 21][2];
int tot[MAXN * 21],cnt = 1;

inline void insert(int x)
{
    int cur = 1;
    for(int i=20;i>=0;i--)
    {
        int res = 0;
        if(x & (1<<i)) res = 1;
        tot[cur]++;
        if(!Trie[cur][res]) Trie[cur][res] = ++cnt,cur = cnt;
        else cur = Trie[cur][res];
    }
    tot[cur]++;
    return;
}

inline int query(int x)
{
    int cur = 1,res = 0;
    for(int i=20;i>=0;i--)
    {
        int now = 0;
        if(x & (1<<i)) now ^= 1;
        if(!Trie[cur][now]) return res;
        if(tot[Trie[cur][now]] < (1 << (i))) cur = Trie[cur][now];
        else cur = Trie[cur][now^1],res |= (1<<i);
    }
    return res;
}

int main()
{
    n = read(),m = read();
    for(int i=1;i<=n;i++) {int x = read();if(!used[x]) insert(x),used[x]=1;}
    int x = 0;
    for(int i=1;i<=m;i++)
    {
        x ^= read();
        printf("%d\n",query(x));
    }
}

 

posted @ 2020-11-12 22:10  wlzs1432  阅读(66)  评论(0编辑  收藏  举报