Early Orders
生活随笔
收集整理的這篇文章主要介紹了
Early Orders
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
題意:
給你一個整數(shù)列表 x1,x2,,… ,xn 和一個數(shù)字 k,它保證從1到 k 的每個 i 至少出現(xiàn)在列表中一次。
現(xiàn)在求一個字典序最小的子序列,子序列有1到k組成
題解:
單調(diào)棧求解
我們先預處理,求出每種數(shù)最后出現(xiàn)的位置,用數(shù)組suf存
比如:這10個數(shù):54321411155
suf[1] = 8
suf[2] = 4
suf[3] = 3
suf[4] = 6
suf[5] = 10
我們設(shè)一個棧,每次讀入新的數(shù)據(jù)x(第i位)時與棧頂元素top比較,如果棧頂元素大于x,且suf[top]>i,我們就將棧頂彈出,直到該條件不滿足,或者棧為空,然后將數(shù)據(jù)x存入棧內(nèi)
原因:
如果suf[top]>i,說明在當前x的后面還會有和棧一樣大小的數(shù),而且棧頂大于x,我們?yōu)榱俗屪值湫蚋?#xff0c;就可以用組合x top代替 top x
就比如說:5 4 5,
我們棧頂為5(第一個元素),讀入第二個元素4,4比5小,且4之后還有5(第三個元素),說明可以組成字典序更小的4 5,而不是5 4,所以將5(第一個元素)彈出,將4存入
代碼:
#include<bits/stdc++.h> typedef long long ll; using namespace std; inline int read(){int s=0,w=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);return s*w; }const int maxn=2e5+9; ll a[maxn]; int vis[maxn]; int st[maxn],suf[maxn]; ll n,m; int main(){cin>>n>>m;for(int i=1;i<=n;i++) a[i]=read();int s = 0;for(int i=1;i<=n;i++) suf[a[i]] = i;for(int i=1;i<=n;i++){if(vis[a[i]]) continue;while(s && a[i]<=a[st[s]] && suf[a[st[s]]]>i) //如果棧頂元素大于當前元素,且棧頂元素后面還會出現(xiàn) vis[a[st[s--]]] = 0;//出棧,并標記為空 st[++s] = i;vis[a[i]] = 1;}for(int i=1;i<=m;i++)printf("%lld ",a[st[i]]);printf("\n");return 0; }總結(jié)
以上是生活随笔為你收集整理的Early Orders的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 黑豆苗的功效与作用、禁忌和食用方法
- 下一篇: 奶茶的热量