题目描述

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作(对于各个以往的历史版本):

  1. 插入x数

  2. 删除x数(若有多个相同的数,因只删除一个,如果没有请忽略该操作)

  3. 查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)

  4. 查询排名为x的数

  5. 求x的前驱(前驱定义为小于x,且最大的数,如不存在输出-2147483647)

  6. 求x的后继(后继定义为大于x,且最小的数,如不存在输出2147483647)

和原本平衡树不同的一点是,每一次的任何操作都是基于某一个历史版本,同时生成一个新的版本。(操作3, 4, 5, 6即保持原版本无变化)

每个版本的编号即为操作的序号(版本0即为初始状态,空树)

输入输出格式

输入格式:

第一行包含一个正整数N,表示操作的总数。

接下来每行包含三个正整数,第 i 行记为 vi​,opti​,xi​。

vi​表示基于的过去版本号( 0≤vi​<i ),opti​ 表示操作的序号( 1≤opt≤6 ), xi​ 表示参与操作的数值

输出格式:

每行包含一个正整数,依次为各个3,4,5,6操作所对应的答案

输入输出样例

输入样例#1:

10
0 1 9
1 1 3
1 1 10
2 4 2
3 3 9
3 1 2
6 4 1
6 2 9
8 6 3
4 5 8
输出样例#1:

9
1
2
10
3

说明

数据范围:

对于28%的数据满足: 1≤n≤10

对于44%的数据满足: 1≤n≤2⋅102

对于60%的数据满足: 1≤n≤3⋅103

对于84%的数据满足: 1≤n≤105

对于92%的数据满足: 1≤n≤2⋅105

对于100%的数据满足:1≤n≤5⋅105 , −109≤xi​≤109

经实测,正常常数的可持久化平衡树均可通过,请各位放心

样例说明:

共10次操作,11个版本,各版本的状况依次是:

  1. [][]

  2. [9][9]

  3. [3, 9][3,9]

  4. [9, 10][9,10]

  5. [3, 9][3,9]

  6. [9, 10][9,10]

  7. [2, 9, 10][2,9,10]

  8. [2, 9, 10][2,9,10]

  9. [2, 10][2,10]

  10. [2, 10][2,10]

  11. [3, 9][3,9]

Solution:

  本题可持久化平衡树板子题(没啥好写的)。

  我们先用无旋treap打下普通平衡树那道板子题,那么可持久化无非是在之前版本的状态基础上每次新开节点记录新的状态就好了。

  于是只需要每次改为新建节点去merge,改为新建节点去split,记录每个版本的树根就好了(感觉很简单啊)。

代码:

/*Code by 520 -- 9.26*/
#include<bits/stdc++.h>
#define il inline
#define ll long long
#define RE register
#define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
#define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)
using namespace std;
const int N=5e5+,inf=0x7fffffff;
int n,root[N],cnt;
struct node{
int ls,rs,siz,date,rnd;
}t[N*]; int gi(){
int a=;char x=getchar();bool f=;
while((x<''||x>'')&&x!='-') x=getchar();
if(x=='-') x=getchar(),f=;
while(x>=''&&x<='') a=(a<<)+(a<<)+(x^),x=getchar();
return f?-a:a;
} il int newnode(int v){
++cnt;
t[cnt].date=v,t[cnt].siz=,t[cnt].rnd=rand();
return cnt;
} il void up(int rt){t[rt].siz=t[t[rt].ls].siz+t[t[rt].rs].siz+;} int merge(int x,int y){
if(!x||!y) return x+y;
if(t[x].rnd<t[y].rnd){
int p=++cnt;t[p]=t[x];
t[p].rs=merge(t[p].rs,y);
up(p);
return p;
}
else {
int p=++cnt;t[p]=t[y];
t[p].ls=merge(x,t[p].ls);
up(p);
return p;
}
} void split(int rt,int k,int &x,int &y){
if(!rt) {x=y=;return;}
if(t[rt].date<=k){
x=++cnt;t[x]=t[rt];
split(t[x].rs,k,t[x].rs,y);
up(x);
}
else {
y=++cnt;t[y]=t[rt];
split(t[y].ls,k,x,t[y].ls);
up(y);
}
} void del(int &root,int v){
int x=,y=,z=;
split(root,v,x,z),split(x,v-,x,y);
y=merge(t[y].ls,t[y].rs);
root=merge(x,merge(y,z));
} void ins(int &root,int v){
int x=,y=; split(root,v,x,y);
root=merge(x,merge(newnode(v),y));
} il int kth(int rt,int v){
while(){
if(v<=t[t[rt].ls].siz) rt=t[rt].ls;
else if(v>t[t[rt].ls].siz+) v-=t[t[rt].ls].siz+,rt=t[rt].rs;
else return t[rt].date;
}
} il int id(int &root,int v){
int x=,y=,ans; split(root,v-,x,y);
ans=t[x].siz+;
root=merge(x,y);
return ans;
} il int pre(int &root,int v){
int x=,y=,ans; split(root,v-,x,y);
if(!x) return -inf;
ans=kth(x,t[x].siz);
root=merge(x,y);
return ans;
} il int suc(int &root,int v){
int x=,y=,ans; split(root,v,x,y);
if(!y) return inf;
ans=kth(y,);
root=merge(x,y);
return ans;
} int main(){
srand(time());
n=gi();
int v,opt,x;
For(i,,n){
v=gi(),opt=gi(),x=gi();
root[i]=root[v];
if(opt==) ins(root[i],x);
if(opt==) del(root[i],x);
if(opt==) printf("%d\n",id(root[i],x));
if(opt==) printf("%d\n",kth(root[i],x));
if(opt==) printf("%d\n",pre(root[i],x));
if(opt==) printf("%d\n",suc(root[i],x));
}
return ;
}

