zoukankan      html  css  js  c++  java
  • [LeetCode 1671.] 玩游戏

    1671. 玩游戏

    CAT 专属题目 hard 难度

    题目描述

    N 个人在玩游戏,每局游戏有一个裁判和 N-1 个平民玩家。给出一个数组 A, A[i] 代表玩家 i 至少需要成为平民 A[i] 次,返回最少进行游戏的次数。

    样例

    样例 1:

    输入:A = [2, 2, 2, 2]
    输出:3
    解析:
    A[0] = 2表示玩家0至少需要成为2次平民
    第一局:玩家0担任裁判,此时 A[0] = 0, A[1] = 1, A[2] = 1, A[3] =1
    第二局:玩家1担任裁判,此时 A[0] = 1, A[1] = 1, A[2] = 2, A[3] = 2
    第三局:玩家2担任裁判,此时 A[0] = 2, A[1] = 2, A[2] = 2, A[3] = 3
    此时每个玩家都达到了要求,所以进行三局游戏即可

    样例 2:

    输入:A = [84,53]
    输出:137
    解析:
    第一局:玩家1担任裁判 ,此时 A[0] = 1, A[1] = 0
    ......
    第三十一局:玩家1担任裁判,此时 A[0] = 31, A[1] = 0
    第三十二局:玩家0担任裁判,此时 A[1] = 31, A[1] = 1
    第三十三局:玩家1担任裁判,此时 A[1] = 32, A[1] = 1
    第三十四局:玩家0担任裁判,此时 A[1] = 32, A[1] = 2
    ......
    第一百三十七局:玩家1担任裁判,此时 A[1] = 84, A[1] = 53
    此时每个玩家都达到了要求,所以进行一百三十七局游戏即可
    注意事项

    • ∑Ai<=1e18
    • 1 < n < 1000

    解题思路

    想法1:从后往前逆推,从现有状态猜测上一轮的裁判是谁。
    每一轮都让分数最低的人当裁判,这样高分选手才能尽快降下来。
    但是每一轮都找最低分,然后给其余元素更新,时间复杂度O(n*MAX)太高。

    想法2:分段解决。
    先把最高分的分数凑出来。然后看其余人有没有没满足的,再补上不够的分数。
    关键的问题是,怎么判定阈值是多少?怎么给出应该补多少分?

    凑够最高分需要 MAX 轮,n个人总共得分 (n-1)*MAX 分。如果总得分少于这个数,则可以凑出来,凑分方案如下:

    从前往后推。每次选取分数最高的人做裁判,如果都相等则任取一人做裁判。这样n个人从全部为0分到最高为MAX分,所需轮数是MAX轮。
    注意,因为每次选分数最高的做裁判,所以这n个人的分数相差不会超过1。

    逆向操作,从后往前推。这里直接对于最高分之外的其余人,各自减去最高分,这样就都变成了负分。

    • 如果这个负数的绝对值不少于最高分,那么这意味着这n-1个人的分数少于凑最高分所需分数,凑最高分的过程中就能满足这些人的分数需求。
    • 如果这个负数的绝对值小于最高分,那么还需要填补这些分数,这几轮让最高分来担任裁判,这n-1个人一起加分。

    参考代码

    class Solution {
    public:
        /**
         * @param A: 
         * @return: nothing
         */
        long long playGames(vector<int> &A) {
            // Write your code here
            std::sort(A.begin(), A.end());
            size_t n = A.size();
            int maxA = A[n-1];
            long long sum = 0LL;
            long long res = 0LL;
            for (size_t i=0; i<n-1; i++) {
                A[i] -= maxA;
                sum += A[i];
            }
            if (sum + maxA <= 0) {
                return maxA;
            } // 前n-1个人轮流做裁判就够了
            return ceil((double)(sum + maxA) / (n - 1)) + maxA; //还需要补几轮,前n-1个人均摊一下
        }
    };
    
  • 相关阅读:
    Spark Streaming 应用实例
    Spark Streaming 应用实例
    利用 Spark Streaming 构建高效健壮的流数据计算系统注意事项
    利用 Spark Streaming 构建高效健壮的流数据计算系统注意事项
    Kafka 集群搭建步骤
    Kafka 集群搭建步骤
    php微信开发-tp5下验证服务器的代码
    php微信公众号开发,入门篇(实现了关注公众号发送欢迎信息,发关键词自回复)
    【php技术】PHP错误类型和屏蔽方法
    自制在线富文本编辑器,精简完整版
  • 原文地址:https://www.cnblogs.com/zhcpku/p/14259486.html
Copyright © 2011-2022 走看看