题意:传送门
题解:首先考虑样例怎么做
1
,
3
,
2
,
4
1, 3, 2, 4
1,3,2,4,先把
1
1
1压入栈
1
1
1,然后弹出,接着把
3
3
3压进去,把
2
2
2再压进去,把
2
2
2弹出来,把
3
3
3弹出来,再把
4
4
4压进去,这样利用一个栈就可以实现,并且是字典序最小,那么何时需要两个栈呢?再随便搞组样例试试,
2
2
2,
3
3
3,
1
1
1,发现什么啦,发现
1
1
1弹出后,这个
2
2
2按理说要比
3
3
3先弹出来,但是被卡住了,所以在需要来个栈帮忙下,这其实是一个性质,就是一个序列中,两个位置(比如
i
i
i与
j
j
j)要是能放入一个栈操作的话,必然不能满足
a
[
k
]
<
a
[
i
]
<
a
[
j
]
,
i
<
j
<
k
a[k]<a[i]<a[j],i<j<k
a[k]<a[i]<a[j],i<j<k,这也是个充分必要条件,这样必然会卡住前面的数出不来,所以可以将这样的数通过二分图连接起来,白色的用一个栈,黑色用用一个栈,如果不满足二分图,说明可能要用超过
2
2
2个栈,那样输出
0
0
0即可, 接着考虑如何字典序最小,栈一操作最小,可以将二分图先染为白色,然后再染为黑色,白色的就用
1
1
1栈,黑色的用
2
2
2栈,然后就用栈模拟输出就完全可以了。
c
o
d
e
:
code:
code:
#include<bits/stdc++.h>
using namespace std;
const int N=1000+10;
int T,n,a[N],f[N],g[N][N],color[N];
stack<int>stk1,stk2;
bool dfs(int u,int c)
{
color[u]=c;
for(int i=1;i<=n;i++){
if(g[u][i]){
if(color[i]==c)return false;
if(color[i]==-1&&!dfs(i,!c))return false;
}
}
return true;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
f[n+1]=N;
for(int i=n;i>=1;i--)f[i]=min(f[i+1],a[i]);
memset(g,false,sizeof g);
for(int i=1;i<n;i++){
for(int j=i+1;j<=n;j++){
if(a[i]<a[j]&&f[j+1]<a[i])g[i][j]=g[j][i]=true;
}
}
memset(color,-1,sizeof color);
bool flag=true;
for(int i=1;i<=n;i++){
if(color[i]==-1&&!dfs(i,0))flag=false;
}
if(!flag){
cout<<0<<endl;
}else{
int now=1;
for(int i=1;i<=n;i++){
if(color[i]==0){
stk1.push(a[i]);
cout<<"a"<<" ";
}else{
stk2.push(a[i]);
cout<<"c"<<" ";
}
while(233){
if(stk1.size()&&stk1.top()==now){
stk1.pop();
cout<<"b"<<" ";
now++;
}else if(stk2.size()&&stk2.top()==now){
stk2.pop();
cout<<"d"<<" ";
now++;
}else{
break;
}
}
}
cout<<endl;
}
return 0;
}