传送门
解析:
首先需要知道单栈排序的结论:
一个序列如果存在
i
<
j
<
k
i<j<k
i<j<k且
a
k
<
a
i
<
a
j
a_k<a_i<a_j
ak<ai<aj,肯定无法完成单栈排序。
证明十分显然,我们需要将 k k k排序,要先将 i , j i,j i,j压入栈中,然而压入了 j j j之后就无法把 i i i从栈里面弹出来了,所以肯定gg。
而判断可以采用预处理后缀最大值的方式来把复杂度降为 O ( n 2 ) O(n^2) O(n2)。
那么不能单栈排序的考虑怎么双栈排序。
首先所有有上面这个情况的数对 a i , a j a_i,a_j ai,aj不能放在一个栈中排序,反之一定可以。所以可以采用二分图染色的方式判断。
为了使字典序最小,我们将先染的颜色尽可能放在第一个栈中,之后能弹栈时尽量弹就行了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline int getint(){
re int num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
return num;
}
cs int N=1003;
vector<int> e[N];
int col[N];
inline void dye(int u){
for(int re i=0;i<e[u].size();++i){
int re v=e[u][i];
if(!~col[v]){
col[v]=col[u]^1;
dye(v);
}
else if(col[v]!=(col[u]^1))cout<<0,exit(0);
}
}
stack<int> s1,s2;
int n,now;
int a[N],minn[N];
signed main(){
memset(col,-1,sizeof col);
n=getint();
for(int re i=1;i<=n;++i)a[i]=getint();
minn[n+1]=0x3f3f3f3f;
for(int re i=n;i;--i)minn[i]=min(a[i],minn[i+1]);
for(int re i=1;i<=n;++i){
for(int re j=i+1;j<=n;++j){
if(a[i]<a[j]&&a[i]>minn[j+1]){
e[i].push_back(j);
e[j].push_back(i);
}
}
}
now=1;
for(int re i=1;i<=n;++i)if(!~col[i])col[i]=1,dye(i);
for(int re i=1;i<=n;++i){
if(col[i])s1.push(a[i]),pc('a');
else s2.push(a[i]),pc('c');
pc(' ');
while(true){
if((s1.empty()||s1.top()!=now)&&(s2.empty()||s2.top()!=now))break;
if(!s1.empty()&&s1.top()==now)pc('b'),s1.pop();
else pc('d'),s2.pop();
pc(' ');
++now;
}
}
return 0;
}