伸展树小结

这么炫酷的数据结构简直飘逸到不行,竟然在这么狂躁的状态下过了一遍基础题型,略浪费。

强项:在一维的情况下可以完成区间查询,更新,翻转,子区间的增删,确定前驱后即,总是一句话线段树能做的它就能做,线段树不太好做的他也能很方便的实现。

弱项:没有办法向更高维度扩展(反正本渣没有想出来),这也是一个局限吧。代码太长. . . . . 太致命了。

伸展操作:核心操作,通过一系列的旋转将某个节点旋转到目标位置。

void Rotate(int root,int dir)
{
    st[st[root].pre].son[dir] = st[root].son[1^dir];
    st[root].son[1^dir] = st[root].pre;

    if(st[st[st[root].pre].pre].son[0] == st[root].pre)
        st[st[st[root].pre].pre].son[0] = root;
    else
        st[st[st[root].pre].pre].son[1] = root;
    int temp = st[root].pre;
    st[root].pre = st[st[root].pre].pre;
    st[temp].pre = root;

    if(st[temp].son[dir] != -1)
        st[st[temp].son[dir]].pre = temp;
    Updata(temp);
    Updata(root);
}

int Splay(int root,int goal)
{
    while(st[root].pre != goal)
    {
        Rotate(root,(st[st[root].pre].son[0] == root ? 0 : 1));
    }

    return root;
}

确定待伸展节点位置的函数模板

int Search_Site(int root,int site)
{
    Push_Down(root);

    int temp;

    if(st[root].ls + 1 == site)
        temp = root;
    else if(st[root].ls + 1 < site)
        temp = Search_Site(st[root].son[1],site-st[root].ls-1);
    else
        temp = Search_Site(st[root].son[0],site);

    Updata(root);
    return temp;
}


一些细节:

1.通过虚拟根结点以及虚拟的两个区间端点在减少代码长度的同时避免RE。

2.对于任何一棵子树,其根结点代表为该子树的信息。

3.当查询区间[L,R]上的信息时,需将R+1旋转至根结点,再将L-1旋转至根结点,则此时根结点的左孩子的右子树代表的即为[L,R]。

4.大多时候,在伸展之前需将待伸展节点与目标位置路径上的延迟标记擦出(Push_Down && Push_Up,这个很像线段树)。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值