题意
题意很简单 给定一个序列 其中包括个数 然后找一个他的子序列 要求包含
中的每一个数 每一个数有且仅出现一次
然后找到字典序最小的这个序列
这个题目说实话不难 而且我在上个学期的时候是刷了单调栈和单调队列的专题的 我的第一反应就是这样做的 如果看了我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;
} 
京公网安备 11010502036488号