可持久化 01Trie 总结
众所周知,01 Trie 是一种动态开点单点修改线段树。
线段树可以写平衡树,所以它可以写平衡树:
#include<bits/stdc++.h>
using namespace std;
int n;
const int N=1e5;
int cnt,sz[(N*26)+5],sons[(N*26)][2];
void insert(int x){
int pos=1;
for(int i=25;i>=0;i--){
sz[pos]++;
if(!sons[pos][(x>>i)&1]) sons[pos][(x>>i)&1]=++cnt;
pos=sons[pos][(x>>i)&1];
}
sz[pos]++;
}
void erase(int x){
int pos=1;
for(int i=25;i>=0;i--){
sz[pos]--;
pos=sons[pos][(x>>i)&1];
}
sz[pos]--;
}
int queryrk(int x){
int pos=1,ans=0;
for(int i=25;i>=0;i--){
if(pos==0) return ans;
if((x>>i)&1){
ans+=sz[sons[pos][0]];
pos=sons[pos][1];
}
else{
pos=sons[pos][0];
}
}
return ans;
}
int querykth(int x){
int pos=1,ans=0;
for(int i=25;i>=0;i--){
if(x<=sz[sons[pos][0]]){
pos=sons[pos][0];
ans<<=1;
}
else{
x-=sz[sons[pos][0]];
pos=sons[pos][1];
ans<<=1;
ans|=1;
}
}
return ans;
}
int prev(int x){
return querykth(queryrk(x));
}
int nxt(int x){
return querykth(queryrk(x+1)+1);
}
const int P=(1<<24);
int main(){
cnt=1;
cin>>n;
for(int i=1;i<=n;i++){
int op,x;
cin>>op>>x;
if(op==1){
insert(x+P);
}
else if(op==2) erase(x+P);
else if(op==3) cout<<queryrk(x+P)+1<<"\n";
else if(op==4) cout<<querykth(x)-P<<"\n";
else if(op==5) cout<<prev(x+P)-P<<"\n";
else cout<<nxt(x+P)-P<<"\n";
}
return 0;
}
线段树有可持久化,那 01Trie 呢?
板子糊脸:
#include<bits/stdc++.h>
using namespace std;
int n;
const int N=5e5;
int cnt,sons[(N<<5)+5][2],sz[(N<<5)+5],vcnt,rt[N+5];
void insert(int ver,int x){
int tmp=rt[ver],pos=++cnt;
rt[++vcnt]=cnt;
for(int i=30;i>=0;i--){
sz[pos]=sz[tmp]+1;
int v=((x>>i)&1);
sons[pos][v]=++cnt;
sons[pos][v^1]=sons[tmp][v^1];
pos=sons[pos][v];
tmp=sons[tmp][v];
}
sz[pos]=sz[tmp]+1;
}
void erase(int ver,int x){
int tmp=rt[ver];
bool res=false;
for(int i=30;i>=0;i--){
if(!sz[sons[tmp][(x>>i)&1]]){
res=true;
break;
}
tmp=sons[tmp][(x>>i)&1];
}
if(res){
rt[++vcnt]=rt[ver];
return;
}
tmp=rt[ver];
int pos=++cnt;
rt[++vcnt]=pos;
for(int i=30;i>=0;i--){
sz[pos]=sz[tmp]-1;
int v=(x>>i)&1;
sons[pos][v]=++cnt;
sons[pos][v^1]=sons[tmp][v^1];
pos=sons[pos][v];
tmp=sons[tmp][v];
}
sz[pos]=sz[tmp]-1;
}
int queryrk(int ver,int x){
int pos=rt[ver],ans=0;
for(int i=30;i>=0;i--){
if(pos==0) return ans;
if((x>>i)&1){
ans+=sz[sons[pos][0]];
pos=sons[pos][1];
}
else{
pos=sons[pos][0];
}
}
return ans;
}
int querykth(int ver,int x){
int pos=rt[ver],ans=0;
for(int i=30;i>=0;i--){
if(x<=sz[sons[pos][0]]){
pos=sons[pos][0];
ans<<=1;
}
else{
x-=sz[sons[pos][0]];
pos=sons[pos][1];
ans<<=1;
ans|=1;
}
}
return ans;
}
int prev(int ver,int x){
int opopop=queryrk(ver,x);
if(opopop==0) return 1-(1ll<<31);
return querykth(ver,opopop);
}
int nxt(int ver,int x){
int opopop=queryrk(ver,x+1);
if(opopop==sz[rt[ver]]) return (1ll<<31)-1;
return querykth(ver,opopop+1);
}
const int P=(1<<30);
int main(){
cin>>n;
rt[0]=cnt=1;
for(int i=1;i<=n;i++){
int ver,op,x;
cin>>ver>>op>>x;
if(op==1){
insert(ver,x+P);
}
else if(op==2){
erase(ver,x+P);
}
else if(op==3){
rt[++vcnt]=rt[ver];
cout<<queryrk(ver,x+P)+1<<"\n";
}
else if(op==4){
rt[++vcnt]=rt[ver];
cout<<querykth(ver,x)-P<<"\n";
}
else if(op==5){
rt[++vcnt]=rt[ver];
cout<<prev(ver,x+P)-P<<"\n";
}
else{
rt[++vcnt]=rt[ver];
cout<<nxt(ver,x+P)-P<<"\n";
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构