Codeforces Round 830 (Div. 2)

\(Codeforces\ Round\ 830\ (Div. 2)\)

\(A\)

\(Problem\)

给定一个长为 \(n\) 的序列 \(a\),问最小代价可以将整个序列的 \(gcd\) 变为 \(1\)

每次操作选择一个下标 \(i\),令 \(a_i = gcd(a_i, i)\),代价为 \(n - i + 1\)

数据一共 \(T\) 组。

\(Scope\ Limitation\)

\(1\leq T\leq 5000,1\leq n\leq 20,1\leq a_i\leq 10 ^ 9\)

\(Solution\)

设所有数的 \(gcd\)\(x\),注意到选择一个下标 \(i\) 等价于令 \(x = gcd(i, x)\)

则实际上,我们只可能选最后两个下标,因为相邻的两个数必定互质,他们的 \(gcd\) 一定为 \(1\),所以选完最后两个数 \(x\) 必然为 \(1\)

答案只可能是 \(0,1,2,3\)

不过题目给到的数据不大,一些优秀的暴力搜索好像也通过了。

\(B\)

\(Problem\)

给定一个长度为 \(n\)\(01\)\(s\),定义一次操作如下:

  • 选择一个下标 \(i\),翻转区间 \([i, n]\),翻转指 \(0\) 变为 \(1\)\(1\) 变为 \(0\)

问最少多少次操作能让整个串单调不降。

\(Scope\ Limitation\)

\(1\leq n\leq 2\times 10 ^5\)

\(Solution\)

\(f_{i,0/1}\)\([1,i]\) 单调不降且 \(s_i = 0/1\) 的最小代价,转移即枚举当前位置为 \(0 / 1\) 与上一个位置为 \(0 / 1\) 并根据 \(f_{i-1,0 / 1}\) 算出操作前的 \(s_i\) 决定是否调整即可。

\(C\)

\(Problem\)

给定长度为 \(n\) 的序列 \(a\),定义 \(f(l,r) = sum(l,r) - xor(l,r)\),其中 \(sum(l,r)\) 表示 \(i\in[l,r]\)\(a_i\) 的和,\(xor(l,r)\) 表示 \(i\in[l,r]\)\(a_i\) 的异或和。

\(q\) 次询问,每次询问给定两个数 \(L,R\),求满足 \(L\leq l \leq r \leq R\) 的最大 \(f(l,r)\),若存在多个,输出使得 \(r - l + 1\) 最小的任意一组 \(l\)\(r\)

\(Scope\ Limitation\)

\(Subtask1: 1\leq n\leq 10^5,q = 1,L_1 = 1, R_1 = n\)

\(Subtask2: 1\leq n\leq 10 ^ 5, q = n\)

\(Solution\)

这题分为两个部分,简单的那个部分中只有一次询问。

这个题目一定程度上打破了我的一种思维定式,与之类似的题目,我的第一想法往往都是枚举一维,然后用一个数据结构维护另一维,不过由于存在异或,我们并不好用线段树等数据结构维护前缀的贡献。

那么思考什么时候我们会取到最大值,我们假设一开始取满了整个序列,最后的答案一定是在左右两边拿掉了一段数,可以为 \(0\)

首先有一个较为显然的性质,就是取满整个序列一定是最大值。

考虑在两端拿掉任意一个数,\(sum\) 会减去这个数,而 \(xor\) 却未必也会减去这个数,那么这个时候我们就亏了。

那在什么时候可以在保持答案不变的情况下拿掉两端的数?即这个数和原来异或和的或恰等于原来的异或和,他们的二进制表示上,这个数为 \(1\) 的位置是原异或和的子集,这样拿掉这个数 \(xor\) 就会失去这个数所有位置的 \(1\),且不会有其他位置变成 \(1\)

还有一个限制是我们拿走的数任意两个进行且运算一定是 \(0\),这是显然的,我们不能连续两次减掉 \(xor\) 中同一个位置的 \(1\)

