题目:

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.每个数的数据范围:[-2e9,2e9]

题解:

splay模板题···表示两周没碰键盘手都生了····

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int N=;
int root,size[N],son[N][],key[N],cnt[N],tot,father[N];
int a,b,n;
inline void clear(int now)
{
size[now]=son[now][]=son[now][]=key[now]=cnt[now]=father[now]=;
}
inline void update(int now)
{
if(now)
{
size[now]=cnt[now];
if(son[now][]) size[now]+=size[son[now][]];
if(son[now][]) size[now]+=size[son[now][]];
}
}
inline int get(int a)
{
return son[father[a]][]==a;
}
inline void rotate(int now)
{
int fa=father[now],ofa=father[fa],which=get(now);
son[fa][which]=son[now][which^],father[son[fa][which]]=fa;
son[now][which^]=fa,father[fa]=now,father[now]=ofa;
if(ofa) son[ofa][son[ofa][]==fa]=now;
update(fa),update(now);
}
inline void splay(int now)
{
while(father[now])
{
if(father[father[now]]) rotate(get(now)==get(father[now])?father[now]:now);
rotate(now);
}
root=now;
}
inline void insert(int x)
{
int now=root,last=;
while(true)
{
if(!now)
{
now=++tot;size[now]=cnt[now]=;father[now]=last;key[now]=x;
son[last][key[now]>key[last]]=now;update(last);splay(now);
break;
}
if(key[now]==x)
{
cnt[now]++;update(now);update(last);splay(now);
break;
}
last=now;now=son[now][x>key[now]];
}
}
inline int find(int x)
{
int now=root,ans=;
while(true)
{
if(x<key[now]) now=son[now][];
else
{
ans+=size[son[now][]];
if(x==key[now]) {splay(now);return ans+;}
ans+=cnt[now];now=son[now][];
}
}
}
inline int findx(int x)
{
int now=root;
while(true)
{
if(x<=size[son[now][]]) now=son[now][];
else
{
int temp=size[son[now][]]+cnt[now];
if(x<=temp) return key[now];
x-=temp;now=son[now][];
}
}
}
inline int pre()
{
int now=son[root][];
while(son[now][]) now=son[now][];
return now;
}
inline int next()
{
int now=son[root][];
while(son[now][]) now=son[now][];
return now;
}
inline void Delete(int x)
{
int nothing=find(x);
if(cnt[root]>) {cnt[root]--;return;}
else if(!son[root][]&&!son[root][])
{clear(root);root=;return;}
else if(!son[root][])
{int oldroot=root;root=son[root][];father[root]=;clear(oldroot);return;}
else if(!son[root][])
{int oldroot=root;root=son[root][];father[root]=;clear(oldroot);return;}
else
{
int leftbig=pre(),oldroot=root;
splay(leftbig);son[root][]=son[oldroot][];
father[son[root][]]=root;clear(oldroot);
update(root);
return;
}
}
inline int findpre(int x)
{
insert(x);int temp=pre();
Delete(x);return key[temp];
}
inline int findnext(int x)
{
insert(x);int temp=next();
Delete(x);return key[temp];
}
int main()
{
//freopen("a.in","r",stdin);
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d%d",&a,&b);
if(a==)
insert(b);
if(a==)
Delete(b);
if(a==)
{
int temp=find(b);
printf("%d\n",temp);
}
if(a==)
{
int temp=findx(b);
printf("%d\n",temp);
}
if(a==)
{
int temp=findpre(b);
printf("%d\n",temp);
}
if(a==)
{
int temp=findnext(b);
printf("%d\n",temp);
}
}
return ;
}

