可持久化 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;
}
posted @   ThisIsLu  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示