题目:

个数的序列,个操作。每次操作给一个,先使当前个数的序列一遍。然后求序列的输出。:未在序列中出现的最小非负整数。


做法:

根据的性质:序列
于是我们不用将累计在序列中,而是可以转化为累计在中。我们将个数插入字典树。每次操作相当于:给一个,在字典树中跑一个值最小且不在树上的数。其实本质还是用字典树实现高位贪心。字典树上每个结点维护该子树的,代表下面存的数的数量。若第值为,先要判断其子树是否满了,若未满则代表了在该子树下,第位为。递归做下去就能一位一位得到了。


代码:

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false), cin.tie(0)
#define debug(a) cout << #a ": " << a << endl
using namespace std;
typedef long long ll;
struct Trie{
    static const int N = 5e6 + 7;
    int tot, ch[N][2], sze[N], val[N];
    void insert(int x, int dep, int rt){
        if (dep == -1){
            val[rt] = x, sze[rt] = 1; return;
        }
        int b = (x>>dep)&1;
        if (!ch[rt][b]) ch[rt][b] = ++tot;
        insert(x, dep-1, ch[rt][b]);
        sze[rt] = 0;
        if (ch[rt][0]) sze[rt] += sze[ch[rt][0]];
        if (ch[rt][1]) sze[rt] += sze[ch[rt][1]];
    }
    int ask(int x){
        int now = 0, ans = 0;
        for (int i = 20; i >= 0; --i){
            int b = (x>>i)&1;
            if (!ch[now][b]) break;
            if (ch[now][b] && sze[ch[now][b]] < (1<<i)){
                now = ch[now][b];
            }else if (!ch[now][b^1]){
                ans |= (1<<i); break;
            }else{
                now = ch[now][b^1], ans |= (1<<i);
            }
        }
        return ans;
    }
}trie;
int main(void){
    IOS;
    int n, m; cin >> n >> m;
    for (int i = 1; i <= n; ++i){
        int x; cin >> x; trie.insert(x, 20, 0);
    }
    int now = 0;
    while (m--){
        int x; cin >> x; now ^= x;
        cout << trie.ask(now) << endl;
    }
    return 0;
}