链接
题意:
给定长度为 n n n的数列,保证数列中出现数字大小 1 ≤ a i ≤ k 1\le a_i\le k 1≤ai≤k,要求给出包含 [ 1 , k ] [1,k] [1,k]所有数字(每个只出现一次)的字典序最小子序列。(子序列可以不连续)
思路:
由于要求字典序最小,所以要让序列尽可能的单调递增。采用单调栈维护递增数列。
入栈与出栈原则:
- 在栈中出现过的元素,表示在栈中的这个元素可以作为当前答案,不予以处理,直接continue
- 当前元素比栈顶元素大 ⇒ \Rightarrow ⇒直接加入栈
- 当前元素比栈顶元素小,找到之前所有在后面还会出现,同时大小比当前元素大的元素进行弹栈。
AC代码:
int a[maxn], has[maxn],ed[maxn];
int q[maxn];
int tail, head;
int main()
{
int n, k;
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = n; i > 0; i--) {
if (ed[a[i]] == 0) {
ed[a[i]] = i;
}
}
q[++tail] = a[1];
head++;
has[a[1]] = 1;
for (int i = 2; i <= n; i++) {
if (has[a[i]])continue;
if (a[i] > q[tail]) {
q[++tail] = a[i];
has[a[i]] = 1;
}
if (a[i] < q[tail]) {
while (tail >= head && ed[q[tail]] > i&&a[i] < q[tail]) {
has[q[tail]] = 0;
tail--;
}
q[++tail] = a[i];
has[a[i]] = 1;
}
}
for (int i = head; i <= tail; i++) {
cout << q[i] << " ";
}
cout << endl;
return 0;
}