NOIP2008提高組 雙棧排序

2021-08-29 02:54:26 字數 2070 閱讀 1815

noip2008提高組試題4。

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,2,3,4)就是乙個「可雙棧排序排列」,而(2,3,4,1)不是。下圖描述了乙個將(1,3,2,4)排序的操作序列:

當然,這樣的操作序列有可能多個,對於上例(1,2,3,4),是另外乙個可行的操作序列。tom 希望知道其中字典序最小的操作序列是什麼。

輸入兩行:

第一行是乙個整數 n 。 

第二行有 n 個用空格隔開的正整數,構成乙個 1~n 的排列。

輸出一行,如果輸入的排列不是「可雙棧排序排列」,輸出數字 0;否則輸出字典最小的操作序列,每個操作之間用空格隔開,行尾沒有空格。

輸入

4

1 3 2 4

輸出

a b a a b b a b
輸入

4

2 3 4 1

輸出

0
輸入

3

2 3 1

輸出

a c a b b d
【資料範圍】 

30% 的資料滿足:n<=10 

50% 的資料滿足:n<=50 

100% 的資料滿足:n<=1000

解析:就算知道是二分圖染色還是不會tt。

首先考慮怎麼判斷是否有解。

a [ i ] 和 a [ j ] 不能壓入同乙個棧(在同乙個棧中出現過)⇔ 存在乙個k,使得 i < j < k 且 a [ k ] < a [ i ] < a [ j ]

嚴格證明就比較複雜了,我就說如何感性理解吧(反正在考場上也沒幾個人會去嚴格證明)。

因為乙個數只能進出一次,k 要排在前面所以彈出 k 時 i 和 j 都在棧裡,如果兩者在同乙個棧彈出後順序就錯誤了,然後找不到除這種情況外的反例,於是就這樣了。。。

所以如果輸入資料不能使得所有限制成立則無解,然後就可以轉化成二分圖染色來判定,不能在同乙個棧中就連邊。

關於輸出答案,因為要讓字典序最小肯定是盡量加在s1裡面,實在不行加進s2。

**:

#include using namespace std;

const int max=1010;

int n,m=1,size,tot1,tot2,p1[max],p2[max];

int first[max],f[max],num[max],vis[max];

struct shuedge[max*max];

inline int get_int()

inline void build(int x,int y)

inline void pre()

inline bool dfs(int p,int color)

return 1;

}int main()

for(int i=1;i<=n;i++) }

return 0;

}

NOIP2008 雙棧排序

link 考慮什麼時候 i,j i,j i,j 可以被放到同乙個棧裡面 我們只需要考慮如果我們把 i,j i,j i,j 放一起後面會不會出現矛盾 假設有 i j i j k,觀察每一種排列,只有當 a k a kak 的時候,是會出現問題的,我們不能構造一種方案滿足這個條件 所以我們通過計算字尾最...

noip 2008 雙棧排序

題目大意 給定n和一串數字,這串數字是乙個1 n的排列。現在要用兩個棧給這些數字排序。首先先判斷是否有解,有解的話再輸出字典序最小的方案 入棧1,輸出a,出棧1,輸出b 入棧2,輸出c,出棧2,輸出d 分析 首先必然要先考慮是否有解。對於沒有解的情況,必然是當到了某乙個數x0時,棧1,棧2隊首元素都...

noip 2008 雙棧排序

題目大意 給定n和一串數字,這串數字是乙個1 n的排列。現在要用兩個棧給這些數字排序。首先先判斷是否有解,有解的話再輸出字典序最小的方案 入棧1,輸出a,出棧1,輸出b 入棧2,輸出c,出棧2,輸出d 分析 首先必然要先考慮是否有解。對於沒有解的情況,必然是當到了某乙個數x0時,棧1,棧2隊首元素都...