NOIp2018提高组 双栈排序
这真是道神奇的题目:
原题链接
首先我们要证明以下的性质:
若原序列为\(\{a_n\}\),\(a_i\)和\(a_j\)不能同时放入一个栈中,当且仅当\(i<j,a_i<a_j\),且存在\(k\),\(s.t. \ k>j\)的同时有\(a_k<a_i\)。
原因很显然,因为有比\(a_i\)还小的元素在后面,若放入同一个栈中,必须先压栈压到\(a_k\),再弹出,但又因为会先弹出\(a_j\),序列的单调性就被破坏了。
所以对于每一对\(a_i\)和\(a_j\),我们都可以用上述性质来判断它们是否能在同一个栈中,再用后缀最大值优化一下,复杂度\(O(n^2)\)。
然后我们就有了这样的一些关系,我们该如何利用这些关系来判断序列是否合法呢?
二分图染色,对于不能在同一个栈中的两个位置,我们连一条无向边,然后dfs判断所有点能否二染色。如果能,序列就是合法的,否则不合法。
对于染色后的图,其实我们已经知道操作顺序了,又因为题目要求字典序最小,所以我们只用模拟一下,优先在栈\(S1\)上操作就行了。
上代码:
#include <bits/stdc++.h>
using namespace std;
#define wrap cout << endl
const int N = 1000;
int n, a[N+5], color[N+5], f[N+5], flag;
vector<int> G[N+5];
void addEdge(int u, int v) {
G[u].push_back(v);
G[v].push_back(u);
}
void dfs(int u) {
for(int i = 0; i < G[u].size(); ++i) {
int v = G[u][i];
if(color[v]) {
if(color[v] == color[u])
flag = 1;
}
else {
color[v] = 3-color[u];
dfs(v);
}
}
}
void solve() {
int cur = 1;
stack<int> s1, s2;
for(int i = 1; i <= n; ++i) { //模拟
if(color[i] == 1) s1.push(a[i]), cout << 'a' << " ";
if(color[i] == 2) s2.push(a[i]), cout << 'c' << " ";
while((!s1.empty() && s1.top() == cur) || (!s2.empty() && s2.top() == cur)) {
if(!s1.empty() && s1.top() == cur) s1.pop(), cout << 'b' << " ";
if(!s2.empty() && s2.top() == cur) s2.pop(), cout << 'd' << " ";
++cur;
}
}
}
int main() {
cin >> n;
for(int i = 1; i <= n; ++i) cin >> a[i];
f[n+1] = 0x3f3f3f3f;
for(int i = n; i >= 1; --i) f[i] = min(f[i+1], a[i]);
for(int i = 1; i <= n; ++i)
for(int j = i+1; j <= n; ++j)
if(a[i] < a[j] && f[j+1] < a[i]) addEdge(i, j); //判断是否加边
for(int i = 1; i <= n; ++i)
if(!color[i])
color[i] = 1, dfs(i);
if(flag) {
cout << "0" << endl;
return 0;
}
solve();
return 0;
}
NOIp2018提高组 双栈排序的更多相关文章
- 双栈排序 2008年NOIP全国联赛提高组(二分图染色)
双栈排序 2008年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description Tom最近在研究一个有 ...
- [NOIP2008] 提高组 洛谷P1155 双栈排序
题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1 ...
- 【提高组NOIP2008】双栈排序 (twostack.pas/c/cpp)
[题目描述] Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈 ...
- BZOJ 2080: [Poi2010]Railway 双栈排序
2080: [Poi2010]Railway Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 140 Solved: 35[Submit][Statu ...
- 双栈排序(codevs 1170)题解
[问题描述] Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈 ...
- [NOIp2018提高组]赛道修建
[NOIp2018提高组]赛道修建 题目大意: 给你一棵\(n(n\le5\times10^4)\)个结点的树,从中找出\(m\)个没有公共边的路径,使得第\(m\)长的路径最长.问第\(m\)长的路 ...
- [NOIp2018提高组]货币系统
[NOIp2018提高组]货币系统 题目大意: 有\(n(n\le100)\)种不同的货币,每种货币的面额为\([1,25000]\)之间的一个整数.若两种货币系统能够组合出来的数是相同的的,那我们就 ...
- NOIP2018提高组省一冲奖班模测训练(四)
NOIP2018提高组省一冲奖班模测训练(四) 这次比赛只AC了第一题,而且花了40多分钟,貌似是A掉第一题里面最晚的 而且还有一个半小时我就放弃了…… 下次即使想不出也要坚持到最后 第二题没思路 第 ...
- NOIP2018提高组省一冲奖班模测训练(三)
NOIP2018提高组省一冲奖班模测训练(三) 自己按照noip的方式考,只在最后一两分钟交了一次 第一题过了,对拍拍到尾. 第二题不会.考试时往组合计数的方向想,推公式,推了一个多小时,大脑爆炸,还 ...
随机推荐
- Unity协程的坑
unity终止协程提供了 StopAllCoroutines() 和 StopCoroutines() 两个方法, 但是都只能终止该文件内的 IEnumerator. 并且具体使用有点坑, 见如下实 ...
- SQL Server 关于 Table 字典数据的查询SQL
分享一个关于查询SQL Server Table 结构的SQL 语句. T-SQL 如下: SELECT (case when a.colorder=1 then d.name else '' end ...
- JPA之@Transient
java 的transient关键字的作用是需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中. 使用示例: ...
- nginx实现新老网站跳转(原URL不变)
新老网站实现跳转 原URL保持不变 通过手动添加cookie 匹配cookie的方法进行跳转第一步 进行添加if判断条件 if ( $query_string ~* "sr=pro" ...
- 怎样保证socket.recv接收完数据
最近在使用python进行网络编程开发一个通用的tcpclient测试小工具.在使用socket进行网络编程中,如何判定对端发送一条报文是否接收完成,是进行socket网络开发必须要考虑的一个问题.这 ...
- ssr
使用Nuxt.js改造已有项目的方法 https://www.jb51.net/article/145203.htm
- Nodejs OracleDB详细解读
//导入oracledb模块 //基于版本@3.0.1 安装指令npm install oracledb //node访问oracleDB需要搭建访问环境,否则无法正常访问 //创建Oracle对象 ...
- SQLserver查询库中包含某个字段的表
select [name] from [TPMS_PRD].[dbo].sysobjects where id in(select id from [TPMS_PRD].[dbo].syscolumn ...
- Effective STL 读书笔记
Effective STL 读书笔记 标签(空格分隔): 未分类 慎重选择容器类型 标准STL序列容器: vector.string.deque和list(双向列表). 标准STL管理容器: set. ...
- Leetcode 27. Remove Element(too easy)
Given an array and a value, remove all instances of that value in-place and return the new length. D ...