[洛谷P3369] 普通平衡树 Treap & Splay
这个就是存一下板子......
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的更多相关文章
- 洛谷P3369普通平衡树(Treap)
题目传送门 转载自https://www.cnblogs.com/fengzhiyuan/articles/7994428.html,转载请注明出处 Treap 简介 Treap 是一种二叉查找树.它 ...
- 洛谷P3391文艺平衡树(Splay)
题目传送门 转载自https://www.cnblogs.com/yousiki/p/6147455.html,转载请注明出处 经典引文 空间效率:O(n) 时间效率:O(log n)插入.查找.删除 ...
- 洛谷P3369 普通平衡树
刚学平衡树,分别用了Splay和fhq-treap交了一遍. 这是Splay的板子,貌似比较短? Splay #include <iostream> #include <cstdio ...
- 洛谷P3391 文艺平衡树 (Splay模板)
模板题. 注意标记即可,另外,涉及区间翻转操作,记得设立首尾哨兵. 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int ...
- 洛谷P3369 【模板】普通平衡树(Treap/SBT)
洛谷P3369 [模板]普通平衡树(Treap/SBT) 平衡树,一种其妙的数据结构 题目传送门 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除 ...
- 【洛谷P3369】【模板】普通平衡树题解
[洛谷P3369][模板]普通平衡树题解 题目链接 题意: 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3 ...
- [洛谷P3391] 文艺平衡树 (Splay模板)
初识splay 学splay有一段时间了,一直没写...... 本题是splay模板题,维护一个1~n的序列,支持区间翻转(比如1 2 3 4 5 6变成1 2 3 6 5 4),最后输出结果序列. ...
- [洛谷日报第62期]Splay简易教程 (转载)
本文发布于洛谷日报,特约作者:tiger0132 原地址 分割线下为copy的内容 [洛谷日报第62期]Splay简易教程 洛谷科技 18-10-0223:31 简介 二叉排序树(Binary Sor ...
- 绝对是全网最好的Splay 入门详解——洛谷P3369&BZOJ3224: Tyvj 1728 普通平衡树 包教包会
平衡树是什么东西想必我就不用说太多了吧. 百度百科: 一个月之前的某天晚上,yuli巨佬为我们初步讲解了Splay,当时接触到了平衡树里的旋转等各种骚操作,感觉非常厉害.而第二天我调Splay的模板竟 ...
随机推荐
- 字符串中子序列出现次数(dp)
躲藏 链接:https://ac.nowcoder.com/acm/problem/15669来源:牛客网 题目描述 XHRlyb和她的小伙伴Cwbc在玩捉迷藏游戏. Cwbc藏在多个不区分大小写的字 ...
- 用数组来实现Stack
1:Stack特点 stack:栈,是一种特殊的数据结构,有着先入后出的特点(first in last out).stack中栈底始终不变,只有一端能变化.栈顶在有数据push的时候增大,有数据po ...
- java8的lambda过滤list遍历集合,排序
1.根据属性过滤list List<AllManagerBean> testLists = broadCastRoomMapper.allManagerlist(); List<Al ...
- Django-rest framework框架的三大认证组件
源码分析:三大认证组件的封装 组件的认证配置: 模型层:models.py class User(BaseModel): username = models.CharField(verbose_nam ...
- NWERC 2015
2015-2016 Northwestern European Regional Contest (NWERC 2015) F H没做 似乎只有 B 题有点意思 D:数论分块枚举所有上取整区间,只需要 ...
- springmvc中那些易被忽略的小知识点
1.springmvc会为没有view的modelandview指定默认view 知道这个的时候我都惊呆了. 我从来都是手动指定view名字,今天看到别人写的代码竟然直接返回了个mav,貌似是在dis ...
- Python笔记_第四篇_高阶编程_GUI编程之Tkinter_2.控件类
1. Label控件: 说明:标签控件,可显示文本 图示1: 实例1: import tkinter # 创建主窗口__编程头部 win = tkinter.Tk() # 设置标题 win.title ...
- oBike退出新加坡、ofo取消免押金服务,全球共享单车都怎么了?
浪潮退去后,才知道谁在裸泳.这句已经被说烂的"至理名言",往往被用在一波接一波的互联网热潮中.团购.O2O.共享单车.共享打车.无人货柜--几乎每一波热潮在退去后会暴露出存在的问题 ...
- vue2.0+mintui+hbuilder 打包移动端app之后出现空白页面的解决方案
1.首先使用的是vue-cli构建的页面,用hbuildX打包成移动端的安装包(hbuildX打包成app的流程,请看自行搜索) 2.cnpm install build 生成dist文件夹,里面包含 ...
- linux下特殊命令集锦
1.ifconfig -a | grep enp0 | cut -d : -f 1 //按照:进行切割网络文件名 如:ifconfig `ifconfig -a | grep enp0 | cut ...