平衡树splay

Posted mysblogs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了平衡树splay相关的知识,希望对你有一定的参考价值。

splay平衡树实现 留坑

spaly权值平衡树:

普通平衡树

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<map>
#include<bitset>
#define inf 2000000000
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dwn(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
typedef long long ll;
const int N=100010;
int n;
int val[N+10],fa[N+10],ch[N+10][2],rec[N+10],sz[N+10];
int &root=ch[0][1],tot=0;
inline int newnode(int v,int f)

    fa[++tot]=f;
    rec[tot]=sz[tot]=1;
    val[tot]=v;
    return tot;

inline void update(int x)sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+rec[x];
inline int ident(int x)return ch[fa[x]][0]==x?0:1;
inline void connect(int x,int f,int how)ch[f][how]=x,fa[x]=f;
void rotate(int x)

    int Y=fa[x],R=fa[Y];
    int Yson=ident(x),Rson=ident(Y);
    connect(ch[x][Yson^1],Y,Yson);
    connect(Y,x,Yson^1);
    connect(x,R,Rson);
    update(Y);update(x);

void splay(int x,int to)

    to=fa[to];
    while(fa[x]!=to)
    
        int y=fa[x];
        if(fa[y]==to) rotate(x);
        else if(ident(x)==ident(y)) rotate(y),rotate(x);
        else rotate(x),rotate(x);
    

void insert(int x)

    if(root==0)
    
        root=newnode(x,0);
        return;
    
    int y=root;
    while(1)
    
        sz[y]++;
        if(val[y]==x)rec[y]++;splay(y,root);return;
        int nxt=x<val[y]?0:1;
        if(!ch[y][nxt])
        
            ch[y][nxt]=newnode(x,y);
            splay(ch[y][nxt],root);
            return;
        
        y=ch[y][nxt];
    

int find(int x)

    int y=root;
    while(1)
    
        if(!y) return 0;
        if(val[y]==x)splay(y,root);return y;
        int nxt=x<val[y]?0:1;
        y=ch[y][nxt];
    

void del(int x)

    int y=find(x);
    if(!y) return;
    if(rec[y]>=2)rec[y]--,sz[y]--;return;
    if(!ch[y][0]&&!ch[y][1])root=0;return;
    if(!ch[y][0])root=ch[y][1];fa[root]=0;return;
    if(!ch[y][1])root=ch[y][0];fa[root]=0;return;
    int left=ch[y][0];
    while(ch[left][1]) left=ch[left][1];
    splay(left,ch[y][0]);
    connect(ch[y][1],left,1);
    connect(left,0,1);
    update(left);

int lower(int x)

    int y=root,ans=-inf;
    while(y)
    
        if(val[y]<x) ans=max(ans,val[y]);
        int nxt=x<=val[y]?0:1;
        y=ch[y][nxt];
    
    return ans;

int upper(int x)

    int y=root,ans=inf;
    while(y)
    
        if(val[y]>x) ans=min(ans,val[y]);
        int nxt=x<val[y]?0:1;
        y=ch[y][nxt];
    
    return ans;

int rk(int x)

    int y=root,ans=0;
    while(1)
    
        if(!y) return 0;
        if(val[y]==x)ans+=sz[ch[y][0]]+1;splay(y,root);return ans;
        int nxt=x<val[y]?0:1;
        if(nxt==1) ans+=sz[ch[y][0]]+rec[y];
        y=ch[y][nxt];
    

int kth(int x)

    int y=root;
    while(1)
    
        int used=sz[ch[y][0]]+rec[y];
        if(sz[ch[y][0]]<x&&x<=used)splay(y,root);return val[y];
        if(x<used) y=ch[y][0];
        else y=ch[y][1],x-=used;
    

int main()

    scanf("%d",&n);
    while(n--)
    
        int opt,x;
        scanf("%d%d",&opt,&x);
        if(opt==1) insert(x);
        if(opt==2) del(x);
        if(opt==3) printf("%d\n",rk(x));
        if(opt==4) printf("%d\n",kth(x));
        if(opt==5) printf("%d\n",lower(x));
        if(opt==6) printf("%d\n",upper(x));
    
    return 0;

splay区间平衡树:

文艺平衡树

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<map>
#include<bitset>
#define inf 2000000000
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dwn(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
typedef long long ll;
const int N=100000;
int n,m;
int tag[N+10],sz[N+10],fa[N+10],ch[N+10][2];
int root,tot=0;
inline void update(int x)sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
inline void connect(int x,int f,int how)ch[f][how]=x,fa[x]=f;
inline int ident(int x)return ch[fa[x]][0]==x?0:1;
int build(int l,int r)

    if(l>r) return 0;
    int mid=(l+r)>>1;
    connect(build(l,mid-1),mid,0);
    connect(build(mid+1,r),mid,1);
    update(mid);
    return mid;

inline void pushdown(int x)

    if(tag[x])
    
        swap(ch[x][0],ch[x][1]);
        tag[ch[x][0]]^=1;
        tag[ch[x][1]]^=1;
        tag[x]=0;
    

inline void rotate(int x)

    int Y=fa[x],R=fa[Y];
    int Yson=ident(x),Rson=ident(Y);
    connect(ch[x][Yson^1],Y,Yson);
    connect(Y,x,Yson^1);
    connect(x,R,Rson);
    if(Y==root) root=x;
    update(Y);update(x);

inline void splay(int x,int to)

    to=fa[to];
    while(fa[x]!=to)
    
        int y=fa[x];
        if(fa[y]==to) rotate(x);
        else if(ident(x)==ident(y)) rotate(y),rotate(x);
        else rotate(x),rotate(x);
    

inline int find(int x)

    int y=root;
    while(1)
    
        pushdown(y);
        if(sz[ch[y][0]]+1==x) return y;
        if(x<=sz[ch[y][0]]) y=ch[y][0];
        else x-=sz[ch[y][0]]+1,y=ch[y][1];
    

void print(int x)

    if(!x) return;
    pushdown(x);
    print(ch[x][0]);
    if(x!=1&&x!=n+2) printf("%d ",x-1);
    print(ch[x][1]);

int main()

    scanf("%d%d",&n,&m);
    root=build(1,n+2);
    rep(i,1,m)
    
        int l,r,lpos,rpos;
        scanf("%d%d",&l,&r);
        lpos=find(l);splay(lpos,root);
        rpos=find(r+2);splay(rpos,ch[root][1]);
        tag[ch[rpos][0]]^=1;
    
    print(root);
    putchar('\n');
    return 0;

以上是关于平衡树splay的主要内容,如果未能解决你的问题,请参考以下文章

平衡树splay

# 伸展树 Splay

bzoj 3224: Tyvj 1728 普通平衡树 && loj 104 普通平衡树 (splay树)

[平衡树-Splay]文艺平衡树_区间翻转

3223. 文艺平衡树平衡树-splay

JZYZOJ1998 [bzoj3223] 文艺平衡树 splay 平衡树