51nod 1255 字典序最小的子序列
单调栈问题
遍历一遍字符串,如果s[i]小于栈中的元素并且这个栈顶元素后面还有就将栈顶元素弹出。入栈就将元素标记,如果已经标记过后面遇到vis[s[i]]=1的就continue,因为如果这个时候s[i]元素已经在栈内,说明此时的栈首一定是大于等于s[i]的因为栈顶元素小于s[i],我们在遍历到栈顶元素的时候就会将栈中的s[i]弹出,所以此时的s[i]一定是大于栈首的。
#include<bits/stdc++.h> #define fp(i,a,b) for(int i=a;i<=b;i++) typedef long long ll; typedef double dl; using namespace std; const int N=1e5+7; const ll M=1e9+7; const int INF=0x3f3f3f3f; int n,m; stack<char> st; char s[N]; map<char,int> mp; int vis[N]; void solve() { scanf("%s",s+1); n=strlen(s+1); //cout<<n<<endl; for(int i=1;i<=n;i++) mp[s[i]]++; for(int i=1;i<=n;i++) { mp[s[i]]--; if(vis[s[i]]) continue; while(!st.empty()&&(st.top()>s[i])&&mp[st.top()]) { vis[st.top()]=0; //printf("pop:%c\n",st.top()); st.pop(); } st.push(s[i]); vis[s[i]]=1; } char x[N]; int cnt=st.size(); int cnt1=cnt; while(!st.empty()) { //printf("%c",st.top()); x[cnt1--]=st.top(); st.pop(); } for(int i=1;i<=cnt;i++) { printf("%c",x[i]); } } int main() { //ios::sync_with_stdio(0); //cin.tie(0),cout.tie(0); //int T; scanf("%d",&T) //for(int i=1;i<=T;i++) solve(); }