3224: Tyvj 1728 普通平衡树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 3948  Solved: 1627
[Submit][Status][Discuss]

Description

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)

Input

第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)

Output

对于操作3,4,5,6每行输出一个数,表示对应答案

Sample Input

10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598

Sample Output

106465
84185
492737

HINT

1.n的数据范围:n<=100000
2.每个数的数据范围:[-1e7,1e7]
 #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int maxn=;
int key[maxn],lc[maxn],rc[maxn],fa[maxn],siz[maxn];
int tot,root;
int T;
void update(int x){
siz[x]=siz[lc[x]]++siz[rc[x]];
}
void r_rotate(int x){
int y=fa[x];
lc[y]=rc[x];
if(rc[x]!=) fa[rc[x]]=y;
fa[x]=fa[y];
if(y==lc[fa[y]]) lc[fa[y]]=x;
else rc[fa[y]]=x;
fa[y]=x; rc[x]=y;
update(x); update(y);
}
void l_rotate(int x){
int y=fa[x];
rc[y]=lc[x];
if(lc[x]!=) fa[lc[x]]=y;
fa[x]=fa[y];
if(y==lc[fa[y]]) lc[fa[y]]=x;
else rc[fa[y]]=x;
fa[y]=x; lc[x]=y;
update(x); update(y);
}
void splay(int x,int s){
int p;
while(fa[x]!=s){
p=fa[x];
if(fa[p]==s){
if(x==lc[p]) r_rotate(x);
else l_rotate(x);
break;
}
if(x==lc[p]){
if(p==lc[fa[p]]) r_rotate(p),r_rotate(x);
else r_rotate(x),l_rotate(x);
}
else{
if(p==rc[fa[p]]) l_rotate(p),l_rotate(x);
else l_rotate(x),r_rotate(x);
}
}
if(s==) root=x;
update(x);
}
int find(int v){//查找在这棵树中键值为v的节点
int x=root;
while(x!=){
if(v<key[x]) x=lc[x];
else if(v>key[x]) x=rc[x];
else if(v==key[x]){
splay(x,);
return x;
}
}
return -;
}
void New_node(int &x,int fath,int v){//建立新节点
x=++tot;
lc[x]=rc[x]=; siz[x]=;
fa[x]=fath;
key[x]=v;
}
void insert(int v){//插入新节点
if(root==){
New_node(rc[],,v);
root=tot;
return ;
}
int p,x=root;
while(x!=){
p=x;
if(v<=key[x]) siz[x]++,x=lc[x];
else siz[x]++,x=rc[x];
}
if(v<=key[p]) New_node(lc[p],p,v);
else New_node(rc[p],p,v);
splay(tot,);
}
int getmax(int x){//找到以x为根的最大值
if(rc[x]!=) return getmax(rc[x]);
return x;
}
int getmin(int x){//找到以x为根的最小值
if(lc[x]!=) return getmin(lc[x]);
return x;
}
int getpre(int x){//找到节点x的前驱
splay(x,);
return getmax(lc[x]);
}
int getne(int x){//找到节点x的后继
splay(x,);
return getmin(rc[x]);
}
void Delete(int v){
int x=find(v);
int pp=getmax(lc[x]);
int nn=getmin(rc[x]);
if(lc[x]==||rc[x]==){
if(lc[x]==&&rc[x]==){
root=; rc[]=;
return ;
}
if(lc[x]==){
rc[]=rc[x]; fa[rc[x]]=; root=rc[x]; rc[x]=;
siz[x]=;
return ;
}
else{
rc[]=lc[x]; fa[lc[x]]=; root=lc[x]; lc[x]=;
siz[x]=;
return ;
}
}
splay(pp,);
splay(nn,root);
fa[lc[nn]]=; siz[lc[nn]]=; lc[nn]=;
update(nn); update(pp);
}
int rank(int rt,int v){//返回键值为v的节点的排名
if(rt==) return ;
if(v<=key[rt]) return rank(lc[rt],v);
else return siz[lc[rt]]++rank(rc[rt],v);
}
int findkth(int x,int k){//在以x为根的树中找第 k大
if(siz[lc[x]]+==k) return key[x];
if(siz[lc[x]]+>k) return findkth(lc[x],k);
return findkth(rc[x],k-siz[lc[x]]-);
} int pred(int rt,int v){//返回比 v小的最大的数
if(rt==) return v;
if(v<=key[rt]) return pred(lc[rt],v);
else{
int ans=pred(rc[rt],v);
if(ans==v) return key[rt];
return ans;
}
}
int succ(int rt,int v){//返回比 v大的最小的数
if(rt==) return v;
if(v>=key[rt]) return succ(rc[rt],v);
else{
int ans=succ(lc[rt],v);
if(ans==v) return key[rt];
return ans;
}
}
int main(){
freopen("phs.in","r",stdin);
freopen("phs.out","w",stdout);
scanf("%d",&T);
while (T--){
int kin,num;
scanf("%d%d",&kin,&num);
if(kin==)
insert(num);//插入
else if(kin==)
Delete(num);//删除(若有多个相同的数,只删除一个)
else if(kin==)
printf("%d\n",rank(root,num));//查询num数的排名(若有多个相同的数,因输出最小的排名)
else if (kin==)
printf("%d\n",findkth(root,num));//查询排名为x的数
else if (kin==)
printf("%d\n",pred(root,num));
else if (kin==)
printf("%d\n",succ(root,num));
}
return ;
}

