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 模拟 搜索