codeforces 842D Vitya and Strange Lesson

本文介绍了一种使用01Trie数据结构高效处理数组MEX(最小未出现非负整数)查询的方法,特别是在数组元素被批量异或修改的情况下。通过构建01Trie树并利用lazy标记进行更新,可以快速找到当前数组的MEX值。
摘要由CSDN通过智能技术生成

题目大意:
定义mex数为数组中第一个没有出现的非负整数.有m个操作,每个操作有一个x,将数组中所有的元素都异或x,然后询问当前的mex

Input

First line contains two integer numbers n and m (1 ≤ n, m ≤ 3·105) — number of elements in array and number of queries.

Next line contains n integer numbers ai (0 ≤ ai ≤ 3·105) — elements of then array.

Each of next m lines contains query — one integer number x (0 ≤ x ≤ 3·105).

Output

For each query print the answer on a separate line.

Examples
Input
2 2
1 3
1
3
Output
1
0
Input
4 3
0 1 5 6
1
2
4
Output
2
0
0
Input
5 4
0 1 5 6 7
1
1
4
5
Output
2
2
0
2
2
0
0
Input
5 4
0 1 5 6 7
1
1
4
5
Output
2
2
0
2
%%%%yzh大佬,学会了新姿势:http://www.cnblogs.com/Yuzao/default.html?page=1
这题正解其实是01Trie
按照理解,Trie用来保存字符串,但也可以通过01分支来保存数
这样我们只要找到树中最靠左的空节点,对应的值即为答案
更新可以用lazy标记,如果有标记,则反转左右子节点
如果左边有空节点,那么就返回向左查找的值
没有则返回右节点查找的值+2^(dep-1)[左节点数量]
然后注意本题是按高位向低位拓展,因为高位分支少,所以会更快

YZD&&HJW&&SAC&&YZH%%%orz大佬
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 struct Node
 7 {
 8   int l,r;
 9 }c[1200001];
10 int seg[1200001],rev[1200001],root,tot,n,m;
11 void insert(int &rt,int x,int dep)
12 {
13   if (!rt) rt=++tot;
14   if (dep==0)
15     {
16       seg[rt]=1;
17       return;
18     }
19   if (x&(1<<dep-1)) insert(c[rt].r,x,dep-1);
20   else insert(c[rt].l,x,dep-1);
21   seg[rt]=seg[c[rt].l]&&seg[c[rt].r];
22 }
23 void pushdown(int &rt,int dep)
24 {
25   if (rev[rt]==0) return;
26   int k=rev[rt];
27   rev[c[rt].l]^=k;
28   rev[c[rt].r]^=k;
29   if (k&(1<<dep-1))
30     swap(c[rt].l,c[rt].r);
31   rev[rt]=0;
32 }
33 int query(int &rt,int dep)
34 {
35   if (dep==0) return 0;
36   pushdown(rt,dep);
37   if (seg[c[rt].l]==0) return query(c[rt].l,dep-1);
38   else return query(c[rt].r,dep-1)+(1<<dep-1);
39 }
40 int main()
41 {int i,j,x;
42   cin>>n>>m;
43   for (i=1;i<=n;i++)
44     {
45       scanf("%d",&x);
46       insert(root,x,20);
47     }
48   for (i=1;i<=m;i++)
49     {
50       scanf("%d",&x);
51       rev[root]^=x;
52       printf("%d\n",query(root,20));
53     }
54 }

转载于:https://www.cnblogs.com/Y-E-T-I/p/7494137.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值