扫描线算法求矩形面积并

本文介绍了扫描线算法求矩形相交面积的基本思想和过程,包括朴素做法和线段树优化方法。朴素做法通过模拟扫描线计算面积,而线段树则通过分段和标记来提高效率。线段树的每个节点存储区间被标记的次数和长度,遇到矩形边时更新标记。最后提供了代码实现。
摘要由CSDN通过智能技术生成

更多文章可以在本人的个人小站:https://kaiserwilheim.github.io 查看。
转载请注明出处。

思想

顾名思义,扫描线就是要模拟一根线,扫过整个图形。至于方向什么的自己根据喜好,这里选用从左往右的方式。

过程

朴素做法

首先我们看一下这个例子:

扫描线1.png

我们有三个矩形,分别用红、蓝、绿三色标注了出来。
他们相交的面积用其他的颜色标了出来。

我们所得到的信息只有矩形的左下端点和右上端点的坐标。也就是我们标红的这几个点:

扫描线2.png

然后我们可以画出一根线来,扫过这个多边形的所有面积。
这根线从最左边的边开始,每遇到一条边,就停下来计算之前扫到的面积,即为距上一条边的距离与扫描线落在图形上的长度之积,再加到之前的和上面。
用动画来做就是这样的:

扫描线3.gif

但是这样做有一处需要注意的地方: 我们怎么才能知道每一次遇到一条边之后扫描线落在图像上的长度是多少
如果我们每一次都去枚举、去找,我们程序的时间复杂度就达不到我们的要求了。
这就是扫描线算法的精髓之处。

线段树

分段

我们把 y y y 轴上的一段区间按照每一个存在的矩形的边的高度值分一下块:

扫描线4.png

我们只需要计算每一段所对应的在 x x x 轴上的长度就行了。

我们可以使用线段树这一强大的数据结构来帮助我们更快地进行区间修改。

扫描线5.png

标记

我们在遇到某个矩形的一条边的时候,我们需要看一下这两个东西:

  1. 它的长度;
  2. 他是起始边还是终止边。

如果是起始边的话,我们把他这条边所包含的所有区块都打上一个标记;如果是终止边的话,我们就把之前起始边打上的标记去掉。这样,只要有标记就是存在,不管有多少个;没有标记就是没有被覆盖,忽略不计。
所以,我们的线段树节点需要存储这个区段被标记的次数。同时,我们还需要存储基本的线段树信息,还有它的长度。
同时,我们用来存储矩形边的位置我们也需要改一下,使之能够存储这条边的上端点和下端点,还要标记这条边是起始边还是终止边。
最终我们使用动画模拟一下就是这个样子的:

扫描线6.gif

代码

上代码。

#include<bits/stdc++.h>
using namespace std;
const int N = 1000010;
int n, cnt = 0;
long long lf, rt, tp, bt, a[N << 1];
struct ScanLine
{
   
	long long l, r, h;
	int mark;
	
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值