[NOI2005] 维护数列 sequence

本文介绍如何使用Splay Tree解决NOI2005第二题,涉及区间添加、删除、更新和查询操作。通过Splay Tree实现区间连续最大和的维护,包括ls、rs和ms的计算。代码中添加了head和tail节点简化边界处理,同时利用null节点优化了维护过程,避免了访问NULL导致的错误。
摘要由CSDN通过智能技术生成

后来加的说明:这个代码版本奇丑无比。。。。

题目详见NOI官方网站http://download.noi.cn/T/noi/noi2005A.pdf 第二题。

这道题令我调试得很痛苦。任何一个小错误即使对拍出来也很难找到,因为太繁琐了。

题目要求对一个序列进维护,但是要求添加和删除区间。显然这里线段树就不能用了,只能用splay。好像也可以用块状链表做,但是据说会非常非常麻烦。

我们这样来对一个序列用splay维护:

对于每个节点,记录它的父亲 pt,儿子 ch[0..1],子树大小(区间大小)size,权值 data,区间和 sum,左端区间连续最大和 ls,右端区间连续最大和 rs,区间连续最大和 ms。

基本的添加,删除区间和区间求和就不详细说了,但是要记住一定要update,即操作结束之后区间更新到根的路径。

对于覆盖 MAKE_SAME 操作和旋转 REVERSE 操作,我们可以类似于线段树,用标记下放来维护,并且在每次旋转的时候都下放标记。这里需要注意的是,旋转的标记应该记为原来旋转标记的not值,并且需要交换 ls 和 rs。覆盖之后,如果覆盖值为负,则ls, rs, ms 的值为覆盖值,否则为新得的 sum。

对于区间连续最大和 ms 的维护,是这道题目的重点之一:

首先,我们需要维护 ls 值和 rs 值。容易知道,ls = max(左子树的rs, 左子树的sum + data, 左子树的sum + data + 右子树的rs,(无左子树时)data + 右子树的rs), rs 也类似于此(证明从略)。

然后我们来看看 ms 值,他的维护更为复杂:ms = max(左子树的ms,右子树的ms,左子树的rs + data,右子树的ls + data,左子树的rs + 右子树的ls + data)。

为了完成以上的维护操作,我们可以通过判断子树的情况(无左右子树,只有左\右子树,左右子树都有)来维护,但是这样比较麻烦,而且如果没判断好,访问 NULL 的成员会直接让程序挂掉。

怎么办呢?我们其实可以这样:直接令一个节点为 null (小写区分于NULL),令他的 sum, size 为 0,而 ls, rs, ms为负无穷。这样做就可以不用在维护ls,rs 的时候判断是否有左右子树了,会使代码变得更清楚,而且更可以避免一些因为访问 NULL 而挂掉的错误。需要注意的是,在update, pushdown的时候要避开对 null 进行操作。

还有一个小技巧可以简省代码:在原序列

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值