还是老规矩,传送门 hdu 1542
不做过多解释了,就是给出n个矩形,求出这些矩形所覆盖的面积和。由于n很小,因而这道题不是必须用线段树
先想想怎么办,先来一个例图(稍微有点复杂)
根据数学知识,我们可以像这样:
将它用红线分割,然后维护每条红线被矩形覆盖的部分的长度,然后乘以两条红线之间的距离,最后累加每一部分的面积而得到答案,没什么问题吧。
接下来,问题转化为维护线段的长度了,于是我们考虑线段树,但我们发现了一个重大问题:x坐标是实数,不能直接用线段树维护,但我们不虚,把浮点离散成整数不就好了吗。
然后,重中之重来了,线段树里存什么:
(1):存节点是否被覆盖:用脑子思考一下,就会发现这不对:例如,离散后最大坐标为6,插入一条线段[2,6],那么3,4之间的一段就消失了,必然WA,就算用强大的码力解决了这个问题,代码也必然会十分恶心,因此,我们不要这样存储
(2):存一段线是否被覆盖:这是正确的,但鉴于鄙人语文不太好,难以用语言解释,上一张图:
例如,离散后最大坐标为6,则我们要这样:
然而,我为了代码好写,传参数时传的依然是离散后的点坐标,因此,dis(L,R)=val[R+1]-val[L],
接下来,就是对线段树进行改造,使之能正确维护线段长度
我们可以这样考虑,在矩形下侧的边进入时,加一,而在上侧的边进入时,加负一,然后,对线段树进行修改,每一个节点中记录这个区间被完全覆盖的次数和被覆盖的长度,
求解前,对2n条边按高度排序,从最低的边开始,逐个枚举到最高的一条边,累加答案即可。
大体的思路有了,但我还要多说两句:
1.输出时两组之间有空行,每组的两行之间没有空行,正确的输出语句应该像下面这样
printf("Test case #%d\nTotal explored area: %.2lf\n\n",cas,ans);
其中:cas记录这是第几组数据,ans为这组数据的结果
2.这道题不建议大家使用万能头文件,因为y1在cmath中是一个函数,这样做会导致CE,当然,强烈不建议手欠打上
#include
习惯不用y1的神犇们请忽略此条建议。
好了,奉上代码
1 #include
2 #include
Original: https://www.cnblogs.com/Grharris/p/10389158.html
Author: Grharris
Title: 线段树扫描线(一) 矩形面积 以hdu 1542为例
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/578006/
转载文章受原作者版权保护。转载请注明原作者出处!