http://www.lydsy.com/JudgeOnline/problem.php?id=3224

题面源于洛谷

题目描述

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

  1. 插入x数

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

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

  4. 查询排名为x的数

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

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

输入输出格式

输入格式:

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

输出格式:

对于操作3,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

——————————————————————————————

http://blog.csdn.net/clove_unique/article/details/50630280

所以最开始学习splay就从上面的博客学的话做这道题就是切。

简单讲几个问题吧。

1.findx操作。

和我前面博客的kthmin(或者query)思路一致,就是变成了非递归的。

2.find操作。

从根出发,判断当前左右子结点的值和x比较就可以知道要往哪里走了。

同时沿途中顺便记录排名即可,方法同findx操作。

3.del操作。

如果看过我前面的博客的话就会发现del操作只能删除根节点。

那么我们怎么删除任意结点呢?很简单,和find函数联动即可。

因为find(x)函数会返回x的排名,但同时会把x放在根上,所以又转换成了删除根节点的问题了。

#include<cstdio>
#include<queue>
#include<cctype>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
const int N=;
inline int read(){
int X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
int fa[N],tr[N][],key[N],cnt[N],size[N];
int root,sz;
inline void clear(int x){
fa[x]=tr[x][]=tr[x][]=key[x]=cnt[x]=size[x]=;
return;
}
inline bool get(int x){
return tr[fa[x]][]==x;
}
inline void update(int x){
if(x){
size[x]=cnt[x];
if(tr[x][])size[x]+=size[tr[x][]];
if(tr[x][])size[x]+=size[tr[x][]];
}
return;
}
inline void rotate(int x){
int old=fa[x],oldf=fa[old],which=get(x);
tr[old][which]=tr[x][which^];fa[tr[old][which]]=old;
fa[old]=x;tr[x][which^]=old;fa[x]=oldf;
if(oldf)tr[oldf][tr[oldf][]==old]=x;
update(old);update(x);
return;
}
inline void splay(int x){
int f=fa[x];
while(f){
if(fa[f])rotate((get(x)==get(f)?f:x));
rotate(x);f=fa[x];
}
root=x;
return;
}
inline void insert(int v){
if(!root){
sz++;tr[sz][]=tr[sz][]=fa[sz]=;
key[sz]=v;cnt[sz]=size[sz]=;root=sz;
return;
}
int now=root,f=;
while(){
if(key[now]==v){
cnt[now]++;update(now);update(f);splay(now);
break;
}
f=now;
now=tr[now][key[now]<v];
if(!now){
sz++;tr[sz][]=tr[sz][]=;fa[sz]=f;
key[sz]=v;cnt[sz]=size[sz]=;
tr[f][key[f]<v]=sz;
update(f);splay(sz);
break;
}
}
return;
}
inline int find(int v){//查询v的排名
int ans=,now=root;
while(){
if(v<key[now])now=tr[now][];
else{
ans+=(tr[now][]?size[tr[now][]]:);
if(v==key[now]){
splay(now);
return ans+;
}
ans+=cnt[now];
now=tr[now][];
}
}
}
inline int findx(int x){//找到排名为x的点
int now=root;
while(){
if(tr[now][]&&x<=size[tr[now][]])now=tr[now][];
else{
int temp=(tr[now][]?size[tr[now][]]:)+cnt[now];
if(x<=temp)return key[now];
x-=temp;now=tr[now][];
}
}
}
inline int pre(){//前驱
int now=tr[root][];
while(tr[now][])now=tr[now][];
return now;
}
inline int nxt(){//后继
int now=tr[root][];
while(tr[now][])now=tr[now][];
return now;
}
inline void del(int x){
find(x);
if(cnt[root]>){
cnt[root]--;return;
}
if(!tr[root][]&&!tr[root][]){
clear(root);root=;return;
}
if(!tr[root][]){
int oldroot=root;root=tr[root][];fa[root]=;clear(oldroot);return;
}
else if(!tr[root][]){
int oldroot=root;root=tr[root][];fa[root]=;clear(oldroot);return;
}
int leftbig=pre(),oldroot=root;
splay(leftbig);
fa[tr[oldroot][]]=root;
tr[root][]=tr[oldroot][];
clear(oldroot);
update(root);
return;
}
int main(){
int n=read();
for(int i=;i<=n;i++){
int opt=read();
int k=read();
if(opt==)insert(k);
if(opt==)del(k);
if(opt==)printf("%d\n",find(k));
if(opt==)printf("%d\n",findx(k));
if(opt==){
insert(k);
printf("%d\n",key[pre()]);
del(k);
}
if(opt==){
insert(k);
printf("%d\n",key[nxt()]);
del(k);
}
}
return ;
}

UPD :Treap

#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int INF=;
const int N=1e5+;
inline int read(){
int X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
struct treap{
int l,r,p,size,cnt,key;
#define lc(x) tr[x].l
#define rc(x) tr[x].r
#define v(x) tr[x].key
#define p(x) tr[x].p
#define c(x) tr[x].cnt
#define s(x) tr[x].size
}tr[N];
int sz,rt;
inline int rand(){
static int seed=;
return seed=(ll)seed*%;
}
inline void upt(int k){
s(k)=s(lc(k))+s(rc(k))+c(k);
}
inline void zig(int &k){
int y=lc(k);lc(k)=rc(y);rc(y)=k;
s(y)=s(k);upt(k);
k=y;
}
inline void zag(int &k){
int y=rc(k);rc(k)=lc(y);lc(y)=k;
s(y)=s(k);upt(k);
k=y;
}
inline void insert(int &k,int v){
if(!k){
k=++sz;v(k)=v;p(k)=rand();
c(k)=s(k)=;lc(k)=rc(k)=;
return;
}
else s(k)++;
if(v(k)==v)c(k)++;
else if(v<v(k)){
insert(lc(k),v);
if(p(lc(k))<p(k))zig(k);
}else{
insert(rc(k),v);
if(p(rc(k))<p(k))zag(k);
}
}
inline void del(int &k,int v){
if(v(k)==v){
if(c(k)>)c(k)--,s(k)--;
else if(!lc(k) || !rc(k))k=lc(k)+rc(k);
else if(p(lc(k))<p(rc(k)))zig(k),del(k,v);
else zag(k),del(k,v);
return;
}
else s(k)--;
if(v<v(k))del(lc(k),v);
else del(rc(k),v);
}
inline int find(int v){
int x=rt,res=;
while(x){
if(v==v(x))return res+s(lc(x))+;
if(v<v(x))x=lc(x);
else res+=s(lc(x))+c(x),x=rc(x);
}
return res;
}
inline int findx(int k){
int x=rt;
while(x){
if(s(lc(x))<k&&s(lc(x))+c(x)>=k)return v(x);
if(s(lc(x))>=k)x=lc(x);
else k-=s(lc(x))+c(x),x=rc(x);
}
return ;
}
inline int pre(int v){
int x=rt,res=-INF;
while(x){
if(v(x)<v)res=v(x),x=rc(x);
else x=lc(x);
}
return res;
}
inline int nxt(int v){
int x=rt,res=INF;
while(x){
if(v(x)>v)res=v(x),x=lc(x);
else x=rc(x);
}
return res;
}
int main(){
int n=read();
for(int i=;i<=n;i++){
int opt=read();
int k=read();
if(opt==)insert(rt,k);
if(opt==)del(rt,k);
if(opt==)printf("%d\n",find(k));
if(opt==)printf("%d\n",findx(k));
if(opt==){
insert(rt,k);
printf("%d\n",pre(k));
del(rt,k);
}
if(opt==){
insert(rt,k);
printf("%d\n",nxt(k));
del(rt,k);
}
}
return ;
}

BZOJ3224:普通平衡树——题解的更多相关文章

  1. 【洛谷P3369】【模板】普通平衡树题解

    [洛谷P3369][模板]普通平衡树题解 题目链接 题意: 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3 ...

  2. [转载]无旋treap:从好奇到入门(例题:bzoj3224 普通平衡树)

    转载自ZZH大佬,原文:http://www.cnblogs.com/LadyLex/p/7182491.html 今天我们来学习一种新的数据结构:无旋treap.它和splay一样支持区间操作,和t ...

  3. [您有新的未分配科技点]无旋treap:从好奇到入门(例题:bzoj3224 普通平衡树)

    今天我们来学习一种新的数据结构:无旋treap.它和splay一样支持区间操作,和treap一样简单易懂,同时还支持可持久化. 无旋treap的节点定义和treap一样,都要同时满足树性质和堆性质,我 ...

  4. [BZOJ3224]普通平衡树(旋转treap,STL-vector)

    3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 20328  Solved: 8979[Submit][St ...

  5. [bzoj3224]普通平衡树/3223文艺平衡树

    这是一道很普通的题.. 最近花了很多时间来想要去干什么,感觉自己还是太拿衣服 做这道题是因为偶尔看到了lavender的blog和她的bzoj早期AC记录,就被题目深深地吸引到了,原因有二: 自己sp ...

  6. BZOJ3224普通平衡树【Splay】

    3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 11751  Solved: 5013 Descriptio ...

  7. [TYVJ1728/BZOJ3224]普通平衡树-替罪羊树

    Problem 普通平衡树 Solution 本题是裸的二叉平衡树.有很多种方法可以实现.这里打的是替罪羊树模板. 此题极其恶心. 前驱后继模块需要利用到rank模块来换一种思路求. 很多细节的地方容 ...

  8. bzoj3224 普通平衡树(c++vector)

    Tyvj 1728 普通平衡树 2014年8月23日6,4365 Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有 ...

  9. BZOJ3224普通平衡树——非旋转treap

    题目: 此为平衡树系列第一道:普通平衡树您需要写一种数据结构,来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数, ...

随机推荐

  1. ORA-15032、ORA-15071错误处理

    遇到一下错误 ERROR at line 1: ORA-15032: not all alterations performed ORA-15071: ASM disk "NOCR_0002 ...

  2. pip源设置 & pandas安装

    pip的官方源python.pypi.org貌似被墙,换用国内安装源 网上的设置方法都是基于Unix的,Windows下的设置略麻烦. 更新..\Lib\site-packages\pip下的cmdo ...

  3. 「日常训练」Known Notation(ZOJ-3829)

    题意与分析 题意是这样的:给一个字符串,字符串中只包含数字和运算符'*'.现在问字符串是不是一个合法的逆波兰式(后缀表达式).已知逆波兰式的空格消除,也就是说123可以看成123也可以看成1和23.如 ...

  4. uvaoj1225Digit Counting(暴力)

    Trung is bored with his mathematics homeworks. He takes a piece of chalk and starts writing a sequen ...

  5. sql注入记录------类型转换错误---convert()函数,一句话图片马制作

    sql注入在联合查询是出现一下错误查不到数据 Illegal mix of collations for operation 'UNION' 用convert() 转换编码为utf8 或者big5 就 ...

  6. 阿里云ECS下Ubuntu 16.04系统安装python3.6.5 环境并设置为默认

    一.添加python3.6安装包并安装: 二.修改系统默认python版本为3.6: 三.安装并升级pip版本: 一.添加python3.6安装包并安装: sudo apt-get install s ...

  7. 关于@media不生效的问题和meta总结

    1:之前做的是两套页面.现在改成响应式布局.发现加上 @media only screen and (max-width: 500px) {    .gridmenu {        width:1 ...

  8. MySql优化浅析

    优化点:合理的使用索引,可以大幅度提升sql查询效率,特别查询的表的数据量大的时候,效果明显.一.引言 公司的产品XX出行上线正式运营,随着数据量的变大,司机2000+,日订单1万+,注册乘客26W+ ...

  9. Open MPI集群运行

    部署完之后,代码也能正确跑起来了,也确实集群分散了.跑一下各种各样的代码,发现了一个错误: $ ~/OpenMpi/bin/mpiexec -np ~/NetWorkTest My rank is M ...

  10. [C++] OOP - Access Control and Class Scope

    Access Control And Inheritance Protected Member Like private, protected members are unaccessible to ...