描述
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希望知道其中字典序最小的操作序列是什么。
格式
輸入格式
第一行是一個整數n。
第二行有n個用空格隔開的正整數,構成一個1~n的排列。
輸出格式
輸出文件共一行,如果輸入的排列不是“可雙棧排序排列”,輸出數字0;
否則輸出字典序最小的操作序列,每兩個操作之間用空格隔開,行尾沒有空格。
數據范圍
30%的數據滿足: n<=10
50%的數據滿足: n<=50
100%的數據滿足: n<=1000
------------------------------------------------------------------------
正解=圖匹配Orz。。
先考慮單棧排序
顯然這是個由下到上的遞減棧。
能單棧排序的情況: 不存在 (i<j<k 且 v[k]<v[i]<v[j])時即可進行排序
必要性 :
當 j 要進棧時,i 必須出棧,但 k 又必須在 i 前出棧,顯然不可以- =
充分性:
當 i<j<k 時除上述情況還有
A : 當 v[i]>v[j] 時
i ,j可以同時在棧中,無論v[k]的值如何,都能進行排序(顯然)
B: 當 v[i]<v[j]<v[k ]時
也顯然可以排序- =
C:當 v[i]<v[k]<v[j]時
好像也顯然可以排序- =
所以顯然除 (i<j<k 且 v[k]<v[i]<v[j])都可進行排序 - =
其實也可以像ak大神(Orz)一樣,拿1 2 3舉例證明,雖不怎么全面,但很好理解。
考慮完單棧回到雙棧排序
就像歸並一樣,兩個都能排序,那合起來也能排序。
如果存在(i<j<k 且 v[k]<v[i]<v[j]))時i , j ,就不能在同一棧里。
預處理i ,j (i<j)如果存在上述情況,那他們就必然不在同一個棧里,在i,j間連一條線
做一遍染色即可,出現非法情況(同一點染上不同顏色)就無解。
讓完后做一個簡單的字典序最小進棧出棧操作,記下當前要出棧的數,然后依題意搞之即可(令人蛋疼- =)。
代碼如下:

1 #include<cstring> 2 #include<algorithm> 3 #include<cstdio> 4 #include<string> 5 #include<iostream> 6 #include<queue> 7 #include<stack> 8 #define INF 99999999 9 #define LL long long 10 using namespace std; 11 int col[1001],next[10010],last[10010],s[10010],T,n,v[1001],K[1001],ans[3000]; 12 stack<int> q[3]; 13 void addedge(int x,int y){ 14 next[++T]=last[x]; last[x]=T; s[T]=y; 15 next[++T]=last[y]; last[y]=T; s[T]=x; 16 } 17 void DFS(int now,int c){ 18 if(!col[now]) col[now]=c; 19 else if(col[now]!=c){ 20 printf("0"); 21 exit(0); 22 } else return ; 23 for(int i=last[now];i;i=next[i]) DFS(s[i],3-c); 24 } 25 int main(){ 26 scanf("%d",&n); 27 for(int i=1;i<=n;i++) scanf("%d",&v[i]); 28 K[n]=v[n]; 29 for(int i=n-1;i;i--) K[i]=min(K[i+1],v[i]); 30 for(int i=1;i<=n;i++) 31 for(int j=i+1;j<n;j++) 32 if(K[j+1]<v[i]&&v[j]>v[i]) 33 addedge(i,j); 34 for(int i=1;i<=n;i++) if(!col[i]) DFS(i,1); 35 int now=1; 36 int T=1; 37 while(1){ 38 if(now>n) break; 39 if(col[T]==1&&(q[1].empty()||q[1].top()>v[T])){ 40 q[1].push(v[T]); 41 ++T; 42 printf("a "); 43 continue ; 44 } 45 if(!q[1].empty()&&q[1].top()==now) { 46 printf("b "); 47 q[1].pop(); 48 ++now; 49 continue ; 50 } 51 if(col[T]==2&&(q[2].empty()||q[2].top()>v[T])){ 52 q[2].push(v[T]); 53 ++T; 54 printf("c "); 55 continue ; 56 } 57 if(!q[2].empty()&&q[2].top()==now) { 58 printf("d "); 59 q[2].pop(); 60 ++now; 61 continue ; 62 } 63 } 64 }