[TJOI2011]树的序

题目描述

众所周知,二叉查找树的形态和键值的插入顺序密切相关。准确的讲:1、空树中加入一个键值k,则变为只有一个结点的二叉查找树,此结点的键值即为k;2、在非空树中插入一个键值k,若k小于其根的键值,则在其左子树中插入k,否则在其右子树中插入k。

我们将一棵二叉查找树的键值插入序列称为树的生成序列,现给出一个生成序列,求与其生成同样二叉查找树的所有生成序列中字典序最小的那个,其中,字典序关系是指对两个长度同为n的生成序列,先比较第一个插入键值,再比较第二个,依此类推。

输入输出格式

输入格式:

第一行,一个整数,n,表示二叉查找树的结点个数。第二行,有n个正整数,k1到kn,表示生成序列,简单起见,k1~kn为一个1到n的排列。

输出格式:

一行,n个正整数,为能够生成同样二叉查找数的所有生成序列中最小的。

输入输出样例

输入样例#1: 复制

4

1 3 4 2

输出样例#1: 复制

1 3 2 4

说明

对于20%的数据,n ≤ 10。

对于50%的数据,n ≤ 100。

对于100%的数据,n ≤ 100,000。

题解

先看出题目是直接建树然后贪心输出中序遍历。

然后交上去。发现如果树是链的话就被卡成\(O(n^2)\)。

怎么办呢?点开题解

发现题解多是笛卡尔树。

笛卡尔树是什么鬼东西(蒟蒻表示不会啊)

那就去学(抄题解)吧。

笛卡尔树类似于\(treap\)。

维护两个值,一个为\(key\)值即点权值,另一个在本题维护为\(id\),即出现顺序。

笛卡尔树是利用单调栈的特性建树的。

按样例的\(key\)值从小到大排序后。

\(id\)值为\(1,4,2,3.\)

我们先把\(1\)放进树。

然后让\(1\)点连右儿子\(key\)值为\(2\),\(id\)为\(4\)的点。

然后\(key\)值为\(3\)时,前面的\(2\)的\(id\)比3的\(id\)大。

即按中序遍历,\(3\)的左儿子是\(2\)。

于是就断开\(1\)连向\(2\)的边,然后连向\(3\),并让\(3\)向\(2\)连一条边作为左儿子。

建树的性质就是这样的。

\(O(n)\)建树。

代码

先上\(O(n^2)\)写法

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
const int N=1000001;
struct node{
int ch[2],vi;
}t[N<<1];
int ch[N],n,cnt=1,ans[N],tot;
int read(){
int x=0,w=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*w;
} void build(int x){
int root=1;
while(t[root].ch[t[root].vi<ch[x]])root=t[root].ch[t[root].vi<ch[x]];
t[root].ch[t[root].vi<ch[x]]=++cnt;
t[cnt].vi=ch[x];
} void dfs(int x){
ans[++tot]=t[x].vi;
if(t[x].ch[0])dfs(t[x].ch[0]);
if(t[x].ch[1])dfs(t[x].ch[1]);
} int main(){
n=read();
for(int i=1;i<=n;i++)ch[i]=read();
t[1].vi=ch[1];
for(int i=2;i<=n;i++)build(i);
dfs(1);
for(int i=1;i<=n;i++)printf("%d ",ans[i]);
return 0;
}

AC代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1000010;
struct node{
int vi,ch[2],fa,id;
}ch[N],t[N];
int n,tot,line[N];
int read(){
int x=0,w=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*w;
} bool cmp(node a,node b){
return a.vi<b.vi;
} void add(int fa,int now,int f){
t[fa].ch[f]=now;
} void dfs(int x){
if(!x)return;
printf("%d ",t[x].vi);
dfs(t[x].ch[0]);dfs(t[x].ch[1]);
} int main(){
n=read();
for(int i=1;i<=n;i++){
ch[i].vi=read();ch[i].id=i;
}
sort(ch+1,ch+n+1,cmp);
for(int i=1;i<=n;i++){
int last=0;
while(tot&&t[line[tot]].id>ch[i].id)
last=tot--;
t[i].id=ch[i].id;t[i].vi=ch[i].vi;
add(line[tot],i,1);add(i,line[last],0);
line[++tot]=i;
}
dfs(t[0].ch[1]);
return 0;
}

