[M贪心] lc1353. 最多可以参加的会议数目(扫描线+STL优先队列)

Posted Ypuyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[M贪心] lc1353. 最多可以参加的会议数目(扫描线+STL优先队列)相关的知识,希望对你有一定的参考价值。

1. 题目来源

链接:1353. 最多可以参加的会议数目

精选题解:扫描算法+贪心


2. 题目解析

只是本题比较像扫描线,并不是扫描线的经典应用。

每个时间点只会参加一次会议,所以可以按照天数从 1~MAX 开始扫描,即扫描每个时间点。

如果会议在当前时间点之前还未开始,或者这个会议在这个时间点在进行中但并未结束,则这些会议都可以参加。

但显然,应该参加一个结束时间早的会议,这样,会有更多时间去参加别的会议。每个会议的权值是一样的。

线性扫描时间点,用小根堆动态维护当前所有能参加会议的结束时间。在每个时间点,先将当前时间点开始的会议加入小根堆,并将当前时间点结束的会议移除小根堆(这点非常类似扫描线),最后选择一个结束时间最早的会议参加即可。

预处理每个任务的开始时间及对应下标,方便等会顺序枚举时间点的时候添加进该点的所有任务的结束时间。


时间复杂度: O ( T l o g N ) O(TlogN) O(TlogN)

空间复杂度: O ( n ) O(n) O(n)


代码:

class Solution {
public:
    const int MAX = 1e5+1;
    int maxEvents(vector<vector<int>>& events) {
        vector<vector<int>> left(MAX);      // 初始化 MAX 个一维数组,存每个时间点下的开始任务下标
        for (int i = 0; i < events.size(); i ++ ) left[events[i][0]].push_back(i);

        int ans = 0;
        priority_queue<int, vector<int>, greater<int>> pq;
        for (int i = 1; i < MAX; i ++ ) {
            for (int j : left[i]) pq.push(events[j][1]);        // 加入开始的会议,只加入结束时间
            while (pq.size() && pq.top() < i) pq.pop();         // 弹出结束的会议
            if (pq.size()) pq.pop(), ans ++ ;                   // 选择结束时间最早的会议作为该时间点加入
        }

        return ans;
    }
};

以上是关于[M贪心] lc1353. 最多可以参加的会议数目(扫描线+STL优先队列)的主要内容,如果未能解决你的问题,请参考以下文章

[M扫描] lc5805. 最小未被占据椅子的编号(顺序扫描+双周赛57_2)

C语言刷leetcode——贪心

LeetCode 2127. 参加会议的最多员工数

[M贪心] lc1833. 雪糕的最大数量(贪心+水题)

[M贪心] lc763. 划分字母区间(贪心+代码实现)

[M贪心] lc763. 划分字母区间(贪心+代码实现)