1.      双栈排序

(twostack.pas/c/cpp)

Tom 最近在研究一个有趣的排序问题。如图所示,通过 2 个栈 S1 和 S2,Tom 希望借助

以下 4 种操作实现将输入序列升序排序。

操作 a

如果输入序列不为空,将第一个元素压入栈 S1

操作 b

如果栈 S1 不为空,将 S1 栈顶元素弹出至输出序列

操作 c

如果输入序列不为空,将第一个元素压入栈 S2

操作 d

如果栈 S2 不为空,将 S2 栈顶元素弹出至输出序列

如果一个 1~n 的排列 P 可以通过一系列操作使得输出序列为 1,2,„,(n-1),n,Tom 就称 P 是一个“可双栈排序排列”。例如(1,3,2,4)就是一个“可双栈排序序列”,而(2,3,4,1) 不是。下图描述了一个将(1,3,2,4)排序的操作序列:<a,c,c,b,a,d,d,b>

当然,这样的操作序列有可能有几个,对于上例(1,3,2,4),<a,c,c,b,a,d,d,b>是另外一个可行的操作序列。Tom 希望知道其中字典序最小的操作序列是什么。

【输入】

输入文件 twostack.in
的第一行是一个整数 n。

第二行有 n
个用空格隔开的正整数,构成一个 1~n
的排列。

【输出】

输出文件 twostack.out
共一行,如果输入的排列不是“可双栈排序排列”,输出数字
0;

否则输出字典序最小的操作序列,每两个操作之间用空格隔开,行尾没有空格。

【输入输出样例1】

twostack.in

twostack.out

4

1 3 2 4

a b a a b b a b

【输入输出样例2】

twostack.in

twostack.out

4

2 3 4 1

0

【输入输出样例3】

twostack.in

twostack.out

3

2 3 1

a c a b b d

【限制】

30%的数据满足:
n<=10

50%的数据满足:
n<=50

100%的数据满足:
n<=1000

【思路】

构造“不可能”边+二分图着色

点的分配转化为了二分图的着色。

(以下摘自洛谷OI【题解】)

考虑对于任意两个数q1[i]和q1[j]来说,它们不能压入同一个栈中的充要条件是什么(注意没有必要使它们同时存在于同一个栈中,只是压入了同一个 栈).实际上,这个条件p是:存在一个k,使得i<j<k且q1[k]<q1[i]<q1[j].

首先证明充分性,即如果满足条件p,那么这两个数一定不能压入同一个栈.这个结论很显然,使用反证法可证.
假设这两个数压入了同一个栈,那么在压入q1[k]的时候栈内情况如下:
…q1[i]…q1[j]…
因为q1[k]比q1[i]和q1[j]都小,所以很显然,当q1[k]没有被弹出的时候,另外两个数也都不能被弹出(否则q2中的数字顺序就不是1,2,3,…,n了).
而之后,无论其它的数字在什么时候被弹出,q1[j]总是会在q1[i]之前弹出.而q1[j]>q1[i],这显然是不正确的.

接下来证明必要性.也就是,如果两个数不可以压入同一个栈,那么它们一定满足条件p.这里我们来证明它的逆否命题,也就是"如果不满足条件p,那么这两个数一定可以压入同一个栈."
不满足条件p有两种情况:一种是对于任意i<j<k且q1[i]<q1[j],q1[k]>q1[i];另一种是对于任意i<j,q1[i]>q1[j].
第一种情况下,很显然,在q1[k]被压入栈的时候,q1[i]已经被弹出栈.那么,q1[k]不会对q1[j]产生任何影响(这里可能有点乱,因为看起 来,当q1[j]<q1[k]的时候,是会有影响的,但实际上,这还需要另一个数r,满足j<k<r且 q1[r]<q1[j]<q1[k],也就是证明充分性的时候所说的情况…而事实上我们现在并不考虑这个r,所以说q1[k]对q1[j]没
有影响).
第二种情况下,我们可以发现这其实就是一个降序序列,所以所有数字都可以压入同一个栈.
这样,原命题的逆否命题得证,所以原命题得证.

此时,条件p为q1[i]和q1[j]不能压入同一个栈的充要条件也得证.

这样,我们对所有的数对(i,j)满足1<=i<j<=n,检查是否存在i<j<k满足p1[k]<p1[i]& lt;p1[j].如果存在,那么在点i和点j之间连一条无向边,表示p1[i]和p1[j]不能压入同一个栈.此时想到了什么?那就是二分图~
二分图的两部分看作两个栈,因为二分图的同一部分内不会出现任何连边,也就相当于不能压入同一个栈的所有结点都分到了两个栈中.
此时我们只考虑检查是否有解,所以只要o(n)检查出这个图是不是二分图,就可以得知是否有解.

然后处理最小字典序问题。实际上对二分图染色后对应的操作显然编号小的优先使用a操作,可以使得字典序尽量小。

这里要提二分图的一个性质:二分图中不同的连通分量染色是互不影响的。所以为了满足最小字典序的问题,可以选取编号最小的未染色结点染成1并对它所在连通分量染色。染完之后,模拟输出序列就可以了。