因此我们可以预处理出 \(l\),表示拿走 \([1,l]\),值仍为最大;预处理出 \(r\),表示拿走 \([r,n]\),值仍为最大。即分别预处理出只拿走一端的最大贡献。

接下来只需要维护一个双指针即可。

对于多次询问,我们发现在 \([1,l]\)\([r,n]\) 中不为 \(0\) 的数一定只有 \(log\) 个,而 \(0\) 不存在任何影响,在需要发生移动的时候暴力跳过一段 \(0\) 到下一个不是 \(0\) 的位置即可,这可以在最开始预处理。

时间复杂度 \(\mathcal O(n + qlogV)\)

\(D\)

\(Problem\)

给你一个空集合,进行如下三种操作:

  • 加入一个数 \(x\),保证其不存在。
  • 查询集合的 \(k-mex\),意思是第一个不存在且可以被 \(k\) 整除的数。
  • 删除一个数 \(x\),保证其存在。

\(Scope\ Limitation\)

\(1\leq n\leq 2\times 10 ^ 5,1\leq x \leq 10 ^ {18},1\leq k \leq 10 ^ {18}\)

\(Solution\)

这题同样分为两个部分,第一个部分不存在删除操作。

这就比较简单了,对于每个不同的询问 \(x\) 记录 \(k\) 表示上次查询时 \(k\times x\) 是一个合法答案,显然我们只用从这个位置向上继续累加 \(k\) 即可,当然所有 \(k\) 初值都可以设置为 \(1\)

考虑有删除操作的情况。

若删除 \(x\),我们考虑在上述暴力的基础上跳过了 \(x\) 的所有查询,并将这些查询加入集合 \(vec_x\)

而删除 \(x\) 时,遍历集合 \(vec_x\) 的所有元素 \(y\),将 \(x\) 加入集合 \(s_y\)

则对于每次查询就分两种情况,若 \(s_y\) 不为空,里面元素的最小值就一定是答案,否则继续做上面的暴力。

经过证明维护的集合有限,不会超时,详细证明可以上 \(CF\) 官方题解上查看,此处不赘述。

\(E\)

\(Problem\)

  • 给定 \(l,r,x\),令 \(i\in[l,r]\)\(a_i = x\)
  • 给定 \(l,r\),查询 \(i\in [l,r]\) 中最小的 \(\frac{lcm(a_i,b_i)}{gcd(a_i,b_i)}\)

\(Scope\ Limitation\)

\(1\leq n,q\leq 5\times 10 ^ 4,1\leq a_i,b_i\leq 5\times 10 ^ 4\)

\(Solution\)

考虑分块。

每次修改暴力询问旁边两个散块的答案,接下来的问题就是如何快速查询到将整个块中的元素修改为 \(x\) 后的答案。

\(ans_x\) 表示块中所有 \(a\) 替换为 \(x\) 的答案,考虑枚举 \(x\) 的一个除数 \(d\),找到块中最小的 \(b_i\),则 \(ans_x = \min\{\frac{x\times b_i}{d\times d}\}\)

同时注意到 \(ans_x = \min\{ans_{x/p}\times p \}\),其中 \(p\)\(x\) 的质因数,因为 \(x/ p\) 中已经枚举过所有除去 \(x\) 本身外的除数,所以这样能统计全答案,乘 \(p\) 是因为对比最开始枚举 \(d\) 计算 \(ans\) 的式子,只有 \(x\) 发生了变化,所以把贡献乘上,算的时候再单独算一下 \(x = d\) 的情况。

预处理所有块的 \(ans_x\) 复杂度就是 \(\mathcal O(\sqrt n AlogA)\)\(A\) 是值域。

剩下的部分就是常规分块了。

posted @ 2022-10-25 08:09  ╰⋛⋋⊱๑落叶๑⊰⋌⋚╯  阅读(61)  评论(2编辑  收藏  举报