这道题目让我又重新认识了一下离散化:
首先总结一下离散化的特点:
1)有时区间的端点并不是整数,或者区间太大导致建树内存开销过大而MLE,那么就需要进行离散化后再建树。
2)意思是将区间范围很大的数据集映射到较小的数据集,这样建树更加有效,或者说我们只取需要的值来用。
这个意思说到底就是进行映射,把原来很大的映射到一个较小的空间中去。
题意:
给定一些海报,它们可能相互重叠,告诉你每个海报的宽度(它们的高度都是一样的)和先后的叠放次序,问没有被完全盖住的海报有多少张?
这里我们注意到了数据的范围:海报最多100000张,而墙的范围最大是10的7次。所以我们肯定不能以墙来建树。(而且这里海报都是完全覆盖每一个墙面的)
所以我们要把海报的左右端点进行离散化,也就是把原先很大的每个端点进行标号,把它转化为更小的数据
这里要注意一点就是:当它们之间距离等于1的时候,只要+1就可以了,但是当距离大于1的时候,那么要+2
原因:(来源于http://blog.csdn.net/non_cease/article/details/7383736)
解法:离散化,如下面的例子(题目的样例),因为单位1是一个单位长度,将下面的
1 2 3 4 6 7 8 10
— — — — — — — —
1 2 3 4 5 6 7 8
离散化 X[1] = 1; X[2] = 2; X[3] = 3; X[4] = 4; X[5] = 6; X[7] = 8; X[8] = 10
于是将一个很大的区间映射到一个较小的区间之中了,然后再对每一张海报依次更新在宽度为1~8的墙上(用线段树),最后统计不同颜色的段数。
但是只是这样简单的离散化是错误的,
如三张海报为:1~10 1~4 6~10
离散化时 X[ 1 ] = 1, X[ 2 ] = 4, X[ 3 ] = 6, X[ 4 ] = 10
第一张海报时:墙的1~4被染为1;
第二张海报时:墙的1~2被染为2,3~4仍为1;
第三张海报时:墙的3~4被染为3,1~2仍为2。
最终,第一张海报就显示被完全覆盖了,于是输出2,但实际上明显不是这样,正确输出为3。
新的离散方法为:在相差大于1的数间加一个数,例如在上面1 4 6 10中间加5(算法中实际上1,4之间,6,10之间都新增了数的)
X[ 1 ] = 1, X[ 2 ] = 4, X[ 3 ] = 5, X[ 4 ] = 6, X[ 5 ] = 10
这样之后,第一次是1~5被染成1;第二次1~2被染成2;第三次4~5被染成3
最终,1~2为2,3为1,4~5为3,于是输出正确结果3。
接下来就是使用线段树来查询已经标号好的区间了。
这里我们进行从后往前查找,这样前面贴上去的海报就不会被覆盖掉了。
插入一张海报时,如果发现它对应的瓷砖有一部分露出来,那么就说明该海报时可见的。
#include
#include
#include
#include
#include
#include
#include