线段树应用——扫描线

扫描线算法是计算矩形面积并和周长并的有效方法,通过线段树加速处理。文章介绍了如何模拟扫描线,利用横边权值和坐标离散化构建线段树,将问题转化为区间查询,实现矩形覆盖的动态计算。
摘要由CSDN通过智能技术生成

扫描线

 扫描线法是一种求矩形面积并/周长并的好方法。

 扫描线:假设有一条扫描线从一个图形的下方扫向上方(或者左方扫到右方),那么通过分析扫描线被图形截得的线段就能获得所要的结果。该过程可以用线段树进行加速。

 面积的求法其实可以简化为 ∑ \sum 截线段长度 × \times ×扫过的高度。这也是扫描线算法最基础的应用。
在这里插入图片描述
 问题在于如何才能模拟扫描线从下向上扫过图形,并且快速计算出当前扫描线被截得的长度。

 现在假设,扫描线每次会在碰到横边的时候停下来(基本思路),如图。
在这里插入图片描述
 简单来说,可对图形面积产生影响的元素,也就是这些横边左右端点的坐标。

 为了快速计算出截线段长度,可以将横边赋上不同的权值,具体为:对于一个矩形,其下边权值为 1 1 1,上边权值为 − 1 -1 1
在这里插入图片描述
 然后把所有的横边按照 y y y坐标升序排序。这样,对于每个矩形,扫描线总是会先碰到下边,然后再碰到上边。那么就能保证扫描线所截的长度永远非负了。

 这样操作以后,就可以和线段树扯上关系。先把所有端点在 x x x轴上离散化(其实就是把所有点的横坐标存到 X [ ] X[] X[]里,然后升序排个序,最后去重)。
在这里插入图片描述
 在这个例子中,四个端点的纵投影总共把x轴切割成了五个部分。取中间的三部分线段,建立一棵线段树,线段树上每个点位维护一条线段(也就是一个区间)的信息:
 1.该线段被覆盖了多少次(被多少个矩形所覆盖)。
 2.该线段内被整个图形所截的长度是多少。
在这里插入图片描述
 显然,只要一条线段被覆盖,那么它肯定被图形所截。所以,整个问题就转化为了一个区间查询问题,即:每次将 当前扫描线扫到的边 对应的信息 按照之前赋上的权值更新,然后再查询线段树根节点的信息最后得到当前扫描线扫过的面积。这就可以用线段树来实现了(毕竟人家叫“线段”树嘛)。

 下面我们来直观感受一下这个过程,图中绿色部分表示已计算的面积。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
 我们已经知道,这棵线段树的每个节点都对应了一条线段。考虑将线段树上节点对应的区间和横边建立映射关系。先看对于一个叶子节点 p p p,建树时保证了 t r e e [ p ] . l = t r e e [ p ] . r tree[p].l=tree[p].r tree[p].l=tree[p].r,但其保存的信息很显然不可能只是某条线段的一个端点。(如果一条线段的两个端点重合,那么它实质上仅是一个点)。再看一个节点的左右儿子,同样地,建树的时候已经保证了左右儿子的区间不会重合(交集为空),但是看这样两条相邻线段:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值