双栈排序——二分图+模拟
二分图建模-双栈排序
题目描述
Tom 最近在研究一个有趣的排序问题。如图所示,通过
操作
操作
操作
操作
如果一个
当然,这样的操作序列有可能有几个,对于上例
输入格式
第一行是一个整数
第二行有
输出格式
共一行,如果输入的排列不是“可双栈排序排列”,输出 0
。
否则输出字典序最小的操作序列,每两个操作之间用空格隔开,行尾没有空格。
样例 #1
样例输入 #1
4
1 3 2 4
样例输出 #1
a b a a b b a b
样例 #2
样例输入 #2
4
2 3 4 1
样例输出 #2
0
样例 #3
样例输入 #3
3
2 3 1
样例输出 #3
a c a b b d
提示
2021.06.17 加强 by SSerxhs。hack 数据单独分为一个 subtask 防止混淆。
分析
首先来考虑单栈排序,不难发现,若使单栈排序无解,当且仅当
证明显然
那么由这个性质,不难发现
那么我们将不能共存的
那么问题就变成了对两个栈进行单栈排序,模拟即可
需要注意的是,两个栈一定都单调的,于是为了保证字典序,我们可以在第二个栈必须出栈的时候再出
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<stack>
using namespace std;
#define N 50500
#define M 3000500
int tot,a[N],cnt,now,c[N],head[N],ver[N],nxt[N],f[N],n,m;
stack<int>s1,s2;
void add(int u,int v){
nxt[++tot]=head[u],ver[head[u]=tot]=v;
}
void dfs(int u,int num){
c[u]=num;
for(int i=head[u];i;i=nxt[i]){
int v=ver[i];
if(!c[v])dfs(v,num==1?2:1);
if(c[v]==c[u]){
puts("0");
exit(0);
}
}
}
void init(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
f[n]=a[n];
for(int i=n-1;i>0;i--)f[i]=min(f[i+1],a[i]);
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(a[i]<a[j]&&f[j]<a[i])
add(i,j),add(j,i);
for(int i=1;i<=n;i++)if(!c[i])dfs(i,1);
}
void solve(int x,int id){
int flag=0;
while(!flag){
flag=1;
while(!s1.empty()&&s1.top()==now+1){
printf("b ");
now++;
flag=0;
s1.pop();
}
if(x!=-1&&c[id]==1&&(s1.empty()||s1.top()>x)){
s1.push(x);
printf("a ");
break;
}
if(x!=-1&&c[id]==2&&(s2.empty()||s2.top()>x)){
s2.push(x);
printf("c ");
}
while(!s2.empty()&&s2.top()==now+1){
printf("d ");
now++;
flag=0;
s2.pop();
}
}
if(x==-1)return ;
}
int main(){
init();
for(int i=1;i<=n;i++)solve(a[i],i);
solve(-1,-1);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!