COJS:1829. [Tyvj 1728]普通平衡树
★★★ 输入文件:phs.in 输出文件:phs.out 简单对比
时间限制:1 s 内存限制:128 MB
【题目描述】
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
【输入格式】
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
【输出格式】
对于操作3,4,5,6每行输出一个数,表示对应答案
【样例输入】
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
【样例输出】
106465
84185
492737
【提示】
SBT版的:
#include<bits/stdc++.h>
using namespace std;
const int maxn=;
int root,tot,N;
int key[maxn],siz[maxn],lc[maxn],rc[maxn];
void r_rotate(int &rt){
int k=lc[rt];
lc[rt]=rc[k];
rc[k]=rt;
siz[k]=siz[rt];
siz[rt]=siz[lc[rt]]+siz[rc[rt]]+;
rt=k;
}
void l_rotate(int &rt){
int k=rc[rt];
rc[rt]=lc[k];
lc[k]=rt;
siz[k]=siz[rt];
siz[rt]=siz[lc[rt]]+siz[rc[rt]]+;
rt=k;
}
void MAINTAIN(int &rt,bool flag){
if(flag==false){//rt的左子树的某子树>rt的右子树
if(siz[lc[lc[rt]]]>siz[rc[rt]]) r_rotate(rt);//如果rt的左孩子的左孩子>rt的右孩子,rt右旋
else if(siz[rc[lc[rt]]]>siz[rc[rt]]){//如果rt的左孩子L的右孩子B > rt的右孩子R:
l_rotate(lc[rt]);//先让rt的左孩子左旋,使rt的左子树变成以B为根
r_rotate(rt);//再右旋再变成以B为根
}
else return;//平衡
}
else{//rt的右子树的某子树>rt的左子树
if(siz[rc[rc[rt]]]>siz[lc[rt]]) l_rotate(rt);
else if(siz[lc[rc[rt]]]>siz[lc[rt]]){
r_rotate(rc[rt]);
l_rotate(rt);
}
else return;
}
MAINTAIN(lc[rt],); MAINTAIN(rc[rt],);//检查是否满足平衡
MAINTAIN(rt,); MAINTAIN(rt,);
}
void insert(int &rt,int v){
if(rt==){//找到合适的位置插入
rt=++tot;
key[rt]=v;
lc[rt]=rc[rt]=; siz[rt]=;
return ;
}
siz[rt]++;
if(v<=key[rt]) insert(lc[rt],v);
else insert(rc[rt],v);
MAINTAIN(rt,v>key[rt]);//调整树结构
}
int Delete(int &rt,int v){
int ans;
siz[rt]--;
if(v==key[rt]||(v<key[rt]&&lc[rt]==)||(v>key[rt]&&rc[rt]==)){
ans=key[rt];
if(lc[rt]==||rc[rt]==) rt=lc[rt]+rc[rt];//没有左子树或者右子树,直接利用&操作,相当于直接以子树接到上个节点
else key[rt]=Delete(lc[rt],key[rt]+);//返回左子树中的最大值,然后替换当前的rt,相当于删掉当前节点,用左子树中最大值放在这个位置来代替
return ans;
}
if(v<key[rt]) ans=Delete(lc[rt],v);
else ans=Delete(rc[rt],v);
return ans;
}
bool find(int &rt,int v){//查找是否有 key值为 v的节点
if(rt==) return false;
else if(v==key[rt]) return true;
else if(v<key[rt]) return find(lc[rt],v);
else if(v>key[rt]) return find(rc[rt],v);
}
int rank(int &rt,int v){//询问排名
if(rt==) return ;
if(v<=key[rt]) return rank(lc[rt],v);
else return siz[lc[rt]]++rank(rc[rt],v);
}
/*
如果元素唯一的话,可以这么写:
int rank(int &rt,int v){
if(rt==0) return 1;
if(v==key[rt]) return siz[lc[rt]]+1;
if(v<key[rt]) return rank(lc[rt],v);
return siz[lc[rt]]+1+rank(rc[rt],v);
}
但此题不行
*/
int select(int &rt,int k){//返回在v位置上的节点,可以改造成取大和取小函数
if(k==siz[lc[rt]]+) return key[rt];
if(k<=siz[lc[rt]]) return select(lc[rt],k);
else return select(rc[rt],k--siz[lc[rt]]);
}
int pred(int &rt,int v){//返回比 v小的最大的数
if(rt==) return v;//要求是比v小,返回v的意思是没找到
if(v<=key[rt]) return pred(lc[rt],v);//key[rt]>v 必然要往更小的方向,即rt的左子树
else{//此时 key[rt]<v,而rt的右子树的key值都大于key[rt]
int ans=pred(rc[rt],v);
if(ans==v) return key[rt];//返回v表示rt的右子树中的key都比v大,返回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;
}
}
void inorder(int rt){//输出中序遍历
if(rt!=){
inorder(lc[rt]);
cout<<key[rt]<<" ";
inorder(rc[rt]);
}
}
int main(){
siz[]=root=tot=;
scanf("%d",&N);
for(int i=,kin,num;i<=N;i++){
scanf("%d%d",&kin,&num);
if(kin==) insert(root,num);
else if(kin==) Delete(root,num);
else if(kin==) printf("%d\n",rank(root,num));
else if(kin==) printf("%d\n",select(root,num));
else if(kin==) printf("%d\n",pred(root,num));
else if(kin==) printf("%d\n",succ(root,num));
}
return ;
}
无注释版的:
#include<bits/stdc++.h>
using namespace std;
const int maxn=;
int root,tot,N;
int key[maxn],siz[maxn],lc[maxn],rc[maxn];
void r_rotate(int &rt){
int k=lc[rt];
lc[rt]=rc[k];
rc[k]=rt;
siz[k]=siz[rt];
siz[rt]=siz[lc[rt]]+siz[rc[rt]]+;
rt=k;
}
void l_rotate(int &rt){
int k=rc[rt];
rc[rt]=lc[k];
lc[k]=rt;
siz[k]=siz[rt];
siz[rt]=siz[lc[rt]]+siz[rc[rt]]+;
rt=k;
}
void MAINTAIN(int &rt,bool flag){
if(flag==false){
if(siz[lc[lc[rt]]]>siz[rc[rt]]) r_rotate(rt);
else if(siz[rc[lc[rt]]]>siz[rc[rt]]){
l_rotate(lc[rt]);
r_rotate(rt);
}
else return;
}
else{
if(siz[rc[rc[rt]]]>siz[lc[rt]]) l_rotate(rt);
else if(siz[lc[rc[rt]]]>siz[lc[rt]]){
r_rotate(rc[rt]);
l_rotate(rt);
}
else return;
}
MAINTAIN(lc[rt],); MAINTAIN(rc[rt],);
MAINTAIN(rt,); MAINTAIN(rt,);
}
void insert(int &rt,int v){
if(rt==){
rt=++tot;
key[rt]=v;
lc[rt]=rc[rt]=; siz[rt]=;
return ;
}
siz[rt]++;
if(v<=key[rt]) insert(lc[rt],v);
else insert(rc[rt],v);
MAINTAIN(rt,v>key[rt]);
}
int Delete(int &rt,int v){
int ans;
siz[rt]--;
if(v==key[rt]||(v<key[rt]&&lc[rt]==)||(v>key[rt]&&rc[rt]==)){
ans=key[rt];
if(lc[rt]==||rc[rt]==) rt=lc[rt]+rc[rt];
else key[rt]=Delete(lc[rt],key[rt]+);
return ans;
}
if(v<key[rt]) ans=Delete(lc[rt],v);
else ans=Delete(rc[rt],v);
return ans;
}
bool find(int &rt,int v){
if(rt==) return false;
else if(v==key[rt]) return true;
else if(v<key[rt]) return find(lc[rt],v);
else if(v>key[rt]) return find(rc[rt],v);
}
int rank(int &rt,int v){
if(rt==) return ;
if(v<=key[rt]) return rank(lc[rt],v);
else return siz[lc[rt]]++rank(rc[rt],v);
}
int select(int &rt,int k){
if(k==siz[lc[rt]]+) return key[rt];
if(k<=siz[lc[rt]]) return select(lc[rt],k);
else return select(rc[rt],k--siz[lc[rt]]);
}
int pred(int &rt,int 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){
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;
}
}
void inorder(int rt){
if(rt!=){
inorder(lc[rt]);
cout<<key[rt]<<" ";
inorder(rc[rt]);
}
}
int main(){
siz[]=root=tot=;
scanf("%d",&N);
for(int i=,kin,num;i<=N;i++){
scanf("%d%d",&kin,&num);
if(kin==) insert(root,num);
else if(kin==) Delete(root,num);
else if(kin==) printf("%d\n",rank(root,num));
else if(kin==) printf("%d\n",select(root,num));
else if(kin==) printf("%d\n",pred(root,num));
else if(kin==) printf("%d\n",succ(root,num));
}
return ;
}
Splay版的:
#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 ;
}
vector版的:
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int INF=;
int n;
vector<int> tree;
int find(int x){
return lower_bound(tree.begin(),tree.end(),x)-tree.begin()+;
}
int main(){
scanf("%d",&n);
tree.reserve();
for(int i=,kin,x;i<=n;i++){
scanf("%d%d",&kin,&x);
if(kin==) tree.insert(upper_bound(tree.begin(),tree.end(),x),x);
else if(kin==) tree.erase(lower_bound(tree.begin(),tree.end(),x));
else if(kin==) printf("%d\n",find(x));
else if(kin==) printf("%d\n",tree[x-]);
else if(kin==) printf("%d\n",*--lower_bound(tree.begin(),tree.end(),x));
else if(kin==) printf("%d\n",*upper_bound(tree.begin(),tree.end(),x));
}
return ;
}
COJS:1829. [Tyvj 1728]普通平衡树的更多相关文章
- cogs 1829. [Tyvj 1728]普通平衡树 权值线段树
1829. [Tyvj 1728]普通平衡树 ★★★ 输入文件:phs.in 输出文件:phs.out 简单对比时间限制:1 s 内存限制:1000 MB [题目描述] 您需要写一种数 ...
- [BZOJ3224]Tyvj 1728 普通平衡树
[BZOJ3224]Tyvj 1728 普通平衡树 试题描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个) ...
- BZOJ 3224: Tyvj 1728 普通平衡树
3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 9629 Solved: 4091[Submit][Sta ...
- BZOJ 3224 TYVJ 1728 普通平衡树 [Treap树模板]
3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 7390 Solved: 3122 [Submit][S ...
- BZOJ 3224: Tyvj 1728 普通平衡树 treap
3224: Tyvj 1728 普通平衡树 Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除 ...
- BZOJ 3224: Tyvj 1728 普通平衡树 vector
3224: Tyvj 1728 普通平衡树 Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除 ...
- bzoj3224 Tyvj 1728 普通平衡树(名次树+处理相同)
3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 5354 Solved: 2196[Submit][Sta ...
- BZOJ 3224: Tyvj 1728 普通平衡树(BST)
treap,算是模板题了...我中间还一次交错题... -------------------------------------------------------------------- #in ...
- [补档][Tyvj 1728]普通平衡树
[Tyvj 1728]普通平衡树 题目 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 1. 插入x数 2. 删除x数(若有多个相同的数,因只删除一个) 3. 查询x数的 ...
随机推荐
- java前后台开发之后台自动上传下载
package downloadTest; import java.io.BufferedReader; import java.io.File; import java.io.FileInputSt ...
- linux文件与目录管理命令(ubuntu)
ls:列出目录 选项与参数: -a:全部文件,隐藏档(开头为.的文件)也会列出: -d:仅列出目录本身(也就是 . ),而不是目录下的所有文件及目录: -l:长字符串列出,包括文件的属性.权限等数据.
- python学习笔记(二)— 集合
s = set()#建立空的集合 s2 = {'}#没有:的为集合,集合天生去重 s3 = {'} #集合是也是无序的 # s2.add('a')#添加值 # s2.remove('2')#删除值 # ...
- linux下的KSM内存共享机制分析
2017-04-26 KSM是内核中的一种内存共享机制,在2.6.36版本的内核中开始引入,简单来说就是其会 合并某些相同的页面以减少页面冗余.在内核中有一个KSM守护进程 ksmd,它定期扫描用户向 ...
- BBS项目部署之数据库的处理
一 数据库的处理: 1.1上传bbs.sql(数据库中的数据) 1.2在mysql中创建bbs库,并导入数据库SQL脚本 在mysqld的文件夹中: mysql> create databas ...
- 网络编程(基于udp协议的套接字/socketserver模块/进程简介)
一.基于UDP协议的套接字 TCP是建立可靠连接,并且通信双方都可以以流的形式发送数据.相对TCP,UDP则是面向无连接的协议. 使用UDP协议时,不需要建立连接,只需要知道对方的IP地址和端口号,就 ...
- Redis 搜索引擎优化
场景 大家如果是做后端开发的,想必都实现过列表查询的接口,当然有的查询条件很简单,一条 SQL 就搞定了,但有的查询条件极其复杂,再加上库表中设计的各种不合理,导致查询接口特别难写,然后加班什么的就不 ...
- 数据结构-平衡二叉树 旋转过程平衡因子分析 c和java代码实现对比
平衡二叉搜索树(Self-balancing binary search tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且 ...
- tkprof参数详解
tkprof参数详解 table=schema.table 指定tkprof处理sql trace文件时临时表的模式名和表名 insert=scriptfile 创建一个文件名为scriptfile的 ...
- php集成财付通支付接口
<?phpif(!defined('DEDEINC')) exit('Request Error!');/** *财付通接口类 */class tenpay{ var $dsql; var $m ...