[M贪心] lc1353. 最多可以参加的会议数目(扫描线+STL优先队列)
Posted Ypuyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[M贪心] lc1353. 最多可以参加的会议数目(扫描线+STL优先队列)相关的知识,希望对你有一定的参考价值。
1. 题目来源
精选题解:扫描算法+贪心
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优先队列)的主要内容,如果未能解决你的问题,请参考以下文章