题解:P11872 [威海市赛 2024] 异或盒子 1
这个 trick 是一个 dalao 告诉我的。
首先,我们从低位到高位建 trie。
对于每个节点,记录 \(xorv,cnt\)。其中 \(xorv\) 表示记录的异或和,\(cnt\) 表示当前节点被 \(cnt\) 个串共用(和普通的 trie 一样)。
维护异或和
首先应当清空本节点的 \(xorv\)。
- 如果有 \(0\) 儿子,异或上它的 \(xorv\)。
- 如果有 \(1\) 儿子,异或上它的 \(xorv\)。
- 如果有 \(1\) 儿子,且它的 \(cnt\) 为 \(k\),那么对当前位的贡献为 \(w_1=\bigoplus\limits_{i=1}^k1=k\bmod 2\)。
之所以不用考虑 \(0\) 儿子对这一位的贡献 \(w_0\),是因为 \(w_0=\bigoplus\limits_{i=1}^{k'}0=0\),相当于没有贡献。
全局加上一
OI Wiki 给出的例子。
1000(8) + 1 = 1001(9) ;
10011(19) + 1 = 10100(20) ;
11111(31) + 1 = 100000(32);
10101(21) + 1 = 10110(22) ;
100000000111111(16447) + 1 = 100000001000000(16448);
我们只需要从低位到高位开始找第一个出现的 \(0\),把它变成 \(1\),然后这个位置后面的 \(1\) 都变成 \(0\) 即可。
因此我们设计函数 \(add(x)\),然后对 \(1\) 儿子操作,并交换左右子树,达到进位,将 \(0\) 变成 \(1\),以及 \(1\) 变成 \(0\) 的效果。
void add(int id){
if(!id)return;
add(t[id].rs);//继续1的,0不
swap(t[id].ls,t[id].rs);
up(id);
}
至此,基本上做完了。
至于修改嘛,删掉这个数,然后再插入新的数就可以了,随便维护一下,记录一个全局增加量 \(Add\) 就行了。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5*30+10;
struct node{
int ls,rs,val,cnt;
}t[maxn];
int tot,root;
void up(int id){
t[id].val=t[id].cnt=0;
if(t[id].ls){
t[id].val^=t[t[id].ls].val<<1;
t[id].cnt+=t[t[id].ls].cnt;
}
if(t[id].rs){
t[id].val^=t[t[id].rs].val<<1;
t[id].cnt+=t[t[id].rs].cnt;
if(t[t[id].rs].cnt%2)t[id].val|=1;
}
}
void insert(int &id,int x,int dep){
if(!id)id=++tot;
t[id].cnt++;
if(!dep)return;
if(x%2==0)insert(t[id].ls,x>>1,dep-1);
else insert(t[id].rs,x>>1,dep-1);
up(id);
}
void erase(int id,int x,int dep){
if(!id)return;
t[id].cnt--;
if(!dep)return;
if(x%2==0)erase(t[id].ls,x>>1,dep-1);
else erase(t[id].rs,x>>1,dep-1);
up(id);
}
void add(int id){
if(!id)return;
add(t[id].rs);//继续1的,0不
swap(t[id].ls,t[id].rs);
up(id);
}
int query(){
return t[root].val;
}
int v[maxn],Add;//v_x
signed main(){
ios::sync_with_stdio(0);cin.tie(0);
int n,q;
cin>>n>>q;
for(int i=1;i<=n;i++)cin>>v[i],insert(root,v[i],20);
while(q--){
int op;
cin>>op;
if(op==0){
int x,p;
cin>>x>>p;
erase(root,v[x]+Add,20);
v[x]=p-Add;//这样下次查到p-Add+Add=p
insert(root,p,20);
}
else if(op==1){
add(root);
Add++;
}
else{
cout<<query()<<endl;
}
}
return 0;
}

浙公网安备 33010602011771号