Splay 板子学习

1 篇文章 0 订阅
1 篇文章 0 订阅

介绍

Spaly是伸展树 也是对二叉查找树的一种改进,虽然它并不能保证树一直是“平衡”的,但对于伸展树的一系列操作,我们可以证明其每一步操作的平摊复杂度都是O(log n)。所以从某种意义上说,伸展树也是一种平衡的二叉查找树。而在各种树状数据结构中,伸展树的空间要求与编程复杂度也都是很优秀的

处理问题

伸展树在区间插入,区间删除,区间翻转,区间旋转的问题中应用较多。

参考

入门解析: https://www.cnblogs.com/cjyyb/p/7499020.html
操作介绍:https://blog.csdn.net/niuox/article/details/8018280
模板参考:https://www.cnblogs.com/Mathics/p/3971220.html
各种树: https://blog.csdn.net/MetalSeed/article/details/11846255

学习

常用模板
1. 处理序列区间问题,以下标来建树
未测试,未写完,待续... 2018.08.03 21:25
insert(l,r,v) del(l,r)未测试,其他测试题为POJ 3580 POJ 3468 2018.08.05 21:45 自己有点懒了,好几天了..., 未写完,待续... 2018.08.05 21:25
insert del 已测试 测试题目 bzoj 1269 其中insert(l,r) del(l,r) sum和 和minn未找到测试题,理论不错... 2018.08.06 15:52 未完待续...

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
#define rd(a) scanf("%d",&a)
#define rld(a) scanf("%lld",&a)
#define rs(a) scanf("%s",a)
#define me(a,b) memset(a,b,sizeof(a))
const ll maxn=3e5+10;
const ll mod =1e9+7;
const ll inf =0x3f3f3f3f;

/*****   板子开始    ******/
int a[maxn];
int f[maxn];  
int ch[maxn][2];
ll sum[maxn];
int val[maxn];
int lazy[maxn];
int size[maxn];
bool flip[maxn];
int minn[maxn];
int root;
int cnt=0;
int n;
struct SplayTree{


    inline void pushUp(int u){ //yes


         size[u]=size[ch[u][0]]+size[ch[u][1]]+1;
         sum[u]=sum[ch[u][0]]+sum[ch[u][1]]+val[u]+lazy[u];
         minn[u]=val[u];
         if(ch[u][0]) minn[u]=min(minn[u],minn[ch[u][0]]);
         if(ch[u][1]) minn[u]=min(minn[u],minn[ch[u][1]]);

    }
    inline void pushDown(int u){ //yes
    if(flip[u]){

            flip[ch[u][0]]^=1;
            flip[ch[u][1]]^=1;
            swap(ch[u][1],ch[u][0]);
            flip[u]=0;

        }
        if(lazy[u]){
            if(ch[u][0]) {
                lazy[ch[u][0]]+=lazy[u];    
                sum[ch[u][0]]+=(ll)lazy[u]*size[ch[u][0]];
                minn[ch[u][0]]+=lazy[u];    
            }
            if(ch[u][1]) {
                lazy[ch[u][1]]+=lazy[u];
                sum[ch[u][1]]+=(ll)lazy[u]*size[ch[u][1]];
                minn[ch[u][1]]+=lazy[u];    
            }
            val[u]+=lazy[u];
            lazy[u]=0;
        }

    }
    inline void addNode(int &u,int fa,int v){ //yes
        u=++cnt;
        f[u]=fa;
        ch[u][1]=ch[u][0]=0;
        flip[u]=false;
        lazy[u]=0;
        val[u]=v;
        minn[u]=v;
        sum[u]=v;
        size[u]=1;
    }
    void bulidTree(int l,int r,int &u,int fa,int num[]){ //yes
        if(l>r) return;
        int mid=(l+r)>>1;
        addNode(u,fa,num[mid]);
        if(l<mid) bulidTree(l,mid-1,ch[u][0],u,num);
        if(r>mid) bulidTree(mid+1,r,ch[u][1],u,num);
        pushUp(u);
    }
    inline void rotate(int x,int p){  yes
        int y=f[x];
        pushDown(y);
        pushDown(x);
        ch[y][!p]=ch[x][p];
        f[ch[x][p]]=y;
        f[x]=f[y];
        if(f[y]) ch[f[y]][ch[f[y]][1]==y]=x;
        f[y]=x;
        ch[x][p]=y;
        pushUp(y);
    }
    void Splay(int x,int  goal) { //goal 为x到根节点路上的点  //yes
        pushDown(x);
        while(f[x]!=goal){
             int y=f[x];
             int z=f[y];
             pushDown(z);
             pushDown(y);
             if(f[y]==goal) rotate(x,ch[y][0]==x);
             else{
                int g=(ch[z][0]==y);
                if(ch[y][g]==x) rotate(x,!g);
                else rotate(y,g);
                rotate(x,g);
             }

        } 
        pushUp(x);
        if(goal==0) root=x;

    } 

