Codeforces 842 D Vitya and Strange Lesson

来源:互联网 发布:php编写99乘法表 编辑:程序博客网 时间:2024/06/05 17:45

题目地址
题意:告诉你一个序列,然后给你m个操作,每个操作就是把这个序列异或上x,然后再得出最小的没有在这个序列中出现的数。
思路:因为异或的定义就是转成2进制的形式,每一位相同的为0,不同的为1。这样的话我们就可以把数转化为二进制存入字典树(二叉树,向左为0向右为1)中,异或的话就是把异或的数转成二进制的形式,把该位为1的翻转一下字典树节点的两个子节点就好了。查询的时候就是一直往左找,直到下面的数是满的就转到右子树去找(这个理解不了可以看下我代码结构体部分的注释),最后得到的结果就是最小的数。(注意因为最大的数才为3*10^5所以20层就好了,不会出现超过20层的情况,然后转成二进制以后要在前面补0,这样就比较好在字典树中存值了)

#include <iostream>#include <cstring>#include <string>#include <queue>#include <vector>#include <map>#include <set>#include <stack>#include <cmath>#include <cstdio>#include <algorithm>#include <iomanip>#define N 300010#define M 2//每个节点的子节点的个数#define LL __int64#define inf 0x3f3f3f3f#define lson l,mid,ans<<1#define rson mid+1,r,ans<<1|1#define getMid (l+r)>>1#define movel ans<<1#define mover ans<<1|1using namespace std;const LL mod = 1000000007;int n, m;int num[N];struct node {    int cnt, res;//cnt存的是它下面有多少个数,就是查询的时候判断这边的数是不是已经完全都有了,res就是记录异或的值,想当与一个延迟标记省时间    node *next[M];    void init() {        for (int i = 0; i < M; i++) {            next[i] = NULL;        }        res = 0;        cnt = 0;    }};void push_down(node *p, int d) {//异或时反转左右孩子,向下传递    for (int i = 0; i < M; i++) {        if (p->next[i]) {            p->next[i]->res ^= p->res;        }    }    if ((p->res >> d) & 1) {        swap(p->next[0], p->next[1]);    }    p->res = 0;}struct Trie {    void insert(node *root, int num) {//需要自定义        node *p = root;        p->cnt++;        for (int i = 20; ~i; i--) {            int k = (num >> i) & 1;            if (p->next[k] == NULL) {                p->next[k] = new node;                p->next[k]->init();            }            p = p->next[k];            p->cnt++;        }    }    int solve(node *root) {        node *p = root;        int ans = 0;        for (int i = 20; ~i; i--) {            push_down(p, i);            if (p->next[0] == NULL || (p->next[0] != NULL&&p->next[0]->cnt != (1 << i))) {                p = p->next[0];            }            else {                p = p->next[1];                ans += 1 << i;            }            if (p == NULL) return ans;        }    }    void Free(node *p) {        for (int i = 0; i < M; i++)if (p->next[i]) Free(p->next[i]);        delete p;    }}tree;int main() {    cin.sync_with_stdio(false);    node *root;    while (cin >> n >> m) {        for (int i = 0; i < n; i++) {            cin >> num[i];        }        sort(num, num + n);        n = unique(num, num + n) - num;        root = new node;        root->init();        for (int i = 0; i < n; i++) {            tree.insert(root, num[i]);        }        for (int i = 0; i < m; i++) {            int k;            cin >> k;            root->res ^= k;            cout << tree.solve(root) << endl;        }        tree.Free(root);    }    return 0;}
阅读全文
0 0
原创粉丝点击