Codeforces Round 1079 Div.1做题记录

Codeforces Round 1079 Div.1

编号 CF2196
赛时解决 A,B,C1,C2
赛后订题 A,B,C1,C2,D

Solution

A

会发现存在正整数 \(k\) 和非负整数 \(b\) 满足 \(p = 2k+b,q = 3k+b\) 时,Bob 才能获胜。

因为 Alice 先手,Bob 只需要给 Alice 相反的减一即可。

不难得到 \(k = q-p\),然后判一下 \(k\) 是否为正数,并且 \(b = p-2k\) 是否非负即可。

B

很有意思的题。统计 \((i,j)\) 满足 \(a_i\times a_j = j-i\) 的二元组个数。

  • \(n \le 2\times 10^5\)\(1 \le a_i \le 10^9\)

发现 \(a_i\) 都是正数,这非常好!那么天然地有 \(i < j\)

有一个很自然的思路,枚举 \(i\),然后 \(a_i\)\(i\) 是已知的。\(j-i\)\(a_i\) 的倍数,所以枚举 \(j = i + k\times a_i\)

这个思路很对!但是当 \(a_i\) 很小的时候复杂度会退化到 \(O(n^2)\)

不过我们发现几个性质:

  • 对于 \(a_i \ge n\),这些 \(a_i\) 一定不会产生贡献。因为 \(\max (j-i) = n-1\)
  • 不会存在满足条件的二元组 \((i,j)\),满足 \(a_i \ge \sqrt n\)\(a_j \ge \sqrt n\),理由同上。

因此,本题中的二元组不妨划定为以下两种情况:

  • \(a_i < \sqrt n, a_j < \sqrt n\)
  • \(a_i < \sqrt n, a_j \ge \sqrt n\)\(a_i \ge \sqrt n, a_j < \sqrt n\)

第一种是很好做的,因为我们只需要根据 \(i\) 枚举 \(j=i+k\times a_i\) 的过程中控制 \(j\) 的值即可。

此时会发现 \(k < \sqrt n\) 是一定成立的,我们枚举的 \(k\) 不超过 \(\sqrt n\) 个,因此复杂度 \(O(n \sqrt n)\) 没问题。

考虑第二种,会发现如果从 \(a_i \ge \sqrt n\) 向左右两边都枚举的话,\(k \le \frac{n}{a_i} \le \sqrt n\)。这样能保证所有第二种的都可以被搜到,所以复杂度 \(O(n \sqrt n)\) 依然没问题。

实现上我直接让所有都向两边搜了,然后如果是第一类的话,那么会统计两次。所以第二类的统计算两次,最终答案除以二即可。

C1 & C2

我觉得 C2 其实很一眼的吧,就是实现起来要好好想想。

因为询问必须 \(n+m\) 次,而且是 DAG,因此我们不难想到,如果一个点 \(u\) 已经被访问完了,那么接下来再访问到 \(u\) 时,我们就知道接下来的 \(d_u\) 个路径字典序是不会有任何好处的。

其中 \(d_u\) 表示点 \(u\) 的出度,此时我们直接跳过 \(d_u\) 个即可。

也就是说,我们需要确保每次询问都要贡献一条有效边。

而我们如果这样跳过的话,很容易发现问的每个都是有效的,同时还会不可避免地问 \(n-1\) 个节点(因为 \(1\) 可以不问)。

最后结束条件,也就是返回为 \(0\),就可以完结撒花啦!

代码实现的话,不妨用 stack 来记录路径上的节点。有点像 DFS,然后注意退出节点时,累加指向它的点的度数并且标记已经访问,下次直接跳过即可。

D

很好的贪心题!

考虑已经配对的,直接删掉即可,对答案没有影响。因为如果我们对配对的对修改的话,会拆散一对,并最多形成一对,这是不优的。

考虑删完配对的对之后,序列形如 )]))])]]](]]((][(([([[([,即圆括号和方括号的相对顺序分别为 )))(((]]][[[

此时我们考虑怎么删。我们发现只要有一对满足左边是 ([,或者右边是 )],那么只需要 \(1\) 次操作即可删掉。

那么这样删到最后,最多只会剩下一对恰好无法用上述方法匹配的,需要 \(2\) 次操作。

发现上述最后剩下一对无法匹配的情况,当且仅当左括号和右括号个数都是奇数,同时存在至少一个左括号在右括号左边。

于是本题就做完了,时间复杂度 \(O(\sum n)\)

posted @ 2026-07-27 13:39  xiang_you  阅读(2)  评论(0)    收藏  举报