J

题目描述

You are given a sequence of  n  integers  x = [x1,x2,...,xn]  and an integer  k . It is guaranteed that 1 ≤ xi ≤ k , and every integer from 1 to  k  appears in the list  x  at least once. 
Find the lexicographically smallest subsequence of  x  that contains each integer from 1 to  k  exactly once. 

输入

The first line of input contains two integers  n  and  k  ( 1 ≤ k ≤ n ≤ 2 ∙105), where  n  is the size of the sequence, and the sequence consists only of integers from 1 to  k . 
Each of the next  n  lines contains a single integer  xi( 1 ≤ xi ≤ k ). These are the values of the sequence  X  in order. It is guaranteed that every value from 1 to  k  will appear at least once in the sequence  X . 

输出

Output a sequence of integers on a single line, separated by spaces. This is the lexicographically smallest subsequence of X that contains every value from 1 to k. 

样例输入 

【样例1】
6 3 
3 
2 
1 
3 
1 
3 
【样例2】
10 5
5 
4 
3 
2 
1 
4 
1 
1 
5 
5 

样例输出 

【样例1】
2 1 3 
【样例2】
3 2 1 4 5 

描述:
找出一个子序列,使得这个子序列中包含给定序列中的所有字符一次,并且找到的子序列字典序要最小。
思路:
单调栈维护即可
入栈的情况:
1.当前元素比栈顶元素小
2.当前元素是最后一次出现了
弹出栈顶的情况:
1.当前栈顶比所选的元素大并且在后面还会出现

代码:

#include <iostream>

using namespace std;

const int N = 200010;

int a[N];
int n, k;
int stk[N], tt = 0;
int cnt[N];
bool st[N];

int main()
{
    cin >> n >> k;
    for (int i = 0; i < n; i ++ ) 
    {
        cin >> a[i];
        cnt[a[i]] ++ ;
    }
    
    stk[0] = -1;  // 防止越界,当哨兵
    for (int i = 0; i < n; i ++ )
    {
        if (tt == 0)  // 只有第一个元素是这个情况,其余不可能存在栈空
        {
            stk[ ++ tt] = a[i];
            st[a[i]] = true;
            cnt[a[i]] -- ;
            continue;
        }
        
        if ((a[i] < stk[tt] || cnt[a[i]] > 0) && !st[a[i]])  // 只要当前的栈顶元素满足就可以考虑入栈
        {
            while (stk[tt] > a[i] && cnt[stk[tt]] > 0) st[stk[tt -- ]] = false;  // 当前栈顶大于a[i],并且栈顶元素不是最后一个就弹出
            stk[ ++ tt] = a[i];
            st[a[i]] = true;
            cnt[a[i]] -- ;
            continue;  // 以上是插入栈顶的操作,这步continue是为了保证每次cnt[a[i]]只减一次
        }
        
        cnt[a[i]] -- ; // 如果当前的a[i]没有考虑入栈,次数也减1
    }
    
    for (int i = 1; i <= tt; i ++ ) cout << stk[i] << ' ';
    puts("");
    
    return 0;
}
posted on 2021-04-07 15:22  Laurance  阅读(121)  评论(0编辑  收藏  举报