【代码】

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<vector>
  4. #include<stack>
  5. using namespace std;
  6. const int maxn = +;
  7.  
  8. int S[maxn],C[maxn];
  9. vector<int> G[maxn];
  10. int n;
  11.  
  12. void dfs(int u,int c){
  13. C[u]=c;
  14. for(int i=;i<G[u].size();i++){
  15. int v=G[u][i];
  16. if(C[v]==C[u]) {
  17. cout<<; exit();
  18. }
  19. else if(!C[v]) dfs(v,-c);
  20. }
  21. }
  22. int main() {
  23. ios::sync_with_stdio(false);
  24.  
  25. cin>>n;
  26. for(int i=;i<=n;i++) cin>>S[i];
  27. int _min[maxn]; _min[n+]=<<;
  28. for(int i=n;i;i--) _min[i]=min(_min[i+],S[i]);
  29. for(int i=;i<n;i++)
  30. for(int j=i+;j<=n;j++) if(S[i]<S[j] && _min[j+]<S[i]) { //i<j<k && (S[k]<S[i]<S[j])
  31. G[i].push_back(j); G[j].push_back(i);
  32. }
  33.  
  34. for(int i=;i<=n;i++) if(!C[i]) dfs(i,);
  35.  
  36. int aim=;
  37. stack<int> sta,stb;
  38. for(int i=;i<=n;i++) {
  39. if(C[i]==) {
  40. sta.push(S[i]); cout<<"a ";
  41. }
  42. else {
  43. stb.push(S[i]); cout<<"c ";
  44. }
  45. while(!sta.empty()&&sta.top()==aim || !stb.empty()&&stb.top()==aim) {
  46. if(!sta.empty()&&sta.top()==aim){
  47. sta.pop(); cout<<"b ";
  48. }
  49. else {
  50. stb.pop(); cout<<"d ";
  51. }
  52. aim++;
  53. }
  54. }
  55. return ;
  56. }

NOIP2008 双栈队列的更多相关文章

  1. Luogu1155 NOIP2008 双栈排序 【二分图染色】【模拟】

    Luogu1155 NOIP2008 双栈排序 题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过 2个栈 S1 和 S2 ,Tom希望借助以下 44 种操作实现将输入序列升序排序. 操作 ...

  2. C++实现一个简单的双栈队列

    双栈队列的原理是用两个栈结构模拟一个队列, 一个栈A模拟队尾, 入队的元素全部压入此栈, 另一个栈B模拟队首, 出队时将栈A的元素弹入栈B, 将栈B的栈顶元素弹出 此结构类似汉诺塔, 非常经典, 这里 ...

  3. NOIP2008双栈排序[二分图染色|栈|DP]

    题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1 ...

  4. noip2008 双栈排序

    题目描述 Description \(Tom\)最近在研究一个有趣的排序问题.如图所示,通过\(2\)个栈\(S_1\)和\(S_2\),\(Tom\)希望借助以下\(4\)种操作实现将输入序列升序排 ...

  5. Noip2008双栈排序

    [问题描述] 用两个栈使一个1...n的排列变得有序.一共有四个操作: A.stack1.push() 读入一个放入栈一 B.stack1.pop() 弹出栈一放入输出序列 C.stack2.push ...

  6. NOIP2008双栈排序(贪心)

    题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1 ...

  7. [题解] [NOIP2008] 双栈排序——关系的冲突至图论解法

    Problem 题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操 ...

  8. [NOIP2008]双栈排序 【二分图 + 模拟】

    题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1 ...

  9. [luogu1155 NOIP2008] 双栈排序 (二分图染色)

    传送门 Description Input 第一行是一个整数 n . 第二行有 n 个用空格隔开的正整数,构成一个 1−n 的排列. Output 共一行,如果输入的排列不是"可双栈排序排列 ...

随机推荐

  1. bzoj 2744: [HEOI2012]朋友圈 二分图匹配

    2744: [HEOI2012]朋友圈 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 612  Solved: 174[Submit][Status] ...

  2. uva 825

    这个......小学生就会的  坑在输入输出了  两个数之间可能不止一个空格....wa了好几遍啊 #include <cstdio> #include <cstring> # ...

  3. jasper ireport create a report with parameters without sql query

    I'm new in jasper ireport , and I want to know if it is possible to create a report only with static ...

  4. 1987-A. 集训队选拔

    描述 南邮ACM暑期集训队一年一度的选拔如火如荼的开始了.按照以往的惯例,通过ACM校赛预赛和决赛的两轮选拔,成绩优异者将入选集训队,获得下半年在各大赛区现场赛上与各路神牛角逐奖牌的机会.但是,校赛的 ...

  5. android webview网页控件

    一个WebView的简单例子 .在开发过程中应该注意几点: 1.AndroidManifest.xml中必须使用许可"android.permission.INTERNET",否则 ...

  6. 缺少编译器要求的成员“System.Runtime.CompilerServices.ExtensionAttribute..ctor” 解决方案

    静态类中添加如下.此方法本人测试有效. //缺少编译器要求的成员“ystem.Runtime.CompilerServices.ExtensionAttribute..ctor” namespace  ...

  7. PowerDesigner15(16)在生成SQL时报错Generation aborted due to errors detected during the verification of the mod

    1.用PowerDesigner15建模,在Database—>Generate Database (或者用Ctrl+G快捷键)来生产sql语句,却提示“Generation aborted d ...

  8. ajax跨域访问的解决方案

    今天的工作中要访问摄像机内部的一个web站点,这就涉及到jquery的ajax跨域访问的问题.我使用的是jquery1.7的版本,下面总结如下: 问题一:一开始用IE调试,总是返回No Transpo ...

  9. laravel5的坑

    以此记录学习laravel的一些问题 问题:laravel转移文件夹到另外一pc或者环境后访问出现500 设置权限为777 问题: 设置路由后页面总是404 not found 解决:需要在apach ...

  10. editplus的配置文件来支持sql语法高亮【转】

      editplus默认是没有sql语法高亮的,原因是它的内部没有sql.stx的这样一个语法文件 我们自己在 EditPlus 的安装目录下面新建一个文件名为sql.stx,然后打开editplus ...