双栈排序
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 const int maxn=1007; 5 const int INF=2147483647; 6 int a[maxn],imin[maxn],col[maxn],n,num; 7 int stk1[maxn],stk2[maxn],top1,top2,head[maxn]; 8 struct Edge{ 9 int next,to; 10 }edge[maxn*maxn*10]; 11 void add(int from,int to){ 12 edge[++num].next=head[from]; 13 edge[num].to=to; 14 head[from]=num; 15 } 16 bool dfs(int x){ 17 for(int i=head[x];i;i=edge[i].next){ 18 int v=edge[i].to; 19 if(!col[v]){ 20 col[v]=col[x]^1; 21 if(!dfs(v)) return false; 22 } 23 else if(col[v]==col[x]) return false; 24 } 25 return true; 26 } 27 int main(){ 28 cin>>n; 29 for(int i=1;i<=n;i++) cin>>a[i];imin[n+1]=INF; 30 for(int i=n;i>=1;i--) imin[i]=min(imin[i+1],a[i]); 31 for(int i=1;i<=n;i++){ 32 for(int j=i+1;j<=n;j++){ 33 if(a[i]<a[j]&&a[i]>imin[j+1]){ 34 add(i,j);add(j,i); 35 } 36 } 37 } 38 for(int i=1;i<=n;i++){ 39 if(!col[i]){ 40 col[i]=2; 41 if(!dfs(i)) {cout<<0<<endl;return 0;} 42 } 43 } 44 int cnt=1; 45 for(int i=1;i<=n;i++){ 46 if(col[i]==2) {stk1[++top1]=a[i];cout<<"a ";} 47 else {stk2[++top2]=a[i];cout<<"c ";} 48 while(top1&&stk1[top1]==cnt||top2&&stk2[top2]==cnt){ 49 if(stk1[top1]==cnt){cout<<"b ";top1--;} 50 else {cout<<"d ";top2--;} 51 ++cnt; 52 } 53 } 54 return 0; 55 }
来自five20
本题二分图染色+栈模拟。
若我们知道每个数应该放在哪个栈中,就可以去模拟了。
考虑数ai,aj,ak不能在同一栈的情况,若i<j<k,ai<aj,ai>aki<j<k,ai<aj,ai>ak那么i,ki,k是肯定不能在同一栈内的,我们对二元组建边,那么就是个二分图染色的模型了。
由于要字典序最小,所以每次染色时另当前未被染色的位置为栈1再去dfs,染色后每个位置所在的栈就确定了。
然后就是纯模拟咯。
(安利一个神奇的调试技巧:用iostream库下的cerr代替cout,在评测机测试时会直接跳过这条输出语句,但在终端可以输出,这样就能防止忘记删调试语句而写挂!>.^_^.<)