题目描述

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


感觉好厉害

让字典序最小,当然尽量进S1

那什么时候必须进S2呢?

a[i]和a[j] 不能压入同一个栈⇔存在一个k,使得i<j<k且a[k]<a[i]<a[j]

因为一个数只能进出一次,k要排在前面所以弹出k时i和j都在栈里,如果两者在同一个栈弹出后顺序就错误了

这样i和j连一条边然后二分图染色再用栈模拟就行了,因为数据是1..n维护cur表示当前该弹出哪个数字

PS:1.建图时先DP用f[i]表示i..n中最小元素

  2.二分图染色可以解决一些有关系,分成两类的问题  

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
int n,a[N];
struct edge{
int v,ne;
}e[N*N];
int h[N],cnt=;
inline void ins(int u,int v){
cnt++;
e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
cnt++;
e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;
}
int f[N];
void dp(){
f[n]=a[n];
for(int i=n-;i>=;i--) f[i]=min(f[i+],a[i]);
for(int i=;i<=n;i++)
for(int j=i+;j<=n;j++)
if(a[i]<a[j]&&f[j]<a[i]) ins(i,j);
}
int col[N];
bool color(int u,int c){
col[u]=c;
for(int i=h[u];i;i=e[i].ne){
int v=e[i].v;
if(col[v]==col[u]) return false;
if(!col[v]&&!color(v,-c)) return false;
}
return true;
}
int s1[N],t1=,s2[N],t2=;
int main(){
n=read();
for(int i=;i<=n;i++) a[i]=read();
dp();
for(int i=;i<=n;i++) if(!col[i]&&!color(i,)) {putchar('');return ;} int cur=;
for(int i=;i<=n;i++){
if(col[i]==) s1[++t1]=a[i],printf("a ");
else s2[++t2]=a[i],printf("c ");
while(s1[t1]==cur||s2[t2]==cur){
if(s1[t1]==cur){printf("b ");t1--;}
else {printf("d ");t2--;}
cur++;
}
}
}

NOIP2008双栈排序[二分图染色|栈|DP]的更多相关文章

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

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

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

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

  3. LOJ P1155 双栈排序 二分图染色 图论

    https://www.luogu.org/problem/show?pid=P1155 题解: https://www.byvoid.com/zhs/blog/noip2008-twostack 开 ...

  4. 洛谷P1155 双栈排序题解(图论模型转换+二分图染色+栈)

    洛谷P1155 双栈排序题解(图论模型转换+二分图染色+栈) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1311990 原题地址:洛谷P1155 双栈排序 ...

  5. 训练指南 UVALive - 3523 (双联通分量 + 二分图染色)

    layout: post title: 训练指南 UVALive - 3523 (双联通分量 + 二分图染色) author: "luowentaoaa" catalog: tru ...

  6. 【POJ 2942】Knights of the Round Table(点双连通分量,二分图染色)

    圆桌会议必须满足:奇数个人参与,相邻的不能是敌人(敌人关系是无向边). 求无论如何都不能参加会议的骑士个数.只需求哪些骑士是可以参加的. 我们求原图的补图:只要不是敌人的两个人就连边. 在补图的一个奇 ...

  7. LG1155 「NOIP2008」双栈排序 二分图判定

    问题描述 LG1155 题解 \(i,j\)如果不能进入一个栈,要满足存在\(k\),使得\(i<j<k\)且\(a_k<a_i<a_j\) 如果\(i,j\)不能进入一个栈, ...

  8. POJ 2942 Knights of the Round Table 补图+tarjan求点双联通分量+二分图染色+debug

    题面还好,就不描述了 重点说题解: 由于仇恨关系不好处理,所以可以搞补图存不仇恨关系, 如果一个桌子上面的人能坐到一起,显然他们满足能构成一个环 所以跑点双联通分量 求点双联通分量我用的是向栈中pus ...

  9. P1155 双栈排序

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

随机推荐

  1. 纪念品分组 2007年NOIP全国联赛普及组

    题目描述 元旦快到了,校学生会让乐乐负责新年晚会的纪念品发放工作.为使得参加晚会的同学所获得的纪念品价值相对均衡,他要把购来的纪念品根据价格进行分组,但每组最多只能包括两件纪念品,并且每组纪念品的价格 ...

  2. JavaScript实现通过的集合类

    集合是一种数据结构,用以表示非重复值的无序集合.集合的基础方法包括添加值.检测值是否在集合中,这种集合需要一种通用的实现,以保证操作效率. JavaScript的对象是属性名以及与之对应的值的基本集合 ...

  3. Java基础学习总结 -- 多线程的实现

    目录: 继承Thread类 start()方法实现多线程的原理 实现Runnable接口 Thread类 与 Runnable接口 的联系与区别 多线程的实现方法: 继承Thread类 实现Runna ...

  4. Javascript对象

    这次的分享,主要还是想跟大家聊聊Javascript语言中很重要的概念之一,对象.为什么说之一呢?因为Javascript其他重要概念还包括:作用域 作用域链 继承 闭包 函数 继承 数组 ..... ...

  5. css(一)

    CSS CSS是Cascading Style Sheets的简称,中文称为层叠样式表,用来控制网页数据的表现,可以使网页的表现与数据内容分离. 一 css的四种引入方式 1.行内式          ...

  6. SharePoint服务器端对象模型 之 使用CAML进展数据查询

    SharePoint服务器端对象模型 之 使用CAML进行数据查询 一.概述 在SharePoint的开发应用中,查询是非常常用的一种手段,根据某些筛选.排序条件,获得某个列表或者某一些列表中相应的列 ...

  7. AngularJS在IE8的支持

    AngularJS一般不会选择IE8支持, 因为很多特性在IE8下效果很差, 性能也不好, 但是由于项目的需要, 客户的机器有些是XP, 只能够装IE8, 所以为了解决这个, 我查阅了相关的资料,发现 ...

  8. asp.netDataTable导出excel方法(2)

    上一篇文章提到看到同事导出excel的新方法,感觉比上一篇简单得多,所以想贴上来,与大家分享. 在后台拼数据,都是用的htmltable标签的写法: string line = "text- ...

  9. html中select标签根据枚举获得值的总结

    不知不觉在公司一个多月了,这一个月做了一个支票申请的web页面功能,都不是特别难,审核有公司给的工作流,分页工具和很多公用工具公司也都给了,所以觉得难度都不是很大.今天主管让我们修改了以前做的项目的代 ...

  10. iOS百度地图SDK集成详细步骤

    1.iOS百度地图下载地址 http://developer.baidu.com/map/index.php?title=iossdk/sdkiosdev-download 根据需要选择不同的版本  ...