思路
先干一件很重要但不难理解的事:题目里的平面是无限的,这太烦了,那我们直接在外面套一个特别大的正方形,把所有东西都关进去。反正 L 给得够大,答案不会受影响,这一步就是为了让后面所有区域都有“边界”。
接下来就是这题真正的灵魂:扫线。
你可以把所有直线按斜率排个序,想象从左往右慢慢扫过去。正常情况下,直线的上下顺序是不会乱的,只有在两条线“相交”的那一瞬间,它们才会换个位置。
所以事情就简单了:我们提前把所有直线两两的交点全算出来,然后按顺序一个一个处理。每次扫到一个交点,只会影响那两条线,中间夹着的那一小块区域发生变化,别的地方一概不管。
查询点怎么处理?也很舒服。扫到某个位置的时候,当前直线顺序已经是确定的了,那我只要二分一下,看这个点在第几条线之间,就知道它属于哪个区域了。先记下来,等这块区域的面积算完再统一结算。
面积怎么算?这里用的是叉积。你可以把它理解成:扫线的时候,区域一点一点“长出来”,每次只加一个小三角形或者小多边形,叉积正好能又快又准地算这个面积。
整个过程就像洗牌:遇到交点,算那一小块,交换两条线,继续扫。
最后所有查询点都已经挂在对应的区域上了,面积也都算完了,直接输出就行。
代码