(本文是基于队爷 @s_r_f 所写题解的完善和补充)
可以发现,如果我们暴力地枚举一个数的因数或倍数,时间复杂度是可接受的。
对于前者,单次复杂度为 O(n)O(\sqrt n)O(n);对于后者,由于题目保证了 C≤10C \leq 10C≤10,所以单次的均摊复杂度应为调和级数 O(lnn)O(\ln n)O(lnn)。
所以,我们可以考虑直接模拟题意中的操作。
首先,我们设 fif_ifi 为以 iii 开头的最长上升倍数子序列的长度。同时,为了方便统计答案的第二项,我们再设一个 fcntifcnt_ifcnti,表示有多少个 jjj 满足 fj=if_j = ifj=i。
有了以上两个数组,我们就可以从小到大枚举 iii,当 fcntifcnt_ifcnti 不为 000 时,我们就同时找到了答案的第一项和第二项,一举两得。
没错!这样做的理论复杂度是 O(nq)O(nq)O(nq) 的,会超时。但这真的是实际的复杂度吗?
注意题目中有这样一句话:保证在任意时刻序列 AAA 非空,其中的元素互不相等。
也就是说,就算是最坏的情况,这个子序列的长度也是不超过 O(log2m)O(\log_2 m)O(log2m) 的,所以上述做法的实际复杂度为:O(qlog2m)O(q\log_2m)O(qlog2m)。
解决完了询问,我们再看看四个操作中哪个最好想。
显然是在序列左端进行的两个操作。究其原因,我们先来推推 fif_ifi 的转移方程式:
考虑枚举 iii 的倍数 jjj,如果 jjj 存在,设 jjj 的位置为 posjpos_jposj,则有:
fi=maxi∣j,posj>0{
fj+1} f_i = \max_{i | j, pos_j > 0}\{f_j + 1\} f