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

题目传送门

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. Android studio2.2 app:transformNative_libsWithStripDebugSymbolForDebug

    开始搜到的问题相关链接: http://blog.csdn.NET/doumingliangdendsc/article/details/52595317 https://www.oschina.ne ...

  2. 深入理解spring中的AOP原理 —— 实现MethodInterceptor接口,自已动手写一个AOP

      1.前言 AOP是面向切面编程,即“Aspect Oriented Programming”的缩写.面对切面,就是面向我们的关注面,不能让非关注面影响到我们的关注面.而现实中非关切面又必不可少,例 ...

  3. 面向对象 part4 构造函数对象重写

    出处 其中深奥之处非看一次能了解 !对象真的有点绕,但是又很严谨

  4. python——print函数

    .print()函数概述 print() 方法用于打印输出,是python中最常见的一个函数. 该函数的语法如下: print(*objects, sep=' ', end='\n', file=sy ...

  5. 长沙中考2019数学T25讲解

    好久没更Blog了... 为了应付完成寒假作业,还是更一下(再不更都庚子年了) Upd:2020.1.22 题目 第一问 还是比较水友好的 给顶点就相当于多给了对称轴-\(\frac{b}{2a}\) ...

  6. Android音视频处理之基于MediaCodec合并音视频

    Android提供了一个MediaExtractor类,可以用来分离容器中的视频track和音频track,下面的例子展示了使用MediaExtractor和MediaMuxer来实现视频的换音: p ...

  7. Matlab高级教程_第一篇:Matlab基础知识提炼_03

    第七节:函数 编程的过程很像是画图纸,编程语言在平时使用的时候不会像是单个的命令去执行,大多数情况下我们把许多重复要执行或者一些常用的编辑好的功能“封装”到一起,方便来使用.函数-----就是这种过程 ...

  8. Ansible部署rsync、nfs及sersync

    rsync nfs sersync httpd环境: 角色 外网IP(NAT) 内网IP(LAN) 主机名 Rsync服务端 eth0:10.0.1.51 eth1:172.16.1.51 backu ...

  9. Python_实战爬虫

    # -*- coding: utf-8 -*-__auther__ = "jiachaojun"__time__ = '2020/1/12 11:03'import request ...

  10. springboot集成websocket实现大文件分块上传

    遇到一个上传文件的问题,老大说使用http太慢了,因为http包含大量的请求头,刚好项目本身又集成了websocket,想着就用websocket来做文件上传. 相关技术 springboot web ...