题意

题意很简单 给定一个序列 其中包括个数 然后找一个他的子序列 要求包含 中的每一个数 每一个数有且仅出现一次

然后找到字典序最小的这个序列

这个题目说实话不难 而且我在上个学期的时候是刷了单调栈和单调队列的专题的 我的第一反应就是这样做的 如果看了我wa的十多发里是有单调栈的影子的 结果主要是还是没学透 白给了

简单来说这个题目就是用单调栈来做 从序列中选最前的一个数出来 如果大于栈顶的数 就压进栈 如果小于就考虑把栈里的数弹出来 但是要注意后面还有没有这个数 如果没有了就不能弹 因为后面就没有机会再压进来了 然后把所有的数都压进来了之后 栈里的数就是要求的序列

为什么这样做 :

因为如果外面的数小于栈里的数(并且在后面还有栈里的数的时候)那么说明栈里的序列不是最小的

应该把现在这个数放在前面 栈里的也就不需要了 反正后面还会压进来

但是如果后面要是没有了 就不能弹出去了 只能卡在这里 然后后面的再去操作

code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll; typedef unsigned long long ull; typedef long double ld;
const ll MOD = 1e9 + 7;

const int N = 2e5 + 7;
const int INF = 0x3f3f3f3f;
int a[N] , last[N];
int ans[N];
bitset<N> b;


int main(void){
    int n , m ;
    scanf("%d%d" , &n , &m);
    for(int i = 1 ; i <= n ; ++i){
        scanf("%d" , &a[i]);
        last[a[i]] = i;
    }
    for(int i = 1 , j = 0 ; i <= n ; ++i){
        if(b[a[i]]) continue;   
        while(ans[j] > a[i] && last[ans[j]] > i){
            b[ans[j--]] = 0;
        }
        ans[++j] = a[i];
        b[a[i]] = 1;
    }
    for(int i = 1 ; i <= m ; ++i){
        printf("%d " , ans[i]);
    }
    return 0;
}