感觉看了题解还是挺简单的,不知道当年chty同学为什么被卡了呢么久……所以说我还是看题解了

原题:

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希望知道其中字典序最小的操作序列是什么。

n<=1000

非常重要的核心结论:S[i],S[j]两个元素不能进入同一个栈 <=> 存在k,满足i<j<k,使得S[k]<S[i]<S[j]

证明略(逃

(其实我连题都没研究,只是看懂这个结论,代码很容易就写出来……)

然而酱紫判断是n^3的,会T,可以用一个很简单的前缀和DP,用f[i]表示i到n的最小值,就可以用O(n^2)的时间完成判断辣

然后限制条件有了,只有两个栈,就用二分图染色

为了使字典序最小,要优先进入1栈,所以在染色的时候要使用邻接矩阵,然后按照序号递增的顺序找边染色,且第一个点要染成1栈的颜色

最后栈的分配方案给出来了,就可以用一个temp来模拟排序后的递增序列,枚举i到n,先把a[i]根据颜色进栈,然后while栈1或栈2的栈头==temp就出栈,为了使字典序最小要先出1栈

代码:

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int oo=;
/*struct ddd{int next,y;}e[2100000];int LINK[210000],ltop=0;
inline void insert(int x,int y){e[++ltop].next=LINK[x];LINK[x]=ltop;e[ltop].y=y;}*/
bool e[][];//因为要按编号递增染色,所以用邻接矩阵
int n,a[];
int f[];
int color[];
int zhana[],topa=,zhanb[],topb=;
bool dfs(int x,int y){
if(color[x]!=- && color[x]==color[y]) return false;
if(color[x]==!color[y]) return true;
color[x]=!color[y];
for(int i=;i<=n;i++)if(e[x][i] && i!=y && !dfs(i,x)) return false;
return true;
}
int main(){//freopen("ddd.in","r",stdin);
memset(e,,sizeof(e));
memset(color,-,sizeof(color));
cin>>n;
for(int i=;i<=n;i++) scanf("%d",&a[i]);
f[n+]=oo;
for(int i=n;i>=;i--) f[i]=min(a[i],f[i+]);
for(int i=;i<n;i++)
for(int j=i+;j<=n;j++)if(a[i]<a[j] && f[j+]<a[i])
e[i][j]=e[j][i]=true;
for(int i=;i<=n;i++)if(color[i]==- && !dfs(i,)){ cout<<<<endl; return ;}
int temp=;//使用temp可以很方便地模拟递增序列
for(int i=;i<=n;i++){
if(!color[i]) zhana[++topa]=a[i],printf("a ");
else zhanb[++topb]=a[i],printf("c ");
while((topa && zhana[topa]==temp) || (topb && zhanb[topb]==temp)){
if(topa && zhana[topa]==temp) topa--,printf("b ");
else topb--,printf("d ");
temp++;
}
}
return ;
}

【NOIP2008】双栈排序的更多相关文章

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

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

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

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

  3. noip2008 双栈排序

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

  4. Noip2008双栈排序

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

  5. NOIP2008双栈排序(贪心)

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

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

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

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

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

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

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

  9. $[NOIp2008]$双栈排序 栈/二分图/贪心

    \(Sol\) 先考虑单栈排序,怎么样的序列可以单栈排序呢?设\(a_i\)表示位置\(i\)是哪个数.\(\exist i<j<k\),都没有\(a_k<a_i<a_j\), ...

  10. [NOIp2008] 双栈排序 (二分图染色 + 贪心)

    题意 给你一个长为 \(n\) 的序列 \(p\) ,问是否能够通过对于两个栈进行 push, pop(print) 操作使得最后输出序列单调递增(即为 \(1 \cdots n\) ),如果无解输出 ...

随机推荐

  1. Andoid activity 生命周期

    今天介绍一下Android中最常用的组件activity的生命周期.当activity处于Android应用中运行时,它的活动状态由Android以Activity栈的形式管理.当前活动的Activi ...

  2. VMware Workstation 10.0.0.1295980 CN

    从V10版本开始,VMware Workstation 官方自带简体中文了,以后大家不需要汉化啦! Winner of more than 50 industry awards, VMware Wor ...

  3. vs2012 断点不能调试

    调试ASP.NET时发现,设置的断点被视而不见 提示错误 debugging information for ‘iisexpress.exe’cannot be found or does not m ...

  4. JAVA 打印九九乘法表

    /** *  * @author liangxiaoyu * @version 1.0 *2015-09-18 */public class JJ { public static void main( ...

  5. self进行weak化

    创建block匿名函数之前一般需要对self进行weak化,否则造成循环引用无法释放controller: __weak MyController *weakSelf = self 或者 __weak ...

  6. hdu 2064

    ps:分析发现,要移动n个到最左端,首先要移动n-1个从A到C,然后从C到A,然后再从A到C,然后中间是把大盘从A到C,两步.递推公式自然就是a[n]=3*a[n-1]+2 代码: #include ...

  7. [zz]Java中的instanceof关键字

    1.What is the 'instanceof' operator used for? stackoverflow的一个回答:http://stackoverflow.com/questions/ ...

  8. 前端开发者应该知道的 CSS 小技巧

    一些小技巧让你的CSS技术更专业 使用:not()去除导航上不需要的边框 为body添加行高 垂直居中任何元素 逗号分离的列表 使用负nth-child选择元素 使用SVG图标 文本显示优化 在纯CS ...

  9. BZOJ 3036 绿豆蛙的归宿

    期望dp.类似记忆化搜索的方法实现. #include<iostream> #include<cstdio> #include<cstring> #include& ...

  10. IndexOf() LastIndexOf() Contains() StartsWith() EndsWith()方法比较

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.I ...