[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. 区间dp+四边形不等式优化

    区间dp+四边形优化 luogu:p2858 题意 给出一列数 \(v_i\),每天只能取两端的数,第 j 天取数价值为\(v_i \times j\),最大价值?? 转移方程 dp[i][j] :n ...

  2. Ubuntu_18.04安装网易云音乐

    首先到网易云音乐官网下载网易云音乐,ubuntu版的,安装. 这时候的图标打不开,缺少libcanberra sudo apt install libcanberra-gtk-module 安装完了配 ...

  3. IOS - ImagePicker 连拍

    - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)sel ...

  4. HDU 1028 Ignatius and the Princess III(母函数整数拆分)

    链接:传送门 题意:一个数n有多少种拆分方法 思路:典型母函数在整数拆分上的应用 /********************************************************** ...

  5. TI低功耗蓝牙(BLE)介绍

    TI低功耗蓝牙(BLE)介绍 本文档翻译和修改自参考资料:CC2540Bluetooth Low Energy Software Developer’s Guide (Rev. B),部分图片直接引用 ...

  6. axios统一拦截配置

    在vue项目中,和后台进行数据交互使用axios.要想统一处理所有的http请求和响应,就需要使用axios的拦截器.通过配置http response inteceptor 统一拦截后台的接口数据, ...

  7. 紫书 习题7-14 UVa 307(暴搜+剪枝)

    这道题一开始我想的是在排序之后只在头和尾往中间靠近来找木块, 然后就WA, 事实证明这种方法是错误的. 然后参考了别人的博客.发现别人是直接暴搜, 但是加了很多剪枝, 所以不会超时. 我也想过这个做法 ...

  8. WinServer-PowerShell基础

    命令的参数: [-name] 这个参数必须要有,string表示name参数接受什么样的实参,<>表示参数可以接受的实参类型,通常出现set get add都会伴随着必须参数 [-name ...

  9. 【转】工具系列:IntelliJ IDEA (Mac) 运行速度优化

    转自工具系列:IntelliJ IDEA (Mac) 运行速度优化 感谢该作者解决了我使用idea debug很慢的问题 背景 IDEA 下运行程序,经常假死 5 s,作为 Mac 怎么能允许暂停 5 ...

  10. HDU 4175 Class Schedule (暴力+一点dp)

    pid=4175">HDU 4175 题意:有C座楼,每座楼有T个教室.一个人须要訪问C个教室.每座楼仅仅能訪问一个教室. 訪问教室须要消耗能量,从x点走到y点须要消耗abs(x-y) ...