Early Orders
题面:
中文题意:
意思是给你个n,k;其中n一定大于等于k。然后输入n行元素,元素范围为1~k,寻找字典序最小且1~k都有的子序列。(子序列未必连续,子串连续)。
思路:
预先统计每个数字最后一次出现的位置,然后往栈中添加元素,如果这个元素添加过了就不用管,如果没用就向里面加,加的时候判断下这个数字是不是比当前栈中最上面的元素小,如果小并且栈顶元素在后面还有那就把栈顶元素移出去,直到上面条件不满足的时候结束,添加当前元素;
代码:
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#include<algorithm>
#include<fstream>
#include<cmath>
#include<map>
using namespace std;
typedef long long ll;
typedef std::pair<int, int> pii;
const int MAXN = 1e5+114514, INF = 0x3f3f3f3f;
int fin[MAXN];
//记录了元素最后出现的位置
int a[MAXN];
int ans[MAXN];
bool flag[MAXN];
int main() {
int n, k;
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i];
fin[a[i]] = i;
}
int beg= 0;
for (int i = 1; i <= n; i++) {
if (flag[a[i]]==0) {
//进行检测
//如果栈顶元素大于当前元素&&栈顶元素在后面还会出现就先弹出栈顶元素
//把当前元素放入
// 尽可能的让小的元素往前放置
while (ans[beg] > a[i] && i < fin[ans[beg]]&&beg) {
flag[ans[beg]] = 0;
//取消标记
beg--;
}
flag[a[i]] = 1;
ans[++beg] = a[i];
//将这个元素放入栈中
}
}
for (int i = 1; i < beg; i++)
cout << ans[i]<<" ";
cout <<ans[beg]<< endl;
}
单调栈问题