通过观察可以发现,直接考虑双栈比较困难,考虑单栈的情况;
不难发现,如果当序列中出现A小于B,A大于C(A在B前面,B在C前面),A和B就不能在同一个栈里;
这样,我们就有了一堆在与不在同一个集合的关系;我们可以通过二分图染色或带偏移量的并查集;
这样我们可以预处理出每一个A的最后一个C,然后和其中的每一个B都连一条边;跑一个二分图染色,优先把点放入0号集合;无解,输出0;有解,我们已经知道方案了,直接模拟一波就好;from
标程:
#include<bits/stdc++.h>
using namespace std;
const int N=1002;
struct node{
int to,ne;
}e[N];
int vis[N],h[N],col[N],st1[N],st2[N],cur,i,j,b[N],a[N],tot,n,cnt1,cnt2;
inline char gc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline int read(){
int x=0,fl=1;char ch=gc();
for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
for (;48<=ch&&ch<=57;ch=gc())x=(x<<3)+(x<<1)+(ch^48);
return x*fl;
}
void add(int x,int y){
e[++tot]=(node){y,h[x]};
h[x]=tot;
}
bool dfs(int u){
vis[u]=1;
for (int i=h[u],v;i;i=e[i].ne)
if (!vis[v=e[i].to]){
col[v]=col[u]^1;
if (!dfs(v)) return 0;
}
else if (col[v]==col[u]) return 0;
return 1;
}
int main(){
n=read();
for (i=1;i<=n;i++) a[i]=read();
for (i=1;i<=n;i++)
for (j=n;j>i;j--)
if (a[j]<a[i]){
b[i]=j;
break;
}
for (i=1;i<=n;i++)
for (j=i+1;j<b[i];j++)
if (a[i]<a[j]) add(i,j),add(j,i);
for (i=1;i<=n;i++)
if (!vis[i])
if (!dfs(i)){
putchar('0');
return 0;
}
cur=1;
for (i=1;i<=n;i++){
if (!col[i]) printf("a "),st1[++cnt1]=a[i];
else printf("c "),st2[++cnt2]=a[i];
while (st1[cnt1]==cur || st2[cnt2]==cur){
if (st1[cnt1]==cur) printf("b "),cnt1--;
else printf("d "),cnt2--;
cur++;
}
}
while (st1[cnt1]==cur || st2[cnt2]==cur){
if (st1[cnt1]==cur) printf("b "),cnt1--;
else printf("d "),cnt2--;
cur++;
}
}