其他分享
首页 > 其他分享> > P1155 [NOIP2008 提高组] 双栈排序

P1155 [NOIP2008 提高组] 双栈排序

作者:互联网

考虑只有一个栈的话。对于三个数字

\[i<j<k,a_k<a_i<a_j \]

那么进行栈排序的话,需要i比j先出栈,k比i,j先出栈,这就产生矛盾了。需要在增加一个栈来了。
显然i,j不能在同一个栈进行排序。所以要分开
我们对于这种情况,在i,j之间连边。跑二分图染色,染色失败则无解.

这题还要求输出字典序最小的操作,push操作的优先级更高,只到栈不合法的时候才pop,就是栈顶到栈底不再单调递增的时候就是非法,要pop。再向第二个栈push的时候,我们要判断第一个栈能不能pop,这样字典序更小.最后按顺序模拟出栈

const int N = 1e3 + 79;
int n, a[N], color[N];

std::stack<int>s[2];
int pos(1);

struct graph {
	int head[N], tot = 1, next[N << 1], ver[N << 1];
	inline void add(int a, int b) {
		ver[++tot] = b;
		next[tot] = head[a];
		head[a] = tot;
	}
} G;
int smin[N];
int q[N];


inline bool Pop(int id) {
	if(s[id].size() && s[id].top() == pos) {
		putchar(id ? 'd' : 'b');
		s[id].pop();
		putchar(' ');
		++pos;
		return true;
	}
	return false;
}

inline void Push(int x, int id) {
	if(id == 1) {
		while(Pop(0));
	}
	while(s[id].size() && s[id].top() < x) {
		if(!Pop(id)) {
			Pop(id ^ 1);
		}
	}
	if(id == 1) {
		while(Pop(0));
	}
	s[id].push(x);
	putchar(id ? 'c' : 'a');
	putchar(' ');
}



int main() {

	read(n);
	rep(i, 1, n) {
		read(a[i]);
	}
	smin[n + 1] = n + 1;
	drp(i, n, 1) {
		smin[i] = min(smin[i + 1], a[i]);
	}
	memset(color, 0xff, sizeof color);
	rep(i, 1, n) {
		rep(j, i + 1, n) {
			if(smin[j + 1] < a[i] && a[i] < a[j]) {
				G.add(i, j);
				G.add(j, i);
			}
		}
	}

	rep(i, 1, n) {
		if(!~color[i]) {
			q[q[0] = 1] = i;
			color[i] = 0;
			rep(kkk, 1, q[0]) {
				int x = q[kkk];
				repg(x) {
					int y(G.ver[i]);
					if(~color[y] && color[y] != (color[x] ^ 1)) {
						puts("0");
						return 0;
					}
					if(!~color[y]) {
						q[++q[0]] = y;
						color[y] = color[x] ^ 1;

					}
				}
			}
		}
	}
	rep(i, 1, n) {
		Push(a[i], color[i]);
	}


	while(s[0].size() || s[1].size()) {
		Pop(0);
		Pop(1);
	}
	return 0;
}

标签:先出,int,NOIP2008,pop,双栈,push,P1155,排序,字典
来源: https://www.cnblogs.com/QQ2519/p/15473224.html