2018.08.22 hyc的xor/mex(线段树/01trie)

版权声明:随意转载哦......但还是请注明出处吧: https://blog.csdn.net/dreaming__ldx/article/details/81952293

hyc的xor/mex

描述

NOIP2017就要来了,备战太累,不如做做hyc的新题?
找回自信吧!
一句话题意:n个数,m个操作
操作具体来讲分两步
1.读入x,把n个数全部xor上x
2.询问当前n个数的mex
意味着每次操作后你都需要输出一次
(注意:是mex,即集合内未出现过的最小非负整数
举2个例子 mex(4,33,0,1,1,5)=2 mex(1,2,3)=0)

输入

第一行两个整数n,m 意义同题面(1 ≤ n, m ≤ 3 * 10^5)
第二行 n个数 ai (0 ≤ ai ≤ 3 * 10^5)
接下来 m 行
每行一个整数 x
表示将所有数xor上x (0 ≤ x ≤ 3 * 10^5).

输出

一共m行
每行表示当前n个数的xor

样例输入

5 4
0 1 5 6 7
1
1
4
5

样例输出

2
2
0
2

提示

30%数据n,m<=1000
100%数据同“输入”

标签

mogician原创

假想有一个01trie,立刻想到对所有数进行异或操作就相当于对有1的二进制位层上的所有节点进行reverse操作,然而这个东西是可以用数组模拟的,于是就只差查询操作了,这个东西直接二进制位贪心查一查就行了。

于是我也分不清楚我写的是01trie还是权值线段树了。
代码:

#include<bits/stdc++.h>
#define N 300005
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
#define inf ((1<<19)-1)
using namespace std;
inline int read(){
    int ans=0;
    char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
    return ans;
}
inline void write(int x){
    if(x>9)write(x/10);
    putchar(x%10^48);
}
int n,m,s[20];
struct Node{int l,r,cnt;}T[N<<2];
inline void pushup(int p){T[p].cnt=T[lc].cnt+T[rc].cnt;}
inline void build(int p,int l,int r){
    T[p].l=l,T[p].r=r;
    if(l==r){T[p].cnt=0;return;}
    build(lc,l,mid),build(rc,mid+1,r);
}
inline void update(int p,int k){
    if(T[p].l==T[p].r){T[p].cnt=1;return;}
    update(p<<1|(k>mid),k),pushup(p);
}
inline int query(int p,int dep){
    if(T[p].l==T[p].r)return 0;
    int tmp=p<<1|s[dep];
    if(T[tmp].cnt==T[tmp].r-T[tmp].l+1)return query(tmp^1,dep-1)+(1<<dep);
    return query(tmp,dep-1);
}
int main(){
    n=read(),m=read();
    build(1,0,inf);
    while(n--)update(1,read());
    while(m--){
        int x=read();
        for(int j=1;j<=19;++j)if(x&(1<<j))s[j]^=1;
        write(query(1,18)),putchar('\n');
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/dreaming__ldx/article/details/81952293