Codeforces Round 830 (Div. 2)
给定一个长为 的序列 ,问最小代价可以将整个序列的 变为 。
每次操作选择一个下标 ,令 ,代价为 。
数据一共 组。
设所有数的 为 ,注意到选择一个下标 等价于令 。
则实际上,我们只可能选最后两个下标,因为相邻的两个数必定互质,他们的 一定为 ,所以选完最后两个数 必然为 。
答案只可能是 。
不过题目给到的数据不大,一些优秀的暴力搜索好像也通过了。
给定一个长度为 的 串 ,定义一次操作如下:
- 选择一个下标 ,翻转区间 ,翻转指 变为 , 变为 。
问最少多少次操作能让整个串单调不降。
设 令 单调不降且 的最小代价,转移即枚举当前位置为 与上一个位置为 并根据 算出操作前的 决定是否调整即可。
给定长度为 的序列 ,定义 ,其中 表示 中 的和, 表示 中 的异或和。
有 次询问,每次询问给定两个数 ,求满足 的最大 ,若存在多个,输出使得 最小的任意一组 和 。
这题分为两个部分,简单的那个部分中只有一次询问。
这个题目一定程度上打破了我的一种思维定式,与之类似的题目,我的第一想法往往都是枚举一维,然后用一个数据结构维护另一维,不过由于存在异或,我们并不好用线段树等数据结构维护前缀的贡献。
那么思考什么时候我们会取到最大值,我们假设一开始取满了整个序列,最后的答案一定是在左右两边拿掉了一段数,可以为 。
首先有一个较为显然的性质,就是取满整个序列一定是最大值。
考虑在两端拿掉任意一个数, 会减去这个数,而 却未必也会减去这个数,那么这个时候我们就亏了。
那在什么时候可以在保持答案不变的情况下拿掉两端的数?即这个数和原来异或和的或恰等于原来的异或和,他们的二进制表示上,这个数为 的位置是原异或和的子集,这样拿掉这个数 就会失去这个数所有位置的 ,且不会有其他位置变成 。
还有一个限制是我们拿走的数任意两个进行且运算一定是 ,这是显然的,我们不能连续两次减掉 中同一个位置的 。
因此我们可以预处理出 ,表示拿走 ,值仍为最大;预处理出 ,表示拿走 ,值仍为最大。即分别预处理出只拿走一端的最大贡献。
接下来只需要维护一个双指针即可。
对于多次询问,我们发现在 和 中不为 的数一定只有 个,而 不存在任何影响,在需要发生移动的时候暴力跳过一段 到下一个不是 的位置即可,这可以在最开始预处理。
时间复杂度
给你一个空集合,进行如下三种操作:
- 加入一个数 ,保证其不存在。
- 查询集合的 ,意思是第一个不存在且可以被 整除的数。
- 删除一个数 ,保证其存在。
这题同样分为两个部分,第一个部分不存在删除操作。
这就比较简单了,对于每个不同的询问 记录 表示上次查询时 是一个合法答案,显然我们只用从这个位置向上继续累加 即可,当然所有 初值都可以设置为 。
考虑有删除操作的情况。
若删除 ,我们考虑在上述暴力的基础上跳过了 的所有查询,并将这些查询加入集合 。
而删除 时,遍历集合 的所有元素 ,将 加入集合 。
则对于每次查询就分两种情况,若 不为空,里面元素的最小值就一定是答案,否则继续做上面的暴力。
经过证明维护的集合有限,不会超时,详细证明可以上 官方题解上查看,此处不赘述。
- 给定 ,令 ,。
- 给定 ,查询 中最小的 。
考虑分块。
每次修改暴力询问旁边两个散块的答案,接下来的问题就是如何快速查询到将整个块中的元素修改为 后的答案。
设 表示块中所有 替换为 的答案,考虑枚举 的一个除数 ,找到块中最小的 ,则 。
同时注意到 ,其中 是 的质因数,因为 中已经枚举过所有除去 本身外的除数,所以这样能统计全答案,乘 是因为对比最开始枚举 计算 的式子,只有 发生了变化,所以把贡献乘上,算的时候再单独算一下 的情况。
预处理所有块的 复杂度就是 , 是值域。
剩下的部分就是常规分块了。
本文作者:未央境
本文链接:https://www.cnblogs.com/Defoliation-ldlh/p/16823706.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2021-10-25 [CSP-S 2021] 回文
2021-10-25 [CSP-S 2021]廊桥分配