当前位置:首页 > 洛谷 > 洛谷P1323题解:优先队列与单调栈解决删数问题

洛谷P1323题解:优先队列与单调栈解决删数问题

7个月前 (08-06)

洛谷P1323题解:优先队列与单调栈解决删数问题 洛谷题解 优先队列 最小堆 单调栈 贪心算法 第1张

一、题目解读

洛谷P1323题要求生成前k个最小的元素,并通过删除m个数字使剩余序列单调递增。题目需结合生成算法与优化删除策略,考验对数据结构与贪心思想的运用。

二、解题思路

1. 生成最小k数:利用优先队列最小堆)维护当前最小元素。每次取出队首元素,生成其衍生元素(2x+1和4x+5),避免重复后加入队列,直至得到k个元素。

2. 删除m数优化:将生成的数字拼接为字符串,采用单调栈策略。遍历字符时,若末尾数字小于当前数字且可删除次数剩余,则弹出栈顶直至满足条件,最终保留单调递增子序列

三、解题步骤

1. 输入k和m,初始化优先队列pq(最小堆)并加入初始元素1。

2. 循环k次:

    取出队首元素,若与上一元素重复则跳过。

    加入队列的新元素为2x+1和4x+5,确保队列始终维护最小元素。

3. 将生成的k个元素拼接为字符串numStr。

4. 遍历numStr,利用单调栈删除:

    若当前字符大于栈顶且可删除次数>0,弹出栈顶直至不满足条件。

    将当前字符入栈,最终栈中序列即为删除m个数字后的最大单调递增子串。

5. 若剩余删除次数未用完,从末尾截断字符串。

6. 输出原始序列和优化后的结果。

四、代码与注释

#include <iostream>
#include <queue>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

int main() {
    int k, m;
    cin >> k >> m; // 输入k和m
    
    // 优先队列(最小堆)生成k个最小元素
    priority_queue<int, vector<int>, greater<int>> pq;
    vector<int> elements;
    pq.push(1); // 初始元素1
    
    while(elements.size() < k) {
        int current = pq.top(); // 取出最小元素
        pq.pop();
        // 避免重复元素
        if (!elements.empty() && current == elements.back()) {
            continue;
        }
        elements.push_back(current); // 加入有效元素
        // 生成新元素加入队列
        pq.push(2 * current + 1);
        pq.push(4 * current + 5);
    }
    
    // 拼接数字为字符串
    string numStr;
    for (int num : elements) {
        numStr += to_string(num);
    }
    cout << numStr << endl; // 输出原始序列
    
    // 单调栈删除m个数字优化
    string result;
    int remove = m;
    for (char digit : numStr) {
        // 贪心删除:若当前数字比栈顶大且可删除
        while (remove > 0 &&!result.empty() && digit > result.back()) {
            result.pop_back(); // 弹出栈顶
            remove--;
        }
        result.push_back(digit); // 加入当前数字
    }
    // 剩余删除次数从末尾截断
    if (remove > 0) {
        result = result.substr(0, result.size() - remove);
    }
    cout << result << endl; // 输出优化结果
    return 0;
}

五、总结

该解法巧妙结合优先队列与单调栈:前者高效生成有序序列,后者通过贪心策略删除元素确保单调性。代码简洁且逻辑清晰,避免复杂循环,时间复杂度低。解题时需注意重复元素的判断与删除操作的边界处理,是处理此类生成+优化问题的典型范例。

原创内容 转载请注明出处

分享给朋友:

相关文章

力扣1221:一次扫描解决分割平衡字符串 时间O(n)空间O(1)

力扣1221:一次扫描解决分割平衡字符串 时间O(n)空间O(1)

题目重解给定一个仅包含'L'和'R'的字符串,要求将其分割成尽可能多的子串,且每个子串中'L'和'R'的数量相等。例如输入"R...

力扣1700题:无法吃午餐的学生数量 - 队列模拟解法详解

力扣1700题:无法吃午餐的学生数量 - 队列模拟解法详解

内容简介本文详细解析了力扣1700题"无法吃午餐的学生数量"的队列模拟解法。通过模拟学生排队取餐的过程,统计无法吃到喜欢三明治的学生数量。文章包含完整注释代码、算法思路讲解和复杂度...

牛客13271题「删除K个数字的最小数」解题报告:贪心算法与栈的应用(附代码注释)

牛客13271题「删除K个数字的最小数」解题报告:贪心算法与栈的应用(附代码注释)

一、题目解读牛客13271题要求从给定的数字字符串中删除K个数字,使得剩余数字按原顺序排列后得到的最小数。题目核心在于如何在保持数字相对顺序的前提下,通过删除操作得到最优解。需注意结果字符串可能包含前...

力扣3112题解法:带时间限制的最短路径问题解析(C++代码)

力扣3112题解法:带时间限制的最短路径问题解析(C++代码)

一、题目解读力扣3112题要求解决带时间限制的最短路径问题:给定一个有向图,节点具有消失时间,需计算从起点到各节点的最短路径,且路径总时间不能超过节点的消失时间。题目难点在于需在传统最短路径算法(如D...

GESP五级题巧夺大奖解题报告:贪心算法优化与代码实现(洛谷B3872)

GESP五级题巧夺大奖解题报告:贪心算法优化与代码实现(洛谷B3872)

一、题目解读2023年GESP五级题目“巧夺大奖”(洛谷B3872)是一个经典的资源分配问题。题目要求玩家在有限时间内选择多个游戏,每个游戏有截止时间和奖励值,需在截止时间前完成游戏以获得奖励。目标是...

洛谷P2190题解:铁路售票系统车厢计算(差分数组+前缀和优化)

洛谷P2190题解:铁路售票系统车厢计算(差分数组+前缀和优化)

一、题目解读洛谷P2190题要求解决铁路售票系统中的车厢数量计算问题。题目给定n个车站和m条订票申请,每条申请包含区间[x,y)及乘客数z。需要计算在不超载的情况下(每节车厢最多36人),满足所有乘客...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。