题解:P11721 [清华集训 2014] 玄学
CommonAnts · · 题解
这题复杂度是一个
做法
对操作序列构建一个线段树
对于线段树上每个节点
查询只需要找到对应操作区间的
由于本题操作是在线地逐个向后增加的,线段树也需要动态构建,具体来说就是每增加一个操作就创建出所有以该操作为右端点的线段节点。大体上不影响时空复杂度。
如果朴素地计算,时间复杂度为
时间瓶颈为每次查询要在
- 线段树上每个节点的分界点序列是两个儿子的分界点序列的有序归并。在线段树节点上记录每个分界点在两个儿子的分界点序列上各自对应的位置。每次查询只需要在线段树根节点二分一次。(此技巧被称为“归并树”)
- 动态构建线段树过程中会有多个线段树根,需要单独讨论。假设这些线段树(二进制分组)的分界点序列分别是
A_1,A_2,\dots A_k ,大小分别是a_1\gt a_2\gt \dots \gt a_k ,采用分散层叠的方法,对于i=1,2,\dots ,k 依次从A_i 中等分取a_{i+1} 个放进A_{i+1} 归并出新的A_{i+1} ,长度最多增加一倍。这样,查询时二分出A_{i+1} 的排名结果后可以知道在A_{i} 中处于相邻的哪两个等分点之间,再在A_i 中二分的时间复杂度是O(\log \frac{a_{i}}{a_{i+1}}) 。因此k 次二分的总时间复杂度是O(\log \frac{a_{1}}{a_{2}}+\log \frac{a_{2}}{a_{3}}+\dots )=O(\log a_1 +k)=O(\log n+\log q) 。 - 按照上述分析,动态构建线段树的时间复杂度仍为线段树节点大小总和的线性(分界点序列类似归并排序可以线性合并,分散层叠每次也只要重构最后一个)。
综上,总时间复杂度为
原题题解是同复杂度的可持久化平衡树做法。见:https://qoj.ac/download.php?type=solution&id=16