NOIP2008双栈排序(贪心)
题目描述
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希望知道其中字典序最小的操作序列是什么。
Solution
先考虑如何判掉不合法的情况,对于一个数,如果它前面有一个数比他大,那他们不能在同一个栈里,我们可以在它们之间连一条边,那么连出来的这张图如果有奇环,就是不合法的。
再考虑对于一个合法解,如何是答案字典序最小。
我们对于一个联通块内让编号最小的点进一号栈,那么所有元素进入栈的编号就确定了,接下来按照题意模拟,有能弹出的元素就弹出。
但这样为什么能保证字典序最小?
考虑当二号栈有元素需要弹出,下一个元素要进一号栈,那么我们应该先让一号进入,二号弹出,我们的做法就出锅了。
所以要加特判
Code
#include<iostream>
#include<cstdio>
#define N 1009
using namespace std;
struct dd
{
int n,to;
}an[N*N];
int a[N],co[N],head[N],tot,n,mi,p,tag,top1,top2,st1[N],st2[N];
bool vis[N];
inline void add(int u,int v)
{
an[++tot].n=head[u];
an[tot].to=v;
head[u]=tot;
}
bool dfs(int u,int fa)
{
vis[u]=;
for(int i=head[u];i;i=an[i].n)
if(an[i].to!=fa)
{
if(co[an[i].to]==-co[u])return ;
co[an[i].to]=-co[u];
if(!vis[an[i].to])if(!dfs(an[i].to,u))return ;
}
return ;
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;++i)scanf("%d",&a[i]);
mi=0x3f3f3f3f;
for(int i=n;i>=;--i)
{
for(int j=;j<i;++j)
if(a[j]<a[i]&&a[j]>mi)add(j,i),add(i,j);
mi=min(mi,a[i]);
}
for(int i=;i<=n;++i)
if(!vis[i])
{
co[i]=;
if(!dfs(i,))
{
printf("");
return ;
}
}
p=;
for(int i=;i<=n;++i)
{
tag=co[i]==?:;
if(tag==)
{
printf("a ");
st1[++top1]=a[i];
}
else
{
printf("c ");
st2[++top2]=a[i];
}
while(st1[top1]==p+||st2[top2]==p+)
if(p+==st1[top1])printf("b "),p++,top1--;
else printf("d "),p++,top2--;
}
return ;
}
NOIP2008双栈排序(贪心)的更多相关文章
- Luogu1155 NOIP2008 双栈排序 【二分图染色】【模拟】
Luogu1155 NOIP2008 双栈排序 题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过 2个栈 S1 和 S2 ,Tom希望借助以下 44 种操作实现将输入序列升序排序. 操作 ...
- $[NOIp2008]$双栈排序 栈/二分图/贪心
\(Sol\) 先考虑单栈排序,怎么样的序列可以单栈排序呢?设\(a_i\)表示位置\(i\)是哪个数.\(\exist i<j<k\),都没有\(a_k<a_i<a_j\), ...
- noip2008 双栈排序
题目描述 Description \(Tom\)最近在研究一个有趣的排序问题.如图所示,通过\(2\)个栈\(S_1\)和\(S_2\),\(Tom\)希望借助以下\(4\)种操作实现将输入序列升序排 ...
- vijos 1605 双栈排序 - 贪心 - 二分图
题目传送门 传送门I 传送门II 题目大意 双栈排序,问最小字典序操作序列. 不能发现两个数$a_{j}, a_{k}\ \ (j < k)$不能放在同一个栈的充分必要条件时存在一个$i$使得$ ...
- [题解] [NOIP2008] 双栈排序——关系的冲突至图论解法
Problem 题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操 ...
- [NOIP2008]双栈排序 【二分图 + 模拟】
题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1 ...
- NOIP2008双栈排序[二分图染色|栈|DP]
题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1 ...
- Noip2008双栈排序
[问题描述] 用两个栈使一个1...n的排列变得有序.一共有四个操作: A.stack1.push() 读入一个放入栈一 B.stack1.pop() 弹出栈一放入输出序列 C.stack2.push ...
- [luogu1155 NOIP2008] 双栈排序 (二分图染色)
传送门 Description Input 第一行是一个整数 n . 第二行有 n 个用空格隔开的正整数,构成一个 1−n 的排列. Output 共一行,如果输入的排列不是"可双栈排序排列 ...
随机推荐
- 11-vue的使用
一.安装 对于新手来说,强烈建议大家使用<script>引入 二. 引入vue.js文件 我们能发现,引入vue.js文件之后,Vue被注册为一个全局的变量,它是一个构造函数. 三.使用V ...
- js刷新界面前事件onbeforeunload
这个方法的作用是防止填写信息时不小心按了刷新(F5,刷新界面,返回). 目前能实现这个需求的只有这个方法. 具体代码如下: 1.首先在body添加 onbeforeunload 这个事件 <bo ...
- js-跨域源资源共享(CORS)
### 一. CORS(Cross-Origin Resource Sharing,跨域源资源共享) 基本思想:使用自定义HTTP头部让浏览器与服务器进行沟通 发送请求时,需附加一个Origin头部 ...
- flutter 动画双指放大图片
class GridAnimation extends StatefulWidget { @override State<StatefulWidget> createState() { r ...
- spring boot中常用的配置文件的重写
@Configuration public class viewConfigSolver extends WebMvcConfigurerAdapter { /* spring boot 已经自动配置 ...
- ssm框架整合配置,用maven配置依赖jar包
1.创建maven project 首先在pom.xml中指定工程所依赖的jar包 <project xmlns="http://maven.apache.org/POM/4.0.0& ...
- Bootstrap之表格、表单应用
代码: <!DOCTYPE html> <html lang="en" xmlns:th="http://www.w3.org/1999/xhtml&q ...
- EChart.js 笔记二
交互组件 Echart.js 中交互组件比较多.例如: legend(图例).title(标题组件).visualMap(视觉映射组件).dataZoom(数据缩放组件).timeline(时间线组件 ...
- 一个简易的C语言文法
<程序>→<外部声明>|<程序><外部声明> <外部声明>→<函数定义>|<声明> <函数定义>→< ...
- ASP.NET Core Building chat room using WebSocket
Creating “Login form” We use here simple form where user can insert his or her preferred nick name f ...