Treap-非指针总结

【Treap】

【介绍】
树堆,在数据结构中也称Treap(tree+heap),是指有一个随机附加域满足堆的性质的二叉搜索树,其结构相当于以随机数据插入的二叉搜索树。其基本操作的期望时间复杂度为O(logn)。相对于其他的平衡二叉搜索树,Treap的特点是实现简单,且能基本实现随机平衡的结构。

【操作】
注:

struct Treap
{
    int x,l,r,w,s,ran;//x表示这个节点的权值,l表示这个节点的左儿子,r表示这个节点的右儿子,w表示该权值的数的个数,s表示这个节点的子树的的节点的w的总和,ran表示随机的权值。
}a[maxn];

void Updata(int k)
{
    a[k].s=a[a[k].l].s+a[a[k].r].s+a[k].w;
}

本人维护的是小根堆。(也可以维护大根堆)
本人目前不会指针。

① 右旋:
这里写图片描述

void Rturn(int &k)
{
    int t=a[k].l; a[k].l=a[t].r; a[t].r=k;
    a[t].s=a[k].s; Updata(k); k=t;
}

② 左旋:
这里写图片描述

void Lturn(int &k)
{
    int t=a[k].r; a[k].r=a[t].l; a[t].l=k;
    a[t].s=a[k].s; Updata(k); k=t;
}

③ 插入x数:

void Insert(int &k,int x)
{
    if (k==0) {k=++tot; a[k].x=x; a[k].w=a[k].s=1; a[k].ran=rand(); return;}
    a[k].s++;
    if (a[k].x==x) a[k].w++;
     else if (x<a[k].x)
      {
        Insert(a[k].l,x);
        if (a[a[k].l].ran<a[k].ran) Rturn(k);
      }
      else
       {
        Insert(a[k].r,x);
        if (a[a[k].r].ran<a[k].ran) Lturn(k);
       }
}

④ 删除x数:

void Delete(int &k,int x)
{
    if (k==0) return;
    if (a[k].x==x)
     {
        if (a[k].w>1) {a[k].w--; a[k].s--; return;}
         else if (!a[k].l||!a[k].r) k=a[k].l+a[k].r;
          else if (a[a[k].l].ran<a[a[k].r].ran) {Rturn(k); Delete(k,x);} else {Lturn(k); Delete(k,x);}//将节点旋转到叶子节点才能删除。
     }
     else if (x<a[k].x) a[k].s--,Delete(a[k].l,x); else a[k].s--,Delete(a[k].r,x);
}

⑤ 查询x数的排名:

int Rank(int k,int x)
{
    if (k==0) return 0;
    if (x==a[k].x) return a[a[k].l].s+1;
    if (x<a[k].x) return Rank(a[k].l,x); else return a[a[k].l].s+a[k].w+Rank(a[k].r,x);
}

⑥ 查询排名为x的数:

int Num(int k,int x)
{
    if (k==0) return 0;
    if (x<=a[a[k].l].s) return Num(a[k].l,x);
     else if (x>a[a[k].l].s+a[k].w) return Num(a[k].r,x-a[a[k].l].s-a[k].w);
      else return a[k].x;
}

⑦ 求x的前驱:

void Pre(int k,int x)
{
    if (k==0) return;
    if (x>a[k].x) {ans=a[k].x; Pre(a[k].r,x);} else Pre(a[k].l,x);
}

⑧ 求x的后继:

void Sub(int k,int x)
{
    if (k==0) return;
    if (x<a[k].x) {ans=a[k].x; Sub(a[k].l,x);} else Sub(a[k].r,x);
}

【例题】
bzoj3224

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值