CF842D Vitya and Strange Lesson

版权声明:欢迎转载 https://blog.csdn.net/yandaoqiusheng/article/details/89282790

题目链接:传送门
给出一个序列,m次操作每次给出一个数x,让序列中的所有数都异或上x,求每次操作完后的序列mex(最小未出现自然数)

会01trie就简单了
把序列去重后加到01trie中
统计每个子树下有多少个数
查询时左儿子满了就往右走,右儿子同理
直到走到空节点就直接返回
一定注意一开始存一个根节点
也就是cnt一开始一定为1

/**
 * @Date:   2019-04-13T10:54:44+08:00
 * @Last modified time: 2019-04-13T14:16:27+08:00
 */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <complex>
#include <algorithm>
#include <climits>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define A 3000010
#define B 2010

using namespace std;
typedef long long ll;
int siz[A], ch[A][2], n, m, a[A], b, s, cnt = 1;
void insert(int x, int fr = 1) {
    for (int i = 20; i > 0; i--) {
        siz[fr]++;
        if (x & (1 << (i - 1))) {
            if (!ch[fr][1]) ch[fr][1] = ++cnt;
            fr = ch[fr][1];
        }
        else {
            if (!ch[fr][0]) ch[fr][0] = ++cnt;
            fr = ch[fr][0];
        }
    }
    siz[fr]++;
}
int ask(int fr = 1, int ans = 0) {
    for (int i = 20; i > 0; i--)
        if (s & (1 << (i - 1))) {
            if (!ch[fr][1]) return ans;
            else if (siz[ch[fr][1]] < (1 << (i - 1))) fr = ch[fr][1];
            else fr = ch[fr][0], ans += (1 << (i - 1))
        }
        else {
            if (!ch[fr][0]) return ans;
            else if (siz[ch[fr][0]] < (1 << (i - 1))) fr = ch[fr][0];
            else fr = ch[fr][1], ans += (1 << (i - 1));
        }
    return ans;
}

int main(int argc, char const *argv[]) {
	cin >> n >> m;
    for (int i = 1; i <= n; i++) cin >> a[i];
    sort(a + 1, a + n + 1);
    n = unique(a + 1, a + n + 1) - a - 1;
    for (int i = 1; i <= n; i++) insert(a[i]);
    while (m--) {
        cin >> b; s ^= b;
        cout << ask() << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yandaoqiusheng/article/details/89282790
今日推荐