洛谷 P1155 【NOIP2008】双栈排序

题目链接

题解

这题有点神啊。。
我们仔细观察一下,发现两个栈内元素必须为降序
那么有结论 如果有\(i < j < k\)\(a[k] < a[i] < a[j]\)\(i\)\(j\)不能存在于同一个栈
证明:
因为栈内元素必须降序,
那么加入\(a[j]\)时一定弹出了\(a[i]\),而又因为从小到大排序,
所以\(a[k]\)应该在\(a[i]\)前弹出,故结论正确。
证毕!

因为是两个栈

那么我们可以搞一个二分图染色

最后贪心模拟一遍

Code

#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
int a[N], s1[N], s2[N], Min[N], t1, t2, ans[N<<1], len, n;
bool G[N][N], vis[N];
int z[N];
void dfs(int x, int c) {
	vis[x] = 1; z[x] = c;
	for (int i = 1; i <= n; i++) {
		if (!G[x][i]) continue;
		if (!vis[i])
			dfs(i, c^1);
		else if (c == z[i]) {
			printf("0\n");
			exit(0);
		}
	}
	return ;
}
int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
	Min[n+1] = 2147483647;
	for (int i = n; i >= 1; i--)
		Min[i] = min(Min[i+1], a[i]);
	for (int i = 1; i < n; i++)
		for (int j = i+1; j <= n; j++)
			if (Min[j+1] < a[i] && a[i] < a[j])
				G[i][j] = G[j][i] = 1;
	for (int i = 1; i <= n; i++)
		if (!vis[i])
			dfs(i, 0);
	int now = 1;
	for (int i = 1; i <= n; i++) {
		if (!z[i]) {
			while (s1[t1] == now) {
				now++;
				t1--;
				ans[++len] = 1;
			}
			s1[++t1] = a[i];
			len++;
		}
		else {
			while (s1[t1] == now) {
				now++;
				t1--;
				ans[++len] = 1;
			}
			while (s2[t2] == now) {
				now++;
				t2--;
				ans[++len] = 3;
			}
			s2[++t2] = a[i];
			ans[++len] = 2;
		}
	}
	while (now <= n) {
		if (s1[t1] == now) ans[++len] = 1, t1--;
		else ans[++len] = 3, t2--;
		now++;
	}
	for (int i = 1; i <= len; i++) printf("%c ", ans[i]+'a');	
	return 0;
}
posted @ 2018-11-04 21:24  zzy2005  阅读(89)  评论(0编辑  收藏  举报