leetcode 2054(排序 + 单调栈,通用做法是 DP)

2054: 两个最好的不重叠活动

题意:在结束时间小于 startTime 的活动中,选择价值最大的活动。

为了方便查找,先把 events 按照++结束时间++从小到大排序。

排序后,对比如下两个活动:

  • 活动一:结束于 3 时刻,价值 999。
  • 活动二:结束于 6 时刻,价值 9。

活动二的结束时间又晚,价值又小,全方面不如活动一,是垃圾数据,直接忽略。

换句话说,在遍历 events 的过程中(注意 events 已按照结束时间排序),只在遇到更大价值的活动时,才记录该活动。把这些活动记录到一个栈(列表)中,那么从栈底到栈顶,结束时间是递增的,价值也是递增的,非常适合++二分查找++。

枚举第二个活动,在单调栈中二分查找结束时间严格小于 startTime 的最后一个活动,即为价值最大的第一个活动。如果没找到,那么只能选一个活动。

为了简化判断逻辑,可以在栈底加一个结束时间为 0,价值也为 0 的哨兵。

复制代码
ranges::sort(events,{},[](auto& e){return e[1];});
复制代码
vector<pair<int,int>> st={{0,0}}; //栈底哨兵

auto it=--ranges::lower_bound(st,start_time,{},&pair<int,int>::first);
ans=max(ans,it->second+value);

单调栈递增,如果找不到,因为有"栈底哨兵",因此找不到满足条件的活动时,it={0,0},it->second=0,不会越界。

复制代码
class Solution {
public:
    int maxTwoEvents(vector<vector<int>>& events) {
        //按照结束时间升序排序
        ranges::sort(events,{},[](auto& e){return e[1];});
        //从栈底到栈顶,结束时间递增,价值递增
        vector<pair<int,int>> st={{0,0}}; //栈底哨兵
        int ans=0;
        for(auto& e:events){
            int start_time=e[0],value=e[2];
            //二分查找最后一个结束时间 < start_time 的活动
            auto it=--ranges::lower_bound(st,start_time,{},&pair<int,int>::first);
            ans=max(ans,it->second+value);
            if(value>st.back().second) st.emplace_back(e[1],value);
        }

        return ans;
    }
};
相关推荐
luj_176829 分钟前
星火科技助力边远地区防病攻坚
c语言·开发语言·c++·经验分享·算法
木木子222 小时前
# 鸿蒙 ArkTS 实战:秒表 Stopwatch(示例 5)
数据结构·华为·list·harmonyos
geats人山人海3 小时前
数据结构第六章c语言 树的存储下二叉树的概念和存储
c语言·数据结构·算法
漂流瓶jz4 小时前
UVA-12627 奇怪的气球膨胀 题解答案代码 算法竞赛入门经典第二版
算法·图论·递归·aoapc·算法竞赛入门经典·uva·12627
jarvisuni4 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
kobesdu4 小时前
流形上的优化:SO(3)与SE(3)的广义加减法在FAST-LIO中如何简化状态估计
人工智能·算法·fastlio
白狐_7985 小时前
408 数据结构算法题 01:线性表暴力求解保分指南
java·数据结构·算法
乐观勇敢坚强的老彭5 小时前
C++信奥:开关门、开关灯问题
开发语言·c++·算法
冻柠檬飞冰走茶5 小时前
PTA基础编程题目集 7-31 字符串循环左移(C语言实现)
c语言·开发语言·数据结构·算法
Hi李耶5 小时前
【LeetCode】4-寻找两个正序数组的中位数
算法·leetcode·职场和发展