Codeforces Round 909 (Div. 3)

· · 个人记录

输麻了,G 的正确代码差 1s 交上,F 干脆没做。
总之手速还是不行。Div.3 没啥难题, AK 难度就在于手速。

A

如果第一次 Vanya 没赢,那么 Vova 就可以重置,让他永远不赢。

B

参考 n 的最大因子个数。
暴力能过。

C

dp_i 表示右端点为 i 的最大大小。

a_ia_{i-1} 奇偶不同,dp_i = \max(a_i,dp_{i-1}+a_i)
否则,dp_i = a_i

最后答案是 \max(dp_1,dp_2,\cdots,dp_n)

D

pw_ia_i 的质因数分解中 2 的出现次数。
bs_i\frac{a_i}{2^{pw_i}}

由小学数学可以推导得知,i,j 能配对,当且仅当 pw_i - a_i = pw_j - a_j

然后 map 统计一下就好了。

E

最终要求没有任意一个 i 使得 a_i \gt a_{i+1}

考虑每次操作的影响。

如果 a_i \gt a_{i+1},那么它本质上消除了一对不合法的数对。

否则相当于不改变。

依次操作下来,当最后一个不合法的 i 被执行操作,排序也就完成了。
设最后一个不合法的 ilst

考虑 [1,lst] 之间每个 i 被执行的影响。

i 个,如果跳出了 [1,lst] 的范围,那么没啥事。
如果没跳出(只要是没跳到 lst 后面就算),那么稍稍想一下依赖关系,必然是陷入了无限循环,无解。

那么如何判断无限循环呢?

只要有 [1,lst] 任意一个 i 操作之后位置不改变,那么一定陷入无限循环,从而间接导致其他的 i 跳不出去。

F

默认根是 1

为了方便实现,我们可以仅仅用两条链构造出两个距离为 d_i 的叶子。

先根据 d_1 构造出大概是这样的两条链(从 1 出发):

第一条链长度固定是 1,而第二条链的长度则根据 d_i 进行变化,这个例子中,d_i = 4

剩下的节点干什么呢?因为第二天链的长度需要时刻变化,所以我们还是从 1 出发,新建第三条链,进行存储。

大概长这样(n=8,d_i=4)

3 条链是 1,6,7,8 组成的。

需要适应 d_i 时,直接配合第三条链进行切割/接尾操作就行。

我为了方便开了 3 个 std::list

G

我们可以将这个问题转化为一个更清新的问题:

给定一个数列 p,并推导得到一个数列 p{'}

size_ii 为根的子树大小,dfn_ii 的 dfs 序。

每次询问给定 $l,r,x$,求是否存在 $i$,使得 $l \le i \le r$,且 $dfn_x \le p'_i \le dfn_x + size_x - 1$。 这种操作,log 数据结构似乎不大好做,自然联想到优雅的暴力——分块。 具体的,每个块预处理哪些 $p'$ 值出现过,并开桶记录(由于任意 $p'_i$ 不会超过 $n$,所以可以用桶) 接下来每个块就可以 $O(1)$ 判断某个值域区间是否有数存在了。 预处理复杂度 $O(n \sqrt n)$,查询复杂度 $O(q \sqrt n)$。