首页 > 代码库 > 洛谷——P1155 双栈排序

洛谷——P1155 双栈排序

题目描述

Tom最近在研究一个有趣的排序问题。如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序。

技术分享

操作a

如果输入序列不为空,将第一个元素压入栈S1

操作b

如果栈S1不为空,将S1栈顶元素弹出至输出序列

操作c

如果输入序列不为空,将第一个元素压入栈S2

操作d

如果栈S2不为空,将S2栈顶元素弹出至输出序列

如果一个1~n的排列P可以通过一系列操作使得输出序列为1,2,…,(n-1),n,Tom就称P是一个“可双栈排序排列”。例如(1,3,2,4)就是一个“可双栈排序序列”,而(2,3,4,1)不是。下图描述了一个将(1,3,2,4)排序的操作序列:<a,c,c,b,a,d,d,b>

技术分享

当然,这样的操作序列有可能有几个,对于上例(1,3,2,4),<a,c,c,b,a,d,d,b>是另外一个可行的操作序列。Tom希望知道其中字典序最小的操作序列是什么。

输入输出格式

输入格式:

 

输入文件twostack.in的第一行是一个整数n。

第二行有n个用空格隔开的正整数,构成一个1~n的排列。

 

输出格式:

 

输出文件twostack.out共一行,如果输入的排列不是“可双栈排序排列”,输出数字0;否则输出字典序最小的操作序列,每两个操作之间用空格隔开,行尾没有空格。

 

输入输出样例

输入样例#1:
【输入样例1】41 3 2 4【输入样例2】42 3 4 1【输入样例3】32 3 1
输出样例#1:
【输出样例1】a b a a b b a b【输出样例2】0【输出样例3】a c a b b d

说明

30%的数据满足: n<=10

50%的数据满足: n<=50

100%的数据满足: n<=1000

 

如果满足 i<j<k &&num[i]<num[j],num[i]>num[k]就不能单栈排序并考虑双栈

  如果 不是二分图 就不能双栈排序

最后模拟输出  ————我居然在模拟上卡了很长时间!!

  1 #include <algorithm>  2 #include <cstring>  3 #include <cstdio>  4 #include <queue>  5   6 using namespace std;  7   8 const int N(1000+15);  9 int n,num[N],pre,mi[N]; 10  11 int head[N],sumedge; 12 struct Edge 13 { 14     int u,v,next; 15     Edge(int u=0,int v=0,int next=0): 16         u(u),v(v),next(next){} 17 }edge[N<<1]; 18 void ins(int u,int v) 19 { 20     edge[++sumedge]=Edge(u,v,head[u]); 21     head[u]=sumedge; 22 } 23  24 int col[N],st1[N],st2[N],to1,to2; 25 void Paint_(int s) 26 { 27     col[s]=0; 28     queue<int>que; 29     que.push(s); 30     while(!que.empty()) 31     { 32         pre=que.front();que.pop(); 33         for(int i=head[pre];i;i=edge[i].next) 34         { 35             int to=edge[i].v; 36             if(col[to]!=-1) 37             { 38                 if(col[to]==col[pre]) 39                 { 40                     puts("0"); 41                     exit(0); 42                 } 43             } 44             else 45             { 46                 col[to]=col[pre]^1; 47                 que.push(to); 48             } 49         } 50     } 51 } 52  53 int main() 54 { 55     scanf("%d",&n); 56     for(int i=1;i<=n;i++) 57         scanf("%d",num+i); 58     mi[n+1]=1e7; 59     for(int i=n;i>=1;i--) 60         mi[i]=min(mi[i+1],num[i]); 61     for(int i=1;i<n;i++) 62       for(int j=i+1;j<=n;j++) 63           if(num[i]<num[j]&&num[i]>mi[j+1]) 64                  ins(i,j),ins(j,i); 65     memset(col,-1,sizeof(col)); 66     for(int i=1;i<=n;i++) 67         if(col[i]==-1) Paint_(i); 68     int now_min=1; 69     for(int i=1;i<=n;i++) 70     { 71         if(col[i]==0) 72         { 73             if(num[i]==now_min) 74             { 75                 printf("a b "),now_min++; 76                 if(st1[to1]==num[i]) to1--; 77             }                  78             else if(!to1||st1[to1]>num[i]) 79                 st1[++to1]=num[i],printf("a "); 80             for(;to1&&st1[to1]==now_min;) 81                 printf("b "),to1--,now_min++; 82         } 83         else 84         { 85             if(num[i]==now_min) 86             { 87                 printf("c d "),now_min++;     88                 if(st1[to1]==num[i]) to1--; 89             } 90             else if(!to2||st2[to2]>num[i]) 91                 st2[++to2]=num[i],printf("c "); 92             for(;to2&&st2[to2]==now_min;) 93                 printf("d "),to2--,now_min++;    94         } 95     } 96     for(;now_min<=n;now_min++) 97     { 98         for(;st1[to1]==now_min;to1--) printf("b "); 99         for(;st2[to2]==now_min;to2--) printf("d ");100     }101     return 0;102 }

 

洛谷——P1155 双栈排序