题目描述

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

插入 xx 数

删除 xx 数(若有多个相同的数,因只删除一个)

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

查询排名为 xx 的数

求 xx 的前驱(前驱定义为小于 xx ,且最大的数)

求 xx 的后继(后继定义为大于 xx ,且最小的数)

输入输出格式

输入格式:

第一行为 nn ,表示操作的个数,下面 nn 行每行有两个数 optopt 和 xx , optopt 表示操作的序号( 1 \leq opt \leq 6 1≤opt≤6 )

输出格式:

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

输入输出样例

输入样例#1: 复制

10

1 106465

4 1

1 317721

1 460929

1 644985

1 84185

1 89851

6 81968

1 492737

5 493598

输出样例#1: 复制

106465

84185

492737

说明

时空限制:1000ms,128M

1.n的数据范围: n \leq 100000 n≤100000

2.每个数的数据范围: [-{10}^7, {10}^7][−10

7

,10

7

]

来源:Tyvj1728 原名:普通平衡树

#include<iostream>
#include<cstdio>
#include<cstring> using namespace std;
const int MAXN = 100005;
const int inf = 0x7f7f7f7f; struct Node{
int v,fa;
int ch[2];
int sum;
int recy;
}node[MAXN]; int n,cnt,points; inline void update(int x){
node[x].sum=node[node[x].ch[1]].sum+node[node[x].ch[0]].sum+node[x].recy;
} inline bool jud(int x){
return node[node[x].fa].ch[0]==x?0:1;
} inline void connect(int x,int f,int son){
node[x].fa=f;
node[f].ch[son]=x;
} inline void rotate(int x){
int y=node[x].fa;
int mroot=node[y].fa;
int mrootson=jud(y);
int yson=jud(x);
int oth=node[x].ch[yson^1];
connect(oth,y,yson);
connect(y,x,(yson^1));
connect(x,mroot,mrootson);
update(y);update(x);
} inline void splay(int at,int to){
to=node[to].fa;
while(node[at].fa!=to){
int up=node[at].fa;
if(node[up].fa==to) rotate(at);
else if(jud(up)==jud(at)){
rotate(up);
rotate(at);
}
else{
rotate(at);
rotate(at);
}
}
} inline int crepoint(int x,int f){
node[++cnt].v=x;
node[cnt].fa=f;
node[cnt].sum=1;
node[cnt].recy=1;
return cnt;
} inline void destroy(int x){
node[x].v=node[x].fa=node[x].sum=node[x].recy=node[x].ch[0]=node[x].ch[1]=0;
if(x==cnt) cnt--;
} inline int find(int v){
int now=node[0].ch[1];
while(1){
if(node[now].v==v){
splay(now,node[0].ch[1]);
return now;
}
int nxt=v<node[now].v?0:1;
if(!node[now].ch[nxt]) return 0;
now=node[now].ch[nxt];
}
} inline int build(int x){
points++;
if(cnt==0){
node[0].ch[1]=1;
crepoint(x,0);
}
else{
int now=node[0].ch[1];
while(1){
node[now].sum++;
if(x==node[now].v){
node[now].recy++;
return now;
}
int nxt=x<node[now].v?0:1;
if(!node[now].ch[nxt]){
crepoint(x,now);
node[now].ch[nxt]=cnt;
return cnt;
}
now=node[now].ch[nxt];
}
}
return 0;
} inline void push(int x){
int add=build(x);
splay(add,node[0].ch[1]);
} inline void pop(int v){
int deal=find(v);
if(!deal) return;
points--;
if(node[deal].recy>1){
node[deal].recy--;
node[deal].sum--;
return;
}
if(!node[deal].ch[0]){
node[0].ch[1]=node[deal].ch[1];
node[node[0].ch[1]].fa=0;
}
else{
int lef=node[deal].ch[0];
while(node[lef].ch[1]) lef=node[lef].ch[1];
splay(lef,node[deal].ch[0]);
int rig=node[deal].ch[1];
connect(rig,lef,1);connect(lef,0,1);
update(lef);
}
destroy(deal);
} int rank(int x){
int ans=0;
int now=node[0].ch[1];
while(1){
if(node[now].v==x) return ans+node[node[now].ch[0]].sum+1;
if(now==0) return 0;
if(x<node[now].v) now=node[now].ch[0];
else{
ans+=node[node[now].ch[0]].sum+node[now].recy;
now=node[now].ch[1];
}
}
if(now) splay(now,node[0].ch[1]);
return 0;
} int atrank(int x){
if(x>points) return -inf;
int now=node[0].ch[1];
while(1){
int minn=node[now].sum-node[node[now].ch[1]].sum;
if(x>node[node[now].ch[0]].sum && x<=minn) break;
if(x<minn) now=node[now].ch[0];
else{
x=x-minn;
now=node[now].ch[1];
}
}
splay(now,node[0].ch[1]);
return node[now].v;
} inline int lower(int x){
int now=node[0].ch[1];
int res=-inf;
while(now){
if(node[now].v<x && node[now].v>res) res=node[now].v;
if(x>node[now].v) now=node[now].ch[1];
else now=node[now].ch[0];
}
return res;
} inline int upper(int x){
int now=node[0].ch[1];
int res=inf;
while(now){
if(node[now].v>x && node[now].v<res) res=node[now].v;
if(x<node[now].v) now=node[now].ch[0];
else now=node[now].ch[1];
}
return res;
} int main(){
scanf("%d",&n);
push(inf);push(-inf);
for(register int i=1;i<=n;i++){
int opt,x;
scanf("%d%d",&opt,&x);
if(opt==1) push(x);
else if(opt==2) pop(x);
else if(opt==3) printf("%d\n",rank(x)-1);
else if(opt==4) printf("%d\n",atrank(x+1));
else if(opt==5) printf("%d\n",lower(x));
else printf("%d\n",upper(x));
}
return 0;
}