[TJOI2011]树的序(贪心,笛卡尔树)的更多相关文章

  1. 7.28 NOI模拟赛 H2O 笛卡尔树 并查集 贪心 长链剖分

    LINK:H2O 这场比赛打的稀烂 爆蛋. 只会暴力.感觉暴力细节比较多不想写. 其实这道题的难点就在于 采取什么样的策略放海绵猫. 知道了这一点才能确定每次放完海绵猫后的答案. 暴力枚举是不行的.而 ...

  2. POJ 1785 Binary Search Heap Construction(裸笛卡尔树的构造)

    笛卡尔树: 每个节点有2个关键字key.value.从key的角度看,这是一颗二叉搜索树,每个节点的左子树的key都比它小,右子树都比它大:从value的角度看,这是一个堆. 题意:以字符串为关键字k ...

  3. PTA 笛卡尔树

    笛卡尔树 (25 分) 笛卡尔树是一种特殊的二叉树,其结点包含两个关键字K1和K2.首先笛卡尔树是关于K1的二叉搜索树,即结点左子树的所有K1值都比该结点的K1值小,右子树则大.其次所有结点的K2关键 ...

  4. Codeforces Round #114 (Div. 1) D. Wizards and Roads 笛卡尔树+树贪心+阅读题

    D. Wizards and Roads 题目连接: http://www.codeforces.com/contest/167/problem/D Description In some count ...

  5. [模板] 笛卡尔树 && RMQ

    话说我noip之前为什么要学这种东西... 简介 笛卡尔树(Cartesian Tree) 是一种二叉树, 且同时具有以下两种性质: 父亲节点的值大于/小于子节点的值; 中序遍历的结果为原序列. 笛卡 ...

  6. 平衡树及笛卡尔树讲解(旋转treap,非旋转treap,splay,替罪羊树及可持久化)

    在刷了许多道平衡树的题之后,对平衡树有了较为深入的理解,在这里和大家分享一下,希望对大家学习平衡树能有帮助. 平衡树有好多种,比如treap,splay,红黑树,STL中的set.在这里只介绍几种常用 ...

  7. 笛卡尔树Cartesian Tree

    前言 最近做题目,已经不止一次用到笛卡尔树了.这种数据结构极为优秀,但是构造的细节很容易出错.因此写一篇文章做一个总结. 笛卡尔树 Cartesian Tree 引入问题 有N条的长条状的矩形,宽度都 ...

  8. XJOI 3606 最大子矩形面积/LightOJ 1083 Histogram(单调栈/笛卡尔树)

    A histogram is a polygon composed of a sequence of rectangles aligned at a common base line. The rec ...

  9. 笛卡尔树 POJ ——1785 Binary Search Heap Construction

    相应POJ 题目:点击打开链接 Binary Search Heap Construction Time Limit: 2000MS   Memory Limit: 30000K Total Subm ...

随机推荐

  1. POJ 2356 Find a multiple( 鸽巢定理简单题 )

    链接:传送门 题意:题意与3370类似 注意:注意输出就ok,输出的是集合的值不是集合下标 /***************************************************** ...

  2. 06002_Redis概述

    1.什么是Redis? (1)Redis是用C语言开发的一个开源的高性能键值对(key-value)数据库,他通过提供多种键值对数据类型类适应不同场景下的存储需求: (2)Redis是一种高级的key ...

  3. Java基础学习总结(56)——学java必知十大学习目标

    诞生至今已有20年的Java,现在依然有很多人使用.回顾过去十五年的成果,Java一直是数一数二的.Java已经成为世界范围内应用最为广泛的编程语言之一.那么在学java的时候你知道到底要学什么吗?一 ...

  4. 2015 Multi-University Training Contest 6 hdu 5361 In Touch

    In Touch Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total ...

  5. ASP.NET-MVC中Entity和Model之间的关系

    Entity 与 Model之间的关系图 ViewModel类是MVC中与浏览器交互的,Entity是后台与数据库交互的,这两者可以在MVC中的model类中转换 MVC基础框架 来自为知笔记(Wiz ...

  6. Oracle安装和使用说明

    很久没有安装Oracle了,今天试了一下重新安装Oracle,然后做了一个总结: 一.Oracle 下载 注意Oracle分成两个文件,下载完后,将两个文件解压到同一目录下即可. 路径名称中,最好不要 ...

  7. echarts 设置x轴的和y轴的属性

    axisLabel:{ interval:0,//横轴信息全部显示 rotate:-30,//-30度角倾斜显示 } splitNumber:10

  8. 【转载】tslib移植_freescale imx6

    本文来自网络:http://blog.csdn.net/xishuang_gongzi/article/details/49422879 环境:host:Ubuntu12.04target:frees ...

  9. [Tools] Create your own mobile emulator device by using Chrome dev tool

    Using the New Device Emulation Interface The Device Emulation interface changed a bit with the newer ...

  10. hdu 5077 NAND(打表)2014 Asia regional 鞍山站 H题

    题目链接:点击打开链接 题意:就是一个按位运算的一个函数.问最少经过多少步运算能够得到给定数. 思路:不是我投机取巧想打表.是特么这题仅仅能打表.. .打表思想用能够得到的数的集合表示状态bfs:最后 ...