• Codeforces Round #430 (Div. 2)


    题目链接:http://codeforces.com/contest/842/problem/D

    题意:定义Mex为一个序列中最小的未出现的正整数,给定一个长度为n的序列,然后有m个询问,每个询问给定一个数x,先对序列每个数与x进行异或运算(^),之后输出当前序列修改完之后的Mex。

    思路:因为对于原序列和x异或后,得到的新序列再与y异或相当于原序列与z(z=x^y)进行异或,所以问题就可以转化为对于一个数val,原序列和val进行异或后得到新序列的Mex是多少? 考虑01字典树,先把序列的n个数插入字典树(相同的数只插一次),考虑现在的val=0,那么如果左子树(边权为0的边)没有满,说明Mex在左子树,否则在右子树,直到最后到叶子结点为止,那么答案就是该叶子所代表的权值。  现在考虑val为任意数,对于val的二进制为0的位,按照上面的分析即可,但是对于二进制为1的位,优先走右子树(边权为1的边,因为1^1=0, 1^0=1,所以对于右子树相当于异或后的左子树, 左子树相当于异或后的右子树), 一直到叶子结点为止。  

    #define _CRT_SECURE_NO_DEPRECATE
    #include<iostream>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<stdio.h>
    #include<queue>
    #include<vector>
    #include<stack>
    #include<map>
    #include<set>
    #include<time.h>
    #include<cmath>
    #include<sstream>
    #include<assert.h>
    using namespace std;
    typedef long long int LL;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3fLL;
    const int MAXN = 3e5 + 24;
    struct Trie{
        int val[MAXN << 4];
        int next[MAXN << 4][2];
        int root, L;
        int newnode(){
            next[L][0] = next[L][1] = -1;  val[L] = 0;
            return L++;
        }
        void init(){
            L = 0; root = newnode(); build(0,0);
        }
        void build(int u,int deep){
            if (deep == 19){
                return;
            }
            next[u][0] = newnode(); 
            next[u][1] = newnode();
            build(next[u][0], deep + 1);
            build(next[u][1], deep + 1);
        }
        void insert(int x){
            int now = root;
            for (int i = 18; i >= 0; i--){
                int num = (1 << i)&x ? 1 : 0;
                now = next[now][num];
                val[now]++;
            }
        }
        int Query(int x){
            int now = root, res = 0;
            for (int i = 18; i >= 0; i--){
                int num = (1 << i)&x ? 1 : 0;
                if (val[next[now][num]] < (1 << i)){ //异或后0的边
                    now = next[now][num];
                }
                else{ //异或后1的边, 顺便把权值累计
                    now = next[now][!num];
                    res |= (1 << i);
                }
            }
            return res;
        }
    }trie;
    set<int>se;
    int main(){
    #ifdef kirito
        freopen("in.txt", "r", stdin);
        freopen("out.txt", "w", stdout);
    #endif
        int start = clock();
        int n, m,val;
        while (~scanf("%d%d", &n, &m)){
            int prexor = 0;
            trie.init(); se.clear();
            for (int i = 1; i <= n; i++){
                scanf("%d", &val);
                if (!se.count(val)){
                    trie.insert(val);
                }
                se.insert(val);
            }
            for (int i = 1; i <= m; i++){
                scanf("%d", &val);
                prexor ^= val;
                printf("%d
    ", trie.Query(prexor));
            }
        }
    #ifdef LOCAL_TIME
        cout << "[Finished in " << clock() - start << " ms]" << endl;
    #endif
        return 0;
    }
  • 相关阅读:
    Nginx下配置SSL安全协议
    Java嵌套类
    python命名空间与作用域
    Effective Java 4:类和接口
    VIM快捷键(转载)
    Eclipse快捷键
    Effective Java 3:对于所有对象都通用的方法
    Effective Java 1:创建和销毁对象-续
    Effective Java 1:创建和销毁对象
    python文件操作(转载)
  • 原文地址:https://www.cnblogs.com/kirito520/p/7452412.html
Copyright © 2020-2023  润新知