P3835 【模板】可持久化平衡树的更多相关文章

  1. luoguP3835 [模板]可持久化平衡树

    https://www.luogu.org/problemnew/show/P3835 因为博主精力和实力有限,学不懂 fhq treap 了,因此只介绍 leafy tree 解法 leafy tr ...

  2. 洛谷.3835.[模板]可持久化平衡树(fhq treap)

    题目链接 对每次Merge(),Split()时产生的节点都复制一份(其实和主席树一样).时间空间复杂度都为O(qlogq).(应该更大些 因为rand()?内存真的爆炸..) 对于无修改的操作实际上 ...

  3. Luogu P3835 【模板】可持久化平衡树(fhq Treap)

    P3835 [模板]可持久化平衡树 题意 题目背景 本题为题目普通平衡树的可持久化加强版. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作(对于各个以往的历史版本 ...

  4. 洛谷P3835 【模板】可持久化平衡树

    题目背景 本题为题目 普通平衡树 的可持久化加强版. 数据已经经过强化 感谢@Kelin 提供的一组hack数据 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作( ...

  5. luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树)(主席树)

    luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树) 题目 #include<iostream> #include<cstdlib> #include< ...

  6. [Luogu 3835]【模板】可持久化平衡树

    Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作(对于各个以往的历史版本): 插入x数 删除x数(若有多个相同的数,因只删除一个,如果没有请忽略该操作 ...

  7. LG3835 【模板】可持久化平衡树

    题意 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作(对于各个以往的历史版本): 插入x数 删除x数(若有多个相同的数,因只删除一个,如果没有请忽略该操作) 查询x数的排名 ...

  8. 2021.07.02 P1383 高级打字机题解(可持久化平衡树)

    2021.07.02 P1383 高级打字机题解(可持久化平衡树) 分析: 从可以不断撤销并且查询不算撤销这一骚操作可以肯定这是要咱建一棵可持久化的树(我也只会建可持久化的树,当然,还有可持久化并查集 ...

  9. 可持久化Trie & 可持久化平衡树 专题练习

    [xsy1629]可持久化序列 - 可持久化平衡树 http://www.cnblogs.com/Sdchr/p/6258827.html [bzoj4260]REBXOR - Trie 事实上只是一 ...

随机推荐

  1. 如何fork比特币的源码并同步更新到本地

    一.首先在Github上fork比特币源码,就会在自己的项目库里创建一份比特币代码的拷贝.   打开https://github.com/bitcoin/bitcoin,点击右上角的“Fok”图标,稍 ...

  2. oracle vm virtualbox 保存虚拟系统,重装后使用

    直接将VirtualBox VMs 文件夹打包,然后在新系统中装好virtualbox 解压virtualBox VMs ,在系统文件夹中找到 .vbox结尾的文件,点击, 就可以看到熟悉的系统出现在 ...

  3. SQL注入原理&分类&危害&防御

    SQL是什么? 结构化查询语句 SQL注入是什么? 是一种将SQL 语句插入或添加到用户输入的参数中,这些参数传递到后台服务器,加以解析并执行 造成注入的原因/原理? 1.对用户输入的参数没有进行严格 ...

  4. vue处理循环列表动态数据问题

    调用方法:Vue.set( target, key, value ) target:要更改的数据源(可以是对象或者数组) key:要更改的具体数据 value :重新赋的值 <!DOCTYPE ...

  5. Elasticsearch的停用词(stopwords)

    1.问题 在使用搜索引擎(Elasticsearch或Solr)作为应用的后台搜索平台的时候,会遇到停用词(stopwords)的问题. 在信息检索中,停用词是为节省存储空间和提高搜索效率,处理文本时 ...

  6. awk之close函数

    echo "21 2 " | awk '{ first[NR]=$ second[NR]=$ }END{ print "======打印第1列并排序:========== ...

  7. Homebrew1.5之后安装PHP和扩展

    Homebrew 1.5 宣布放弃 homebrew/php, 转而使用homebrew/core维护, 详见https://brew.sh/2018/01/19/homebrew-1.5.0/ 于是 ...

  8. a标签的href为空的问题

    在表格里写一个a标签链接刷新表格的时候,没注意,把a标签的href设置为""空字符串,导致每次刷新表格之后会再刷新一次整体页面,找了很久都没发现问题出在哪里,最后无意之间,鼠标在一 ...

  9. VirtualBox安装增强功能

    一.安装依赖包 #yum install kernel-headers #yum install kernel-devel #yum install gcc* #yum install make 二. ...

  10. STL的集合set

    集合: 集合是由元素组成的一个类,其成员可以是一个集合,也可以是一个原子,通常一个元素在一个集合中不能多次出现:由于对实现集合不是很理解,只简单写下已有的STL中的set集合使用: C++中set基本 ...