bzoj 2770 堆的中序遍历性质
我们知道二叉搜索树的中序遍历是一个已经排好序的序列,知道序列我们无法确定树的形态(因为有多种)。
但是,Treap如果告诉我们它的关键字以及权值,那么就可以唯一确定树的形态(Treap的O(logn)的期望时间复杂度就是依靠一个随机堆的深度不会太深)
具体的,已知关键字序列:k1,k2,k3...kn和优先级序列:p1,p2,p3,...pn,
如果我们想要找ki的父亲,只需要找“左边第一个p比它大的和右边第一个p比它大的中,p较小的那个“
至于lca(ki,kj),是对应的pi~pj中的最小值(因为是小根堆)
至于深度,多次找父亲,路径长度就是深度,然后画一下图可以发现轨迹的特点,然后就可以搞了(求两段递增子序列长度)
/**************************************************************
Problem: 2770
User: idy002
Language: C++
Result: Accepted
Time:6140 ms
Memory:46124 kb
****************************************************************/ #include <cstdio>
#include <vector>
#include <algorithm>
#define oo 0x6FFFFFFF
#define maxn 400010
using namespace std; typedef pair<int,int> dpr; struct Node {
int lf, rg, mid;
dpr st;
bool leaf;
Node *ls, *rs;
} pool[maxn*], *tail=pool, *root;
vector<Node*> stk; int disc[maxn], ntot;
int sv[maxn];
int pr[maxn][]; Node *build( int lf, int rg ) {
Node *nd = ++tail;
nd->lf=lf, nd->rg=rg, nd->mid=(lf+rg)>>;
if( lf==rg ) {
nd->st = dpr( oo, );
nd->leaf = true;
} else {
nd->ls = build( lf, nd->mid );
nd->rs = build( nd->mid+, rg );
nd->st = dpr( oo, );
nd->leaf = false;
}
return nd;
}
dpr qu_min( Node *nd, int lf, int rg ) {
if( lf <= nd->lf && nd->rg <= rg ) return nd->st;
dpr rt = dpr( oo, );
if( lf <= nd->mid )
rt = qu_min( nd->ls, lf, rg );
if( rg > nd->mid )
rt = min( rt, qu_min( nd->rs, lf, rg ) );
return rt;
}
void pushup( Node *nd ) {
nd->st = min( nd->ls->st, nd->rs->st );
}
void modify( Node *nd, int pos, int val ) {
if( nd->leaf ) {
nd->st = dpr( val, pos );
return;
}
if( pos <= nd->mid )
modify( nd->ls, pos, val );
else
modify( nd->rs, pos, val );
pushup( nd );
}
int lca( int u, int v ) {
if( u>v ) swap(u,v);
return qu_min( root, u, v ).second;
} int main() {
int n, m, T;
scanf( "%d%d", &n, &m );
T = n+m;
for( int i=; i<=n; i++ ) {
pr[i][] = ;
scanf( "%d", pr[i]+ );
disc[++ntot] = pr[i][];
}
for( int i=; i<=n; i++ )
scanf( "%d", pr[i]+ );
for( int i=n+; i<=T; i++ ) {
char opt[];
scanf( "%s", opt );
pr[i][] = opt[]=='I' ? :
opt[]=='D' ? : ;
if( pr[i][]== ) {
scanf( "%d%d", pr[i]+, pr[i]+ );
disc[++ntot] = pr[i][];
} else if( pr[i][]== ) {
scanf( "%d", pr[i]+ );
} else {
scanf( "%d%d", pr[i]+, pr[i]+ );
}
}
sort( disc+, disc++ntot );
ntot = unique( disc+, disc++ntot ) - disc - ;
for( int i=; i<=T; i++ ) {
pr[i][] = lower_bound( disc+, disc++ntot, pr[i][] )-disc;
if( pr[i][]== )
pr[i][] = lower_bound( disc+, disc++ntot, pr[i][] )-disc;
}
root = build( , ntot );
for( int i=; i<=T; i++ ) {
if( pr[i][]== ) {
modify( root, pr[i][], pr[i][] );
} else if( pr[i][]== ) {
modify( root, pr[i][], oo );
} else {
int u = pr[i][];
int v = pr[i][];
printf( "%d\n", disc[lca(u,v)] );
}
}
}
bzoj 2770 堆的中序遍历性质的更多相关文章
- PAT-2019年冬季考试-甲级 7-4 Cartesian Tree (30分)(最小堆的中序遍历求层序遍历,递归建树bfs层序)
7-4 Cartesian Tree (30分) A Cartesian tree is a binary tree constructed from a sequence of distinct ...
- [leetcode]_根据二叉树的先序遍历(后序遍历) + 中序遍历 重建二叉树
题目1:Construct Binary Tree from Preorder and Inorder Traversal 给定一棵二叉树的先序遍历和中序遍历,求重建二叉树. 思路: 1.先序遍历的第 ...
- PAT-1167(Cartesian Tree)根据中序遍历序列重建最小堆
Cartesian Tree PAT-1167 一开始我使用数组进行存储,但是这样可能会导致无法开足够大的数组,因为树如果是链表状的则无法开这么大的数组(虽然结点很少). 正确的解法还是需要建树,使用 ...
- 10.26最后的模拟DAY2 改造二叉树[中序遍历+严格递增的最长不下降子序列]
改造二叉树 [题目描述] 小Y在学树论时看到了有关二叉树的介绍:在计算机科学中,二叉树是每个结点最多有两个子结点的有序树.通常子结点被称作“左孩子”和“右孩子”.二叉树被用作二叉搜索树和二叉堆.随后他 ...
- nyoj202_红黑树_中序遍历
红黑树 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 什么是红黑树呢?顾名思义,跟枣树类似,红黑树是一种叶子是黑色果子是红色的树... 当然,这个是我说的... & ...
- 二叉树中序遍历 (C语言实现)
在计算机科学中,树是一种重要的非线性数据结构,直观地看,它是数据元素(在树中称为结点)按分支关系组织起来的结构.二叉树是每个节点最多有两个子树的有序树.通常子树被称作“左子树”(left subtre ...
- 证明中序遍历O(n)
算法导论12.1 什么是二叉搜索树 二叉搜索树应满足的性质: 设x是二叉搜索树中的一个结点.如果y是x左子树中的一个结点,那么y.key <= x.key.如果y是右子树中的一个结点,那么y.k ...
- C++编程练习(8)----“二叉树的建立以及二叉树的三种遍历方式“(前序遍历、中序遍历、后续遍历)
树 利用顺序存储和链式存储的特点,可以实现树的存储结构的表示,具体表示法有很多种. 1)双亲表示法:在每个结点中,附设一个指示器指示其双亲结点在数组中的位置. 2)孩子表示法:把每个结点的孩子排列起来 ...
- 根据 中序遍历 和 后序遍历构造树(Presentation)(C++)
好不容易又到周五了,周末终于可以休息休息了.写这一篇随笔只是心血来潮,下午问了一位朋友PAT考的如何,顺便看一下他考的试题,里面有最后一道题,是关于给出中序遍历和后序遍历然后求一个层次遍历.等等,我找 ...
随机推荐
- 大数加法(SDUT“斐波那契”串)4335
题目链接:https://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Contest/contestproblem/cid/2697/pid/4335.ht ...
- 好消息! 不用再羡慕Python有jupyter 我R也有Notebook了【附演示视频】
熟悉python的朋友可能知道jupyter notebook.它是一个Web应用程序,允许你创建和共享代码,方程,可视化和说明性文本文档.现在,我们可以在RStudio中实现R Notebook的功 ...
- 【shell】shell编程(五)-读取参数
通过前几篇文章的学习,我们学会了shell的基本语法.在linux的实际操作中,我们经常看到命令会有很多参数,例如:ls -al 等等,那么这个参数是怎么处理的呢? 接下来我们就来看看shell脚本对 ...
- 我的Apache又挂了之apache错误:server's fully qualified domain name, using 127.0.0.1. Set the 'ServerName'
表示物理机装Apache然后有时候关机会忘了关闭Apache然后长此以往会导致各种Apache起不来的缘故,上一次已经出现过一次.今天又出现了 再次记录一下解决的方法. 1.查看错误日志 /var/l ...
- 关于linux系统如何实现fork的研究(一)【转】
转自:http://www.aichengxu.com/linux/4157180.htm 引言 fork函数是用于在linux系统中创建进程所使用,而最近看了看一个fork()调用是怎么从应用到gl ...
- myeclipse/eclipse安装反编译插件jadclipse
jad是一个使用比较广泛的Java反编译软件,jadClipse是jad在eclipse下的插件,下面像大家介绍下如何将jadclipse加入到myeclipse/eclipse中. 文件下载 (1) ...
- springboot + swagger2 生成api文档
直接贴代码: <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-sw ...
- 到底什么是Upnp?[转载]
本文出自:http://www.cnblogs.com/nehu/archive/2006/05/13/399342.html 解释一. 准确地说,UPnP(Universal Plug and Pl ...
- Windows: 在系统启动时运行程序、定时计划任务、定时关机
lesca今天介绍一些让系统在启动时,而非登录时,加载用户自定义的应用程序或脚本的方法,推荐度从前到后依次递减. 1. Windows任务计划(task scheduler) 用户可以按以下步骤进行操 ...
- StringBuilder基本用法
//StringBuilder用法 public class StringBuilderTest { public static void main(String[] args) { StringBu ...