竞赛讨论区 > 牛客周赛64题解
头像
Silencer76
编辑于 10-20 22:54 北京
+ 关注

牛客周赛64题解

比赛地址:牛客周赛 Round 64
出题人:神崎兰子

A 小红的对错判断

把所有字符都转换成大写形态,将字符串与 比较。
参考代码

B 小红的幂表达

从大到小枚举底数 ,求出对数
如果有 ,输出之。
由于底数从大到小枚举,幂次会是递增的。
对于求对数的环节,计算机并没有对每个 都有 函数。
所以我们使用换底公式
参考代码

C 小红的前缀询问

使用 dict 维护当前位置 之前,有多少个元素等于
是存放元素数量的 dict,则第 个位置的贡献为
我们记这个贡献为 ,则前缀 的贡献和为
在此基础上,对数组 做前缀和,即可快速求解区间之和。
参考代码

D 小红和小紫的博弈游戏

考虑四种组合 , , ,
如果没得取,只有两种可能, ,或者
既然是最优策略,那么都会取最小的那个。
参考代码

E 小红的字符串重排

首先想到一个 trick ,最大的同种字符数量 的关系。
这题要求每个位置都不能放原来的字符,所以需要满足
如果满足,我们考虑字符集整体偏移 个长度。
首先,构造一个长度为 的二元组数组,每个二元组的 first 存放字符,second 存放下标。
然后,按照字符大小进行排序,从小到大或者从大到小都行,这里是为了让同样字符放到一块去。
然后,构造一个存目标字符的数组 ,对于每个二元组,将偏移过后字符放入新的下标。
最终,将字符数组转换为字符串,输出。
参考代码

F 小红的树上路径查询(easy)

由于 ,我们可以考虑时间复杂度为 的算法。
定义 的路径,那么我们需要找出 上所有的点,并且求出其他点到 的最短距离。
现在大问题变成了两个小问题。
1.找出路径上的点。
假设点 在路径上,那么从 的路程中,必然经过点 ,则有
注意到,这些边都是无向边,有
那么上式可转换为
的距离, 的距离。
那么,只要把 当作起点,做一次 bfs ,即可得知 到其他点的最短距离, 同理。
做完两次 bfs ,分别得到每个点与 的距离数组
如果点 ,那么 就是在路径上的点。
2.求出其他点到 的距离。
假设有极端情况,一半的点在路径上,另一半不在。
对所有在路径上的点,分别做一次bfs,然后对每一个非路径点,比较得出最小值,求和。
时间复杂度达到了惊人的 ,不可取。
那么多次 bfs ,我们是否能只做一次 bfs 呢?
你别说,还真有。
我们创建一个虚拟源点(也叫超级源点),连接它和路径上的所有点,边权为
这个源点就是只用做一次 bfs 的起点,它将时间复杂度降到了
在代码实现时,我们不需要真的创建这个点,以及对应的 边。
只需要在初始化队列时,把路径上面的点都扔进去就好(普通bfs只会扔一个点进去)。
bfs 结束之后,把距离数组的值全部加起来,输出。
参考代码

G 小红的树上路径查询(hard)

hard version 的 ,显然 的做法也倒闭了。。。
让我们重新审视点与路径的关系。
点在路径上的情况,已于 F 题解中说明。
那么,点不在路径上的情况呢?
假设点 不在路径上,离它最近且在路径上的点是
路径的两端仍然是
那么,从 或者 从 的路程中,必然经过点
所以有如下推导:




对于在路径上的点,代入上式,也是正确的。
因为此时
所以,对于给定的所有点,都满足上式。
有同学会问,我们知道这个有什么用吗?
别急,我们来反推一波。
我们想求的是全部的 之和,注意,这里并不需要求出具体的
根据上式,移项可得
对所有 的求和为:



相信大家已经看出来了
是点 到所有点的距离之和。
是点 到所有点的距离之和。
是点 到点 的路径长度。
大问题又变成了两个小问题。
可以使用 换根dp 维护。
可以使用 LCA 维护。
对于具体算法,不在此处赘述。
对于单次询问的时间复杂度,换根dp 的复杂度是 ,LCA 的复杂度是 ,总复杂度是
需要注意的是,python 在递归上的效率奇差,需要使用栈来替代递归。
参考代码

感谢阅读!

全部评论

(0) 回帖
加载中...
话题 回帖

等你来战

查看全部

热门推荐