扫描线第一题,求矩形面积的并。思路很好理解,但是实现上有很多的问题。
1 维护的变量ala[o]代表含义是“当前节点对应区间全覆盖的点数”,举个例子来说,现在的区间各个节点的值如果是2 3 3 3 5 5 2,那么ala就应该是2。这个变量这么做的好处就是,当ala不为0的时候一定可以直接把整个区间的Len算出来:就是x[r]-x[l],当他为0的时候说明中间有的点为0,那么我们再考虑左右儿子Len之和。这个东西注意是不要pushdown的,如果pushdown了反而会使得问题变得复杂,因为如果你只是往里面+1也要pushdown的话,那等于原来的可以直接得到的Len现在反而要往下走才可以得到。那么不pushdown会不会出现重复加的情况?也不会,因为这个问题里所有的形状都是矩形,有一个上下边使得ala[o]+1,则一定有另外一个边使得他-1,而这中间的呢?因为肯定这一条线段都是还是属于计算范围的,所以也没有多加,一定是对的,这个特点很重要,今早赖床的时候想了下才明白其中的奥妙所在。。。。
引用一位dalao的话描述一下
这里的区间覆盖不需要打懒惰标记。为什么呢?因为很显然,每个下边都有与之对应的上边,它显然不会被比它的长度小的上边给清除。而如果有比它长的上边,也一定有和那个上边对应的下边还存在。所以用那个上边清除下边的时候,一定会先递归到那个更长的下边,还没有递归到它就停止递归了。所以每个上下边是一一对应的,无需下传标记等。
2 这个线段树不是[l,r],而是[l,r),因为我们这里离散化之后,如果按照闭区间来算,那[mid,mid+1]这一段就不能被计算到了,所以要用左闭右开,这样的话对应的一开始的区间右边要+1,而这样又会有问题就是原来的整个线段,也就是o==1时候的线段,以及所有的右侧端点为整个线段树右端点的线段,他们的右侧怎么处理,这可是个必须要左闭右闭的啊?我这里用的是在xs离散化数组的后面加上一个和xs[cnt1]相等的元素,这样就可以不用特殊判断了。
继续阅读“[线段树][扫描线][面积并] HDU1542 Atlantis”