8月12日 2018百度之星初赛 (B) 题目链接:http://bestcoder.hdu.edu.cn/contests/contest_show.php?cid=826
1001 - degree
思路: 一道比较简单的结论题吧。。。我们贪心地找出一个度数最多的点,当不考虑K时,我们可以将其他的联通块都接在这个点上。当我们考虑K时,我们就可以从联通块上拆下K个点,再接到度数最多的点上,注意一下有没有K个点够拆就好了。
代码:
1 |
|
1003 - odds
思路: 特别好的一道题吧。。。
我们可以把每个叶子节点到根的路径提出来,这样问题可以简化为:一个路径上有K条边,分别有权值$x_1, y_1, x_2, y_2····x_k,y_k$,其中$y_i>=x_i$的。你需要从中选$x$条边取$y_i$,其余边取$x_i$,使这些的乘积最大。根据题目要求,求这个的复杂度应该要在$O(nlogn)$以内的。
于是我们可以想到一个贪心的方法,对于这$K$条边,我们选其中$y_i*x_i$最大的x条边取$y_i$,其余的取$x_i$。证明也很简单:假如已经处理出了前$i-1$条边($i$是应该大于$x$的,否则直接取$y_i$)乘积为$w$。我们考虑第$i$条边:如果第$i$条边取$x_i$,那么乘积为$w*x_i$;如果取$y_i$,那么我们就需要从前$x$条取$y$边中,选出一条边$j$,让它值变为$x_j$,这样乘积就为$w_i*y_i*(x_j/y_j)$。不难看出我们希望乘积尽可能大,那么就需要选$y_i*x_i$尽可能大的边。
有了这个贪心策略后,实现就不难了。用一个multiset动态维护路径上$y_i*x_i$前$x$大的边,同时计算出答案,回溯时要将答案和multiset复原。注意,千万不能对于每一个叶子节点都重新算一遍答案,我比赛时就是这样SB的都算一遍,然后T飞了,比完赛才反应过来。
代码:
1 |
|
1004 - p1m2
思路: 二分应该能够很容易的看出来,对于二分值大的就计算一下正的贡献,小于二分值的计算负的贡献,判断正负贡献是否大于0。
代码:
1 |
|
1006 - rect
思路: 题目有一句比较重要的话就是$x_i,y_i$彼此不重复,这样的话就直接贪心就好了,到哪条边近就向那条边做垂线,这样线段也一定不会交叉重复。
代码:
1 |
|