【01-Trie】维护异或和
题目大意
初始有一个空数组,现有两种操作:
- 向数组中插入一个数字
- 数组中的所有数字+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
*/