- NC https://ac.nowcoder.com/acm/contest/17085/E
大意:有n个景点,m条轨道将某些景点连接起来,每个景点有一个对应的高度,每次只能从某个景点去和它相连的并且高度不高于它的景点。并且可以随时随地回到之前走过的任意一个景点。求从1号景点开始的能走到的最多的景点的数量和最小距离和。1<=n<=1e5,1<=m<=1e6,1<=hi<=1e9
思路:首先很容易想到,对于最多的景点数,就是从1开始dfs,求连通块中点的个数,注意这里是不能用并查集求得,因为起点是确定的,只能从1开始。对于并查集求连通块是没有规定起点的。解决了访问到的最多景点个数的问题,接下来看怎么求最小距离和。首先如果没有高度限制的话就很容易,很简单嘛,最小生成树嘛。但是如果有高度的限制呢?就相当于变成了有向图,最小生成树是对于无向图的。这是还能不能用做最小生成树的算法做了呢?我们先来想想克鲁斯卡尔的算法原理:将边权从小到大排序,然后遍历,如果没有连通就将他们连通。我们这题就是多了高度的限制。其实也是可以做的,我们只需要将高度作为第一关键字排序从大到小,边权从小到大排序就行了,这样我们就确保了进行连通的时候是从先连的高度较高的点,这样就不会出现走到了高度较低的点,但是有高度较高的点却走不了了。我们要先确保景点总数最多,然后才是距离最小。
总结:(1)理解了算法的原理,才能做变形。(2)克鲁斯卡尔算法的原理。(3)dfs和并查集求连通的点的数量的区别。
- NC https://ac.nowcoder.com/acm/contest/17085/C
大意:有1个容量为v的背包,有n个物品,每一个物品有一个价值 ai,以及体积bi,现在不是要 求不超过背包容量的最大价值,而是需要求不超过背包容量选确定的m个中位数最大值,(m为偶数是,中位数为中间的两个值平均值,下取整)。(n ≤ 1e5, 1 ≤ m ≤ n, ai ≤ 1e9, v ≤ 1e9, bi ≤ v)
思路:一般的有关中位数问题很多情况下与堆、二分、排序有关。
首先根据数据范围很明显不是背包问题了。因为要求中位数,很容易想到先将价值排个序。对于m为奇数,也就是中位数前面有m/2个数,后面有m/2个数,并且是他们的价值尽可能的小,也就是枚举中位数,维护符合条件的最大值就行了。显然对于每次排序计算是会超时的。接下来就是堆的常用操作了,用堆预处理出任意一个位置作为中位数,前面选m/2个体积和的最小值以及后面选m/2个体积之和的最小值。即每次往后移动一个位置就和堆顶比较,如果比堆顶小就更新,如果比堆顶还大,那么就一定不会更新。预处理完成之后通过遍历每个位置作为中位数,维护满足条件的最大值就行了。对于m为偶数的情况,因为要选择中间两个数的平均值尽可能大,这样的要怎么做呢?显然枚举两个数是不行的,时间复杂度o( n 2 n^2 n2),但是如果我们确定了两个数中的前面那一个,那么对于后面那个一定是越靠后越好,也就变成了找符合条件的起点尽可能靠后的m/2个,显然通过预处理出前面m/2-1 和后面m/2,对于后面的m/2个的查找是可以二分的。
总结:(1)有关中位数的问题很多与堆、排序、二分有关。(2)用堆可以动态维护选择固定个数物品的最值。