FHQ Treap

话不多说,直接进入正题。

一:基本保存信息

struct node
{
    int key,val;//val为权值,key为真实值
    int l,r;//左右儿子的编号
    int size;//树的大小
}tr[N];

二:构造新节点


int newnode(int v)
{
    tr[++idx].val=v;
    tr[idx].key=rand();
    tr[idx].size=1;
    return idx;
}

三:向上更新

void pushup(int p)
{
    tr[p].size=tr[tr[p].l].size+tr[tr[p].r].size+1;
}

四:分裂

void split(int p,int v,int &x,int &y)
{
    if(!p) x=y=0,return ;
    
    if(tr[p].val<=v)
    {
        x=p;
        split(tr[x].r,v,tr[x].r,y);
    }
    
    else 
    {
        y=p;
        split(tr[y].l,v,x,tr[y].l);
    }
    pushup(p);
}

五:合并

int merge(int x,int y)
{
    if(!x || !y)
    {
        return x+y;
    }
    
    if(tr[x].key<tr[y].key)
    {
        tr[x].r=merge(tr[x].r,y);
        pushup(x);
        return x;
    }
    
    else
    {
        tr[y].l=merge(x,tr[y].l);
        pushup(y);
        return y;
    }
}

六:插入

int newnode(int v)
{
    tr[++idx].val=v;
    tr[idx].key=rand();
    tr[idx].size=1;
    return idx;
}

void insert(int v)
{
    int x,y,z;
    split(root,v,x,y);
    z=newnode(v);
    root = merge(merge(x,z),y);
}

七:删除

void del(int v)
{
    int x,y,z;
    
    split(root,v,x,z);
    split(x,v-1,x,y);
    y=merge(tr[y].l,tr[y].r);
    root=merge((x,y),z);
}

八:返回第K个节点

int get_k(int p,int k)
{
    if(k<=tr[tr[p].l].size)
    {
        return get_k(tr[p].l,k);
    }
    if(k==tr[tr[p].l].size+1) return p;
    return get_k(tr[p].r,k-tr[tr[p].l].size-1);
}

九:返回前驱

void grt_pre(int v)
{
    int x,y;
    split(root,v-1,x,y);
    int p=get_k(x,tr[x].size());
    printf("%d\n",tr[p].val);
    merge(x,y);
}

十:返回后驱

void get_suc(int v)
{
    int x,y;
    split(root,v,x,y);
    int p=get(x,1);
    printf("%d\n",tr[p].val);
    root=merge(x,y);
}

十一:得到排名

void get_rank(int v)
{
    int x,y;
    split(root,v-1,x,y);
    printf("%d\n",tr[x].size+1);
    root=merge(x,y);
}

十二:得到第k个数

int get_val(int v)
{
    int p = get_k(root,k);
    printf("%d\n",tr[p].val);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值