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. IE的文档模式, 及Textarea呈现bug一例

    做了个非常简单的页面, 仅有几行html代码, 内容如下: <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtm ...

  2. Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded.

    EF6进行Insert操作的时候提示错误 Store update, insert, or delete statement affected an unexpected number of rows ...

  3. Powershell运行Invoke-Sqlcmd命令的先决条件

    运行Invoke-Sqlcmd命令,使用这个命令需满足如下条件: 1.在运行服务器中安装SQL Server 2008 R2 Management ObjectsI 2.在运行命令 invoke-sq ...

  4. mysql 使用命令执行外部sql文件

    语句 source e:\\phpPro\\fileName.sql 注意,不需要再后面加  分号  !!!!!

  5. buffer/interger overflow /return-to-libc攻击实验

    buffer/interger overflow /return-to-libc攻击实验 http://blog.sina.com.cn/s/blog_70dd16910100rdgn.html ht ...

  6. IDEA 录制宏+设置快捷键 实现写时编译

    参考: IDEA 录制宏+设置快捷键 实现写时编译:https://blog.csdn.net/wangjie919/article/details/79487981 IDEA 设置运行时不编译项目: ...

  7. 洛谷 P4451 [国家集训队]整数的lqp拆分

    洛谷 这个题目是黑题,本来想打表的,但是表调不出来(我逊毙了)! 然后随便打了一个递推,凑出了样例, 竟然. 竟然.. 竟然... A了!!!!!!! 直接:\(f[i]=f[i-1]*2+f[i-2 ...

  8. 【我的Android进阶之旅】解决bug:You need to use a Theme.AppCompat theme (or descendant) with this activity.

    前言 今天用Android Studio 生成Activity的时候,默认继承AppCompatActivity ,而在AndroidManifest.xml我对该Activity设置了一个主题,然后 ...

  9. 解决Object() takes on paramenters的问题

    先贴上今天的代码: 解决:是由于父类中的_init_()写成了_int_(),由于粗心导致,下次注意.

  10. C++中的默认成员函数

    一般而言,对于一个用户自定义的类类型,以下四个函数在用户没有自定义的情形下,会由编译器自动生成: 1.default constructor 2.copy constructor Someclass: ...