Splay专题模板

0 篇文章 0 订阅

调了差不多一天的splay终于把splay写对了

顺便纠正了一些原来的错误

但是喵喵喵idy002学长的板子似乎是惰性修改可能会有错。。

Splay写了两个部分

第一个是区间反转,比较简单,比较好写,在find的时候pushdown翻转标记即可

第二个就是普通平衡树,耗了我一天下午

找前驱和后继终于学到了方便的方法

前驱 int pos=T.rank(x)  pre=T.kth(pos-1);

后继 int pos=T.rank(x+1)  suf=T.kth(pos);

贴代码溜了。

bzoj3224

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int maxn=1e5+5;

int n,root,cnt;

struct Splay {
    int fa[maxn],son[maxn][2],size[maxn],key[maxn];
    void update(int nd) {
        size[nd]=size[son[nd][0]]+size[son[nd][1]]+1;
    }
    void rotate(int nd,int d) {
        int baba=fa[nd];
        int s=son[nd][!d];
        int ss=son[s][d];
        son[nd][!d]=ss;
        son[s][d]=nd;
        son[baba][nd==son[baba][1]]=s;
        if (!baba) {
            root=s;
        }
        fa[nd]=s;
        fa[s]=baba;
        if (ss) {
            fa[ss]=nd;
        }
        update(nd);
        update(s);
    }
    void splay(int nd,int goal) {
        while (fa[nd]!=goal) {
            int baba=fa[nd];
            int pd1=nd==son[baba][0];
            if (fa[baba]==goal) {
                rotate(baba,pd1);
            } else {
                int yeye=fa[baba];
                int pd2=baba==son[yeye][0];
                if (pd1==pd2) {
                    rotate(yeye,pd2);
                    rotate(baba,pd1);
                } else {
                    rotate(baba,pd1);
                    rotate(yeye,pd2);
                }
            }
        }
    }
    int newnode(int f,int val) {
        int nd=++cnt;
        fa[nd]=f;
        key[nd]=val;
        size[nd]=1;
        son[nd][0]=son[nd][1]=0;
        return nd;
    }
    void insert(int num) {
        if (!root) {
            root=newnode(0,num);
            return ;
        }
        int nd=root;
        while (son[nd][num>key[nd]]) {
            nd=son[nd][num>key[nd]];
        }
        son[nd][num>key[nd]]=newnode(nd,num);
        update(nd);
        splay(nd,0);
    }
    int find(int num) {
        int nd=root;
        while (key[nd]!=num) {
            nd=son[nd][num>key[nd]];
        }
        splay(nd,0);
        return nd;
    }
    void del(int num) {
        int nd=find(num);
        int lnd=son[nd][0];
        int rnd=son[nd][1];
        if (!lnd&&!rnd) {
            root=0;
        } else if (!lnd) {
            root=rnd;
            fa[rnd]=0;
        } else if (!rnd) {
            root=lnd;
            fa[lnd]=0;
        } else {
            while (son[lnd][1]) lnd=son[lnd][1];
            while (son[rnd][0]) rnd=son[rnd][0];
            splay(lnd,0);
            splay(rnd,lnd);
            son[rnd][0]=0;
            update(rnd);
            update(lnd);
        }
    }
    int kth(int k) {
        int nd=root;
        while (1) {
            int ls=size[son[nd][0]];
            if (k<=ls) {
                nd=son[nd][0];
            } else if (k>=ls+2){
                nd=son[nd][1];
                k-=(ls+1);
            } else {
                splay(nd,0);
                return key[nd];
            }
        }
    }
    int rank(int num) {
        int nd=root;
        int rt=1;
        int last;
        while (nd) {
            last=nd;
            if (key[nd]<num) {
                rt+=size[son[nd][0]]+1;
                nd=son[nd][1];
            } else {
                nd=son[nd][0];
            }
        }
        splay(last,0);
        return rt;
    }
}T;

int main() {
    scanf("%d",&n);
    for (int i=1;i<=n;i++) {
        int opt,x;
        scanf("%d%d",&opt,&x);
        if (opt==1) {
            T.insert(x);
        } else if (opt==2) {
            T.del(x);
        } else if (opt==3) {
            printf("%d\n",T.rank(x));
        } else if (opt==4) {
            printf("%d\n",T.kth(x));
        } else if (opt==5) {
            int pos=T.rank(x);
            printf("%d\n",T.kth(pos-1));
        } else {
            int pos=T.rank(x+1);
            printf("%d\n",T.kth(pos));
        }
    }
    return 0;
}

bzoj3223

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>

using namespace std;
    
const int maxn=1e5+5;

int root;

int n,m;

struct Splay {
    int rev[maxn],size[maxn],fa[maxn],son[maxn][2];
    void update(int nd) {
        size[nd]=size[son[nd][1]]+size[son[nd][0]]+1;
    }
    int build(int f,int lf,int rg) {
        if (lf>rg) return 0;
        int mid=(lf+rg)>>1;
        fa[mid]=f;
        son[mid][0]=build(mid,lf,mid-1);
        son[mid][1]=build(mid,mid+1,rg);
        update(mid);
        return mid;
    }
    void init() {
        root=build(0,1,n+2);
    }
    void pushdown(int nd) {
        if (rev[nd]) {
            swap(son[nd][1],son[nd][0]);
            if (son[nd][0]) rev[son[nd][0]]^=1;
            if (son[nd][1]) rev[son[nd][1]]^=1;
            rev[nd]=0;
        }
    }
    void rotate(int nd,int d) {
        int baba=fa[nd];
        int s=son[nd][!d];
        int ss=son[s][d];
        son[s][d]=nd;
        son[nd][!d]=ss;
        son[baba][nd==son[baba][1]]=s;
        if (!baba) {
            root=s;
        }
        fa[nd]=s;
        fa[s]=baba;
        if (ss) {
            fa[ss]=nd;
        }
        update(nd);
        update(s);
    }
    void splay(int nd,int goal) {
        while (fa[nd]!=goal) {
            int baba=fa[nd];
            int pd1=nd==son[baba][0];
            if (fa[baba]==goal) {
                rotate(baba,pd1);
            } else {
                int yeye=fa[baba];
                int pd2=baba==son[yeye][0];
                if (pd1==pd2) {
                    rotate(yeye,pd2);
                    rotate(baba,pd1);
                } else {
                    rotate(baba,pd1);
                    rotate(yeye,pd2);
                }
            }
        }
    }
    int find(int pos) {
        int nd=root;
        while (1) {
            pushdown(nd);
            int ls=size[son[nd][0]];
            if (pos<=ls) {
                nd=son[nd][0];
            } else if (pos>=ls+2) {
                nd=son[nd][1];
                pos-=(ls+1);
            } else {
                splay(nd,0);
                return nd;
            }
        }
    }
    void reverse(int lf,int rg) {
        int lnd=find(lf-1);
        int rnd=find(rg+1);
        splay(lnd,0);
        splay(rnd,lnd);
        rev[son[rnd][0]]^=1;
        splay(rnd,0);
    } 
}T;	


    
int main(){
    scanf("%d%d",&n,&m);
    T.init();
    for (int i=1;i<=m;i++) {
        int lf,rg;
        scanf("%d%d",&lf,&rg);
        T.reverse(lf+1,rg+1);
    }
    for (int i=2;i<=n+1;i++) {
        printf("%d ",T.find(i)-1);
    }
    return 0;
}

这个中序遍历是nlogn的,似乎听说可以n的直接跑,不过感觉不可行。逃之夭夭。。。。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值