谈区间合并线段树

对于以前做的区间合并线段树颇有微词,对于大神们使用三个数组来记录节点的情况很是不解。对于当前点,只需要能提供所需的w长度区间即可向下进行判断,左子树优先提供,左右子树合并提供,右子树最后提供,否则输出不可行。

故我认为只需要一个记录当前节点的情况的数组即可,不需要三个数组,故用一个数组实际编写了代码。后发现此法是不行的.... 首先判断左右子树能否提供的问题,lsum+rsum>=w则返回m-lsum+1,这样用三个数组很方便,若用一个数组会有很多bug,因为一个数组只是记录自己的情况:左右子树提供给自己的东西。而没有考虑区间的连续性。举例来说:1-10的线段树,左子树右子树分别提供4,但是5,6两点已经被占,这时要提供8长度的区间显然不可能,但是只用一个数组会出现可行的情况而且答案是2.为何要使用三个数组?因为我对这些数组各自的功能不是很清楚,现在来看,lsum与rsum有各自的用处。lsum,rsum各自记录当前点向左向右的连续区间各多长,也就是说这两个数组实际上起的作用就是用来判断区间连续与否。

void PushUp( int rt,int m ) 
{ 
lsum[rt]=lsum[rt<<1]; //当前lsum直接取左子树的lsum[]值 
rsum[rt]=rsum[rt<<1|1]; //当前sum直接取右子树的rsum[]值 
if( lsum[rt]==(m-(m>>1)) )lsum[rt]+=lsum[rt<<1|1];//若左子树是满的,则向右拓展 求和 
if( rsum[rt]==m>>1 )rsum[rt]+=rsum[rt<<1];//若右子树是满的,则向左拓展 求和 
msum[rt]=max( lsum[rt<<1|1]+rsum[rt<<1],max( msum[rt<<1],msum[rt<<1|1]) ); 
//当前msum的值为左右子树中空闲点,和 左子树的右边和右子树的左边的和中最大值 
} 

合并区间的重要操作就在于PushUp操作中,其他的地方lsum与rsum用法相同,共同更新,这也是我产生错觉的原因。看来对于理解这些算法真的很是重要啊~ 我果然还是太弱了!加油!!










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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值