- 代码源挑战赛 Round 2
代码源挑战赛 Round 2 题解
- 2025-3-10 16:14:53 @
T1
100%
- 方法1:
因为 的范围不超过 ,可以直接三重循环枚举选哪三个人,选的人不要重复就可以了。
时间复杂度 。
- 方法2:
显然选能力值最大的三个人是最优的。如果 的范围达到了 ,可以将能力值排序,然后取最大的三项之和。
时间复杂度 。
- 方法3:
可以不用排序,直接维护最大的三个值 ,可以参考以下代码:
now = a[i];
for (int j = 0; j < 3; j++) {
if (now > mx[j])
swap(now, mx[j]);
}
时间复杂度 。
T2
60%
两重循环,外层循环枚举第 个人,内层循环枚举 验证是否高度都低于 。
时间复杂度 。
100%
用一个变量维护前缀最大值 ,如果 说明 前面的人高度都低于他,答案增加 。
时间复杂度 。
T3
30%
直接三重循环枚举 ,如果满足 那么答案增加 。
时间复杂度 。
60%
对于测试点#4~6,统计每种数字分别出现了多少次。假设数字 出现了 次,那么 的三元组有 个。
因为 ,所以可以直接用数组来统计,加一个偏移量即可,比如 的出现次数维护在 。
因为只选三个,可以直接用 $\binom {k}{3}=\frac{k\times(k-1)\times(k-2)}{1\times 2\times 3}$ 计算。
记 的值域跨度为 。
时间复杂度 。
结合第一部分可以拿到 的分数。
100%
- 方法1:
的数据范围下不能用数组来维护了。
可以将 排序,这样相同的值的位置就在一起了,就可以统计每种数字的出现次数了。
时间复杂度 。
- 方法2:
也可以用 来统计每种数字的数量。
时间复杂度 。
T4
20%
对于每个询问,暴力验证每个 是否是 的倍数。
时间复杂度 。
50%
对于测试点#3~5, 和 的范围达到了 ,但是 和 的范围只有 ,所以可以预处理每个 对应的答案。
先统计 中每种数字出现的次数 ,再用双重循环枚举 和 ,如果 是 的倍数,那么 。
记 最大值为 。
时间复杂度 。
结合第一部分可以拿到 的分数。
100%
发现在第二部分中只有 是 的倍数时才维护答案。所以我们内层循环枚举 时直接枚举 的倍数。
实现上类似埃氏筛。
时间复杂度 。
T5
20%
用 算法处理出任意两点间的距离,然后枚举所有 种访问顺序。
注意代表无法到达的无穷大要设置得足够大。
注意最后要回到点 。
时间复杂度 。
30%
对于测试点#3,因为 所以路线只有 这一条。
用 等单源最短路算法,分别从 和 出发,求出这两段最短路的长度再加起来。
时间复杂度 。
结合第一部分可以拿到 的分数。
50%
对于测试点#4~5,路线有 和 两条。
先枚举访问顺序,分别从 出发跑单源最短路,按顺序求出每段最短路的长度加起来。再比较两种路线哪条更短。
时间复杂度 。
结合第一部分可以拿到 的分数。
100%
不难发现过程中用到的最短路,起点和终点全都是 或 ,所以我们分别从这 个点出发跑最短路,预处理出 段最短路的长度。
然后再枚举访问顺序,计算每种路线的长度,比较出最短的一条路线。
时间复杂度 。
T6
10%
操作 就是从大到小选,操作 就是从小到大选。 和 的范围都是 ,可以直接暴力维护 。
每次查询前需要排序,推荐两种实现方法:
①将 复制到数组 ,对 进行排序。
②用 同时存储值和下标,询问前按值排序,询问后按下标排序还原。
然后暴力枚举取多少个就可以了。
注意答案为 或 的情况。
时间复杂度 。
20%
对于测试点#2,因为 和 的范围只有 ,可以用 维护 中有多少项值为 。
操作 只要将原本的 ,再将 即可。
询问时直接枚举取的最后一项的值,通过前缀和的方式来计算答案。
记 的最大值为 。
时间复杂度 。
结合第一部分可以拿到 的分数。
40%
对于测试点#3~4,没有修改操作的情况下,可以直接对 进行排序。
查询时可以用二分的方法来求答案。
时间复杂度 。
结合第一、第二部分可以拿到 的分数。
80%
用权值线段树维护区间和,二分取的最后一项的值,思路类似测试点#2。
时间复杂度 。
100%
其实询问就对应权值线段树的前缀区间或后缀区间,可以用线段树二分的技巧,代替外层的对最后一项取值的二分。
具体来说,对于询问 ,对应线段树上一个后缀区间,如果当前节点的右子树的和大于等于 ,那么在右子树内继续寻找;否则 减去右子树的和,在左子树内继续寻找。对于询问 ,就是找前缀区间,思路类似。
时间复杂度 。