题目描述

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

插入 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. 6、Python 中 利用 openpyxl 读 写 excel 操作

    __author__ = 'Administrator' from openpyxl import load_workbook # Excel_Util 类 class Excel_util: #初始 ...

  2. php 学习一 变量的定义

    //php有如下几种数据类型 // false true boolean类型 //integer int 整数 //float 浮点数就是小数 //string 字符串 //string null 空 ...

  3. vue css动画原理

    从隐藏到显现 从显现到隐藏 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> ...

  4. javascript基本类型及类型转换

    每种语言都有自己的基本类型,javascript也不例外.在javascript中有五大基本类型,分别是number,string,boolean,null,undefined.其他不属于这五种基本类 ...

  5. Github pages博客搭建与域名绑定

    Github Page github page是由用户编写的托管在github上的静态网页,为了搭建一个个人博客,我们可以租用一个云服务器然后部署我们的博客项目,常见的比如wordpress,像wp这 ...

  6. DUBBO+Zookeeper在Centos7中本地搭建及小案例

    环境: 1.centos7 2.jdk-7u76-linux-x64.tar.gz 2.tomcat:apache-tomcat-7.0.59.tar.gz 3.zookeeper-3.4.6.tar ...

  7. STM32嵌入式开发学习笔记(四):使用滴答计时器实现精准计时

    前面我们讲过,因为在STM32上没有系统时间的接口,因此无法调用sleep函数,在本文中,笔者将利用滴答计时器实现精准延时. 查阅技术手册,滴答计时器依赖于一个SysTick_Type类型寄存器,定义 ...

  8. python 生成json格式文件,并存储到手机上

    上代码 #!/usr/bin/env python # -*- encoding: utf-8 -*- import json import os import random "" ...

  9. linux开机故障解决方法

    无法进grub方法1光盘或者网络引导进入Rescue切换原机系统 chroot /mnt/sysimage/ 安装grub grub-install /dev/sda 方法2 直接命令 grub-in ...

  10. 屏幕操作录制成gif图的技巧

    我呢,在记录一些做过得实例的时候,总需要上一两张效果图,截静态图太浪费时间了,于是就找了一些录制git图的软件 一.Gif动画录制工具 这是我在360软件中心下载的,用了一下,不好用,录制出来的图是黑 ...