扫描线

一种求多个矩形和周长\(∪\)的方法数组

扫描线:假设有一条扫描线从一个图形的下方扫向上方(或者左方扫到右方),那么经过分析扫描线被图形截得的线段就能得到所要的结果。该过程能够用线段树实现——洛谷题解spa

面积并

二话不说先上图——本身画图贼丑,因此暂且借一下洛谷的图blog

如何求上面两个矩形的面积呢??排序

咱们假设一条扫描线从下方开始向上扫,扫到横边的时候中止、class

首先咱们将矩形的上下边分为上位边(即y坐标大的那条平行于x轴的边),和下位边(y坐标小的平行于x轴的边).而后咱们把全部矩形的上下位边按照他们y坐标从小到大排序,能够获得4条扫描线:方法

根据图能够看出,对图形面积有贡献的是横边左右端点的坐标,咱们把矩形的下边赋予权值为1,上边为-1,而后把全部的边按照纵坐标大小升序排序(模拟扫描过程);im

而后捏??查询

线段树是个好东西(每次都挂img

咱们把全部的边离散化,把横坐标存到一个数组里,升序排列,而后去重(防止x为浮点数且很大没法进行线段树)兼容

上图能够看出,四个横坐标把x轴分红了5段,咱们取中间3段间线段树维护

其中每一个端点维护每一个线段信息:

1.该线段被覆盖了多少次(被多少个矩形所覆盖)
2.该线段内被整个图形所截的长度是多少

显然,只要一条线段被覆盖,那么它确定被图形所截。因此,整个问题就转化为了一个区间查询问题,即:每次将 当前扫描线扫到的边 对应的信息 按照以前赋上的权值更新,而后再查询线段树根节点的信息,最后获得当前扫描线扫过的面积。这就能够用线段树来实现了

模拟过程

咱们已经知道,这棵线段树的每一个节点都对应了一条线段。考虑将线段树上节点对应的区间和横边创建映射关系。先看对于一个叶子节点\(x\),建树时保证了\(tree[x].l=tree[x].r\)但其保存的信息很显然不可能只是某条线段的一个端点(若是一条线段的两个端点重合,那么它实质上仅是一个点)。再看一个节点的左右儿子,一样地,建树的时候已经保证了左右儿子的区间不会重合(交集为空),可是看这样两条相邻线段:\([1,2],[2,3]\)你会发现\([1,2]∩[2,3]={2}\),也就是说左儿子的右端点和右儿子的左端点实际上是重合的。

考虑把线段树每一个节点\(x\)对应的区间\((tree[x].l,tree[x].r)\)不变,改变区间和横边的映射关系,具体为:节点\(x\)对应\([X[tree[x].l],X[tree[x].r+1]]\)这条横边。能够看到,这里很机智地把右端点的对应关系给改了下,因而就兼容了

相关文章
相关标签/搜索