Treap学习小计

来源:互联网 发布:破解手机收费软件 编辑:程序博客网 时间:2024/05/18 01:36

啊啊啊啊,终于学会打treap了啊啊啊啊啊

一个小故事

从前,Tree和Heap相遇了,他们相爱了,于是生下了一个孩子,他叫什么呢?于是他姓Tr名字叫eap,所以他就叫Treap(啦啦啦啦啦啦啦)

Treap的性质

既然他爸是Tree,他妈是Heap,那必定会遗传他爸和他妈的血统啊。
所以他是棵Balanced Binary Tree,同时从其每个点的键值来看,他的形态又是一棵不严格的Heap,当然由于这是从他妈那遗传的,所以他仅仅满足了Heap中:一个点的键值小于(或大于)他的两个儿子的键值。

插入

对于一个点的插入,我们像普通的二叉搜索树一样找到相应位置然后插入,注意我们要维护其heap的形态,所以我们要将新插入的点到根节点的路径类似普通的Heap的方法一样向上,但是由于这是棵二叉搜索树,于是我们要用旋转而非交换。

删除

删除一个节点,若其只有一个儿子或没有儿子,那么其直接用其儿子代替它或直接删掉,若它有两个儿子,那么看它的左右儿子那个键值小,若左儿子小则右旋,右儿子小则左旋,然后继续删除。

其它操作

由于其它操作与普通平衡树基本一样,我就不说了哈。

code(向hzw学习了呀)

#include<cstring>#include<cstdio>#include<algorithm>#include<cmath>#include<iostream>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;typedef long long LL;typedef double db;int get(){    char ch;    int s=0;    bool pd=0;    while(ch=getchar(),(ch<'0'||ch>'9')&&ch!='-');    if (ch=='-')pd=1;    else s=ch-'0';    while(ch=getchar(),ch>='0'&&ch<='9')s=s*10+ch-'0';    if (pd)return -s;    return s;}const int N = 100010;struct point{    int l,r,tot,v,key,w;}tree[N];int tot,n,root;void updata(int x){    tree[x].tot=tree[tree[x].l].tot+tree[tree[x].r].tot+tree[x].w;}void rturn(int &x){    int y=tree[x].l;tree[x].l=tree[y].r;tree[y].r=x;    tree[y].tot=tree[x].tot;updata(x);x=y;}void lturn(int &x){    int y=tree[x].r;tree[x].r=tree[y].l;tree[y].l=x;    tree[y].tot=tree[x].tot;updata(x);x=y;}void insert(int &now,int x){    if (!now){        tree[now=++tot].v=x;        tree[now].key=rand();        tree[now].tot=tree[now].w=1;        return;    }    tree[now].tot++;    if (x==tree[now].v)tree[now].w++;    else    if (x<tree[now].v){        insert(tree[now].l,x);        if (tree[tree[now].l].key<tree[now].key)rturn(now);    }    else{        insert(tree[now].r,x);        if (tree[tree[now].r].key<tree[now].key)lturn(now);    }}void del(int &now,int x){    if (tree[now].v==x){        if (tree[now].w>1){            tree[now].w--;            tree[now].tot--;            return;        }        if (tree[now].l*tree[now].r==0)now=tree[now].l+tree[now].r;        else{            if (tree[tree[now].l].key<tree[tree[now].r].key)rturn(now),del(now,x);            else lturn(now),del(now,x);        }        return;    }    tree[now].tot--;    if (tree[now].v>x)del(tree[now].l,x);    else del(tree[now].r,x);}int rank(int now,int x){    if (!now)return -N;    if (tree[now].v==x)return tree[tree[now].l].tot+1;    if (x<tree[now].v)return rank(tree[now].l,x);    return tree[tree[now].l].tot+tree[now].w+rank(tree[now].r,x);}int kth(int now,int k){    if (!now)return 0;    if (tree[tree[now].l].tot<k&&k<=tree[tree[now].l].tot+tree[now].w)    return now;    if (k<=tree[tree[now].l].tot)return kth(tree[now].l,k);    return kth(tree[now].r,k-tree[tree[now].l].tot-tree[now].w);}int pre(int now,int x){    if (!now)return 0;    if (tree[now].v<x){        int v=pre(tree[now].r,x);        if (v)return v;        return now;    }    return pre(tree[now].l,x);}int suf(int now,int x){    if (!now)return 0;    if (tree[now].v>x){        int v=suf(tree[now].l,x);        if (v)return v;        return now;    }    return suf(tree[now].r,x);}int main(){    n=get();    srand(57789);    int tim=0;    fo(i,1,n){        int w,opt=get(),x=get();        switch(opt){        case 1:insert(root,x);break;        case 2:del(root,x);break;        case 3:printf("%d\n",rank(root,x));break;        case 4:w=kth(root,x);printf("%d\n",tree[w].v);break;        case 5:w=pre(root,x);printf("%d\n",tree[w].v);break;        case 6:w=suf(root,x);printf("%d\n",tree[w].v);break;        }    }    return 0;}

建议学习新的平衡树可以用【bzoj3224】Tyvj 1728 普通平衡树 这题啊

0 0
原创粉丝点击