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

题目传送门

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. python计算范数的问题

    计算norm时, 注意把数据改为float 类型, 否则结果不对! import numpy.linalg as LA d = LA.svd(features.toarray(),full_matri ...

  2. 17.3.10--关于C元的变量类型所占字节问题和类型转化

    在C语言并没有对于严格规定short,int  long所占字节,只是做了宽泛要求:short:至少连个字节 int建议为一个机器字长,32位环境下机器字长是4个字节,64位环境机器字长是8个字节 s ...

  3. 第2章 ZooKeeper安装与启动

    第2章 ZooKeeper安装 2-1 JDK的安装 需要先在Linux系统下安装JDK1.8 tar -zxvf jdk-8u231-linux-x64.tar.gz rm -f jdk-8u231 ...

  4. redis 会丢数据吗

    不管是以前的主从模式(哨兵模式),还是现在的集群模式,因为都用了slave of 同步; 而slave of 同步会丢弃本地数据,直接用对方的数据来覆盖本地,所以会丢失数据 1.主备网络不通,后续主节 ...

  5. 并发与高并发(二)-JAVA内存模型

    一.java内存模型(JMM)-同步操作与规则 它描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式.一个线程如何和何时能看到其他线程共享 ...

  6. JavaScript学习笔记 - 进阶篇(3)- 流程控制语句

    if语句 if语句是基于条件成立才执行相应代码时使用的语句. 语法: if(条件) { 条件成立时执行代码} 注意:if小写,大写字母(IF)会出错! 假设你应聘web前端技术开发岗位,如果你会HTM ...

  7. jquery.marquee.js - 有点奇怪的跑马灯动画,不过还是加上去了

    客户想要一个跑马灯的效果,最终我用了jquery.marquee.js. 这个库很简单就能用. 效果是这样,从左到右,移动速度都不一样. 1. HTML <div class="mar ...

  8. CodeForces 993A Two Squares(数学 几何)

    https://codeforces.com/problemset/problem/993/A 题意: 给你两个矩形,第一行是一个正面表示的矩形,第二个是一个旋转四十五度角的矩形,问这两个矩形是否相交 ...

  9. 1.windows-oracle实战第一课

    一.oracle是目前最流行的数据库之一,功能强大.性能卓越.学习要有信心.oracle也做软件,不仅仅是数据库.比如ERP(企业资源计划,用友.金蝶) 二.目前的数据库   相对而言:       ...

  10. java select单线程 服务器

    package com.Select; /** *select单线程 服务器 **/ import java.io.IOException; import java.net.InetSocketAdd ...