算法复习——splay(bzoj3224)的更多相关文章

  1. 算法复习——splay+启发式合并(bzoj2733-永无乡)

    题目: Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通 ...

  2. C#冒泡算法复习

    C#冒泡算法复习 冒泡算法的意思:每一趟找到一个最小或最大的数放到最后面,比较总数的n-1次(因为比较是2个双双比较的) 第一层循环表示进行比较的次数,总共要比较(数的)-1次 (因为比较是2个双双比 ...

  3. C语言排序算法复习

    排序算法有很多种,这里在复习和分析的基础上,做一个自己的总结: 首先要知道有哪些排序算法,google一下,有云C语言7大经典排序算法(也有8大).主要包括冒泡排序,快速排序,选择排序,插入排序,希尔 ...

  4. KMP算法复习【+继续学习】

    离NOIP还剩12天,本蒟蒻开始准备复习了. 先来个KMP[似乎我并没有写过KMP的blog] KMP KMP算法是解决字符串匹配问题的一个算法,主要是单对单的字符串匹配加速,时间复杂度O(m + n ...

  5. 算法复习周------“动态规划之‘最长公共子序列’”&&《计蒜课》---最长公共子串题解

    问题描述: 这个问题其实很容易理解.就是给你两个序列X={x1,x2,x3......xm} Y={y1,y2,y3......ym},要求找出X和Y的一个最长的公共子序列. 例:Xi={A, B, ...

  6. [算法] 数据结构 splay(伸展树)解析

    前言 splay学了已经很久了,只不过一直没有总结,鸽了好久来写一篇总结. 先介绍 splay:亦称伸展树,为二叉搜索树的一种,部分操作能在 \(O( \log n)\) 内完成,如插入.查找.删除. ...

  7. K-Means聚类和EM算法复习总结

    摘要: 1.算法概述 2.算法推导 3.算法特性及优缺点 4.注意事项 5.实现和具体例子 6.适用场合 内容: 1.算法概述 k-means算法是一种得到最广泛使用的聚类算法. 它是将各个聚类子集内 ...

  8. 通过“回文字算法”复习C++语言。

    一.什么是回文字 给定一个字符串,从前往后读和从后往前读,字符串序列不变.例如,河北省农村信用社的客服电话是“96369”,无论从后往前读,还是从前后往后读,各个字符出现的位置不变. 二.功能实现 ( ...

  9. 算法模板——splay区间反转 2

    实现功能:同splay区间反转 1(基于BZOJ3223 文艺平衡树) 这次改用了一个全新的模板(HansBug:琢磨了我大半天啊有木有),大大简化了程序,同时对于splay的功能也有所完善 这里面没 ...

随机推荐

  1. ftpclient 遇到的一些问题

    1. FTPFile[] files=ftpClient.listFiles(ftpDirectory); 没有数据 public static boolean ftpLogin(String ser ...

  2. selenium+chrome浏览器驱动-爬取百度图片

    百度图片网页中中,当页面滚动到底部,页面会加载新的内容. 我们通过selenium和谷歌浏览器驱动,执行js,是浏览器不断加载页面,通过抓取页面的图片路径来下载图片. from selenium im ...

  3. winhex与磁盘格式与 数据恢复

    第一阶段: 熟悉WinHex的使用. n 熟悉磁盘工具的使用. n 利用WinHex查看物理磁盘和逻辑磁盘. n 了解WinHex中相关工具的用法. 以管理员身份运行winhex(以便之后修改) 上方 ...

  4. nuxt 初接触

    对于nuxt服务端渲染让人动心的是不会再想vue一样去定义无数的路由了这一点是挺爽的!!! 先直接晒张图 在api这块增加了一个fetch方法   它会在组件每次加载前被调用(即在服务端或切换至目标路 ...

  5. 背包问题2 (lintcode)

    这里: for(int j = 1;j <= m;j++) result[0][j] = 0x80000000; 不能从0开始,result[0][0]是可以取到的,是0.其他情况取不到才用最小 ...

  6. Mac如何让调整窗口大小更简单

    在使用Mac的时候,你能把鼠标的光标悬停在任何程序的边缘,当光标自动变成箭头样式后,按住鼠标左键你将能随意拖动来改变程序窗口的大小.但是,这里有个问题,我们有时候很难控制把鼠标光标移动在正确的窗口边缘 ...

  7. MySQL 实时监控日志

    简单的梳理一下为什么要写这边文章,主要是学了ORM之后,发现通过ORM插入数据真的很方便,但是通过ORM生成的SQL语句又是怎么写的呢,百思不得姐.于是就找到了这个办法 首先查看一下查看MySQL 日 ...

  8. iptables 过滤字符串

    iptables 过滤字符串 1. 开启iptables iptables -P OUTPUT ACCEPT       ###允许输出链 service iptables save          ...

  9. 前端css学习记录

    参考资料:CSS权威指南(第三版)中文版 核心要点: HTML负责标记文档的结构(HyperText Markup Language),结构化语言. CSS 负责表现文档的样式(Cascading S ...

  10. [LUOGU] P1828 香甜的黄油 Sweet Butter

    题目描述 农夫John发现做出全威斯康辛州最甜的黄油的方法:糖.把糖放在一片牧场上,他知道N(1<=N<=500)只奶牛会过来舔它,这样就能做出能卖好价钱的超甜黄油.当然,他将付出额外的费 ...