ZOJ - 3324 Machine

线段树还真是纠结了我好几天。由于几乎0基础,所以先研究别人AC的代码。

链接如下:http://hi.baidu.com/forverlin1204/blog/item/5b0b533110d9d595a8018e5b.html

 

开始不懂:为什么一个区间的高度不是0,就直接不去判断它的子区间中是否有满足题意的连续块了。

 

后来才发现原来是题意理解错了,一个push对应一个release。所以如果父区间的height不为0的话,子区间的height就不可能为0。

 

最后自己跌跌撞撞得写好了代码, 发现提交WA。对比那AC的代码发现,自己的代码就差:对于离散化后的点,如果两点间的间距大于1的

 

话,那么要在这两个点之间加入这两个点的终点。

 

表示无法理解为什么这么做,感觉离散化后的点就能正确地表示每个区间了的。所以为什么要加个点呢?后来自己在纸上模拟了下两种不同表示时候的插入情况。才发现如果不加这个点的话, 那么离散化后,原先不连续的两点就被当成连续的了。

 

比如输入的坐标包含1, 2, 4, 5。

 

转化后为0(1), 1(2), 2(4), 3(5)。于是乎,原先的2,4点变成1,2点后被当做连续的了。所以我们只需这两个点之间随便地插入一个点。

 

下面说一下解题的细节:

 

一、首先树的构造:

 

struct Node{

int height, right, left, cnt, r, l;

};

height: 区间的高度。push则加1,release则减一。(从图像上看好像有点有违常理)

right, left:记录区间的最右边(左边)是不是属于某个连续块的。

cnt: 记录这个区间里有多少个高度为0的连续块。

r, l: 区间的左右界限。

 

 

二、接着是如何标记

 

我们只需标记找到的能覆盖的最大区间就行。

由于一个区间的height为0的话肯定没有符合题意的连续块,所以push或release一个区间后,如果heigh不为0,则将它的cnt以及right和

 

left都赋值为0。

 

三、如何更新(传递标记)

 

做法总是递归更新,问题就在于如何根据子区间的状态来更新父区间。

 

首先,如果父区间的高度不为0的话,那么是不用考虑子区间的具体情况的。cnt总为0。

 

如果父区间高度为0,那么就要考虑子区间了。cnt等于两个子区间的cnt相加。还要注意减去重复计算的(如果有的话)。

 

还有就是要把子区间的right,left标记传上来。 最后,更新时还要留意区间是不是叶子节点的情况。

 

 

ps.这回终于体会到什么是真正的离散化了:只记录需要的。 之前做的那个求线段并的,只是离散化初体验,感觉不到明显的离散—_—

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值