分析:
发现如果i<j<k&&a[i]<a[j]&&a[i]>a[k],a[i]和a[j]就不能在一个栈中。
因为a[i]<a[j],所以a[j]不能去a[i]的栈里,并且a[i]不能弹出,因为a[k]还在。
这种关系可以用并查集维护,当然用二分图染色也可以。
若a[i],a[j]不能在一个栈,那在i和j间连一条边。
这张图如果是二分图,则有解。
输出解时直接模拟即可。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
int n,a[1005],f[1005],ecnt,head[1005],col[1005];
int stk1[1005],stk2[1005],top1,top2;
struct Edge{
int to,nxt;
}e[1000005];
inline void add_edge(int bg,int ed){
ecnt++;
e[ecnt].to=ed;
e[ecnt].nxt=head[bg];
head[bg]=ecnt;
}
void dfs(int x,int c){
col[x]=c;
for(int i=head[x];i;i=e[i].nxt){
int ver=e[i].to;
if(col[ver]==-1) dfs(ver,c^1);
else if(col[ver]==(c^1)) continue;
else{
printf("0\n");
exit(0);
}
}
}
int main(){
memset(col,-1,sizeof col);
scanf("%d",&n);f[n+1]=1e9;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=n;i;i--) f[i]=min(f[i+1],a[i]);
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++){
if(a[i]>=a[j]) continue;
if(a[i]<=f[j+1]) continue;
add_edge(i,j);add_edge(j,i);
}
for(int i=1;i<=n;i++)
if(col[i]==-1) dfs(i,0);
int now=0;
for(int i=1;i<=n;i++){
if(col[i]==0){
stk1[++top1]=a[i];printf("a ");
}
else{
stk2[++top2]=a[i];printf("c ");
}
while(stk1[top1]==now+1||stk2[top2]==now+1){
if(stk1[top1]==now+1){
top1--;printf("b ");
}
else{
top2--;printf("d ");
}
now++;
}
}
return 0;
}