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隊首元素都...