题目大意:
给你一个长度为 n n n的序列。让你选出 k k k个数,使得其字典序最小,且 [ 1 , k ] [1,k] [1,k]每个数恰好出现一次。
题目思路:
这题有一个弱化版:https://leetcode-cn.com/problems/remove-k-digits/
如果没有第二个限制,这题就是上面那题。所以可以想象这题也能使用单调栈做。
假设前面已经选了 k k k个数。现在新增一个从未出现过的数 x x x。如果最后一个数比 x x x大并且之后还有这个数,则可以删除这个数,并且保证答案仍然存在。往复这个过程即可.
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pb push_back
#define vi vector<int>
#define vl vector<ll>
const int maxn = 2e5 + 5;
const int mod = 1e9 + 7;
int a[maxn] , bk[maxn] , ok[maxn];
int main()
{
ios::sync_with_stdio(false);
int n , k;
cin >> n >> k;
for (int i = 1 ; i <= n ; i++){
cin >> a[i];
bk[a[i]]++;
}
stack<int> s;
for (int i = 1 ; i <= n ; i++){
if (!ok[a[i]]){
while (s.size() && s.top() > a[i] && bk[s.top()]) {
ok[s.top()] = false;
s.pop();
}
ok[a[i]] = 1;
s.push(a[i]);
}
bk[a[i]]--;
}
vi ans;
while (s.size()) ans.pb(s.top()) , s.pop();
reverse(ans.begin(),ans.end());
for (auto g : ans) cout << g << " ";
cout << endl;
return 0;
}