普通平衡树(bzoj 3224)
2024-09-08 02:57:08
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
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
84185
492737
HINT
1.n的数据范围:n<=100000
2.每个数的数据范围:[-1e7,1e7]
数据如下http://pan.baidu.com/s/1jHMJwO2
/*
一个平衡树的模板写了一上午了,能犯的错误基本都犯了。。。
首先没加哨兵,再就是删除操作时没有更新sz(这个巨坑),真是长记性了。
*/
#include<cstdio>
#include<iostream>
#define N 100010
using namespace std;
int son[N][],fa[N],val[N],cnt[N],sz[N],m,rt,size; void pushup(int x){
sz[x]=sz[son[x][]]+sz[son[x][]]+cnt[x];
} void rotate(int x,int &k){
int y=fa[x],z=fa[y],l,r;
if(son[y][]==x) l=;else l=;r=l^;
if(y==k) k=x;
else {
if(son[z][]==y) son[z][]=x;
else son[z][]=x;
}
fa[x]=z;fa[y]=x;fa[son[x][r]]=y;
son[y][l]=son[x][r];son[x][r]=y;
pushup(y);pushup(x);
} void splay(int x,int &k){
while(x!=k){
int y=fa[x],z=fa[y];
if(y!=k){
if((son[y][]==x)^(son[z][]==y)) rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
} void insert(int v){
int k=rt,y=;
while(k&&val[k]!=v) y=k,k=son[k][v>val[k]];
if(k) cnt[k]++;
else {
k=++size;sz[k]=;cnt[k]=;fa[k]=y;val[k]=v;
if(y) son[y][v>val[y]]=k;
}
splay(k,rt);
} void find1(int v){//查找v的位置
int k=rt;if(!k)return;
while(son[k][v>val[k]]&&val[k]!=v)
k=son[k][v>val[k]];
splay(k,rt);
} int find2(int x){//查找排名为x的数
x++;
int k=rt;
if(sz[k]<x)return ;
while(){
if(sz[son[k][]]<x&&sz[son[k][]]+cnt[k]>=x) return k;
if(sz[son[k][]]>=x) k=son[k][];
else x-=(sz[son[k][]]+cnt[k]),k=son[k][];
}
return k;
} int nxt(int x,int f){
find1(x);
if((val[rt]>x&&f)||val[rt]<x&&!f) return rt;
int p=son[rt][f];
while(son[p][f^]) p=son[p][f^];
return p;
} void del(int v){
find1(v);
int x=rt,k;
if(cnt[x]>){cnt[x]--;sz[x]--;return;}
if(!son[x][]||!son[x][]){
rt=son[x][]+son[x][];
}
else {
k=son[x][];
while(son[k][])k=son[k][];sz[k]+=sz[son[x][]];
fa[son[x][]]=k;son[k][]=son[x][];
rt=son[x][];
}
fa[rt]=;splay(k,rt);
} int main(){
insert(-0x7fffffff);insert(0x7fffffff);
scanf("%d",&m);
for(int i=;i<=m;i++){
int opt,x;scanf("%d%d",&opt,&x);
if(opt==) insert(x);
if(opt==) del(x);
if(opt==) find1(x),printf("%d\n",sz[son[rt][]]);
if(opt==) printf("%d\n",val[find2(x)]);
if(opt==) printf("%d\n",val[nxt(x,)]);
if(opt==) printf("%d\n",val[nxt(x,)]);
}
return ;
}
最新文章
- git 设置不需要输入密码
- c++ 模运算
- makefile--#的不正确使用
- 学习第一个头文件stdio.h
- java学习之url
- oracle——用户
- Tomcat时区设置方法[转]
- 泊爷带你学go -- 加锁的问题
- 项目开发中关于jquery中出现问题小结(textarea,disabled,关键字等)
- Ubuntu上查内存情况
- dokuwiki 配置 sendmail 邮件发送
- Writing Reentrant and Thread-Safe Code(译:编写可重入和线程安全的代码)
- wordpress注册后重定向到自定义页面
- IIS目录
- Docker-compose 在up之后,各个子服务容器的hosts文件中不能找到父服务的域名
- CSS 小结笔记之选择器
- Phaser3 对象池随机产生炸弹并销毁
- python 输入三个整数,按照从小到大的顺序打印
- Restore IP Addresses——边界条件判定
- activemq安装运行及其在springboot中的queue和topic使用