昨天写得太慢了,以致于忘了写总结了。所以,特来补下。
首先,是离散化压缩空间,虽然,可能存在不要离散化的情况,但那主要是用于线段不长的情况下,对于比较长的线段,就需要有到离散化,把线段的端点进行排序,确定端点数后再建树。
这里很抱歉,昨天的算法只提到了离散化,但是实际上并没有完成,所以对于未离散的数据来说,比较好理解,但是不知道如何离散。
来个例子,试试吧。
假设有5条边(我真懒,真的……),分别是[1,10],[5,20],[12,25],[21,30],[32,50]。端点排序(本例的端点没有重复的)后,点的值和对应下标分别为:
1,5,10, 12, 20, 21, 25, 30, 32, 50
1,2,03, 04, 05, 06, 07, 08, 09, 10
再看看那个数据结构:
typedef struct Segment { int left, right; int n;}Segment;
left和right在离散化后,表示是该结点的左右端点的顺序,就是下面一行的值,跟点个数有关。需要时,可以根据排序好的端点数组转成端点的值,当然也可以直接把端点的存进来,不过要多加两个成员变量了。
线段输入时,则是根据segtree[pos].a 对应的端点的实际值来判断线段匹配。
这里就是什么时候用位置,什么时候用端点值的问题了。我就不解释了,根据模板改改就可以了。
然后思想,主要是分治……这种不停取一半的总是跟分治有亲戚关系。不停地分成原问题的一半大小,直到边界条件,这是分的过程,治的过程可能是边分边治比如快排,也可能是分完再治,比如归并。
而且貌似这种数据结构很容易就和动态规划拉上关系了……具体看什么问题了。
今天的目标是后缀数组,这三个完成之后,过去的遗憾就补完了,开始把ACM涉及的重要的算法、数据结构过一遍吧,一边做点题目。还是那句话,计算几何除外,看心情可能会看看……