2024 syzx 冬季训练 5 - 数据结构
A
对于每种颜色分别做, 和 的贡献可以分别求和,排序即可。
B
二分答案,枚举最小值点,预处理出左右两边的最大贡献。
C
因为用到的操作只有求中位数,所以只用二分最终的答案,就可以把一开始大于等于 mid 的数视为 +1,小于 mid 的数视为 -1。再使用一些前缀和技巧模拟即可。
D
题意:定义 为比 大的且二进制上 1 的个数小于等于 的最小的数。对于所有 ,将 与 连边,得到一个森林。 次操作,每次将一个点到所在树的根的路径上的点权加 ,或者查询编号在 到 之间的点的点权的和。
发现 ,所以树高只有 log,先把所有单点修改都找出来,重新离线+离散化,再拿树状数组做一遍。
E
正解:
对于一个 ,假设在 内存在一盏灯满足条件,那么输出 即可 保证结果正确。因此等价于找到最小的 满足答案位于 ,共 个区间。 对于一个区间 ,如何对于每个 判断是否存在一盏灯满足条件? 令 表示坐标为 且编号在 中的灯的颜色,若不存在则为 0; 令 表示坐标为 的灯的颜色,若不存在则为 0。 则 有解当且仅当 。反转 后拆掉平方为卷积的形式,FFT 求解即可。 时间复杂度 。
bitset 做法:
不需要使用模糊答案的性质。
枚举答案(从小到大枚举编号),维护当前已经出现的可行的距离 ,使用除了当前颜色之外的颜色的 std::bitset
可以计算出新增答案的位置,只枚举这些新增的位置来更新答案即可。需要使用根号分治来优化空间。 时间复杂度 。
F
题意:一棵树,每个点颜色 ,你可以选择一条路径,把颜色排成一个序列,然后任取一个子序列,但是你需要保证这个子序列是回文的。求最终子序列的最大长度,
每种颜色出现次数不大于 2
正解:
设与点 的颜色相同的另一个点为 。设 表示现在已经选了 和 ,最多选了多少。
使用刷表法转移 dp, 可以转移到的 在 dfs 序上是一个矩形。
线段树套线段树维护。
树剖做法:
选出的回文串其实有两个部分,第一个部分匹配的两个点是祖先关系,第二部分不是。
dp 的定义和正解一样,我们先对第一部分转移。我们对树进行 dfs,如果 是 的祖先,则得到 之后把它插入到 的位置,每次查询 到 的最值。dfs 退出 的时候删除贡献。
第二部分类似,只不过查询时变成了路径查询,使用树剖。
(我怎么感觉这两个部分其实可以合并)
G
首先考虑如何计算固定的 的答案。将所有盘子按照 从小到大排序,枚举第 个盘子作为选中的 最大的盘子,那么剩下的 个盘子显然是贪心选择前 个盘子 中 最小的 个。给定 和 ,可以通过可持久线段树在 的时间内求出对应方案 的值 。 令 f(k) 表示使 取到最优解的 。对于两个不同的决策 ,若 , 那么增大 之后由于 的可选择范围严格包含了 的可选择范围,因此 新选的 值一定不 大于 所选的,即 对于 恒成立。由此可得 ,最优决策具有单调性,可以分治求解,共需计算 个 的值。 时间复杂度 。
H
先求出两个序列分别的异或和记为 ,则修改位置 相当于让两者同时异或 ai ⊕ bi,则可以将所有 ai ⊕ bi 构造线性基。接下来从 A, B 的高位往低位考虑,对于一位:
-
如果都是 1,且线性基这一位有值,则同时异或线性基这一位,都变成 0 肯定更优。
-
如果都是 0,则不管。
-
如果一个 1 一个 0,后面肯定让这一位是 1 的尽可能小,0 的不用管,则用线性基贪心即可。如果 这一位线性基有值,那么需要枚举是否异或这个值,两种情况都往下贪一次即可。
时间复杂度为 O(n log w),其中 w 为值域。
I
注意到如果 为真,那么 一定为真。 从小到大枚举询问中 a 的值,按横坐标从小到大依次加入每个点,维护 表示最小的 b 满 足 query(a, b, c) 为真。假设当前正在加入点 (x, y, w),有 。 观察状态转移方程可知,如果 ,那么就没有更新的必要。令 , 那么如果 y ≥ m,则这个点是完全无用的,可以直接跳过。 由于数据随机,可以近似地认为加入 k 个点后,所有 个子集和模 n 的结果在 [0, n) 等 概率均匀分布。可以看作 个小球随机放入 n 个洞之中,填满所有 n 个洞所需的期望球数 是 O(n log n),因此 k = O(log n) 时期望可以填满整个 f 数组。这说明,f 数组的最大值的 期望值等于所有已经加入的点的纵坐标的第 O(log n) 小值,即 O( n log n k )。 于是,加入的第 k 个点的纵坐标 y < m 的概率为 O( log n k ),期望只需要更新 遍 f 数组。由于这个值并不大,每次暴力 O(n) 更新整个数组即可。有了 f 数组就 可以很容易地求出最终的答案。 时间复杂度 O(n log^2 n)。
如果你没想到 表示最小值,你可以一边扫一边维护前 log 小的 yi(只算扫到的点的 y) 的背包,背包的值是 01,用 bitset 优化。时间 。
J
一个 的网格,有一些矩形(端点都是整点),问拿走恰好两个矩形之后剩下矩形的交的面积的最小值。
统计每个格子被多少矩形覆盖。现在每个矩形内的 1 是拿走这个矩形一定可以带来的贡献。拿走两个矩形时,它们交集里面的 2 也会产生贡献。所以我们枚举 2 的格子,找到那两个矩形就能统计贡献。
问题是怎么找到那两个矩形?处理出每个格子被覆盖的矩形的编号和、编号平方和,就可以解方程解出那两个矩形的编号。
K
可以线段树维护哈希,开两棵树分别维护 正过来的哈希和 倒过来的哈希,每次线段树上二分就 好了。
由于值域比较大,可能需要双模/较大模数。
L
考虑枚举答案,再按在序列中的顺序枚举它的倍数。对于可能对答案有贡献的三元组 (i,j,k),一定满足 i与 j相邻,且 k是离 j最近的合法的标号。显然这样的三元组个数最多只有O(nd) 个。
接下来考虑怎么求每个三元组 (i,j,k)。一种写法是,因为对于一个枚举到的答案,随着 i的增加,k 是没有单调性的,所以想求出所有三元组只能二分答案。但是如果我们从右往左枚举 i,用双指针维护 k,虽然没有办法求出所有三元组,但对于每个错过的三元组 (i,j,k),一定存在一个三元组(i',j',k') 使得 i'<=i 且 k<=k'。所以我们错过的三元组一定不优。于是我们就可以在 O(nd) 的时间内求出所有合法三元组。
另一种常数更小的写法是:我们不直接枚举答案,而是从左往右扫,对每个数 ai 枚举它的因数 x。设上一 次出现 x的倍数的位置是 lst_x,这样所有在 2i-lst_x 后面的数 k都能组成 (lst_x,i,k) 且答案为 x 的 三元组。于是我们把 x挂在 2i-lst_x 上就可以方便地求出所有三元组 (i,j,k)。
接下来,我们离线询问,将三元组 (i,j,k)与对应的答案挂在 i或 k上,就只需要做一个二维数点。由于 与 d同阶,且要做 O(nd) 次修改和 O(q) 次查询,我们用 O(1) 修改 O(sqrt n) 查询的分块即可做到 的复杂度。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】