Codeforce842D Vitya and Strange Lesson

Posted 2855669158

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforce842D Vitya and Strange Lesson相关的知识,希望对你有一定的参考价值。

题意:一个序列(n<3e5),m个查询,每次序列所有的数亦或x,问这个序列的mex(mex定义是最小没有出现过的非负整数),保留每一次的更改

题解:首先要知道mex怎么求,把每一个数分解为二进制,按高位到低位进行建一颗二叉树,可以o(logn)查询到mex

其次要知道异或有结合率,也就是求一个前缀就可以了

分解每次查询的数,从高位到低位遍历,遍历到该为为bit,判断sum[(t<<1)+bit]这棵树有没有装满,装满的话就答案就在另一棵树

#include <bits/stdc++.h>
#define ll long long
#define maxn 300100
int a[maxn], n, m, sum[1<<20];
using namespace std;
void build(){
    for(int i=0;i<n;i++){
        bitset<19>bit(a[i]);
        int t = 1;
        for(int i=18;i>=0;i--){
            if(bit[i] == 0) t = t*2;
            else t =t*2+1;
        }
        sum[t] = 1;
    }
    for(int i=(1<<20)-1;i>=1;i--)
        sum[i>>1] += sum[i];
}
int query(int temp){
    bitset<19>bit(temp);
    int t = 1, ans = 0, cnt;
    for(int i=18;i>=0;i--){
        cnt = (1<<i);
        ans = ans*2;
        if(bit[i] == 0){
            if(sum[t<<1] == cnt) t = t<<1|1, ans++;
            else t = t<<1;
        }
        else{
            if(sum[t<<1|1] == cnt) t = t<<1, ans++;
            else t = t<<1|1;
        }
    }
    return ans;
}
int main(){
    scanf("%d%d", &n, &m);
    for(int i=0;i<n;i++) scanf("%d", &a[i]);
    build();
    int temp = 0;
    while(m--){
        scanf("%d", &n);
        temp ^= n;
        printf("%d\n", query(temp));
    }
    return 0;
}

 

以上是关于Codeforce842D Vitya and Strange Lesson的主要内容,如果未能解决你的问题,请参考以下文章

cf842d Vitya and Strange Lesson

CodeForeces 842d Vitya and Strange Lesson ——(带lazy标记的01字典树)

D. Vitya and Strange Lesson(01-Trie)

Kilani and the Game-吉拉尼的游戏 CodeForce#1105d 模拟 搜索

codeforce 621B Wet Shark and Bishops

Codeforce 515A - Drazil and Date