做题记录整理栈2 P1155 [NOIP2008 提高组] 双栈排序(2022/9/15)
首先,需要发现就是对于对于三个位置 i < j < k 若存在 p_k < p_i < p_j,则第i个数和第j个数不能存进一个栈中
所以我们需要将序列划分成两个互相都能共存的序列,那很明显是二分图染色,划分完之后再模拟就可以了,有个需要注意的点就是要求输出字典序最小,所以在对第二个栈进行操作之前需要看一下此时第一个栈的操作是不是能做的都做完了(比如第一个栈还可以先输出一些数)
#include<bits/stdc++.h>
#define for1(i,a,b) for(int i = a;i<=b;i++)
#define ll long long
#define mp(a,b) make_pair(a,b)
using namespace std;
struct node{
	int to;
	int nex;
}a[500005];
int cnt,hd[500005];
int rs[500005],mi[500005];
queue<int > dl;
bool vis[500005];
int z[500005],n;
int zhan1[500005],zhan2[500005],top1,top2;
int ans[500005];
void ru(int x,int y)
{
	a[++cnt].to=y;
	a[cnt].nex=hd[x];
	hd[x]=cnt;
}
int main()
{
	cin>>n;
	for1(i,1,n) scanf("%d",&z[i]);
	for1(i,1,n*2) mi[i]=1e9;
	for(int i=n;i>=1;--i) mi[i]=min(mi[i+1],z[i]);
	for1(i,1,n)
	{
		for1(j,i+1,n)
		{
			if(mi[j+1]<z[i]&&z[i]<z[j])
			{
				ru(i,j);
				ru(j,i);
			}
		}
	}
	for(int i=1;i<=n;++i)
	{
		if(!rs[i])
		{
			dl.push(i);
			rs[i]=1;
			while(!dl.empty())
			{
				int x=dl.front();
				dl.pop();
				for(int j=hd[x];j;j=a[j].nex)
				{
					int y=a[j].to;
					if(rs[y])
					{
						if(rs[y]^rs[x]) 
							continue;
						puts("0");
						return 0;
					}
					rs[y]=rs[x]*(-1);
					dl.push(y);
				}
			}
		}
	}
	int now=1;
	int ji=0;
	for1(i,1,n)
	{
		while(1)
		{
		if(top1!=0&&zhan1[top1]==now)
		{
			top1--;
			ans[++ji]=2;
			now++;
		}
		else if(top2!=0&&zhan2[top2]==now)
		{
			top2--;
			ans[++ji]=4;
			now++;
		}
		else break;
		}
		
		if(rs[i]==1)//第一个栈
		{
			zhan1[++top1]=z[i];
				ans[++ji]=1;
		 } 
		 if(rs[i]==-1)//第二个栈 
		 {
				zhan2[++top2]=z[i];
				ans[++ji]=3;	
		 }
	}
	while(top1!=0||top2!=0)
	{
		if(zhan1[top1]==now)
		{
			top1--;
			ans[++ji]=2;
			now++;
		}
		if(zhan2[top2]==now)
		{
			top2--;
			ans[++ji]=4;
			now++;
		}
	}
	for1(i,1,ji)
	{
		if(ans[i]==4&&ans[i+1]==1) swap(ans[i],ans[i+1]);
	}
	for1(i,1,ji)
	{
		cout<<(char)('a'-1+ans[i]);
		cout<<' ';
	}
    return 0;
}

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号