当前位置: 首页 > news >正文

牛客NC14893 栈和排序(贪心 + 栈 + 后缀最大值维护)

题目描述

给定一个从 111nnn 的排列 PPP,以及一个空栈。你需要按顺序将排列中的元素依次入栈。在任何时刻,你都可以选择将栈顶元素出栈并将其加入输出序列(前提是栈非空)。入栈顺序不可改变。

你的目标是通过合法的出栈顺序,尽可能使输出序列为一个严格递减序列:n,n−1,...,1n, n-1, ..., 1n,n1,...,1

然而,由于栈的操作限制,这并不总是可能实现。因此,请你输出字典序最大的合法出栈序列。

输入格式

第一行一个整数 nnn,表示排列的大小。(1≤n≤106)(1 \leq n \leq 10^6)(1n106)

第二行 nnn 个两两不同的正整数,表示排列 PPP,是 1∼n1 \sim n1n 的一个排列。

输出格式

输出一行若干个整数,为最终的出栈序列(以空格分隔),结尾不能有多余空格。

输入样例

5
2 1 5 3 4

输出样例

5 4 3 1 2

样例解释

入栈顺序和出栈过程如下:

2 入栈
1 入栈
5 入栈
5 出栈 → 输出 5
3 入栈
4 入栈
4 出栈 → 输出 4
3 出栈 → 输出 3
1 出栈 → 输出 1
2 出栈 → 输出 2

最终得到的合法出栈序列为:5 4 3 1 2,是所有合法出栈方案中字典序最大的。

说明/提示

  • 1≤n≤1061 \leq n \leq 10^61n106

  • 保证输入的排列是 1∼n1 \sim n1n 的一个合法全排列。

提交链接

栈和排序

思路分析

💡 解题思路:贪心

我们不能随意调整入栈顺序(只能按给定排列顺序依次压入),但可以控制什么时候出栈。

要想得到字典序最大的出栈序列,本质上就是要尽量让大的数先出现在结果序列的前面。

因此我们采用如下贪心策略:

🎯 贪心

  1. 维护一个变量 ididid,表示当前还未出现在输出序列中的最大值,初始为 nnn

  2. 遍历输入序列:

    • 如果当前元素等于 ididid,说明它已经是当前剩下元素中最大的,应该立即输出,并将 id−−id--id

    • 否则暂时入栈,等待后续时机。

  3. 输入序列遍历完后,将栈中的元素按栈顶到栈底的顺序依次输出(即后进先出)。

这个策略的关键:尽可能早地把大的数输出,小的数先“藏起来”放在栈中等待

参考代码

#include <bits/stdc++.h>
using namespace std;
int main()
{int n, id;cin >> n;stack<int> s;id = n; // 从n开始出栈,保证字典序最大// n 个数字依次入栈for (int i = 1; i <= n; i++){int x;cin >> x;if (x == id){cout << x << " ";id--;}else{s.push(x);}}while (!s.empty()){cout << s.top() << " ";s.pop();}return 0;
}

💡 解题思路:后缀最大值维护

我们要在遵循栈操作规则的前提下,构造出 字典序最大的出栈序列。

🔍 核心观察

每次只能将栈顶元素输出。

元素必须按输入顺序依次入栈。

想要字典序最大,就应该尽量先输出大的数。

✅ 贪心策略

  1. 从左到右遍历输入序列,维护一个栈:每次将当前元素 P[i]P[i]P[i] 入栈。

  2. 不断检查当前栈顶是否是“可以放心输出”的最大值。即:当前栈顶元素大于或等于后面所有还未入栈的元素。换句话说,如果后面不会再出现比它更大的数,就可以把它输出。

为了快速判断后面是否还有比栈顶更大的数,我们可以提前预处理出每个位置后缀最大值 sufMax[i]

参考代码

#include <bits/stdc++.h>
using namespace std;
int main()
{int n;cin >> n;vector<int>p(n);for(auto &it : p)cin >> it;vector<int>sufmax(n + 1);  //维护i~n-1的最大值for(int i = n - 1; i >= 0; i--){sufmax[i] = max(sufmax[i + 1] , p[i]);}stack<int>sk;for(int i = 0 ; i < n; i++){sk.push(p[i]);while(!sk.empty() && sk.top() > sufmax[i + 1]){cout << sk.top() << " ";sk.pop();}}return 0;
}
http://www.dtcms.com/a/288705.html

相关文章:

  • 【机器学习|学习笔记】详解支持向量机(Support Vector Machine,SVM)为何要引入核函数?为何对缺失数据敏感?
  • 深入解析Hadoop中的EditLog与FsImage持久化设计及Checkpoint机制
  • Hadoop小文件合并技术深度解析:HAR文件归档、存储代价与索引结构
  • LeetCode|Day20|9. 回文数|Python刷题笔记
  • IP协议介绍
  • Linux: rsync+inotify实时同步及rsync+sersync实时同步
  • Leetcode 710. 黑名单中的随机数
  • 使用 Pyecharts 绘制精美饼状图:从基础到高级技巧
  • PDF 编辑器:多文件合并 拆分 旋转 顺序随便调 加水印 密码锁 页码背景
  • 微服务雪崩防护最佳实践之sentinel
  • Java 大视界 -- Java 大数据在智能安防门禁系统中的权限动态管理与安全审计(353)
  • 嵌入式硬件篇---舵机(示波器)
  • 测试学习之——Pytest Day4
  • python中读取 Excel 表格数据
  • 将EXCEL或者CSV转换为键值对形式的Markdown文件
  • 推荐一款基于.NET的进程间通信框架
  • 【橘子分布式】gRPC(编程篇-下)
  • 基于SHAP的特征重要性排序与分布式影响力可视化分析
  • ZooKeeper学习专栏(一):分布式协调的核心基石
  • 28.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--单体转微服务--币种服务(二)
  • 智能驾驶整体技术架构详解
  • OPC UA, CAN, PROFINET, SOCKET, MODBUS, HTTP, S7七种物联网常用协议解释
  • Shell脚本-tee工具
  • 《计算机网络》实验报告三 UDP协议分析
  • DAY 20 奇异值分解(SVD)
  • 【Elasticsearch】冷热集群架构
  • 【数据结构】二维差分数组
  • 【milvus检索】milvus检索召回率
  • `TransportService` 是 **Elasticsearch 传输层的“中枢路由器”**
  • java-chains 是 Vulhub 团队开发的一款专注于 Java 反序列化漏洞利用链(Gadget Chains) 的安全测试工具