hdu 3487 Play with Chain(伸展树)

此题乃传说中splay的简单应用。

不愧是传说中的数据结构,花了两天才写出来,第一次写debug可是费了不少功夫啊。

老实说写这种数据结构还真是不简单,上次学treap的时候也是花了好大功夫。  

不过最终好歹是写出来了,而且学到了不少东西。算是值了。

 

上次写treap的时候,旋转操作写了两个函数,这次学会了一种新写法,可以将旋转操作直接写成一个函数。

 

在结构体中  用ch[2]  来记录儿子节点。

用ch[0]表示左儿子,用ch[1]表示右儿子。

 

于是rotate操作就可以写成

 

 

 

其中s=0 表示x节点是其父节点的左儿子    s=1则表示x是其父节点的右儿子

 

这样一来两种旋转操作就可以用一个函数搞定了。     

 

至于伸展树的核心操作splay(int x,int f)   将x节点旋转到f节点的下方。则是两种原始旋转操作的组合,注意一字型旋转和之字型旋转时,旋转节点的顺序就行了。

 

 

有一种写法很不容易想到,就是标记法。

比如  将某一区间的数字反转,我们再提取该区间后,不用马上将该区间所有数进行反转操作,只需用一个标记标记该区间在访问时候需要反转。   这样的话,可以省很多时间。因为不访问时,进行反转操作是没有必要的。   比如在该区间被访问之前需要经历2×n次反转,那么实际上该区间最后的效果是不需要反转,我们只要修改标记就可以达到这个效果;

当访问到该区间时,我们对该节点执行标记的相应操作,然后将标记下移即可。    

 

如果写过线段树的话,这点应该很容易理解了。

 

如果想学习splay ,可以看看杨思雨的论文,baidu一下就出来了

 

 

贴下我自己的代码吧:

跑了600多MS,写的挺一般的。    

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值