一道平衡规划分析复杂度的题目。
题意:你开始有 $n$ 个集合 $\{a_1\}, \{a_2, \}\cdots, \{a_n\}$,其中 $a_1, a_2, \cdots, a_n$ 是一个排列。你可以合并两个集合 $A$ 和 $B$,但需要保证 $\max(A)<\min(B)$。注意合并之后 $A$ 和 $B$ 仍然存在。给定 $q$ 次询问 $[l, r]$,你需要合并出一个 $\{a_l, a_{l + 1},\cdots, a_r\}$,并输出编号。$n\leq 2 ^ {12}, q\leq 2 ^ {16}$,要求最后集合总数不超过 $2.2\times 10 ^ 6$。
先不考虑复杂度,我们直接考虑合并出所有答案:建一个值域线段树,计算当值域区间为 $[l, r]$,询问区间为 $[ql, qr]$ 时的答案,输出的编号显然是 $[1, n]$ 的答案。直接考虑在线段树上合并,将 $[l, mid]$ 和 $[mid + 1, r]$ 的答案合并起来。
这样其实是 $O(nq)$ 的,但是大家肯定都能想到将所有在一个节点的询问记忆化一下,还可以把 $[l, r]$ 区间离散化到当前节点所对应所有位置的集合再记忆化。
等你码完之后,你小心翼翼地写好提交,正准备迎接 Wrong Answer 的事实时,却发现过了!(如果你没有被卡常的话
下面考虑分析复杂度。假设 $d = \lceil\log_2 q\rceil, t = \lceil\log_2 n\rceil$,对于下面的 $\dfrac d2$ 层,假设所有的询问能将这些所有层的所有区间卡满,这一部分就是:
其中第一部分表示节点个数,第二部分表示每一个节点所有的子区间。
对于上面的 $t - \dfrac d2$ 层,由于一次询问最多只能覆盖一个节点的一个区间,于是这一部分就是:
于是最多只会合并出 $O(n\sqrt q)$ 个区间,在本题数据范围下为 $10 ^ 6$,实际运行为 $1.7\sim 2.0 \times 10 ^ 6$,可以通过。
1 | void build(int x, int l, int r) |