splay 模板 洛谷3369的更多相关文章

  1. 【数论】卢卡斯定理模板 洛谷P3807

    [数论]卢卡斯定理模板 洛谷P3807 >>>>题目 [题目] https://www.luogu.org/problemnew/show/P3807 [输入格式] 第一行一个 ...

  2. KMP字符串匹配 模板 洛谷 P3375

    KMP字符串匹配 模板 洛谷 P3375 题意 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.(如果 ...

  3. 在洛谷3369 Treap模板题 中发现的Splay详解

    本题的Splay写法(无指针Splay超详细) 前言 首先来讲...终于调出来了55555...调了整整3天..... 看到大部分大佬都是用指针来实现的Splay.小的只是按照Splay的核心思想和原 ...

  4. BZOJ3224 洛谷3369 Tyvj 1728 普通平衡树 splay

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3224 题意概括 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. ...

  5. 【模板】LIS模板 洛谷P1091 [NOIP2004提高组]合唱队形 [2017年4月计划 动态规划11]

    以题写模板. 写了两个:n^2版本与nlogn版本 P1091 合唱队形 题目描述 N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形. 合唱队形是指这样的一种队 ...

  6. 树链剖分模板(洛谷P3384)

    洛谷P3384 #include <bits/stdc++.h> #define DBG(x) cerr << #x << " = " < ...

  7. (treap)[bzoj3224][洛谷3369][cogs1829]Tyvj 1728 普通平衡树

    Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数 ...

  8. 洛谷.3369.[模板]普通平衡树(Splay)

    题目链接 第一次写(2017.11.7): #include<cstdio> #include<cctype> using namespace std; const int N ...

  9. 【Splay】洛谷3372 【模板】线段树 1

    Splay区间加,询问区间和. #include<cstdio> #include<iostream> #include<cstring> #include< ...

随机推荐

  1. nodejs模块——fs模块 读取文件

    readFile读取文件 fs.readFile(filename,[option],callback) 方法读取文件. 参数说明: filename String 文件名 option Object ...

  2. MyEclipse6.0中使用aptana插件,添加jquery提示功能

    MyEclipse6.0中使用aptana插件,添加jquery提示功能 第一:查看当前MyEclipse集成的eclipse的版本,, 查看路径    D:/MyEclipse 6.0/eclips ...

  3. tomcat源码分析一之getCanonicalFile和getAbsolutePath的区别

    最近在看tomcat源码 1.getPath(): 返回定义时的路径,(就是你写什么路径,他就返回什么路径) 2.getAbsolutePath(): 返回绝对路径,但不会处理“.”和“..”的情况 ...

  4. eclipse git项目的冲突文件处理

    https://jingyan.baidu.com/article/3c48dd34895a07e10ae35871.html

  5. xshell突出显示集

    xshell突出显示集(参考mobaxterm,直接拷贝过来不行,应该是xshell对正则表达式的支持不够好): Underline: \b(http(s)?://[A-Za-z0-9_./& ...

  6. window安装reidis完成之后,想要把数据存入redis,必须开扩展,不然报错,redis windows phpstudy 安装扩展

    redis windows phpstudy 安装扩展   1.http://windows.php.net/downloads/pecl/releases/redis/3.1.5rc1/ 2.htt ...

  7. fatal error C1076: compiler limit : internal heap limit reached; use /Zm to specify a higher limit

    最近想用一下Xtreme ToolkitPro 界面库,安装后用VC6根据向导 产生一个工程,编译时出现如下的错误: fatal error C1076: compiler limit : inter ...

  8. appium无法定位连接的真机元素

    报错信息: com.android.ddmlib.SyncException:Remote object dosen't exist! 解决办法: 错误原因是因为没有dump下来界面的信息保存到uid ...

  9. SPSS把一个数据样本随机分为两部分

    SPSS把一个数据样本随机分为两部分 1.  打开SPSS数据文件. 2.  选择DATA>SELECT CASES,打开"Select Cases"对话框 3. 选择&qu ...

  10. HA配置

    主T800 eth0 192.168.2.32备T600 eth1 192.168.2.33安装nginx yum install -y nginx 关闭主备的防火墙iptables.selinux ...