「贪心」做题记录

「贪心」做题记录

  1. P2672 [NOIP2015 普及组] 推销员

    由于不会走多余的路,所以行走产生的疲劳值只和最远的被推销的住户有关。设 fX(i) 表示总共选 X 家住户,且第 i 户是最远的被推销的住户的情况下,最大的疲劳值。显然可以贪心地在前 i1 户中选择 X1 户疲劳值最大的住户,所以 fX(i)=2Si+Ai+(i1)Aj(X1)Aj

    可以用小根堆(优先队列)维护前 k 大和。由于要枚举 X,总的时间复杂度为 O(N2logN),可以得到 60 分。代码

    下面是本题的正解贪心做法。

    考虑贪心地选取前 X 个疲劳值最大的住户。但这并不一定是最优的:我们可能选取一个疲劳值更小,但比原来所有住户都更远的住户,从而通过行走距离获得更大的疲劳值。

    具体地,我们要放弃原先的多少个住户呢?实际上最多放弃 1 个,然后选择未被选择的住户中,2Si+Ai 最大的住户 i。如果放弃多于 1 个住户,一定不优于只放弃 1 个。(不知道怎么表达证明过程)

    AC 代码

  2. [ABC137D] Summer Vacation

    如果一个工作在某一天做完之后,直到结束都不能领到工资,那么还不如不做。所以可以把一个工作可以做的区间看作一段前缀。从后往前枚举天数,维护可以做的工作的集合,每次选择集合中价值最大的工作来做。(不会严谨证明,但前缀的观点或许有助于理解。)

    提交记录

  3. [AGC004D] Teleporter

    洛谷的题解都他妈是什么东西?怎么都这么意识流,还有的是如写

    首先根据题目中图的性质,可以得出在忽略 1 出发的边以后,图一定是一棵以 1 为根的内向树。

    证明:删去 1 出发的边显然不影响其它点到 1 的可达性,这时边数 = 点数 1。根据连通性,可以得知图是树。再根据除了 1 之外的点都可达 1,可以得知图是以 1 为根的内向树。

    从树的角度来看,可以得出 1 必须指向自己。因为在树上两点的路径唯一,而且是内向树,如果一个点的深度小于 K,并且没有这个自环,它就无法通过恰好 K 次传送到达 1

    如果一个点的深度大于 K,那么它显然无法经过恰好 K 次传送到达根节点;否则一定可以,缺少的部分可以通过一直走 1 的自环来补足。那么我们把问题转化成了:给定一棵树,修改最少的边,使得所有点的深度不大于 K

    这个问题还可以进一步转化:删除最少的边,使得剩下的所有弱连通块(每个弱连通块都是树)都满足以下条件:

    • 如果根节点为 1,那么树的高度不超过 K
    • 否则,树的高度不超过 K1

    采用 dfs ,自下往上解决此问题。如果一棵子树的高度大于等于 K1,并且它的父节点不是 1,那么需要删除它连向父节点的边,否则更新父节点的高度。

    function<void(int)> dfs = [&](int u)
    {
        h[u] = 0;
        for(int v: G[u])
        {
            dfs(v);
            if(u != 1 && h[v] == K - 1)
                ans++;
            else
                h[u] = max(h[u], h[v] + 1);
        }
    };
    dfs(1);
    

    这样得出来的图一定满足条件,但删边数的最少性不会证明。官方题解用的就是这个做法。

    完整代码

posted @   DengStar  阅读(2)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示