平衡树

  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去留坑这里。

原文地址:https://www.cnblogs.com/chdy/p/10702458.html