• [NOIP2008] 提高组 洛谷P1155 双栈排序


    题目描述

    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:
    【输入样例1】
    4
    1 3 2 4
    【输入样例2】
    4
    2 3 4 1
    【输入样例3】
    3
    2 3 1
    
    
    输出样例#1:
    【输出样例1】
    a b a a b b a b
    【输出样例2】
    0
    【输出样例3】
    a c a b b d

    说明

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

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

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

    考虑单栈排序:如果有三个元素a[i]<a[j] && a[i]>a[k],且它们的顺序 i<j<k,a[i]出栈以后a[j]才能进栈,a[k]出栈以后a[i]才能出栈,显然无法满足要求。

    所以,如果三个数满足以上条件,它们是不能同进一个栈的。

    先n downto 1倒推出每个数后面最小的数,作为a[k],然后枚举a[i],a[j],若符合上述条件,则在i,j之间连边,表示它们不能进同一个栈。

    之后进行二分图染色,如果遇到颜色矛盾,说明不能把冲突的点对分成两组,也就是问题无解。

    如果没有冲突,则问题有解,模拟即可。

     1 /*by SilverN*/
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cstdio>
     6 #include<cmath>
     7 #include<stack>
     8 using namespace std;
     9 const int mxn=12000;
    10 struct edge{
    11     int v;
    12     int nxt;
    13 }e[mxn];
    14 int hd[mxn],mct=0;
    15 void add_edge(int u,int v){
    16     e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;
    17     return;
    18 }
    19 int a[mxn],n;
    20 int mini[mxn];
    21 int c[mxn];
    22 int ans[mxn],t=0;
    23 bool dfs(int u){
    24     if(c[u]==-1)c[u]=0;
    25     for(int i=hd[u];i;i=e[i].nxt){
    26         int v=e[i].v;
    27         if(c[v]==-1){
    28             c[v]=c[u]^1;
    29             if(!dfs(v))return 0;
    30         }
    31         else{
    32             if(c[v]==c[u])return 0;
    33         }
    34     }
    35     return 1;
    36 }
    37 stack<int>tp1,tp2;
    38 int main(){
    39     memset(c,-1,sizeof c);
    40     int i,j;
    41     scanf("%d",&n);
    42     mini[n+1]=0x3f3f3f;
    43     for(i=1;i<=n;i++)scanf("%d",&a[i]);
    44     for(i=n;i;i--) mini[i]=min(mini[i+1],a[i]);
    45     for(i=1;i<n;i++)
    46      for(j=i+1;j<=n;j++){
    47          if(a[i]<a[j] && a[i]>mini[j+1]){
    48              add_edge(j,i);
    49              add_edge(i,j);
    50          }
    51      }
    52     for(i=1;i<=n;i++)
    53         if(c[i]==-1){
    54             if(!dfs(i)){
    55                 printf("0
    ");
    56                 return 0;
    57             }
    58         }
    59     int now=1;
    60     i=1;
    61     while(1){
    62         if(now>n)break;
    63         if(c[i]==0 && (tp1.empty() || tp1.top()>a[i])){
    64             tp1.push(a[i]);
    65             ans[++t]=1;
    66             i++;
    67             continue;
    68         }
    69         if(!tp1.empty() && tp1.top()==now){
    70             ans[++t]=2;
    71             tp1.pop();
    72             now++;
    73             continue;
    74         }
    75         if(c[i]==1 && (tp2.empty() || tp2.top()>a[i])){
    76             tp2.push(a[i]);
    77             ans[++t]=3;
    78             i++;
    79             continue;
    80         }
    81         if(!tp2.empty() && tp2.top()==now){
    82             tp2.pop();
    83             ans[++t]=4;
    84             now++;
    85             continue;
    86         }
    87     }
    88     for(i=1;i<=t;i++)printf("%c ",(char)ans[i]+'a'-1);
    89     printf("
    ");
    90     return 0;
    91 }
  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    领导满意的高逼格报告,可视化吊打Excel,仅用5步就能教会你
    TTL
    s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 0)
    VSCode的配置和插件同步到多台电脑
    C 语言编程 — 高级数据类型 — void 类型
    C 语言编程 — 高级数据类型 — 字符串
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6026975.html
Copyright © 2020-2023  润新知