这个就是存一下板子......

题目传送门

Treap的实现应该是比较正经的。

插入删除前驱后继排名什么的都是平衡树的基本操作。

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
using namespace std; int n,root,tot; struct treap
{
int ls,rs,v,rd,sz,h;
}t[]; void update(int p)
{
t[p].sz=t[t[p].ls].sz+t[t[p].rs].sz+t[p].h;
} void zig(int &p)
{
int r=t[p].rs;
t[p].rs=t[r].ls;
t[r].ls=p;
t[r].sz=t[p].sz;
update(p);
p=r;
} void zag(int &p)
{
int l=t[p].ls;
t[p].ls=t[l].rs;
t[l].rs=p;
t[l].sz=t[p].sz;
update(p);
p=l;
} void insert(int &p,int val)
{
if(p==)
{
tot++;
p=tot;
t[p].sz=t[p].h=;
t[p].v=val;
t[p].rd=rand();
return;
}
t[p].sz++;
if(t[p].v==val)t[p].h++;
else if(t[p].v<val)
{
insert(t[p].rs,val);
if(t[p].rd>t[t[p].rs].rd)zig(p);
}else
{
insert(t[p].ls,val);
if(t[p].rd>t[t[p].ls].rd)zag(p);
}
} void del(int &p,int val)
{
if(!p)return;
if(t[p].v==val)
{
if(t[p].h>)
{
t[p].h--;
t[p].sz--;
return;
}
if(t[p].ls*t[p].rs==)p=t[p].ls+t[p].rs;
else if(t[t[p].ls].rd<t[t[p].rs].rd)
{
zag(p);
del(p,val);
}else
{
zig(p);
del(p,val);
}
}else if(t[p].v<val)
{
t[p].sz--;
del(t[p].rs,val);
}else
{
t[p].sz--;
del(t[p].ls,val);
}
} int qrank(int p,int val)
{
if(!p)return ;
if(t[p].v==val)return t[t[p].ls].sz+;
else if(t[p].v<val)return t[t[p].ls].sz+t[p].h+qrank(t[p].rs,val);
else return qrank(t[p].ls,val);
} int qnum(int p,int rk)
{
if(!p)return ;
int lsz=t[t[p].ls].sz+t[p].h;
if(rk<=t[t[p].ls].sz)return qnum(t[p].ls,rk);
else if(rk>lsz)return qnum(t[p].rs,rk-lsz);
else return t[p].v;
} void pre(int p,int val,int &ans)
{
if(!p)return;
if(t[p].v<val)
{
ans=p;
pre(t[p].rs,val,ans);
}else pre(t[p].ls,val,ans);
} void post(int p,int val,int &ans)
{
if(!p)return;
if(t[p].v>val)
{
ans=p;
post(t[p].ls,val,ans);
}else post(t[p].rs,val,ans);
} int main()
{
scanf("%d",&n);
int op,x;
while(n--)
{
scanf("%d%d",&op,&x);
if(op==)insert(root,x);
if(op==)del(root,x);
if(op==)printf("%d\n",qrank(root,x));
if(op==)printf("%d\n",qnum(root,x));
if(op==){int r=;pre(root,x,r);printf("%d\n",t[r].v);}
if(op==){int r=;post(root,x,r);printf("%d\n",t[r].v);}
}
return ;
}

今天突然想用splay写一下,复习复习。

之后发现第12个点T飞了......

下载输入数据之后,发现这个数据是构造的,依次插入了1~50000这50000个数。

用cfree调试了一下,发现这样会在splay上弄出一个长长的链。

可能是我太菜了,但是我用了两种方法(具体见代码)都会出链导致T飞。

