• 「题解」P7043 「MCOI-03」村国


    原题链接

    其实最开始看到这道题目的时候是没有什么做法的,但是看到(M le 10 ^ {18}) 之后感觉应该是个结论题,所以自己画图手玩了一下发现了做法

    首先对于一个最开始到达的点,它是好感度最大且编号最小的,并且他只会影响到他周围的点(显然),所以我们先随便画个图:

    下文称权值最大且编号最小的点为 (Max),与他相连的次大的且编号最小的点为 (Max_S)

    对于这个图,标红的是我们会选择的第一个点,因为他只会对周围的点造成影响,所以不在他周围的次大的点是不会对答案造成贡献的,那么我们会一直选这个点作为 (Max) 直到他周围的点和他幸福度相同的时候,如下图

    显然,当有一个点的权值和他一样时,我们会选择这两个点中编号较小的一个,在图中是结点1的标号更小,所以我们继续选择一号结点,且这个和第一个 与(Max) 权值相同的点一定是 (Max_S)那么,当 (Max_S) 的优先级 高于 (Max) 时,即 (Max_S) 成为 (Max) 时,原来的 (Max) 一定是 (Max_s), 这个下文再画图解释

    (Max_S) 成为 (Max) 时,即图中的7号结点在第4次更新后,权值变成8,这个时候我们会选择7号结点作为 (Max)。接着我们又会更新7号结点周围的点,导致一号结点成为 (Max) 然后重复这个操作,那么我们发现,答案最终只会在最初的 (Max)(Max_S) 中产生。

    那么我们先算出 (Max)(Max_S) 的差值,并且当 (Max) 的标号大于 (Max_S) 时,交换他们两个的值保证(Max) 的标号小于 (Max_S),将它与 (M) 进行比较,如果 (M) 小于这个差值,那么我们直接输出(Max) 值,如果大于等于的话,我们将这个差值 % 2,如果余数等于1,输出(Max_S),因为这个时候我们选择的是最开始的 (Max) 所以更新了 (Max_S) 的值使其的幸福度大于 (Max) ,而当余数等于0时,我们输出 (Max) 因为此时 (Max)(Max_S) 的幸福度相等,而前者标号小于后者。

    记得对 (n = 1) 的情况进行特判,因为这个时候我们找不到任何一个 (Max_S), 所以直接输出唯一的一个点。

    然后对一些上文提到的问题进行解释

    (Max_s) 的优先级 高于 (Max) 时,即 (Max_S) 成为 (Max) 时,原来的 (Max) 一定是 (Max_S)

    (Q) : 如果有一个点在 (Max_S) 成为 (Max) 时与(Max_S) 相连且幸福度同样与 (Max_S) 相等,标号还要小些怎么办,要选择那个点吗

    (A) : 你看

    如果存在这样一个点,那么在最开始选择我们这个理想的 (Max) 的时候是不会更新这个一号结点的,也就是说一号结点最开始的幸福度就和5号结点一样大,所以在最开始我们就会选择1号结点而不是5号结点,当 (Max) 的标号小于 (Max_S) 的时候同理。

    附上代码

    #include <bits/stdc++.h>
    using namespace std;
    #define LL long long
    const LL MAXN = 2000000  + 10;
    LL head[MAXN], to[MAXN << 1], nxt[MAXN << 1];
    LL val[MAXN], cnt, Max, Maxs;
    inline LL read() {
    	LL x = 0;char c = getchar();
    	while (c < '0' || c > '9') c = getchar();
    	while (c >= '0' && c <= '9') x = x * 10 + c -'0',c = getchar();
    	return x;
    }
    int main ()  {
        LL T; T = read();
        while(T --) {
            memset(head, 0, sizeof(head));
            cnt = 0; Max = 0; Maxs = 0;
            LL n, m; n = read(); m = read();
            for(register LL i = 1; i <= n; i ++) {
                val[i] = read();
                if(val[Max] < val[i]) Max = i;
            }
            for(register LL i = 1; i < n; i ++) {
                LL x, y; x = read(); y = read();
                if(y == Max) swap(x, y);
                if(x == Max) {
                    if(val[Maxs] < val[y]) Maxs = y;
                    else if(val[Maxs] == val[y])
                        Maxs = min(Maxs, y);
                }
            }
            if(n == 1) {printf("%lld
    ", Max); continue;}
            if(val[Max] - val[Maxs] <= m) {
                m -= (val[Max] - val[Maxs]);
                if(Maxs < Max) swap(Max, Maxs);
                if(m % 2 & 1) printf("%lld
    ", Maxs);
                else printf("%lld
    ", Max);
            }
            else printf("%lld
    ", Max);
        }
        return 0;
    }
    

    如果对于文章中有什么疑问或是错误,欢迎在评论或私信提出

  • 相关阅读:
    网络协议栈(6)RFC793TCP连接时部分异常流程及实现
    网络协议栈(5)sendto/send返回成功意味着什么
    LeetCode——Detect Capital
    LeetCode——Find All Numbers Disappeared in an Array
    LeetCode——Single Number
    LeetCode——Max Consecutive Ones
    LeetCode——Nim Game
    LeetCode——Reverse String
    LeetCode——Next Greater Element I
    LeetCode——Fizz Buzz
  • 原文地址:https://www.cnblogs.com/Van-Yang/p/13934283.html
Copyright © 2020-2023  润新知