Treap 模板

int ch[N][2];    //记录左右儿子,0左,1右
int val[N];      //节点的权重
int counts[N];   //重复值的个数
int r[N];        //随机值
int size[N];     //代表下边节点的个数,包括自己
int tot,root;    //总共结点的个数; 根节点
int Newnode(int &rt,int v)        //添加新节点
{
    rt = ++tot;
    val[rt] = v;           
    ch[rt][0] = ch[rt][1] = 0;   
    counts[rt] = size[rt] = 1;
    r[rt] = rand();                   //随机值
    return rt;
}
inline void PushUp(int rt)        //更新以rt为根的节点个数
{
    size[rt] = size[ch[rt][0]]+size[ch[rt][1]]+counts[rt];    //左儿子+右儿子+当前rt的重复个数
}
void Rotate(int &x,int kind)           //为了维持最小(大)堆(节点的随机值)旋转
{
    int y = ch[x][kind^1];
    ch[x][kind^1] = ch[y][kind];
    ch[y][kind] = x;
    PushUp(x);
    PushUp(y);
    x = y;
}
int Insert(int &rt,int v)              //插入
{
    if(rt == 0)
        return Newnode(rt,v);
    int ans;
    if(v == val[rt]) 
        counts[rt] ++, ans = rt;
    else
    {
        int kind = (v > val[rt]);
        ans = Insert(ch[rt][kind], v);
        if(r[ch[rt][kind]] < r[rt])
        Rotate(rt, kind^1);
    }
    PushUp(rt);
    return ans;
}
int select(int rt,int k)    //查询第k小值
{
    if(size[ch[rt][0]] >= k) return select(ch[rt][0],k);      //在左子树
    if(size[ch[rt][0]]+counts[rt] >= k) return val[rt];       //在当前结点
    return select(ch[rt][1],k-size[ch[rt][0]] - counts[rt]);  //在右子树
}
void remove(int &rt, int v)       //删除,旋转到叶子节点
{
    if(val[rt] == v)
    {
        if(counts[rt] > 1)     //个数大于1
            counts[rt] --;
        else if(!ch[rt][0] && !ch[rt][1])   //是叶子结点
        {
            rt = 0;
            return;
        }
        else
        {
            int kind=r[ch[rt][0]] < r[ch[rt][1]];
            Rotate(rt,kind);
            remove(rt,v);
        }
    }
    else remove(ch[rt][v > val[rt]],v);
    PushUp(rt);
}
void Init()
{
    ch[0][0] = ch[0][1] = 0;
    size[0] = counts[0] = val[0] = 0;
    tot = root = 0;
    r[0] = (1LL<<31)-1;
    Newnode(root,2000000001);
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值