P1155 [NOIP2008 提高组] 双栈排序(二分图)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1155 [NOIP2008 提高组] 双栈排序(二分图)相关的知识,希望对你有一定的参考价值。

P1155 [NOIP2008 提高组] 双栈排序(二分图)

在这里插入图片描述

大佬的题解,大概看懂了。

因为 i < j , a [ i ] > a [ j ] i<j,a[i]>a[j] i<j,a[i]>a[j],所以必须用一个栈暂存 a [ i ] a[i] a[i],不然 a [ i ] a[i] a[i] a [ j ] a[j] a[j]先进栈,但是要求 a [ i ] a[i] a[i] a [ j ] a[j] a[j]先出栈,所以不能满足。

然后三个的话,首先 i < k , a [ i ] > a [ k ] i<k,a[i]>a[k] i<k,a[i]>a[k]与上面同理,所以要用一个栈来保存 a [ i ] a[i] a[i],又因为 a [ j ] > a [ k ] a[j]>a[k] a[j]>a[k],所以要用一个栈来保存 a [ j ] a[j] a[j]。如果 a [ i ] , a [ j ] a[i],a[j] a[i],a[j]在同一个栈的话, a [ i ] a[i] a[i]要比 a [ k ] a[k] a[k]后出栈, a [ j ] a[j] a[j]要比 a [ k ] a[k] a[k]后出栈, a [ i ] a[i] a[i]要比 a [ j ] a[j] a[j]先出栈。

也就是说 a [ i ] , a [ j ] a[i],a[j] a[i],a[j]要存起来,如果存到一个栈里, a [ i ] a[i] a[i] a [ j ] a[j] a[j]先进栈,但是后出栈则不行。

有点类似逆序对,但又不完全是。

code

// Problem: P1155 [NOIP2008 提高组] 双栈排序
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1155
// Memory Limit: 128 MB
// Time Limit: 1000 ms
// Date: 2021-07-04 21:23:48
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=1e3+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define ios ios::sync_with_stdio(false),cin.tie(0) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\\n",a[n]); 
}
int n,p[N],mn[N],cnt=1;
stack<int>s[2];
void out(char ch){
	putchar(ch);putchar(' ');
}
bool Pop(int i){
	if(!s[i].empty()&&s[i].top()==cnt){
		out(i?'d':'b');s[i].pop();++cnt;
		return true;
	}
	return false;
}
void Push(int x,int i){
	if(i==1) while(Pop(0));//如果要push 尽可能把之前第一个栈中可以的出来,保证字典序最小.
	while(!s[i].empty()&&s[i].top()<x)	//直到不能保持栈的单调性才出栈.
		if(!Pop(i)) Pop(i^1); //如果此时不能出栈则一定是另一个出栈.
	if(i==1) while(Pop(0));	//可能又有新的可以丢.
	s[i].push(x);out(i?'c':'a');
}
vector<int>g[N];
int c[N];
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&p[i]);mn[n+1]=n+1;
	for(int i=n;i;i--) mn[i]=min(mn[i+1],p[i]);
	for(int i=1;i<=n;i++)
		for(int j=i+1;j<=n;j++)	
			if(p[i]<p[j]&&mn[j+1]<p[i]) g[i].pb(j),g[j].pb(i),c[i]=c[j]=-1;
	queue<int>q;
	for(int i=1;i<=n;i++)
		if(!~c[i]){		//二分图染色 判断是否有解
			q.push(i);
			c[i]=0;
			while(!q.empty()){
				int u=q.front();q.pop();
				for(int v:g[u]){
					if(~c[v]&&c[u]==c[v]) return puts("0"),0;
					if(!~c[v]) q.push(v);
					c[v]=c[u]^1;
				}
			}
		}
	for(int i=1;i<=n;i++) Push(p[i],c[i]);
		bool flag = true;
	while (flag) {
		flag = false;
		while(Pop(0)) flag = true;
		while(Pop(1)) flag = true;
	}
	return 0;
	
}

以上是关于P1155 [NOIP2008 提高组] 双栈排序(二分图)的主要内容,如果未能解决你的问题,请参考以下文章

Vijos1605 NOIP2008 提高组T4 双栈排序 BFS

2017.2.18[codevs1170]NOIP2008提高组复赛T4双栈排序

P1155 双栈排序

P1155 双栈排序

AC日记——双栈排序 洛谷 P1155

P1155 双栈排序