单调队列优化O(N)建BST P1377 [TJOI2011]树的序
洛谷 P1377 [TJOI2011]树的序 (单调队列优化建BST
题意分析
本题思路很简单,根据题意,我们利用所给的Bst生成序将Bst建立起来,然后输出该BST的先序遍历即可;
但,如果我们不加优化,建BST的时间复杂度在最劣情况下将达到O(n^2),显然,在1e5的数据下是过不去的,所以我们考虑利用利用单调队列优化来建BST;
算法思路
BST建树本质上便是按照权值将新加入节点插入到对应的位置,该过程受插入顺序
影响
我们考虑可以将读入的生成序列的下标变成权值,本身权值变为下标
for(int i=1;i<=n;i++){
x=read();
a[x]=i;
}
因为权值为1-n的序列,我们将该数组从1-n遍历,本质便是按权值从小到大遍历(如
果权值不是1-n的序列,将其离散化即可)
我们按该方式维护一个单调队列,当一个新数进队列后不在向前更新时,我们便将
该节点插到单调队列中它左侧节点的右子树中,原因很简单,该节点左侧的节点先
入队列,说明左侧权值一定比该节点小,故将该点插入到左侧节点的右子树上,假设
该节点进队列过程中压掉了节点,则将该节点插入到被它压掉的最后一个节点的左
子树上,我们用此方法便可以在O(n)的时间复杂度下建成一颗bst了,建树代码如下
int tot=0;
int pos=0;
for(int i=1;i<=n;i++){
tot=pos;
while(pos&&a[q[pos]]>a[i]){
pos--;
}
if(pos){
r[q[pos]]=i;
}
if(pos<tot){
l[i]=q[pos+1];
}
q[tot=++pos]=i;
}
为什这样建树可以建出正确的bst呢?
我们举个例子
比如3 2 4 1这个序列
排序后变为了1(4) 2(2) 3(1) 4(3)
括号内为权值,括号外为下标
第一步,插入1(4)
第二步,插入2(2)因为在单调队列中我们将其压掉了所以,将1(4)a插入到2(2)的左子树中
第三步
同理
第四步,目前单调队列中只有3(1)新点4(3)进入后无法压掉3(1)便放在3(1)的左子树中
建树完毕,我们按权值加入,每进入一个点便插入到目前的合适位置,当更优的点
出现时,倘若恰好将此点压掉,我们便将上一个点与该点的连接关系断开,将新节
点插入到这两个节点之间,如下图
红色为新加入节点
为什么后续加入的节点不会插到以经压入的节点下呢?得益于我们加入节点是按权值从小到大加入的
比如说上图,既然红色节点已经入队列了,能红色节点的子树中插入的节点一定小于红色节点的权值,但已经没有了
这就是整个算法的思路
完整代码如下
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int maxn=1e6+10;
inline int read(){
int ret=0;
int f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-'){
f=-f;
}
ch=getchar();
}
while(ch>='0'&&ch<='9'){
ret=ret*10+(ch^'0');
ch=getchar();
}
return ret*f;
}
int q[maxn];
int l[maxn];
int r[maxn];
int a[maxn];
int n;
void dfs(int ro){
if(!ro){
return ;
}
cout<<ro<<" ";
dfs(l[ro]);
dfs(r[ro]);
return ;
}
int main(){
n=read();
int x;
for(int i=1;i<=n;i++){
x=read();
a[x]=i;
}
int tot=0;
int pos=0;
for(int i=1;i<=n;i++){
tot=pos;
while(pos&&a[q[pos]]>a[i]){
pos--;
}
if(pos){
r[q[pos]]=i;
}
if(pos<tot){
l[i]=q[pos+1];
}
q[tot=++pos]=i;
}
dfs(q[1]);
return 0;
}
完结撒花!
单调队列优化O(N)建BST P1377 [TJOI2011]树的序的更多相关文章
- 洛谷 P1377 [TJOI2011]树的序 解题报告
P1377 [TJOI2011]树的序 题目描述 众所周知,二叉查找树的形态和键值的插入顺序密切相关.准确的讲:1.空树中加入一个键值\(k\),则变为只有一个结点的二叉查找树,此结点的键值即为\(k ...
- Luogu P1377 [TJOI2011]树的序:离线nlogn建二叉搜索树
题目链接:https://www.luogu.org/problemnew/show/P1377 题意: 有一棵n个节点的二叉搜索树. 给出它的插入序列,是一个1到n的排列. 问你使得树的形态相同的字 ...
- [洛谷 P1377] TJOI2011 树的序
问题描述 众所周知,二叉查找树的形态和键值的插入顺序密切相关.准确的讲:1.空树中加入一个键值k,则变为只有一个结点的二叉查找树,此结点的键值即为k:2.在非空树中插入一个键值k,若k小于其根的键值, ...
- BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP
BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP Description 有一排n棵树,第i棵树的高度是Di. MHY要从第一棵树到第n棵树去找他的妹子玩. 如果MHY在 ...
- BZOJ 2806: [Ctsc2012]Cheat [广义后缀自动机 单调队列优化DP 二分]
2806: [Ctsc2012]Cheat 题意: 多个主串和多个询问串,每次询问将询问串分成多个连续子串,如果一个子串长度>=L且在主串中出现过就是熟悉的 如果熟悉的字符串长度>=询问串 ...
- 2018.09.06 烽火传递(单调队列优化dp)
描述 烽火台是重要的军事防御设施,一般建在交通要道或险要处.一旦有军情发生,则白天用浓烟,晚上有火光传递军情. 在某两个城市之间有 n 座烽火台,每个烽火台发出信号都有一定的代价.为了使情报准确传递, ...
- Mice and Holes 单调队列优化dp
Mice and Holes 单调队列优化dp n个老鼠,m个洞,告诉你他们的一维坐标和m个洞的容量限制,问最小总距离.1 ≤ n, m ≤ 5000. 首先列出朴素的dp方程:\(f[i][j] ...
- BZOJ 2806 [Ctsc2012]Cheat ——后缀自动机 单调队列优化DP
先建出广义后缀自动机. 然后跑出文章中每一个位置的最大匹配距离. 然后定义$f[i]$表示匹配到以$i$结尾的串时,最长的匹配距离. 显然可以二分$L$的取值. 然后容易得到$DP$方程 $f[i]= ...
- 【BZOJ2806】【CTSC2012】Cheat - 广义后缀自动机+单调队列优化DP
题意: Description Input 第一行两个整数N,M表示待检查的作文数量,和小强的标准作文库的行数 接下来M行的01串,表示标准作文库 接下来N行的01串,表示N篇作文 Output N行 ...
随机推荐
- 3分钟教会你如何发布Qt程序
导读:Qt程序编写好以后该如何发布.本文教你使用Qt自带工具windeployqt来进行操作. 本文字数:500,阅读时长大约:3分钟 (1)编写一个简单的程序 我们先做一个简单的窗口,添加一个图片资 ...
- HTML5移动开发之路(1)——jqMobi中Side Menu实现(类似人人网)
记得以前在做Native App的时候类似于人人网侧边滑动的效果非常的热,很多app仿照该效果进行开发,在jqMobi中也有类似的效果被称为Side Menu.下面我们来一步一步实现该效果. 首先新建 ...
- 不要再学 JSP 了,学 SpringBoot + Thymeleaf + Vue吧
老读者就请肆无忌惮地点赞吧,微信搜索[沉默王二]关注这个在九朝古都洛阳苟且偷生的程序员.本文 GitHub github.com/itwanger 已收录,里面还有我精心为你准备的一线大厂面试题. 读 ...
- WPF新手快速入门系列 1.布局
[概要] 该系列文章主要描述,新手如何快速上手做wpf开发.看过网上部分的教程,主要讲述的是介绍控件.这并没有问题,但是没有把自己的使用经验也完整的描述出来. 所以特此编写此系列文章希望能帮助到,因为 ...
- 华师2019软件专硕复试机试题最后一题G:找数
G. 找数 单点时限: 1.0 sec 内存限制: 256 MB 问题描述 输入一个整数 n( 2≤n≤10 ) ,你需要找到一些 n 位数(允许有前置 0 ,见样例),这些 n 位数均 由 0 ~ ...
- elementui table fixed错位
目前在官方没有解决这个bug前如果有人碰到类似问题.建议大家监听table数据,每次数据得到或改变的时候去重新渲染一下 /* 监听table数据对象 */ watch: { tableDa ...
- IOS 打包相关
Unity 导出的Xcode工程 http://gad.qq.com/article/detail/29330 [Unity3D]Unity 生成的XCode工程结构 http://blog.163. ...
- WebStorm 运行Rect Native 项目
今天教大家如何直接使用WebStorm这个IDE直接完成编码+运行项目工作.这样就可以不用打开Xcode了. 1.首先点击WebStorm右上方的下拉箭头弹出的Edit Configurations. ...
- Spring.Net依赖注入(属性注入)学习笔记
一.前言: Spring.Net是Java开源框架迁移过来的,主要分为 1)依赖注入 2)面向方面编程 3)数据访问抽象 4)Asp.Net扩展 四个模块功能,这里只是简单介绍依赖注入模块功能. 对于 ...
- 20190925-01安装redis 000 022
1.将redis压缩包放入Linux系统有4种办法. 第一:如果安装了VMware Tools工具可以直接进行拖拽 第二:在windows中找到配置好的共享文件夹将redis压缩包放入其中,在Linu ...