用字典树代替平衡树,一个神奇的操作

最近在学平衡树(Splay),想过一道模版题,但是我太弱了,老是写炸,于是想了一种方法代替平衡树,代码长度也十分优秀。

好了,不BB了,让我来讲一下我想出来的方法吧。

首先,我们分析一下Splay吧,思路比较简单,主要是rotate有点难理解其他都和BST差不多,但是代码实现起来有点麻烦,细节也比较多。

对于这道模版题,我的思路是把插入的数都补位,补到10位数(其实只用补到8位),然后把它当作字符串一样插入字典树中,这样就可以保证树的高度是10,不会退化,然后就很爽了

对了,还有要处理负数,这里我就直接用了一个很暴力的方法,加了个偏移量。

详情可以参照我的代码(好像代码风格有点丑)

#include<bits/stdc++.h>
using namespace std;
const int N = 1000005;
const int PY = 10000000;
int ch[N][10],gs,cnt[N],n,size[N];
void insert(string x){
    int p=0;
    for(int i=0;i<x.length();i++){
        if(ch[p][x[i]-'0']==0) ch[p][x[i]-'0']=++gs;
        p=ch[p][x[i]-'0'];
        size[p]++;
    }
    cnt[p]++;
}
void del(string x){
    int p=0;
    for(int i=0;i<x.length();i++){
        p=ch[p][x[i]-'0'];
        size[p]--;
    }
    cnt[p]--;
}
int find_rank(string x){
    int p=0,ret=0;
    for(int i=0;i<x.length();i++){
        for(int j=0;j<x[i]-'0';j++){
            if(ch[p][j])ret+=size[ch[p][j]];
        }
        p=ch[p][x[i]-'0'];
    }
    return ret;
}
int find_rt(string x){
    int p=0,ret=0;
    for(int i=0;i<x.length();i++){
        for(int j=0;j<x[i]-'0';j++){
            if(ch[p][j])ret+=size[ch[p][j]];
        }
        p=ch[p][x[i]-'0'];
    }
    return cnt[p];
}
int find_x(int x){
    int p=0;
    string ans;
    for(int i=0;i<10;i++){
        for(int j=0;j<10;j++){
            if(ch[p][j]){
                if(size[ch[p][j]]<x) x-=size[ch[p][j]];
                else {p=ch[p][j];ans=ans+char(j+'0');break;}
            }
        }
    }
    string anss="";
    int o=0;
    for(int i=1;i<=9;i++) if(ans[i]!='0') {o=i;break;} 
    for(int i=o;i<=9;i++)  anss=anss+ans[i];
    int s=0;
    for(int i=0;i<anss.length();i++) s=s*10+anss[i]-'0';
    s=s-PY;
    return s;
}
string x,xx;
int c,ss;
int main(){
    ios::sync_with_stdio(false);
    cin>>n;
    while(n--){
        cin>>c;
        cin>>x;
        ss=0;
        for(int i=0;i<x.length();i++) if(x[i]!='-')ss=ss*10+x[i]-'0';
        if(x[0]=='-') ss=-ss;
        ss=ss+PY;
        int o=ss;
        x="";
        while(o){
            x=char(o%10+'0')+x;
            o/=10;
        }
        ss-=PY;
        xx="";
        for(int i=0;i<x.size();i++) xx=xx+x[i];
        while(xx.size()<9){
            xx="0"+xx;
        }
        xx="0"+xx;
        if(c==1) insert(xx);
        if(c==2) del(xx);
        if(c==3) cout<<find_rank(xx)+1<<endl;
        if(c==4) cout<<find_x(ss)<<endl;
        if(c==5) insert(xx),cout<<find_x(find_rank(xx)+1-1)<<endl,del(xx);
        if(c==6) insert(xx),cout<<find_x(find_rank(xx)+1+find_rt(xx))<<endl,del(xx);
    }
    return 0;
}

这一个方法感觉可拓展性不强,欢迎大家讨论(>_<)

猜你喜欢

转载自blog.csdn.net/qq_38944163/article/details/80607386