这篇题解写的真是太好辣!
虽然实际上是我自己脑补的
看题解之前先看清楚题意。。原序列是个排列,不是有序的,要把 [ l , r ] [l,r] [l,r] 位置的集合合并出来,合并要保证值域有序。
对值域分块,然后将每一块中位置在 [ l , r ] [l,r] [l,r] 的段提取出来,依次合并。这一步合并次数是 n q B \frac {nq}B Bnq 的。
然后考虑怎么把值域块内的每个位置连续段合并出来,因为位置连续段的值域并不一定连续,再次对值域分治,先合并出值域在
[
L
,
M
]
,
[
M
+
1
,
R
]
[L,M],[M+1,R]
[L,M],[M+1,R] 的位置连续段,然后归并得到
[
L
,
R
]
[L,R]
[L,R] 的所有位置。枚举位置连续段的左右端点,将该段值域在
[
L
,
M
]
[L,M]
[L,M] 的段提取出来,与值域在
[
M
+
1
,
R
]
[M+1,R]
[M+1,R] 的段合并。
合并的次数是
f
(
V
)
=
V
2
2
+
2
f
(
V
2
)
=
V
2
f(V)=\frac {V^2}2+2f(\frac V2)=V^2
f(V)=2V2+2f(2V)=V2 的,每块大小
B
B
B,总次数就是
B
2
∗
n
B
=
n
B
B^2*\frac nB=nB
B2∗Bn=nB 的。
取 B = q B=\sqrt q B=q 就可以做到 2 n q 2n\sqrt q 2nq
看代码的时候发现 STL 的 merge 函数居然有归并的功能,i了i了。