zoukankan      html  css  js  c++  java
  • CF842D Vitya and Strange Lesson

    题意简述

    (n)个数(a_1,a_2,cdots,a_n),有(m)个操作,每次操作给一个数(x),要求:

    • 将所有数(operatorname{xor} space x)
    • 求此时数列的( ext{mex})
      ( ext{mex})指当前数列未出现的最小非负整数。
      数据范围自行查看题目。

    简单口胡

    先考虑一下没有第一个(operatorname{xor})操作的时候怎么做。我们将所有数插入一个01-trie中,对于每一位我们都想:最好往0走。但是什么时候是不能往0走的呢?
    如果左子树(即0节点的子树)是一个满二叉树,说明如果走到0节点,那么就没有不出现的数了,而我们要找的是( ext{mex}),违背定义,这时候只能退而求其次,走1节点。

    加上了(operatorname{xor})其实也是差不多的,异或具有结合律,即(a operatorname{xor} x_1 operatorname{xor} x_2 = a operatorname{xor} (x_1 operatorname{xor} x_2)),所以记录(s)为当前的(operatorname{xor})和,如果第(i)(s)为1,那么就是说明01-trie的第(i)层要取反,那么也就是最好往1走,如果是0那就是一样的。

    写的话还是看水平,反正我写了好久/kk

    # include <bits/stdc++.h>
    using namespace std;
    
    const int N = 3e5 + 5;
    
    int n,m;
    
    int a[N];
    
    int s;
    
    struct _01trie
    {
        int T[N << 2][2],siz[N << 2];
        int tot = 0;
    
        void insert(int x)
        {
            int root = 0;
            for(int i = 20; i >= 0; i--)
            {
                int p = (x >> i) & 1;
                if(T[root][p] == 0) T[root][p] = ++tot;
                root = T[root][p];
            }
            return;
        }
        void dfs(int root)
        {
            
            if(T[root][0] == 0 && T[root][1] == 0) 
            {
                siz[root] = 1;
                return;
            }
            if(T[root][0]) dfs(T[root][0]);
            if(T[root][1]) dfs(T[root][1]);
            siz[root] += siz[T[root][0]] + siz[T[root][1]] + 1;
            // printf("root = %d,siz[%d] = %d
    ",root,root,siz[root]);
            return;
        }
        int query(void)
        {
            int root = 0;
            int ans = 0;
            for(int i = 20; i >= 0; i--)
            {
                int p = (s >> i) & 1;
                // if(p == 1) 
                // {
                //     printf("i = %d
    ",i);
                //     printf("root = %d
    ",root);
                //     printf("T = %d
    ",T[root][p]);
                //     printf("siz = %d
    ",siz[T[root][p]]);
                // }
                if(T[root][p] != 0 && siz[T[root][p]] == (1 << (i + 1)) - 1) 
                {
                    // printf("root = %d
    ",root);
                    root = T[root][p ^ 1],ans += (1 << i);
                
                }
                else root = T[root][p];
                if(!root) break;
            }
            return ans;
        }
    }Trie;
    
    int main(void)
    {   
        scanf("%d%d",&n,&m);
        for(int i = 1; i <= n; i++) scanf("%d",&a[i]);
        sort(a + 1,a + n + 1);
        int Newn = unique(a + 1,a + n + 1) - a - 1;
        for(int i = 1; i <= Newn; i++) 
        {
            Trie.insert(a[i]);
        }
        Trie.dfs(0);
        while(m--)
        {
            int x;
            scanf("%d",&x);
            s ^= x;
            printf("%d
    ",Trie.query());
        }
        return 0;
    }
    
  • 相关阅读:
    uniDAC 8.4.1一个严重的bug
    Delphi Event Bus进阶(三)如何使用通道?
    从delphi 10.3到delphi 10.4的改变实务
    uniDAC 8.4.1 database is locked
    调整Delphi IDE代码的行间距
    Deployment Manager now Open Source
    Delphi 10.4.2 Android 64位发布格式之App Bundle格式aab
    每日日报79
    每日日报78
    团队冲刺博客(四)
  • 原文地址:https://www.cnblogs.com/luyiming123blog/p/14350334.html
Copyright © 2011-2022 走看看