首页 > 其他 > 详细

E : Early Orders 题解

时间:2021-03-13 00:11:13      阅读:34      评论:0      收藏:0      [点我收藏+]

题意:

给定n和k,输入一段长为n的数字序列,选取一个子序列,该子序列中仅有数字1~k且正好出现一次,最后找到字典序最小的那个。


思路:

模拟样例我们发现该序列需要尽可能的把小的数字放在前面,可以用单调栈来模拟解决。先把第一个数扔进栈里面,之后的数如果小于栈顶元素,那就可以考虑能不能把这个栈顶元素扔掉了,扔掉的前提是栈顶元素在后续有出现。

维护好这个单调栈后,就可以看一下能否把当前这个元素进栈,这个需要判断元素在栈中是否出现过,栈里已经有了该元素就不用让他进栈了。

(其他细节在代码中实现)

 

代码:

#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;
int n,k,m;
int a[200005];
int b[200004];
int in[200004];
int ans[200004];
stack<int>st;
int main()
{
    cin >> n >> m;
    for(int i = 0; i < n; i++){
        cin >> a[i];
        b[a[i]] ++;
    }
    for(int i = 0; i < n; i++){
        b[a[i]]--;
        if(i == 0){
            st.push(a[i]);
            in[a[i]] = 1;
        }
        else{
            while(!st.empty() && st.top() > a[i] && in[a[i]] == 0 && b[st.top()] > 0){
                in[st.top()] = 0;
                st.pop();
            } 
            if(in[a[i]] == 0){
                st.push(a[i]);
                in[a[i]] = 1;
            }
        }
    }
    int t = 0;
    while(!st.empty()) {
        ans[t++] = st.top();
        st.pop();
    }
    for(int i = t - 1; i >= 0; i--){
        cout << ans[i] << " ";
    }
}

 

E : Early Orders 题解

原文:https://www.cnblogs.com/sizhen/p/14526438.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!