伸展树基础(Splay)的更多相关文章

  1. 伸展树(Splay Tree)进阶 - 从原理到实现

    目录 1 简介 2 基础操作 2.1 旋转 2.2 伸展操作 3 常规操作 3.1 插入操作 3.2 删除操作 3.3 查找操作 3.4 查找某数的排名.查找某排名的数 3.4.1 查找某数的排名 3 ...

  2. 伸展树(Splay)学习笔记

    二叉排序树能够支持多种动态集合操作,它可以被用来表示有序集合,建立索引或优先队列等.因此,在信息学竞赛中,二叉排序树应用非常广泛. 作用于二叉排序树上的基本操作,其时间复杂度均与树的高度成正比,对于一 ...

  3. 伸展树(Splay树)的简要操作

    伸展树(splay树),是二叉排序树的一种.[两个月之前写过,今天突然想写个博客...] 伸展树和一般的二叉排序树不同的是,在每次执行完插入.查询.删除等操作后,都会自动平衡这棵树.(说是自动,也就是 ...

  4. 数据结构(二) --- 伸展树(Splay Tree)

    文章图片和代码来自邓俊辉老师课件 概述 伸展树(Splay Tree),也叫分裂树,是一种二叉排序树,它能在O(log n)内完成插入.查找和删除操作.它由丹尼尔·斯立特Daniel Sleator ...

  5. 纸上谈兵:伸展树(splay tree)

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 我们讨论过,树的搜索效率与树的深度有关.二叉搜索树的深度可能为n,这种情况下,每次 ...

  6. 伸展树(splay tree)

    伸展树的设计思路,鉴于数据访问的局部性(28原则)在实际应用中普遍存在,将按照"最常用者优先"的启发策略.尽管在最坏情况下其单次操作需要 O(n) 时间,但分摊而言仍然 O(log ...

  7. 伸展树(Splay)复杂度证明

    本文用势能法证明\(Splay\)的均摊复杂度,对\(Splay\)的具体操作不进行讲述. 为了方便本文的描述,定义如下内容: 在文中我们用\(T\)表示一棵完整的\(Splay\),并(不严谨地)用 ...

  8. 平衡树之伸展树(Splay Tree)题目整理

    目录 前言 练习1 BZOJ 3224 普通平衡树 练习2 BZOJ 3223 文艺平衡树 练习3 BZOJ 1588 [HNOI2002]营业额统计 练习4 BZOJ 1208 [HNOI2004] ...

  9. [转] Splay Tree(伸展树)

    好久没写过了,比赛的时候就调了一个小时,差点悲剧,重新复习一下,觉得这个写的很不错.转自:here Splay Tree(伸展树) 二叉查找树(Binary Search Tree)能够支持多种动态集 ...

随机推荐

  1. 《转》架设一个BLOG需要整合多少东西?

    本文转载自大CC 1 Wordpress本身需要花费功夫的地方不多,比较容易,但Themes要花不少功夫调整,有时还得改CSS.推荐几个Wordpress Themes网站: - http://the ...

  2. AngularJS 讲解,二 模块

    AngularJS允许我们使用angular.module()方法来声明模块,这个方法能够接受两个参数,第一个是模块的名称,第二个是依赖列表,也就是可以被注入到模块中的对象列表. angular.mo ...

  3. [hihoCoder] KMP算法

    Each time we find a match, increase the global counter by 1. For KMP, algorithm, you may refer to th ...

  4. PAT 甲级 1019 General Palindromic Number(简单题)

    1019. General Palindromic Number (20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN ...

  5. python之MySQL学习——输出指定条件的结果集

    # 引入pymysql模块 import pymysql as pm # 数据库连接 db = pm.connect(host=",database='task', charset='utf ...

  6. 疯狂Html+CSS+JS 中JS总结

    来自:http://mzkmzk.github.io/blog/2015/10/05/amazeing-js/ 0 总结 本书的JS 第一章有讲语法有挺多常见的坑点和原理解释很不错 第二章DOM编程讲 ...

  7. hdu 4512 吉哥系列故事——完美队形I【LCIS经典应用】

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=4512 http://acm.hust.edu.cn/vjudge/contest/view.action ...

  8. 从es中拉取全部数据/大量数据 使用scroll+scan避免深分页

    es一次请求默认返回的数据条数是10条,可以通过设置size参数来控制返回数据的条数: 如果要返回很多数据,可以把size设置的很大,不过elastic search默认size最大不能超过1万. 那 ...

  9. flannel相关资料链接

    1.DockOne技术分享(十八):一篇文章带你了解Flannel http://dockone.io/article/618 2.理解Kubernetes网络之flannel网络http://ton ...

  10. Python列表切片详解([][:][::])

    Python切片是list的一项基本的功能,最近看到了一个程序,里面有这样一句类似的代码: a = list[::10] 1 不太明白两个冒号的意思就上网百度,发现大多数人写的博客中都没有提到这一个用 ...