Vijos1605 NOIP2008 提高组T4 双栈排序 BFS
欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目传送门 - Vijos1605
题意概括
有1个1~n的排列,有2个栈,现在通过以下操作,使得出栈序列有序。
操作a 当前元素入栈<S1>
操作b 弹出S1栈顶元素
操作c 当前元素入栈<S2>
操作d 弹出S2栈顶元素
如果无法使得出栈序列有序,那么输出0.
否则输出满足条件的字典序最小的操作序列。
题解
首先我们可以证明,任意时刻,任意一个栈中的元素,一定满足自底向上呈降序。
如果不呈降序呢?
那么会出现大的先出栈,小的后出栈的情况,所以一定不行。
我们考虑2个元素a[i],a[j],(i<j)。
可以得到信息:
如果a[i]<a[j]那么a[i]先出栈
否则 a[j]先出栈
然后好像没有其他信息了。
问题很严峻。
于是我们考虑3个元素a[i],a[j],a[k](i<j<k)
考虑所有情况。
如果a[i]<a[j]<a[k],那么a[i],a[j]可能在同一个栈中。
同样,
如果a[i]<a[k]<a[j],那么a[i],a[j]可能在同一个栈中。
如果a[j]<a[i]<a[k],那么a[i],a[j]可能在同一个栈中。
如果a[j]<a[k]<a[i],那么a[i],a[j]可能在同一个栈中。
如果a[k]<a[j]<a[i],那么a[i],a[j]可能在同一个栈中。(这5中情况都可以有具体操作次序,注意是“可能”)
但是,
如果a[k]<a[i]<a[j],那么a[i],a[j]一定不可能在同一个栈中。
为什么?
首先a[i]进栈。
因为a[k]<a[i],所以在a[k]出栈之前,a[i]不能出栈。
然而因为a[i]<a[j],如果a[i]与a[j]放在同一个栈中,那么会出现题解第一句中表述的不合法情况。
因此a[i],a[j]一定不会在同一个栈中。
于是我们可以先确定i,j,然后大力枚举k,按照不在同一个栈中的关系建立无向图。相邻的节点一定不会在同一个栈中。这个操作的复杂度为n^3。
而实际上,我们可以先预处理一个后缀最小值,那么大力枚举k的时间复杂度就被压缩掉了。
优化之后,这个操作的复杂度为n^2。
建图之后,就是匹配栈。
黑白染色即可。(假设栈1为白色(0),栈2为黑色(1))
又由于题目要字典序最小的,所以我们尽量给编号小的节点染成白色就可以了。
于是我们大力跑一遍广搜。
当然染色的过程中会出现相邻节点颜色相同的情况,那么就是无解,直接输出0。
广搜完了之后,每一个数字安排的栈位置都已经弄好了。
然后就是模拟了。
模拟的时候,还是要注意字典序最小的问题。
注意按照之前匹配的一定有解的。
模拟具体过程:
我们弄一个计数器cnt,表示当前出栈到了哪一个数字。
对于每次压入元素前,如果栈1的栈顶元素是cnt+1,那么要先将栈1出栈。
因为,如果当前元素匹配的是栈2,那么自然就是栈1出栈优先。
如果是栈1,那么元素值一定会比cnt+1要大,不满足最前面的那一条。
然后,注意对于同一个栈,入栈的优先级一定比出栈高。
所以,我们尽量提前入栈。
但是入栈是有条件的,要维持序列降序。
那么就要先出栈,直到满足降序为止。
出栈也是有规矩的。要满足cnt+1,所以是两个栈乱序出栈的。
我的程序貌似有点小问题,但是数据水,过去了……
具体:
如果匹配栈2,那么出栈操作之后,满足栈2降序之后,其实有字典序更小的方案。
因为栈2入栈,是c,而栈1出栈是b,所以栈1先出栈是赚的。但是我忘记判这个情况了。
然后居然……
至此,rzO膜拜大佬出据人Orz
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | #include <cstring> #include <cstdio> #include <algorithm> #include <cstdlib> #include <cmath> #include <queue> using namespace std; const int N=1000+5,Inf=100000; struct Stack{ int v[N],t; void clear(){ t=0; } void push( int x){ v[++t]=x; } void pop(){ t--; } bool empty(){ return t==0; } int top(){ if (t==0) return Inf; return v[t]; } }s1,s2; int n,a[N],Min[N],match[N],vis[N],cnt; bool g[N][N]; queue < int > q; int main(){ scanf ( "%d" ,&n); for ( int i=1;i<=n;i++) scanf ( "%d" ,&a[i]); Min[n]=10000; for ( int i=n-1;i>=1;i--) Min[i]=min(Min[i+1],a[i+1]); memset (g,0, sizeof g); for ( int i=1;i<=n;i++) for ( int j=i+1;j<=n;j++) if (a[i]<a[j]&&Min[j]<a[i]) g[i][j]=g[j][i]=1; memset (vis,0, sizeof vis); for ( int i=1;i<=n;i++){ if (vis[i]) continue ; while (!q.empty()) q.pop(); vis[i]=1,match[i]=0; q.push(i); while (!q.empty()){ int x=q.front(); q.pop(); for ( int j=1;j<=n;j++){ if (!g[x][j]) continue ; if (!vis[j]){ match[j]=match[x]^1; q.push(j); vis[j]=1; } else if (match[j]==match[x]){ printf ( "0" ); fclose (stdin); fclose (stdout); return 0; } } } } cnt=0; s1.clear(),s2.clear(); for ( int i=1;i<=n;i++){ while (s1.top()==cnt+1){ printf ( "b " ); s1.pop(); cnt++; } if (match[i]==0){ while (a[i]>s1.top()&&(s1.top()==cnt+1||s2.top()==cnt+1)) if (s1.top()==cnt+1){ printf ( "b " ); s1.pop(); cnt++; } else { printf ( "d " ); s2.pop(); cnt++; } s1.push(a[i]); printf ( "a " ); } if (match[i]==1){ while (a[i]>s2.top()&&(s1.top()==cnt+1||s2.top()==cnt+1)) if (s1.top()==cnt+1){ printf ( "b " ); s1.pop(); cnt++; } else { printf ( "d " ); s2.pop(); cnt++; } s2.push(a[i]); printf ( "c " ); } } while (!s1.empty()||!s2.empty()) if (s1.top()<s2.top()){ printf ( "b " ); s1.pop(); } else { printf ( "d " ); s2.pop(); } return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
· 手把手教你更优雅的享受 DeepSeek
· AI工具推荐:领先的开源 AI 代码助手——Continue
· 探秘Transformer系列之(2)---总体架构
· V-Control:一个基于 .NET MAUI 的开箱即用的UI组件库
· 乌龟冬眠箱湿度监控系统和AI辅助建议功能的实现