zoukankan      html  css  js  c++  java
  • 普通平衡树

    普通平衡树


    splay

    板子、、、写的有点长

    // It is made by XZZ
    #include<cstdio>
    #include<algorithm>
    #include<cstdlib>
    #include<ctime>
    #define Fname "splay"
    using namespace std;
    #define rep(a,b,c) for(rg int a=b;a<=c;a++)
    #define drep(a,b,c) for(rg int a=b;a>=c;a--)
    #define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
    #define il inline
    #define rg register
    #define vd void
    typedef long long ll;
    il int gi(){
        rg int x=0,f=1;rg char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    const int maxn=100010;
    int ch[maxn][2],fa[maxn],siz[maxn],val[maxn],cnt[maxn],root,tot;
    il vd updata(const int&x){if(x)siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+cnt[x];}
    il vd clear(const int&x){fa[x]=ch[x][0]=ch[x][1]=siz[x]=val[x]=cnt[x]=0;}
    il vd rotate(const int&x){
        rg int y=fa[x],z=fa[y],k=x==ch[y][1];
        fa[x]=z;
        if(z)ch[z][y==ch[z][1]]=x;
        ch[y][k]=ch[x][k^1],fa[ch[y][k]]=y;
        fa[y]=x,ch[x][k^1]=y;
        updata(y),updata(x);
    }
    il vd splay(const int&x,const int&f=0){
        rg int y,z;
        while(fa[x]^f){
        y=fa[x],z=fa[fa[x]];
        if(z^f)
            if((x==ch[y][0])^(y==ch[z][0]))rotate(x);
            else rotate(y);
        rotate(x);
        }
        if(f==0)root=x;
    }
    il vd ins(const int&v){
        if(root==0){++tot,cnt[tot]=1,val[tot]=v,siz[tot]=1,root=tot;return;}
        int x=root,y=0;
        while(1){
        if(v==val[x]){++cnt[x],updata(x),updata(y),splay(x);return;}
        y=x,x=ch[x][val[x]<v];
        if(!x){
            ++tot;
            fa[tot]=y,ch[y][val[y]<v]=tot;
            siz[tot]=cnt[tot]=1,val[tot]=v;
            updata(y),splay(tot);return;
        }
        }
    }
    il int rk(int k){
        int x=root,ret=1;
        while(1)
        if(k<val[x])x=ch[x][0];
        else{
            ret+=siz[ch[x][0]];
            if(k==val[x]){splay(x);return ret;}
            ret+=cnt[x],x=ch[x][1];
        }
    }
    il int kth(int k){
        int x=root;
        while(1)
        if(k<=siz[ch[x][0]])x=ch[x][0];
        else{
            k-=cnt[x]+siz[ch[x][0]];
            if(k<=0){splay(x);return val[x];}
            x=ch[x][1];
        }
    }
    il int pre_next(bool k){
        int x=ch[root][k];
        while(ch[x][k^1])x=ch[x][k^1];
        return x;
    }
    il vd del(int x){
        rk(x);
        int old=root;
        if(cnt[root]>1){--cnt[root],updata(root);return;}
        if(!ch[root][0]&&!ch[root][1]){clear(root);root=0;return;}
        if(!ch[root][0]){root=ch[root][1],fa[root]=0,clear(old);return;}
        if(!ch[root][1]){root=ch[root][0],fa[root]=0,clear(old);return;}
        int k=rand()%2,pre=pre_next(k);
        splay(pre);
        ch[root][k^1]=ch[old][k^1];
        fa[ch[old][k^1]]=root;
        clear(old),updata(root);
    }
    int main(){
        srand(time(NULL));
        int n=gi(),opt,x;
        rep(i,1,n){
        opt=gi(),x=gi();
        if(opt==1)ins(x);
        else if(opt==2)del(x);
        else if(opt==3)printf("%d
    ",rk(x));
        else if(opt==4)printf("%d
    ",kth(x));
        else{
            ins(x);
            printf("%d
    ",val[pre_next(opt-5)]);
            del(x);
        }
        }
        return 0;
    }
    

    旋转版treap

    跑得快然而没卵用。

    // It is made by XZZ
    #include<cstdio>
    using namespace std;
    #define rep(a,b,c) for(rg int a=b;a<=c;a++)
    #define drep(a,b,c) for(rg int a=b;a>=c;a--)
    #define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
    #define il inline
    #define rg register
    #define vd void
    #define Ls tree[now].ls
    #define Rs tree[now].rs
    typedef long long ll;
    il int gi(){
        rg int x=0,f=1;rg char ch=getchar();
        while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    struct node{
        int ls,rs,value,rand,sum,size;
        node(){ls=rs=value=rand=sum=size=0;}
    }tree[100001];
    int root=0,siz=0;
    ll seed=19260817;
    il int Rand(){return seed=seed*48271LL%2147483647;}
    il vd reset(int now){
        tree[now].size=tree[Ls].size+tree[Rs].size+tree[now].sum;
    }
    il vd lrot(int&now){
        int ls=tree[now].ls;
        tree[now].ls=tree[ls].rs,tree[ls].rs=now;
        tree[ls].size=tree[now].size;reset(now);now=ls;
    }
    il vd rrot(int&now){
        int rs=tree[now].rs;
        tree[now].rs=tree[rs].ls,tree[rs].ls=now;
        tree[rs].size=tree[now].size;reset(now);now=rs;
    }
    il vd ins(int&now,int num){
        if(now==0){
        ++siz,now=siz,tree[now].size=tree[now].sum=1,tree[now].value=num,tree[now].rand=Rand();
        return;
        }
        ++tree[now].size;
        if(tree[now].value==num)++tree[now].sum;
        else if(num<tree[now].value){
        ins(Ls,num);
        if(tree[Ls].rand<tree[now].rand)lrot(now);
        }else{
        ins(Rs,num);
        if(tree[Rs].rand<tree[now].rand)rrot(now);
        }
    }
    il vd del(int&now,int num){
        if(now==0)return;
        if(tree[now].value==num){
        if(tree[now].sum>1){--tree[now].sum,--tree[now].size;return;}
        if(!Ls||!Rs)now=Ls|Rs;
        else if(tree[Ls].rand<tree[Rs].rand)lrot(now),del(now,num);
        else rrot(now),del(now,num);
        return;
        }
        --tree[now].size;
        if(num<tree[now].value)del(Ls,num);
        else del(Rs,num);
    }
    il int getrank(int now,int num){
        if(now==0)return 0;
        if(tree[now].value==num)return tree[Ls].size+1;
        if(num>tree[now].value)return tree[Ls].size+tree[now].sum+getrank(Rs,num);
        else return getrank(Ls,num);
    }
    il int getnum(int now,int num){
        if(num<=tree[Ls].size)return getnum(Ls,num);
        else if(num>tree[Ls].size+tree[now].sum)return getnum(Rs,num-tree[Ls].size-tree[now].sum);
        else return tree[now].value;
    }
    int ans;
    il vd lower(int now,int num){
        if(now==0)return;
        if(tree[now].value<num)ans=now,lower(Rs,num);
        else lower(Ls,num);
    }
    il vd upper(int now,int num){
        if(now==0)return;
        if(tree[now].value>num)ans=now,upper(Ls,num);
        else upper(Rs,num);
    }
    int main(){
        int n=gi(),opt,x;
        while(n--){
        opt=gi(),x=gi();
        switch(opt){
            case 1:ins(root,x);break;
            case 2:del(root,x);break;
                case 3:printf("%d
    ",getrank(root,x));break;
            case 4:printf("%d
    ",getnum(root,x));break;
            case 5:ans=0,lower(root,x),printf("%d
    ",tree[ans].value);break;
            case 6:ans=0,upper(root,x),printf("%d
    ",tree[ans].value);break;
        }
        }
        return 0;
    }
    

    无旋treap

    是不是我常数写大了?好慢。。。

    // It is made by XZZ
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define rep(a,b,c) for(rg int a=b;a<=c;a++)
    #define drep(a,b,c) for(rg int a=b;a>=c;a--)
    #define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
    #define il inline
    #define rg register
    #define vd void
    #define mp make_pair
    typedef long long ll;
    il int gi(){
        rg int x=0,f=1;rg char ch=getchar();
        while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    #define Now tree[now]
    struct node{int ls,rs,value,rand,size;}tree[100010];
    int root,siz;
    int seed=151806+150605+151127;//mou shen ben xue hao+mou da lao xue hao+mou ju ruo xue hao
    il int Rand(){return seed=seed*48271%2147483647;}
    il vd reset(int now){Now.size=tree[Now.ls].size+tree[Now.rs].size+1;}
    il int merge(int a,int b){
        if(!a||!b)return a|b;
        if(tree[a].rand<tree[b].rand){tree[a].rs=merge(tree[a].rs,b),reset(a);return a;}
        else {tree[b].ls=merge(a,tree[b].ls),reset(b);return b;}
    }
    il pair<int,int> split(int now,int num){
        if(!now)return mp(0,num);
        int ls=Now.ls,rs=Now.rs;
        if(num==tree[ls].size){Now.ls=0,reset(now);return mp(ls,now);}
        if(num==tree[ls].size+1){Now.rs=0,reset(now);return mp(now,rs);}
        if(num<tree[ls].size){
        pair<int,int>T=split(ls,num);
        Now.ls=T.second,reset(now);
        return mp(T.first,now);
        }else{
        pair<int,int>T=split(rs,num-tree[ls].size-1);
        Now.rs=T.first,reset(now);
        return mp(now,T.second);
        }
    }
    il int getrank(int now,int num){
        int ret=0,t=1e9;
        while(now){
        if(num==Now.value)t=min(t,ret+tree[Now.ls].size+1);
            if(num<=Now.value)now=Now.ls;
            else ret+=tree[Now.ls].size+1,now=Now.rs;
        }
        return t==1e9?ret:t;
    }
    il int getnum(int now,int num){
        while(1){
            if(tree[Now.ls].size==num-1)return Now.value;
            if(tree[Now.ls].size>num-1)now=Now.ls;
            else num-=tree[Now.ls].size+1,now=Now.rs;
        }
    }
    il int lower(int now,int num){
        int ret;
        while(now)if(tree[now].value<num)ret=tree[now].value,now=Now.rs;
            else now=Now.ls;
        return ret;
    }
    il int upper(int now,int num){
        int ret;
        while(now)if(tree[now].value>num)ret=tree[now].value,now=Now.ls;
            else now=Now.rs;
        return ret;
    }
    il vd ins(int num){
        int Rank=getrank(root,num),now;
        pair<int,int>tmp=split(root,Rank);
        now=++siz;
        Now.value=num,Now.rand=Rand(),Now.size=1;
        root=merge(tmp.first,siz);
        root=merge(root,tmp.second);
    }
    il vd del(int num){
        int Rank=getrank(root,num);
        pair<int,int>t1=split(root,Rank),t2=split(t1.first,Rank-1);
        root=merge(t2.first,t1.second);
    }
    int main(){
        int n=gi(),opt,x;
        while(n--){
        opt=gi(),x=gi();
        switch(opt){
            case 1:ins(x);break;
            case 2:del(x);break;
                case 3:printf("%d
    ",getrank(root,x));break;
            case 4:printf("%d
    ",getnum(root,x));break;
            case 5:printf("%d
    ",lower(root,x));break;
            case 6:printf("%d
    ",upper(root,x));break;
        }
        }
        return 0;
    }
    

    SGT

    即替罪羊树。重构的思想很不错,常数小,因为我把alpha设成了0.7233333

    // It is made by XZZ
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define rep(a,b,c) for(rg int a=b;a<=c;a++)
    #define drep(a,b,c) for(rg int a=b;a>=c;a--)
    #define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
    #define il inline
    #define rg register
    #define vd void
    typedef long long ll;
    il int gi(){
        rg int x=0,f=1;rg char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    const int maxn=1e6+2;
    const double alpha=0.7233333;
    int root,id,val[maxn],ch[maxn][2],siz[maxn],cover[maxn],b[maxn];
    bool del[maxn];
    il int newnode(int _val){val[++id]=_val,ch[id][0]=ch[id][1]=0,siz[id]=cover[id]=1;return id;}
    il vd dfs(const int&rt){
        if(!rt)return;
        dfs(ch[rt][0]);
        if(!del[rt])b[++b[0]]=rt;
        dfs(ch[rt][1]);
    }
    il int divide(int l,int r){
        if(l>r)return 0;
        int mid=(l+r)>>1;
        ch[b[mid]][0]=divide(l,mid-1);
        ch[b[mid]][1]=divide(mid+1,r);
        siz[b[mid]]=siz[ch[b[mid]][0]]+siz[ch[b[mid]][1]]+!del[b[mid]];
        cover[b[mid]]=cover[ch[b[mid]][0]]+cover[ch[b[mid]][1]]+1;
        return b[mid];
    }
    il vd rebuild(int&rt){
        b[0]=0;dfs(rt);rt=divide(1,b[0]);
    }
    il int*_Insert(int&rt,const int&num){
        if(!rt){rt=newnode(num);return NULL;}
        ++siz[rt],++cover[rt];
        int*ret=_Insert(ch[rt][num>=val[rt]],num);
        if(max(cover[ch[rt][0]],cover[ch[rt][1]])>alpha*cover[rt])ret=&rt;
        return ret;
    }
    il vd Insert(const int&x){int*ls=_Insert(root,x);if(ls)rebuild(*ls);}
    il int Rank(const int&x){
        int ret=1,now=root;
        while(now)
        if(x<=val[now])now=ch[now][0];
        else ret+=siz[ch[now][0]]+!del[now],now=ch[now][1];
        return ret;
    }
    il int Kth(int k){
        int now=root;
        while(now){
        if(!del[now]&&k==siz[ch[now][0]]+1)return val[now];
        if(k<=siz[ch[now][0]])now=ch[now][0];
        else k-=siz[ch[now][0]]+!del[now],now=ch[now][1];
        }
    }
    il vd _Erase(int k){
        int now=root;
        while(now){
        --siz[now];
        if(!del[now]&&k==siz[ch[now][0]]+1){del[now]=1;return;}
        if(k<=siz[ch[now][0]])now=ch[now][0];
        else k-=siz[ch[now][0]]+!del[now],now=ch[now][1];
        }
    }
    il vd Erase(const int&x){
        _Erase(Rank(x));
        if(siz[root]<cover[root]*alpha)rebuild(root);
    }
    int main(){
        int n=gi(),opt,x;
        while(n--){
        opt=gi(),x=gi();
        if(opt==1)Insert(x);
        else if(opt==2)Erase(x);
        else if(opt==3)printf("%d
    ",Rank(x));
        else if(opt==4)printf("%d
    ",Kth(x));
        else if(opt==5)printf("%d
    ",Kth(Rank(x)-1));
        else printf("%d
    ",Kth(Rank(x+1)));
        }
        return 0;
    }
    

    vector

    %烂hzwer大佬。。。

    // It is made by XZZ
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    using namespace std;
    #define rep(a,b,c) for(rg int a=b;a<=c;a++)
    #define drep(a,b,c) for(rg int a=b;a>=c;a--)
    #define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
    #define il inline
    #define rg register
    #define vd void
    typedef long long ll;
    il int gi(){
        rg int x=0,f=1;rg char ch=getchar();
        while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    vector<int>A;
    int main(){
        int n=gi(),opt,x;
        while(n--){
        opt=gi(),x=gi();
        if(opt==1)A.insert(upper_bound(A.begin(),A.end(),x),x);
        else if(opt==2)A.erase(lower_bound(A.begin(),A.end(),x));
        else if(opt==3)printf("%d
    ",lower_bound(A.begin(),A.end(),x)-A.begin()+1);
        else if(opt==4)printf("%d
    ",A[x-1]);
        else if(opt==5)printf("%d
    ",*--lower_bound(A.begin(),A.end(),x));
        else printf("%d
    ",*upper_bound(A.begin(),A.end(),x));
        }
        return 0;
    }
    

    BIT+二分答案

    用一颗区间修改单点查询的BIT存储rk就行了,剩下全用二分

    // It is made by XZZ
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define Fname "phs"
    using namespace std;
    #define rep(a,b,c) for(rg int a=b;a<=c;a++)
    #define drep(a,b,c) for(rg int a=b;a>=c;a--)
    #define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
    #define il inline
    #define rg register
    #define vd void
    typedef long long ll;
    il int gi(){
        rg int x=0,f=1;rg char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    int n,m;
    struct bit{//区间修改、单点查询的BIT,存的是有多少个数小于这个数
        int tree[100010];
        il int lb(const int&a){return a&-a;}
        bit(){memset(tree,0,sizeof tree);}
        il vd Updata(int pos,int num){while(pos<=m)tree[pos]+=num,pos+=lb(pos);}
        il int Query(int pos){int ret=0;while(pos)ret+=tree[pos],pos-=lb(pos);return ret;}
    };
    int opt[100010],x[100010],data[100010];
    bit t;
    int main(){
        n=gi();
        rep(i,1,n){
        opt[i]=gi(),x[i]=gi();
        if(opt[i]!=4)data[++m]=x[i];
        }
        sort(data+1,data+m+1);
        m=unique(data+1,data+m+1)-data-1;
        rep(i,1,n)if(opt[i]!=4)x[i]=lower_bound(data+1,data+1+m,x[i])-data;
        int l,r,mid,k;
        rep(i,1,n){
        if(opt[i]==1)t.Updata(x[i]+1,1);
        else if(opt[i]==2)t.Updata(x[i]+1,-1);
        else if(opt[i]==3)printf("%d
    ",t.Query(x[i])+1);
        else if(opt[i]==4){
            l=1,r=m;
            while(l<r){
            mid=(l+r)>>1;
            if(t.Query(mid+1)>=x[i])r=mid;
            else l=mid+1;
            }
            printf("%d
    ",data[l]);
        }else if(opt[i]==5){
            k=t.Query(x[i]);
            l=1,r=x[i]-1;
            while(l<r){
            mid=(l+r)>>1;
            if(t.Query(mid+1)==k)r=mid;
            else l=mid+1;
            }
            printf("%d
    ",data[l]);
        }else{
            k=t.Query(x[i]+1);
            l=x[i]+1,r=m;
            while(l<r){
            mid=(l+r)>>1;
            if(t.Query(mid)==k)l=mid+1;
            else r=mid;
            }
            printf("%d
    ",data[l-1]);
        }
        }
        //基本是二分答案(OwO)
        return 0;
    }
    

    还有几个没写

    • 值域线段树
    • set(加二分和氧气也是可以的吧?)
    • 还有二进制trie树?
    • 平板电视pb_ds库有自带吧

    另外,置顶&坐看访问量暴涨

  • 相关阅读:
    如何实现浏览器内多个标签页之间的通信?
    vue组件库的基本开发步骤(源代码)
    vue组件库的基本开发步骤
    Websocket原理
    TCP和UDP的区别
    一句话概括 tcp三次握手
    简单说一下你对http和https的理解
    .Ajax(async异步与sync同步)
    get和post请求方式的区别
    面试易忽略状态码
  • 原文地址:https://www.cnblogs.com/xzz_233/p/phs-simple.html
Copyright © 2011-2022 走看看