• 平衡树


      dp啃不动啊 太难了还是数据结构好 但是不思考是会学傻的。。。

    先说平衡树吧,treap 还算简单但是我学了一下午真笨。

    BST 很好理解 上升的treap 不过是支持旋转罢了,更好的维护平衡的性质罢了。

    书上是这样说的我们发现随机下的BST是趋近与平衡的,所以treap是利用随机来创造平衡条件的。

    插入操作:在BST中进行查找不在treap中进行检索有相同的数字的话就++;

    没有的话在检索到的这个位置生成新的节点并get一个随机值。自底向上进行更新。

    利用随机出来的值进行旋转什么的 维护平衡状态:

    inline void insert(int &p,int val)
    {
        if(p==0)
        {
            p=New(val);
            return;
        }
        if(val==val(p))
        {
            ++cnt(p);
            update(p);return;
        }
        if(val<val(p))
        {
            insert(l(p),val);
            if(dat(p)<dat(l(p)))zig(p);
        }
        else
        {
            insert(r(p),val);
            if(dat(p)<dat(r(p)))zag(p);
        }
        update(p);
    }
    View Code

    删除操作:删除x 如果树中没有x不需删除 如果有重复减少副本数即可。

    没有的话 看其是不是叶子节点 是的话直接删不是的话向下旋转直到旋转到叶子节点。

    inline void re(int &p,int val)
    {
        if(p==0)return;
        if(val==val(p))
        {
            if(cnt(p)>1)
            {
                --cnt(p);
                update(p);
                return;
            }
            if(l(p)||r(p))
            {
                if(r(p)==0||dat(l(p))>dat(r(p)))
                    zig(p),re(r(p),val);
                else zag(p),re(l(p),val);
                update(p);
            }
            else p=0;
            return;
        }
        val<val(p)?re(l(p),val):re(r(p),val);
        update(p);return;
    }
    View Code

    找排名这个好找直接检索即可。

    inline int getrankbyval(int p,int val)
    {
        if(p==0)return 0;
        if(val==val(p))return sz(l(p))+1;
        if(val<val(p))return getrankbyval(l(p),val);
        return getrankbyval(r(p),val)+sz(l(p))+cnt(p);
    }
    View Code

    getvalbyrank的话也比较简单注意细节即可

    inline int getvalbyrank(int p,int rank)
    {
        if(p==0)return INF;
        if(sz(l(p))>=rank)return getvalbyrank(l(p),rank);
        if(sz(l(p))+cnt(p)>=rank)return val(p);
        return getvalbyrank(r(p),rank-sz(l(p))-cnt(p));
    }
    View Code

    求x的前驱 其实就是检索x 考虑直接在树中检索x 遇到的都是比x小或比x大的节点不断的去检索x那么此时更新大答案即可。

    出现x这个的话那么前驱其实就是x的左子树的最右边的儿子了。

    inline int getpre(int val)
    {
        int ans=1,p=root;
        while(p)
        {
            if(val==val(p))
            {
                if(l(p)>0)
                {
                    p=l(p);
                    while(r(p))p=r(p);
                    ans=p;
                }
                break;
            }
            if(val(p)<val&&val(p)>val(ans))ans=p;
            p=val<val(p)?l(p):r(p);
        }
        return val(ans);
    }
    View Code

    至于求后继和求前驱其实是一样的。

    inline int getnext(int val)
    {
        int ans=2,p=root;
        while(p)
        {
            if(val==val(p))
            {
                if(r(p))
                {
                    p=r(p);
                    while(l(p))p=l(p);
                    ans=p;
                }
                break;
            }
            if(val(p)>val&&val(p)<val(ans))ans=p;
            p=val<val(p)?l(p):r(p);
        }
        return val(ans);
    }
    View Code

    完整代码:

    //#include<bits/stdc++.h>
    #include<iostream>
    #include<cstdio>
    #include<iomanip>
    #include<cstring>
    #include<string>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<cctype>
    #include<utility>
    #include<set>
    #include<bitset>
    #include<queue>
    #include<stack>
    #include<deque>
    #include<map>
    #include<vector>
    #include<ctime>
    #define INF 2147483646
    #define ll long long
    #define max(x,y) (x>y?x:y)
    #define min(x,y) (x>y?y:x)
    #define l(x) t[x].l
    #define r(x) t[x].r
    #define val(x) t[x].val
    #define dat(x) t[x].dat
    #define cnt(x) t[x].cnt
    #define sz(x) t[x].sz
    using namespace std;
    char buf[1<<15],*fs,*ft;
    inline char getc()
    {
        return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
        int x=0,f=1;char ch=getc();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
        return x*f;
    }
    inline void put(int x)
    {
        x<0?putchar('-'),x=-x:0;
        int num=0;char ch[50];
        while(x)ch[++num]=x%10+'0',x/=10;
        num==0?putchar('0'):0;
        while(num)putchar(ch[num--]);
        putchar('
    ');return;
    }
    //平衡树->splay Author:chdy
    const int MAXN=100010;
    int n,root,tot;
    struct wy
    {
        int l,r;
        int val,dat;
        int cnt,sz;
    }t[MAXN];
    inline int New(int val)
    {
        val(++tot)=val;
        dat(tot)=rand();
        cnt(tot)=sz(tot)=1;
        return tot;
    }
    inline void update(int p)
    {
        sz(p)=sz(l(p))+sz(r(p))+cnt(p);
        return;
    }
    inline void build()
    {
        New(-INF);New(INF);
        root=1;r(1)=2;
        update(root);
    }
    inline int getrankbyval(int p,int val)
    {
        if(p==0)return 0;
        if(val==val(p))return sz(l(p))+1;
        if(val<val(p))return getrankbyval(l(p),val);
        return getrankbyval(r(p),val)+sz(l(p))+cnt(p);
    }
    inline int getvalbyrank(int p,int rank)
    {
        if(p==0)return INF;
        if(sz(l(p))>=rank)return getvalbyrank(l(p),rank);
        if(sz(l(p))+cnt(p)>=rank)return val(p);
        return getvalbyrank(r(p),rank-sz(l(p))-cnt(p));
    }
    inline void zig(int &p)//右旋
    {
        int q=l(p);
        l(p)=r(q);r(q)=p;p=q;
        update(r(p));update(p);
    }
    inline void zag(int &p)
    {
        int q=r(p);
        r(p)=l(q);l(q)=p;p=q;
        update(l(p));update(p);
    }
    inline void insert(int &p,int val)
    {
        if(p==0)
        {
            p=New(val);
            return;
        }
        if(val==val(p))
        {
            ++cnt(p);
            update(p);return;
        }
        if(val<val(p))
        {
            insert(l(p),val);
            if(dat(p)<dat(l(p)))zig(p);
        }
        else
        {
            insert(r(p),val);
            if(dat(p)<dat(r(p)))zag(p);
        }
        update(p);
    }
    inline int getpre(int val)
    {
        int ans=1,p=root;
        while(p)
        {
            if(val==val(p))
            {
                if(l(p)>0)
                {
                    p=l(p);
                    while(r(p))p=r(p);
                    ans=p;
                }
                break;
            }
            if(val(p)<val&&val(p)>val(ans))ans=p;
            p=val<val(p)?l(p):r(p);
        }
        return val(ans);
    }
    inline int getnext(int val)
    {
        int ans=2,p=root;
        while(p)
        {
            if(val==val(p))
            {
                if(r(p))
                {
                    p=r(p);
                    while(l(p))p=l(p);
                    ans=p;
                }
                break;
            }
            if(val(p)>val&&val(p)<val(ans))ans=p;
            p=val<val(p)?l(p):r(p);
        }
        return val(ans);
    }
    inline void re(int &p,int val)
    {
        if(p==0)return;
        if(val==val(p))
        {
            if(cnt(p)>1)
            {
                --cnt(p);
                update(p);
                return;
            }
            if(l(p)||r(p))
            {
                if(r(p)==0||dat(l(p))>dat(r(p)))
                    zig(p),re(r(p),val);
                else zag(p),re(l(p),val);
                update(p);
            }
            else p=0;
            return;
        }
        val<val(p)?re(l(p),val):re(r(p),val);
        update(p);return;
    }
    int main()
    {
        //freopen("1.in","r",stdin);
        build();
        n=read();
        for(int i=1;i<=n;++i)
        {
            int p,x;
            p=read();x=read();
            switch(p)
            {
                case 1:insert(root,x);
                break;
                case 2:re(root,x);
                break;
                case 3:put(getrankbyval(root,x)-1);
                break;
                case 4:put(getvalbyrank(root,x+1));
                break;
                case 5:put(getpre(x));
                break;
                case 6:put(getnext(x));
                break;
            }
        }
        return 0;
    }
    View Code

    还有splay 听说学过它之后就能搞LCT了 真棒但是先放下去搞dp去留坑这里。

  • 相关阅读:
    js导出table到excel,同时兼容FF和IE
    Android 程式开发:(廿一)消息传递 —— 21.3 使用Intent发送短信
    [置顶] 让金融互联网-P2P网贷融资量增长10倍的广告宣传公益活动
    Headroom.js插件用法
    HDU 5289 Assignment(单调队列)
    sh_Spring整合Hibernate
    怎样高速启动Android模拟器(Android Emulator)
    设计模式——介绍与工厂模式(扁平管理模式VS职业经理人模式)
    在c++11中你最惊讶的新feature是什么?
    python的私有化
  • 原文地址:https://www.cnblogs.com/chdy/p/10702458.html
Copyright © 2020-2023  润新知