性质
若存在k>i>j且a[k]<a[i]<a[j] 则i,j不可被放进同一个栈
充分性、必要性均易证
对这样的i,j连一条无向边,再判断整个图是不是二分图
代码
#include<iostream>
#include<cstdio>
#include<memory.h>
using namespace std;
int n;
bool mark;
int a[1005];
struct edge
{
int to,nxt;
}e[1000005];
int h[1005],tot;
int col[1005];
void add_edge(int x,int y)
{
e[++tot].to=y;
e[tot].nxt=h[x];
h[x]=tot;
}
void dfs(int x)
{
for(int i=h[x];i;i=e[i].nxt)
{
if(col[e[i].to]==-1)
{
col[e[i].to]=col[x]^1;
dfs(e[i].to);
}
else if(col[e[i].to]==col[x]){mark=true;return;}
}
}
int s1[1005],s2[1005],top1,top2;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
{
scanf("%d",&a[i]);
}
int k=a[n];
for(int i=n-1;i>=1;--i)
{
for(int j=i-1;j>=1;--j)
{
if(a[j]<a[i]&&k<a[j])
{
add_edge(i,j),add_edge(j,i);
}
}
k=min(k,a[i]);
}
memset(col,-1,sizeof(col));
for(int i=1;i<=n;++i)
{
if(col[i]==-1)
{
col[i]=0,dfs(i);
if(mark)break;
}
}
if(mark)
{
printf("0\n");
return 0;
}
int num=1;
for(int i=1;i<=n;++i)
{
if(col[i]==0)
{
s1[++top1]=a[i];
printf("a ");
}
else
{
s2[++top2]=a[i];
printf("c ");
}
while(num==s1[top1]||num==s2[top2])
{
if(num==s1[top1])printf("b "),--top1;
else printf("d "),--top2;
++num;
}
}
printf("\n");
return 0;
}