最后为了男人的尊严,我用了一些玄学(随机)算法总算A掉了。

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#define id(x) (s[f[x]][1]==x)
using namespace std; int n,root=,tot=;
int f[],s[][];
int v[],h[],sz[]; void pushup(int p)
{
sz[p]=sz[s[p][]]+sz[s[p][]]+h[p];
} void rotate(int p)
{
int k=id(p);
int fa=f[p];
s[fa][k]=s[p][!k];
s[p][!k]=fa;
s[f[fa]][id(fa)]=p;
f[p]=f[fa];
f[fa]=p;
f[s[fa][k]]=fa;
pushup(fa);
pushup(p);
} void splay(int p,int g)
{
while(f[p]!=g)
{
int fa=f[p];
if(f[fa]==g)
{
rotate(p);
break;
}
if(id(p)^id(fa))rotate(p);
else rotate(fa);
rotate(p);
}
if(!g)root=p;
} void pre(int p,int val,int &ans)
{
if(!p)return;
if(v[p]>=val)pre(s[p][],val,ans);
else ans=p,pre(s[p][],val,ans);
} void post(int p,int val,int &ans)
{
if(!p)return;
if(v[p]<=val)post(s[p][],val,ans);
else ans=p,post(s[p][],val,ans);
} int qrank(int p,int num)
{
if(!p)return ;
if(num<v[p])return qrank(s[p][],num);
if(num==v[p])return sz[s[p][]]+;
return sz[s[p][]]+h[p]+qrank(s[p][],num);
} int qnum(int p,int rk)
{
if(!p)return ;
int lm=sz[s[p][]]+h[p];
if(rk<=sz[s[p][]])return qnum(s[p][],rk);
if(rk>lm)return qnum(s[p][],rk-lm);
return v[p];
} int d[]; void ins(int val)
{
/*int bef,aft;
pre(root,val,bef);
post(root,val,aft);
splay(bef,0);
splay(aft,root);
int gp=s[root][1];
if(!s[gp][0])
{
s[gp][0]=++tot;
f[tot]=gp;
v[tot]=val;
}
h[s[gp][0]]++,sz[s[gp][0]]++;
pushup(gp),pushup(root);*/ int p=root,fa=;
while(p&&v[p]!=val)
{
fa=p;
p=s[p][val>v[p]];
}
if(!p)
{
p=++tot;
s[fa][val>v[fa]]=p;
sz[p]=;
f[p]=fa;
v[p]=val;
}
h[p]++;
splay(p,);
int k=rand()%tot+;
while(d[k])k=rand()%tot+;
splay(k,);
} void del(int val)
{
int bef,aft;
pre(root,val,bef);
post(root,val,aft);
splay(bef,);
splay(aft,root);
int gp=s[root][];
h[s[gp][]]--;
sz[s[gp][]]--;
if(!h[s[gp][]])d[s[gp][]]=,s[gp][]=;
pushup(gp),pushup(root);
} int main()
{
scanf("%d",&n);
f[]=;
s[][]=;
v[]=-0x3f3f3f3f;
v[]=0x3f3f3f3f;
h[]=h[]=sz[]=;
sz[]=;
for(int i=;i<=n;i++)
{
int op,x;
scanf("%d%d",&op,&x);
if(op==)ins(x);
if(op==)del(x);
if(op==){int rk=qrank(root,x)-;printf("%d\n",rk);}
if(op==){int num=qnum(root,x+);printf("%d\n",num);}
if(op==){int pos;pre(root,x,pos);printf("%d\n",v[pos]);}
if(op==){int pos;post(root,x,pos);printf("%d\n",v[pos]);}
}
return ;
}

