大江东去,浪淘尽,千古风流人物。故垒西边,人道是,三国周郎赤壁。乱石穿空,惊涛拍岸,卷起千堆雪。江山如画,一时多少豪杰。遥想公瑾当年,小乔初嫁了,雄姿英发。羽扇纶巾,谈笑间,樯橹灰飞烟灭。故国神游,多情应笑我,早生华发。人生如梦,一尊还酹江月。

【noip2008】双栈排序

参考神仙的博客

以下是我对正确性的一些解释

由于元素按顺序进栈,所以我们要保证在前面的字典序尽可能小,所以优先让先进栈的进栈1,进不了栈1才进栈2,故两个栈中的元素是唯一确定的

  1. 由于我们需要按一定顺序入栈,故入栈顺序显然是一定的,即a,c相对顺序一定
  2. 由于我们对元素进行了排序,故出栈的相对顺序是一定的,即b,d相对顺序一定
  3. 根据yxc老师的证明,如果只有一个栈,那么进出栈顺序是一定的,即a,b相对顺序和c,d相对顺序一定

但是b,c的相对顺序和a,d的相对顺序是不确定的

b,c对应出栈1,入栈2,由于我们在代码中能出栈就出栈,所以字典序是正确的

a,d对应入栈1,出栈2,由于我们在代码中能出栈就出栈,所以会输出d,a,而实际上a,d是更优的

所以我们只需要在不改变上述确定的相对顺序的前提下交换d,a即可,即交换所有相邻的d,a

代码如下,欢迎hack

#include<bits/stdc++.h>
using namespace std;

#define go(i,a,b) for(int i=a;i<=b;++i)
#define com(i,a,b) for(int i=a;i>=b;--i)
#define mem(a,b) memset(a,b,sizeof(a))
#define fo(i,a) for(int i=0;i<a;++i)
#define il inline

const int inf=0x3f3f3f3f,N=1010;

int n,a[N],suf[N],co[N],tot;
bool g[N][N];
char ans[N*2];

bool dfs(int u,int c){
	co[u]=c;
	go(i,1,n){
		if(!g[u][i]) continue;
		if(co[i]==c) return 0;
		if(!co[i]&&!dfs(i,3-c)) return 0;
	}
	return 1;
}

void solve(){
	stack<int>s1,s2;
	int now=1;
	go(i,1,n){
		if(co[i]==1){
			s1.push(a[i]);
			ans[++tot]='a';
		}
		else{
			s2.push(a[i]);
			ans[++tot]='c';
		}
		while(1){
			if(!s1.empty()&&s1.top()==now) s1.pop(),ans[++tot]='b',++now;
			else if(!s2.empty()&&s2.top()==now) s2.pop(),ans[++tot]='d',++now;
			else break;
		}
	}
	go(i,1,tot)
		if(ans[i]=='a'&&ans[i-1]=='d')
			swap(ans[i],ans[i-1]);
}

int main(){
	//freopen("input.txt","r",stdin);
	cin>>n;
	go(i,1,n) scanf("%d",a+i);
	suf[n+1]=inf;
	com(i,n,1) suf[i]=min(suf[i+1],a[i]);
	go(i,1,n)
		go(j,i+1,n){
			if(a[i]<a[j]&&suf[j+1]<a[i]) g[i][j]=g[j][i]=1;
		}
	go(i,1,n){
		if(!co[i]&&!dfs(i,1)){
			puts("0");
			return 0;
		}
	}
	solve();
	go(i,1,tot) printf("%c ",ans[i]);
	return 0;
}
posted @ 2019-11-07 17:08  White_star  阅读(177)  评论(0编辑  收藏  举报
}