    int getPre(int x){   
        Splay(x,0); 
        int temp=ch[root][0];
        if(!temp) return 0;
        pushDown(temp);
        while(ch[temp][1]) temp=ch[temp][1],pushDown(temp);
        return temp;
    }
    int getNex(int x){  
        Splay(x,0); 
        int temp=ch[x][1];
        if(!temp) return 0;
        pushDown(temp);
        while(ch[temp][0]) temp=ch[temp][0],pushDown(temp);
        return temp;

    }
    int findx(int x){  yes
        x++;
        int r=root;
        pushDown(r);
        while(x){       
            if(size[ch[r][0]]>=x){
                r=ch[r][0];
            }else{
                x-=size[ch[r][0]]+1;
                if(!x) return r;
                r=ch[r][1];
            }

            pushDown(r);
        }

        return r;

    }
    inline void xgth(int x,int goal){
        Splay(findx(x),goal);
    }
    inline void insert(int x,int v){ //yes
        xgth(x-1,0);
        xgth(x,root);
        addNode(ch[ch[root][1]][0],ch[root][1],v);
        pushUp(ch[root][1]);
        pushUp(root);
    }
    inline void insert(int x,int l,int r,int v[]){
        xgth(x-1,0);
        xgth(x,root);
        bulidTree(l,r,ch[ch[root][1]][0],ch[root][1],v);
        pushUp(ch[root][1]);
        pushUp(root);       

    }
    inline ll query_sum(int l,int r){ //yes
        xgth(l-1,0);
        xgth(r+1,root);
        return sum[ch[ch[root][1]][0]];     
    }
    inline int query_min(int l,int r){ //yes
        xgth(l-1,0);
        xgth(r+1,root);
        return minn[ch[ch[root][1]][0]];
    }
    inline void update(int l,int r,int v){ //yes
        xgth(l-1,0);
        xgth(r+1,root);
        lazy[ch[ch[root][1]][0]]+=v;
        minn[ch[ch[root][1]][0]]+=v;
        sum[ch[ch[root][1]][0]]+=(ll)v*size[ch[ch[root][1]][0]];
    }
    inline void  reversal(int l,int r){ //yes
         xgth(l-1,0);
         xgth(r+1,root);
         flip[ch[ch[root][1]][0]]^=1;


    }
    inline void del(int x){ //yes
        xgth(x-1,0);
        xgth(x+1,root);
        ch[ch[root][1]][0]=0;
        pushUp(ch[root][1]);
        pushUp(root);
    }
    inline void del(int l,int r){
        xgth(l-1,0);
        xgth(r+1,root);
        ch[ch[root][1]][0]=0;
        pushUp(ch[root][1]);
        pushUp(root);

    }
    inline void print(int r,int v){     //yes
        pushDown(r);
        if(ch[r][0]) print(ch[r][0],v);
        if(val[r])   printf("%d%c",val[r],r==v?'\n':' ');
        if(ch[r][1]) print(ch[r][1],v);

    }
    inline void print(){
        int v=findx(n);
        print(root,v);
    }
    inline void init(){
        root=cnt=0;
        addNode(root,0,0);
        addNode(ch[root][1],root,0);
        /*输入*/
        for(int i=0;i<n;i++)
        {
            a[i]= i+1;
        }

        bulidTree(0,n-1,ch[ch[root][1]][0],ch[root][1],a);
        pushUp(ch[root][1]);
        pushUp(root);

    }
    inline void init_v(){
        root=cnt=0;
        addNode(root,0,0);
        addNode(ch[root][1],root,0);
        /*输入*/
        for(int i=0;i<n;i++)
        {
            rd(a[i);
        }
        bulidTree(0,n-1,ch[ch[root][1]][0],ch[root][1],a);
        pushUp(ch[root][1]);
        pushUp(root);

    }


};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值