以CF600E为例,没看过题目的先去看题。
本题的线段树做法,即对题目所给树中每个结点所在子树建树维护数字出现情况。此做法中,当前节点和其兄弟节点对应的线段树需要合并到父节点上,最后父节点上权值update到新树。也就是说对于每个非叶子节点,其有x个子节点,就要合并x次(其实也可以看成x-1次,第一次是合并到空节点上,复杂度忽略不计)。
画出线段树结构示意图,如下
首先区分开做法中update和merge的复杂度,update不用谈,稳定logn复杂度。
对于merge复杂度,我们考虑线段树上每个节点,分析每个节点在所有merge操作可能被访问多少次即可。
对于线段树上第一层节点,即根节点,如图
合并两树不为空时,一定会访问一次这个节点。其实更抽象一点,只要合并的两棵树同时包含了这个节点的子孙,那么这个节点非访问不可。既然他是根节点,那每次合并都要访问他了,所以线段树上的根节点在O(N)次合并中,会被访问O(N)次。
考虑第二层左边的节点
它对应了最底层左边四个节点,放在题目中的意义就是1-4这四种颜色,所以如果两棵树同时有1-4颜色中的一种,那么这个节点要选。
现在结合题目给出树讨论什么时候在哪些节点需要访问这个节点。
下面是题目所给树的一个可能情形
特意标黑的节点表示属于1-4颜色的节点,现思考什么地方合并会访问到第二层左边的节点。
首先1号黑点和2号黑点不存在合并操作,他们的复杂度已经在update贡献中计算过了。从3号黑点往上看,因为3号点的兄弟没有一个是1-4颜色的,所以他们的合并过程不会访问线段树左半边的任何点。接下来到合并到3号黑点的父节点,由于4号节点的颜色是1-4,两线段树都同时存在线段树左半边的节点,最起码2号点一定在两颗线段树中重叠了,所以也贡献一次复杂度。而再上去,如果兄弟节点都是白色,且它们的子树中都不含黑色节点的话,那么这个节点就不会对合并过程贡献复杂度。
到这里已经有点显然了,这个节点对于merge操作的复杂度贡献最多为O(黑点个数-1)。读者可以试试用归纳法去证明一下?
再考虑线段树第二层右边节点的复杂度,同理,就是O(4-8颜色的节点个数-1)。
重点来了,有没有可能,这两组节点有相交的空间呢?
当然没可能,除非一个节点有两个颜色。
所以线段树第二层节点对merge操作的复杂度贡献,同样为O(N)。
到此想必已非常明了,线段树每一层对merge操作的复杂度贡献都为O(N)。
一共logn层,总复杂度为O(NlogN)。