最大的团队表现值(定一法,单调栈优化)

传送门

视频题解

公司有编号为 1 到 n 的 n 个工程师,给你两个数组 speed 和 efficiency ,其中 speed[i] 和 efficiency[i] 分别代表第 i 位工程师的速度和效率。请你返回由最多 k 个工程师组成的 ​​​​​​最大团队表现值 ,由于答案可能很大,请你返回结果对 10^9 + 7 取余后的结果。

团队表现值 的定义为:一个团队中「所有工程师速度的和」乘以他们「效率值中的最小值」。

 

示例 1:

输入:n = 6, speed = [2,10,3,1,5,8], efficiency = [5,4,3,9,7,2], k = 2
输出:60
解释:
我们选择工程师 2(speed=10 且 efficiency=4)和工程师 5(speed=5 且 efficiency=7)。他们的团队表现值为 performance = (10 + 5) * min(4, 7) = 60 。
示例 2:

输入:n = 6, speed = [2,10,3,1,5,8], efficiency = [5,4,3,9,7,2], k = 3
输出:68
解释:
此示例与第一个示例相同,除了 k = 3 。我们可以选择工程师 1 ,工程师 2 和工程师 5 得到最大的团队表现值。表现值为 performance = (2 + 10 + 5) * min(5, 4, 7) = 68 。
示例 3:

输入:n = 6, speed = [2,10,3,1,5,8], efficiency = [5,4,3,9,7,2], k = 4
输出:72
 

提示:

1 <= n <= 10^5
speed.length == n
efficiency.length == n
1 <= speed[i] <= 10^5
1 <= efficiency[i] <= 10^8
1 <= k <= n

这个题有两个变量,所以我们要固定一个来枚举另一个

优先级队列是一个以对数级插入和取出为代价提供常数级最大最小值的查询的容器适配器。

解题思路:
①:将效率从大到小进行排序(之所以从大到小是因为,这样能保证在我们不断进行选取基准效率时,我们不需要对之前选择的效率做处理(因为都大于当前的效率基准))
②:对于每个工程师的效率值,我们计算在以他作为最小效率值情况下,最大的团队表现值
③:假如优先级队列里面的元素多余k,我们就弹出队首位置(因为更具我们设置的小根堆优先级队列,队首位置总speed是最小的,因此我们弹出它)
④:比较,注意,因为这里是需要比较我们不能在过程中取模,这会导致错误


这个题的接替思路就是,我们先按照效率拍个序,枚举一个效率这时效率大与i的有很多,就是小于i的所有效率都可以,

然后怎么找max(sum(speed))呢,我们可以用一个优先队列维护这个speed,每一次使得最小的speed出栈

class Solution 
{
public:
    int maxPerformance(int n, vector<int>& speed, vector<int>& efficiency, int k) 
    {
        long long res = 0;
        long long cur_speed_sum = 0;
        vector<pair<long long, long long>> a;                               // 存储  {速度, 效率}
        priority_queue<int, vector<int>, greater<int>> min_heap_speed;      //速度  的 最小堆
        for (int i = 0; i < n; i ++)
        {
            a.emplace_back(speed[i], efficiency[i]);
        }
        sort(a.begin(), a.end(), [&](pair<long long, long long> x, pair<long long, long long> y)
        {
            return x.second > y.second;         //按招 efficiency 降序排列
        });

        for (int i = 0; i < n; i ++)
        {
            long long cur_speed = a[i].first;
            long long cur_min_efficiency = a[i].second;         //因为a按招efficiency降序排序了  当前的efficiency就是目前的k个最低效率
            min_heap_speed.push(cur_speed);
            cur_speed_sum += cur_speed;
            if (min_heap_speed.size() > k)                      //超过k个速度了  就有的选择了  
            {
                long long cur_min_speed = min_heap_speed.top();     min_heap_speed.pop();
                cur_speed_sum -=  cur_min_speed;         //把最小的速度扔掉  如果就是当前这个速度最小怎么办  那前面一步,一定比这一步大
                if (cur_min_speed == cur_speed)                 //如果当前的速度,就是最小速度  当前的效率又低
                    continue;                                   //直接判断下一个  别丢人了 赶紧略过  不用和res比较了
            }
            res = std::max(res, cur_speed_sum * cur_min_efficiency);
        }

        return res % (1000000007) ;       
    }
};

 

class Solution {
public:
    int maxPerformance(int n, vector<int>& speed, vector<int>& efficiency, int k) {
        vector<pair<int,int>> v;
        for(int i=0;i<n;i++){
            v.push_back({efficiency[i],speed[i]});
        }
        sort(v.begin(),v.end());
        priority_queue<int,vector<int>,greater<int>> heap;
        long long  sum=0,ans=0;
        for(int i=n-1;i>=0;i--){//枚举的是每一个效率    
            heap.push(v[i].second);
            sum+=v[i].second;
            if(heap.size()>k){
                sum-=heap.top();
                heap.pop();
            }
            ans=max(ans,sum*v[i].first);
        }
        return ans%1000000007;
    }
};

 

posted @ 2021-05-11 22:58  lipu123  阅读(148)  评论(0)    收藏  举报