1. 程式人生 > 實用技巧 >【01-Trie】維護異或和

【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
*/