臨考前攢波rp。
備考複習往年noip題目,做到了這個雙棧排序,網上大部分解法又有什麼推結論啊,動歸最佳化啊,二分圖染色啊特別麻煩。但是cs他路子野啊,題目說什麼他幹什麼,一個dfs解決問題,我就再簡化了下程式,直接一個for迴圈,加一個check()函數解決,代碼量和理解難度瞬間往下降了幾個層次,跟類比差不多了。i,j,k的那個結論還是需要的,網上證明有很多,我也就不再贅述。要提一下的是check()函數裡兩個迴圈都可以預先處理掉,都是求尾碼第一個比它大的值,但還是避不開迴圈,常數級的最佳化吧。
雙棧排序
題目描述 Description
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)排序的操作序列:
#include <iostream>#include <cstdio>using namespace std;int a[1005] ,b[1005] ,f[1005] ,n ,u=1 ,v ,c=2 ,p=1;char ans[2005];bool check(){ if(!v) return 1; int i ,j; for(i = c+1 ;i <= n ;i++) if(f[i] > f[c] && f[i] > b[v]) break; for(j = i ;j <= n ;j++) if(f[j] < f[c]) return 0; return 1;}int main(){ scanf("%d",&n); for(int i = 1 ;i <= n ;i++) scanf("%d",&f[i]); ans[1] = 'a'; a[1] = f[1]; for(int i = 2 ;i <= 2*n ;i++){ if(a[u] == p && u) { u-- ,p++; ans[i] = 'b'; continue; } if(b[v] == p && u && v) { v-- ,p++; ans[i] = 'd'; continue; } if(a[u] > f[c] && check() || !u){ ans[i] = 'a'; a[++u] = f[c++]; continue; } if(b[v] > f[c] || !v){ ans[i] = 'c'; b[++v] = f[c++]; continue; } } if(ans[2*n] == 0){ printf("0"); return 0; } for(int i = 1 ;i <= 2*n ;i++) printf("%c ",ans[i]); return 0;}