daimayuan 608. 字典序最小

题意:

在长为n的数组中选一个字典序最小的子序列,要求这个子序列是 1~m 的排列。

保证答案存在。这字典序就是整数的字典序,不必按位考虑或者变成字符串之类的

\(1\le m \le n\le 1e6, 1\le a_i \le m\)

思路:

开一个单调栈,里面存的恰是 \(a_1\sim a_i\) 的答案。

对每个 \(a_i\),若整数 \(a_i\) 已在栈中就啥也不干,否则出栈比 \(a_i\) 小的数。注意要记录一下每个数出现的最后位置,若栈顶是该数的最后一个则不能出栈。

const signed N = 1e6 + 3;
int n, m, a[N], last[N];
int stk[N], tt; bool vis[N];

signed main() {
    iofast;
    cin >> n >> m;
    for(int i = 1; i <= n; i++) cin >> a[i], last[a[i]] = i;

    for(int i = 1; i <= n; i++) {
        if(vis[a[i]]) continue;
        while(tt && stk[tt] > a[i] && last[stk[tt]] > i)
            vis[stk[tt]] = 0, tt--;
        stk[++tt] = a[i], vis[a[i]] = 1;
    }

    for(int i = 1; i <= m; i++)//这题最后不能有空格
        cout << stk[i] << " \n"[i==m];
}

posted @ 2022-03-22 23:31  Bellala  阅读(143)  评论(0)    收藏  举报