码迷,mamicode.com
首页 > 其他好文 > 详细

线段树 (扫描线)

时间:2015-01-10 00:56:17      阅读:194      评论:0      收藏:0      [点我收藏+]

标签:

  这里用HDU的1542题作为例子,一个经典的扫描线题目,计算矩形并的和。

  首先介绍扫描线,就是一根假想的线,从左到右的一条竖线扫描过去。

  扫描线可以用来填充多边形,具体请看 http://blog.csdn.net/orbit/article/details/7368996  写的很好。

  然后就是扫描线在这个题里的应用。

  技术分享

  计算这两个矩形的面积等价于计算红色,绿色,蓝色三块的面积的和。

  所以说从左到右的扫描线扫描的时候,线段树维护的是区间内被覆盖的总长度,然后乘以两条扫描线之间的距离,就是一块的面积,然后更新线段树,以此论推,得到的就是总面积了。

  不过这个题要注意三个地方:

  1,离散化,每条边的坐标是浮点数,要进行离散化,要记得去重。

  2,就是区间覆盖的长度计算问题,这里我纠结了老久,首先如果按照点来覆盖的话对区间2,8覆盖其实是对1,5和6,10进行覆盖(如果线段树左右子树的区间是1,5和6,10的话,那么5和6中间那一块就没有被计算上,就出问题了。。。

  所以说不能按照点来覆盖,应该把每个点当作是表示这个点到下一个点之间的这条线段,这样就不会漏掉中间那一个了。

  如果是表示线段的话,那么如果有10个点,那么有9条线段,所以线段树是1到9(而不是10),每次计算长度的时候记得右边要加一。

  3,就是线段树的更新问题,每加一条线段或者减一条线段的话,并不是简单的覆盖就好,而是应该记录这个区间被覆盖了几次,直到减到零的时候才是没有线段在覆盖这个区间。这样的话每加一条线段就是对线段的区间+1,去一条线段就是-1。

  不过这样的话pushDown就不好用了,因为如果把一个节点的COL值推到下面两个之后,之后如果再覆盖,这个节点的COL变成-1了,那就不好算这个节点维护的值了。所以根据杭电大神的写法,不用pushDown,而是在计算pushUP的时候,如果这个节点已经被覆盖为大于0的就直接计算(因为这个节点表示的整个区间都被覆盖了,直接右面减去左面就是了。),否则才求助于下面的两个节点。而且,询问只是询问节点1的值,所以不会出错。

 

  差不多就这三个了,水平有限,敬请谅解。

 

例题:

  HDU  1542  题解请单击

  HDU  1828  题解请单击

线段树 (扫描线)

标签:

原文地址:http://www.cnblogs.com/whywhy/p/4214353.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!