zoukankan      html  css  js  c++  java
  • Splay_Tree 模板(区间修改,旋转操作)

    1.旋转操作

    #define MAXN 100100
    
    bool Add[MAXN];//延迟标记
    
    struct Splay_Tree
    {
        int cnt, rt;//cnt为节点数,rt == root
    
        struct Tree{
            int key;//关键字
            int num, size;//num是这个节点有多少重复,size是以这个节点为根的子树大小。
            int fa, son[2];
        }T[MAXN];
    
        inline void init()
        {
            cnt = 0;//初始化超级根节点(标记为0的节点)
            T[0].size = 0;
            rt = 0;
            memset(Add,0,sizeof(Add));//开始初始化0
        }
        inline void PushUp(int x)
        {
            T[x].size=T[T[x].son[0]].size+T[T[x].son[1]].size+T[x].num;
        }
    
        inline void PushDown(int x)
        {
            //翻转操作,这一步最为关键
            if(Add[x])
            {
                swap(T[x].son[0],T[x].son[1]);
                Add[T[x].son[0]] ^= 1;
                Add[T[x].son[1]] ^= 1;
                Add[x] = 0;
            }
        }
    
        inline int Newnode(int key, int fa) //新建一个节点并返回
        {
            ++cnt;
            T[cnt].key=key;
            T[cnt].num=T[cnt].size=1;
            T[cnt].fa=fa;
            T[cnt].son[0]=T[cnt].son[1]=0;
            return cnt;
        }
    
        inline void Rotate(int x, int p) //0左旋 1右旋
        {
            int y=T[x].fa;
            PushDown(y);//你是说这个有问题。
            PushDown(x);
            T[y].son[!p]=T[x].son[p];
            T[T[x].son[p]].fa=y;
            T[x].fa=T[y].fa;
            if(T[x].fa)
                T[T[x].fa].son[T[T[x].fa].son[1] == y]=x;
            T[x].son[p]=y;
            T[y].fa=x;
            PushUp(y);
            PushUp(x);
        }
    
        void Splay(int x, int To) //将x节点移动到To的子节点中
        {
            while(T[x].fa != To)
            {
                
                if(T[T[x].fa].fa == To)
                {
                    //在这里面得
                    PushDown(T[x].fa);
                    PushDown(x);
                    Rotate(x, T[T[x].fa].son[0] == x);
                }
                else
                {
                    int y=T[x].fa, z=T[y].fa;
                    PushDown(z);
                    PushDown(y);
                    PushDown(x);
                    int p=(T[z].son[0] == y);
                    if(T[y].son[p] == x)
                        Rotate(x, !p), Rotate(x, p); //之字旋
                    else
                        Rotate(y, p), Rotate(x, p); //一字旋
                }
            }
            if(To == 0) rt=x;
        }
    
        int GetPth(int p, int To) //返回第p小的节点 并移动到To的子节点中
        {
            if(!rt || p > T[rt].size) return 0;
            int x=rt;
            while(x)
            {
                PushDown(x);
                if(p >= T[T[x].son[0]].size+1 && p <= T[T[x].son[0]].size+T[x].num)
                    break;
                if(p > T[T[x].son[0]].size+T[x].num)
                {
                    p-=T[T[x].son[0]].size+T[x].num;
                    x=T[x].son[1];
                }
                else
                    x=T[x].son[0];
            }
            Splay(x, 0);
            return x;
        }
    
        int Find(int key) //返回值为key的节点 若无返回0 若有将其转移到根处
        {
            if(!rt) return 0;
            int x=rt;
            while(x)
            {
                PushDown(x);
                if(T[x].key == key) break;
                x=T[x].son[key > T[x].key];
            }
            if(x) Splay(x, 0);
            return x;
        }
    
        int Prev() //返回根节点的前驱 非重点
        {
            if(!rt || !T[rt].son[0]) return 0;
            int x=T[rt].son[0];
            PushDown(x);
            while(T[x].son[1])
            {
                x=T[x].son[1];
                PushDown(x);
            }
            Splay(x, 0);
            return x;
        }
        
        int next() //返回根结点的后继 非重点
        {
            if(!rt || !T[rt].son[1]) return 0;
            int x=T[rt].son[1];
            PushDown(x);
            while(T[x].son[0])
            {
                x=T[x].son[0];
                PushDown(x);
            }
            Splay(x, 0);
            return x;
        }
        
        void Insert(int key) //插入key值
        {
            if(!rt)
                rt=Newnode(key, 0);
            else
            {
                int x=rt, y=0;
                while(x)
                {
                    PushDown(x);
                    y=x;
                    if(T[x].key == key)
                    {
                        T[x].num++;
                        T[x].size++;
                        break;
                    }
                    T[x].size++;//既然一定调整
                    x=T[x].son[key > T[x].key];
                }
                if(!x)
                    x = T[y].son[key > T[y].key] = Newnode(key, y);
                Splay(x, 0);
            }
        }
    
        void Delete()//直接改成删除根节点
        {
            if(rt == 0) return ;//已经没有节点了
            if(T[rt].num > 1)
            {
                T[rt].num --;
                T[rt].size --;
                return ;
            }
            if(T[rt].son[0] == 0)
            {
                rt = T[rt].son[1];
                T[rt].fa = 0;
            }
            else
            {
                int preid = T[rt].son[0];
                PushDown(preid);
                while(T[preid].son[1])
                {
                    preid = T[preid].son[1];
                    PushDown(preid);
                }
                Splay(preid, rt);
                T[preid].son[1] = T[rt].son[1];
                T[ T[rt].son[1] ].fa = preid;
                rt = preid;
                T[rt].fa = 0;
                PushUp(rt);
            }
        }
    
    //    int GetRank(int key) //获得值<=key的节点个数 并将其转移到根处 若<key只需将<=换为<
    //    {
    //        //我没有写PUSH_UP 和 PUSH_DOWN
    //        if(!rt) return 0;
    //        int x=rt, ret=0, y=0;
    //        while(x)
    //        {
    //            y=x;
    //            if(T[x].key <= key)
    //            {
    //                ret += T[T[x].son[0]].size + T[x].num;
    //                x=T[x].son[1];
    //            }
    //            else
    //                x=T[x].son[0];
    //        }
    //        Splay(y, 0);
    //        return ret;
    //    }
    
    //    这个删除太丑了
    //    void Delete(int l, int r) //删除值在[l, r]中的所有节点 l!=r
    //    {
    //        if(!Find(l)) Insert(l);// 你这样写真的好吗? 泥煤
    //        int p=Prev();
    //        if(!Find(r)) Insert(r);
    //        int q=next();
    //        if(!p && !q)
    //        {
    //            rt=0;
    //            return;
    //        }
    //        if(!p)
    //        {
    //            T[rt].son[0]=0;
    //            PushUp(rt);
    //            return;
    //        }
    //        if(!q)
    //        {
    //            Splay(p, 0);
    //            T[rt].son[1]=0;
    //            PushUp(rt);
    //            return;
    //        }
    //        Splay(p, q);
    //        T[p].son[1]=0;
    //        PushUp(p);
    //        PushUp(q);
    //    }
        
        void display(int x)
        {
            if(x==0) return ;
            PushDown(x);
            display(T[x].son[0]);
            printf("%d ",T[x].key);
            display(T[x].son[1]);
        }
        
    }spt;
    
    //
    //int main() {
    //    //SPT 独特的旋转操作!
    //    int n;
    //    while(scanf("%d",&n) && n)
    //    {
    //        spt.init();
    //        for(int i=1;i<=n;i++)
    //        {
    //            int tmp;
    //            scanf("%d",&tmp);
    //            g[i].key = tmp;
    //            g[i].id = i;
    //            spt.Insert(i);
    //        }
    //        
    //        sort(g+1,g+1+n,cmp);
    //        for(int i=1;i<=n;i++)//开始旋转
    //        {
    //            //step one 将当前最小的点,移动到树根处
    //            spt.Splay(g[i].id, 0);
    //            
    //            //step two 将整个左子树旋转
    //            int sonid = spt.T[g[i].id].son[0];
    //            printf("%d",spt.T[sonid].size+i);
    //            if(i!=n) printf(" ");
    //            if(sonid != 0)
    //            {
    //                Add[sonid] ^= 1;//修改区间
    //            }
    //            spt.Delete();
    //            
    //            //每次操作之后,都把结果打印一遍
    //            //spt.display(spt.rt);
    //            //printf("
    ");
    //        }
    //        printf("
    ");
    //    }
    //    return 0;
    //}

    2.成段更#define MAXN 200100

    
    long long Add[MAXN];//延迟标记
    
    struct Splay_Tree
    {
        int cnt, rt;//cnt为节点数,rt == root
    
        struct Tree{
            long long K;
            long long sumk;
            int key;//关键字
            int num, size;//num是这个节点有多少重复,size是以这个节点为根的子树大小。
            int fa, son[2];
        }T[MAXN];
    
        inline void init()
        {
            cnt = 0;//初始化超级根节点(标记为0的节点)
            T[0].size = 0;
            T[0].sumk = 0;
            T[0].K = 0;
            rt = 0;
            memset(Add,0,sizeof(Add));
        }
        inline void PushUp(int x)
        {
            T[x].size=T[T[x].son[0]].size+T[T[x].son[1]].size+T[x].num;
            T[x].sumk=T[T[x].son[0]].sumk+T[T[x].son[1]].sumk+T[x].K;
        }
    
        inline void PushDown(int x)
        {
            if(Add[x])
            {
                if(T[x].son[0])//
                {
                    T[T[x].son[0]].K += Add[x];
                    T[T[x].son[0]].sumk += T[T[x].son[0]].size*Add[x];
                    Add[T[x].son[0]]+=Add[x];
                }
                if(T[x].son[1])
                {
                    T[T[x].son[1]].K+=Add[x];
                    T[T[x].son[1]].sumk += T[T[x].son[1]].size*Add[x];
                    Add[T[x].son[1]]+=Add[x];
                }
                Add[x]=0;//不管子节点有没有,这层一定往下推,没有子节点相当于标记无效。
            }
        }
    
        inline int Newnode(int key, int fa,int K) //新建一个节点并返回
        {
            ++cnt;
            T[cnt].K = T[cnt].sumk = K;
            T[cnt].key=key;
            T[cnt].num=T[cnt].size=1;
            T[cnt].fa=fa;
            T[cnt].son[0]=T[cnt].son[1]=0;
            return cnt;
        }
    
        inline void Rotate(int x, int p) //0左旋 1右旋
        {
            int y=T[x].fa;
            PushDown(y);//这里是不是必须的,我感觉从小往上不需要往上推
            PushDown(x);
            T[y].son[!p]=T[x].son[p];
            T[T[x].son[p]].fa=y;
            T[x].fa=T[y].fa;
            if(T[x].fa)
                T[T[x].fa].son[T[T[x].fa].son[1] == y]=x;
            T[x].son[p]=y;
            T[y].fa=x;
            PushUp(y);
            PushUp(x);
        }
    
        void Splay(int x, int To) //将x节点移动到To的子节点中
        {
            while(T[x].fa != To)
            {
                if(T[T[x].fa].fa == To)
                    Rotate(x, T[T[x].fa].son[0] == x);
                else
                {
                    int y=T[x].fa, z=T[y].fa;
                    int p=(T[z].son[0] == y);
                    if(T[y].son[p] == x)
                        Rotate(x, !p), Rotate(x, p); //之字旋
                    else
                        Rotate(y, p), Rotate(x, p); //一字旋
                }
            }
            if(To == 0) rt=x;
        }
    
        int GetPth(int p, int To) //返回第p小的节点 并移动到To的子节点中
        {
            if(!rt || p > T[rt].size) return 0;
            int x=rt;
            while(x)
            {
                PushDown(x);
                if(p >= T[T[x].son[0]].size+1 && p <= T[T[x].son[0]].size+T[x].num)
                    break;
                if(p > T[T[x].son[0]].size+T[x].num)
                {
                    p-=T[T[x].son[0]].size+T[x].num;
                    x=T[x].son[1];
                }
                else
                    x=T[x].son[0];
            }
            Splay(x, 0);
            return x;
        }
    
        int Find(int key) //返回值为key的节点 若无返回0 若有将其转移到根处
        {
            if(!rt) return 0;
            int x=rt;
            while(x)
            {
                PushDown(x);
                if(T[x].key == key) break;
                x=T[x].son[key > T[x].key];
            }
            if(x) Splay(x, 0);
            return x;
        }
    
        int Prev() //返回根节点的前驱 非重点
        {
            if(!rt || !T[rt].son[0]) return 0;
            int x=T[rt].son[0];
            while(T[x].son[1])
            {
                PushDown(x);
                x=T[x].son[1];
            }
            Splay(x, 0);
            return x;
        }
    
        int next() //返回根结点的后继 非重点
        {
            if(!rt || !T[rt].son[1]) return 0;
            int x=T[rt].son[1];
            while(T[x].son[0])
            {
                PushDown(x);
                x=T[x].son[0];
            }
            Splay(x, 0);
            return x;
        }
    
        void Insert(int key,int K) //插入key值
        {
            if(!rt)
                rt=Newnode(key, 0, K);
            else
            {
                int x=rt, y=0;
                while(x)
                {
                    PushDown(x);
                    y=x;
                    if(T[x].key == key)
                    {
                        T[x].num++;
                        T[x].size++;
                        break;
                    }
                    T[x].size++;//既然一定调整
                    x=T[x].son[key > T[x].key];
                }
                if(!x)
                    x = T[y].son[key > T[y].key] = Newnode(key, y, K);
                Splay(x, 0);
            }
        }
      
      

    //    void Delete()//直接改成删除根节点

    
    

    //    {

    
    

    //        if(rt == 0) return ;//已经没有节点了

    
    

    //        if(T[rt].num > 1)

    
    

    //        {

    
    

    //            T[rt].num --;

    
    

    //            T[rt].size --;

    
    

    //            return ;

    
    

    //        }

    
    

    //        if(T[rt].son[0] == 0)

    
    

    //        {

    
    

    //            rt = T[rt].son[1];

    
    

    //            T[rt].fa = 0;

    
    

    //        }

    
    

    //        else

    
    

    //        {

    
    

    //            int preid = T[rt].son[0];

    
    

    //            PushDown(preid);

    
    

    //            while(T[preid].son[1])

    
    

    //            {

    
    

    //                preid = T[preid].son[1];

    
    

    //                PushDown(preid);

    
    

    //            }

    
    

    //            Splay(preid, rt);

    
    

    //            T[preid].son[1] = T[rt].son[1];

    
    

    //            T[ T[rt].son[1] ].fa = preid;

    
    

    //            rt = preid;

    
    

    //            T[rt].fa = 0;

    
    

    //            PushUp(rt);

    
    

    //        }

    
    

    //    }

    void Delete(int key) //删除值为key的节点1个,这个操作可能有问题。。。
        {
            int x=Find(key);
            if(!x) return;
            if(T[x].num>1)
            {
                T[x].num--;
                PushUp(x);
                return;
            }
            int y=T[x].son[0];
            while(T[y].son[1])
                y=T[y].son[1];
            int z=T[x].son[1];
            while(T[z].son[0])
                z=T[z].son[0];
            if(!y && !z)
            {
                rt=0;
                return;
            }
            if(!y)
            {
                Splay(z, 0);
                T[z].son[0]=0;
                PushUp(z);
                return;
            }
            if(!z)
            {
                Splay(y, 0);
                T[y].son[1]=0;
                PushUp(y);
                return;
            }
            Splay(y, 0);
            Splay(z, y);
            T[z].son[0]=0;
            PushUp(z);
            PushUp(y);
        }
    
        int GetRank(int key) //获得值<=key的节点个数 并将其转移到根处 若<key只需将<=换为<
        {
            if(!rt) return 0;
            int x=rt, ret=0, y=0;
            while(x)
            {
                y=x;
                if(T[x].key <= key)
                {
                    ret += T[T[x].son[0]].size + T[x].num;
                    x=T[x].son[1];
                }
                else
                    x=T[x].son[0];
            }
            Splay(y, 0);
            return ret;
        }
    
    //    这个删除太丑了
    //    void Delete(int l, int r) //删除值在[l, r]中的所有节点 l!=r
    //    {
    //        if(!Find(l)) Insert(l);// 你这样写真的好吗? 泥煤
    //        int p=Prev();
    //        if(!Find(r)) Insert(r);
    //        int q=next();
    //        if(!p && !q)
    //        {
    //            rt=0;
    //            return;
    //        }
    //        if(!p)
    //        {
    //            T[rt].son[0]=0;
    //            PushUp(rt);
    //            return;
    //        }
    //        if(!q)
    //        {
    //            Splay(p, 0);
    //            T[rt].son[1]=0;
    //            PushUp(rt);
    //            return;
    //        }
    //        Splay(p, q);
    //        T[p].son[1]=0;
    //        PushUp(p);
    //        PushUp(q);
    //    }
    }spt;
  • 相关阅读:
    Java 深拷贝和浅拷贝 利用序列化实现深拷贝
    算法题005 剑指Offer面试题29 数组中出现次数超过一半的数字
    算法题003 斐波那契(Fibonacci)数列
    Android Sensors (4) 传感器使用最佳实践
    Android WebView使用基础
    Java 多线程(八) 线程状态图
    算法题006 判断两个链表是否相交
    Java 多线程(五) 多线程的同步
    算法题001 剑指Offer 面试题三:二维数组中的查找
    Android绘制基础及手写绘制实例
  • 原文地址:https://www.cnblogs.com/chenhuan001/p/5346483.html
Copyright © 2011-2022 走看看