[洛谷P3369] 普通平衡树 Treap & Splay的更多相关文章

  1. 洛谷P3369普通平衡树(Treap)

    题目传送门 转载自https://www.cnblogs.com/fengzhiyuan/articles/7994428.html,转载请注明出处 Treap 简介 Treap 是一种二叉查找树.它 ...

  2. 洛谷P3391文艺平衡树(Splay)

    题目传送门 转载自https://www.cnblogs.com/yousiki/p/6147455.html,转载请注明出处 经典引文 空间效率:O(n) 时间效率:O(log n)插入.查找.删除 ...

  3. 洛谷P3369 普通平衡树

    刚学平衡树,分别用了Splay和fhq-treap交了一遍. 这是Splay的板子,貌似比较短? Splay #include <iostream> #include <cstdio ...

  4. 洛谷P3391 文艺平衡树 (Splay模板)

    模板题. 注意标记即可,另外,涉及区间翻转操作,记得设立首尾哨兵. 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int ...

  5. 洛谷P3369 【模板】普通平衡树(Treap/SBT)

    洛谷P3369 [模板]普通平衡树(Treap/SBT) 平衡树,一种其妙的数据结构 题目传送门 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除 ...

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

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

  7. [洛谷P3391] 文艺平衡树 (Splay模板)

    初识splay 学splay有一段时间了,一直没写...... 本题是splay模板题,维护一个1~n的序列,支持区间翻转(比如1 2 3 4 5 6变成1 2 3 6 5 4),最后输出结果序列. ...

  8. [洛谷日报第62期]Splay简易教程 (转载)

    本文发布于洛谷日报,特约作者:tiger0132 原地址 分割线下为copy的内容 [洛谷日报第62期]Splay简易教程 洛谷科技 18-10-0223:31 简介 二叉排序树(Binary Sor ...

  9. 绝对是全网最好的Splay 入门详解——洛谷P3369&BZOJ3224: Tyvj 1728 普通平衡树 包教包会

    平衡树是什么东西想必我就不用说太多了吧. 百度百科: 一个月之前的某天晚上,yuli巨佬为我们初步讲解了Splay,当时接触到了平衡树里的旋转等各种骚操作,感觉非常厉害.而第二天我调Splay的模板竟 ...

随机推荐

  1. mysql脚本文件

    DELIMITER $$ -- USE `dev_seal_chip_sell_ms_v1`$$; DROP FUNCTION IF EXISTS `GET_ORDER_STATUS`$$ CREAT ...

  2. 吴裕雄--天生自然 PHP开发学习:MySQL 预处理语句

    <?php $servername = "localhost"; $username = "root"; $password = "admin& ...

  3. UML-SSD总结

    1.不是所有场景都需要画SSD.需要画SSD的场景: 1).主成功场景 2).频繁发生的场景 3).复杂的场景 2.角色 1).参与者 2).系统(没有类,即黑盒) 3.画SSD时间不要过长,一般几分 ...

  4. emacs 配置文件

    使用方式: git clone 到本地,把 emacs 复制到 ~/.emacs.d 打开 emacs 会自动安装包 https://github.com/NorseLZJ/lzj-config/tr ...

  5. 注册登录页面修订-Python使用redis-手机验证接口-发送短信验证

    登录页面修订 views.Login.vue <template> <div class="login box"> <img src="@/ ...

  6. ZJNU 1067 - 约瑟夫——中级

    打表处理(否则Case 1超时) 对m进行枚举,每次枚举进行一次判断 因为好人坏人均为k个,那么只要让下一个死亡的人的位置p保证在1~剩余坏人数量之间即可,不满足则直接break枚举下一个m 实际上对 ...

  7. Python笔记_第三篇_面向对象_9.Python中的"get"和"set"方法(@property和@.setter)

    1. 限制访问的问题: 如果学过C# 语言的我们可以知道C# 语言有get和set方法.我们之前想要获取父类中的私有变量,只能通过写一个set和get的函数进行访问或者通过类生成的新关键字来访问私有属 ...

  8. Python笔记_第三篇_面向对象_2.第一个Python类

    1. 设计一个类: 设计一个类主要从三个方面进行考虑: 第一:类名:类名要见名知意.首字母大写. 第二:属性. 第三:方法. 备注:在Python中有些东西并不是绝对化的事情,有些根据Python社区 ...

  9. maven打包springboot项目的插件配置概览

    jar包的术语背景: normal jar: 普通的jar,用于项目依赖引入,不能通过java -jar xx.jar执行,一般不包含其它依赖的jar包. fat jar: 也叫做uber jar,是 ...

  10. 使用conda管理python环境

    一.动机 最近打算折腾vn.py,但只有py27版本的,因为一向习惯使用最新稳定版的,所以不得不装py27的环境,不得不说 Python的全局锁真的很烦. 身为懒癌患者,必然使用全功能的anacond ...