【01-Trie】维护异或和

#2049. 多重集合

题目大意

初始有一个空数组,现有两种操作:

  1. 向数组中插入一个数字
  2. 数组中的所有数字+1

给出 n 个操作,输出每次操作后整个数组的异或和。

题解

01字典树板子题

代码

//#include<bits/stdc++.h>
#include<map>
#include<set>
#include<vector>
#include<stack>
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>

using namespace std;

#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
const int seed=233;
const int N=2e5+10;

struct Trie
{
    int ch[N*32][2],w[N*32],rt,tot,maxh;
    ll val[N*32];
    #define ls ch[u][0]
    #define rs ch[u][1]
    Trie()
    {
        rt=tot=0,maxh=31;
    }
    int mknode()
    {
        ++tot;
        ch[tot][0]=ch[tot][1]=w[tot]=val[tot]=0;
        return tot;
    }
    void mallain(int u)
    {
        val[u]=0,w[u]=w[ls]+w[rs];
        if(rs) val[u] ^= (val[rs]<<1) | (w[rs]&1);
        if(ls) val[u]^= val[ls]<<1;
    }
    void insert(int &u,int x,int dep)//插入某数字
    {
        if(!u) u=mknode();
        if(dep==maxh) return (void)w[u]++;
        insert(ch[u][x&1],x>>1,dep+1);
        mallain(u);
    }
    void erase(int &u,int x,int dep)//删除某数字
    {
        if(dep==maxh) return (void)w[u]--;
        erase(ch[u][x&1],x>>1,dep+1);
        mallain(u);
    }
    void add(int u)//全局加1
    {
        if(rs) add(rs);
        swap(ls,rs);
        mallain(u);
    }
}trie;

int main()
{
    int n;
    scanf("%d",&n);
    while(n--){
        int op;
        scanf("%d",&op);
        if(op==1){
            trie.add(trie.rt);
        }else{
            int x;
            scanf("%d",&x);
            trie.insert(trie.rt,x,1);
        }
        printf("%lld\n",trie.val[1]);
    }
    return 0;
}
/*
3
2 2
2 1
1
*/

posted @ 2020-12-05 16:45  Valk3  阅读(505)  评论(0编辑  收藏  举报