平衡树 2
板子
无旋Treap
点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int o=2222222;
struct Treap{
struct node{
int l,r;
int size;
int val;
int k;
}t[o];
int tot,root;
int add(int x){
tot++;
t[tot].val=x;
t[tot].k=rand();
t[tot].size=1;
return tot;
}
void pushup(int x){
t[x].size=t[t[x].l].size+t[t[x].r].size+1;
}
void split(int x,int &l,int &r,int v){
if(x==0){
l=r=0;
return ;
}
if(v<t[x].val){
split(t[x].l,l,t[x].l,v);
r=x;
pushup(r);
return;
}
else{
split(t[x].r,t[x].r,r,v);
l=x;
pushup(l);
return;
}
}
int merge(int x,int y){
if(!y||!x){
return x|y;
}
if(t[x].k<t[y].k){
t[x].r=merge(t[x].r,y);
pushup(x);
return x;
}
else{
t[y].l=merge(x,t[y].l);
pushup(y);
return y;
}
}
void pop(int x){
int l,m,r;
split(root,l,r,x);
split(l,l,m,x-1);
m=merge(t[m].l,t[m].r);
r=merge(merge(l,m),r);
}
int kthval(int x,int id){
if(t[t[x].l].size+1==id){
return t[x].val;
}
if(t[t[x].l].size>=id){
return kthval(t[x].l,id);
}
return kthval(t[x].r,id-t[t[x].l].size-1);
}
int rank(int x){
int l=0,r=0,ans=0;
split(root,l,r,x-1);
ans=t[l].size+1;
root=merge(l,r);
return ans;
}
int pre(int x){
int l=0,r=0,ans=0;
split(root,l,r,x-1);
ans=kthval(l,t[l].size);
root=merge(l,r);
return ans;
}
int next(int x){
int l=0,r=0,ans=0;
split(root,l,r,x-1);
ans=kthval(r,1);
root=merge(l,r);
return ans;
}
}T;
int main(){
return 0;
}
Splay
点击查看代码
int root,N,tot;
struct SplayTree{
struct node{
int ch[2];
int fa;
int cnt;
int val;
int son;
}t[o];
void pushup(int x){//infomation
t[x].son=t[t[x].ch[1]].son+t[t[x].ch[0]].son+t[x].cnt;
}
void rotate(int x){//
int y=t[x].fa;
int z=t[y].fa;
int k=t[y].ch[1]==x;
t[z].ch[t[z].ch[1]==y]=x;
t[x].fa=z;
t[y].ch[k]=t[x].ch[k^1];
t[t[x].ch[k^1]].fa=y;
t[x].ch[k^1]=y;
t[y].fa=x;
/*info*/
pushup(y);
pushup(x);
}
void splay(int x,int to){
while(t[x].fa!=to){
int y=t[x].fa;
int z=t[y].fa;
if(z!=to){
if((t[y].ch[0]==x)^(t[z].ch[0]==y)){
rotate(x);
}
else{
rotate(y);
}
}
rotate(x);
}
if(to==0){
root=x;
}
}
void add(int x){
int u=root,fa=0;
while(u&&t[u].val!=x){
fa=u;
u=t[u].ch[x>t[u].val];
}
if(u){
t[u].cnt++;
}
else{
u=++tot;
if(fa){
t[fa].ch[x>t[fa].val]=u;
}
t[tot].ch[0]=0;
t[tot].ch[1]=0;
t[tot].fa=fa;
t[tot].val=x;
t[tot].cnt=1;
t[tot].son=1;
}
splay(u,0);
}
void find(int x){
int u=root;
if(!u){
return ;
}
while(t[u].ch[x>t[u].val]&&x!=t[u].val){
u=t[u].ch[x>t[u].val];
}
splay(u,0);
// return t[t[root].ch[0]].son;
}
int next(int x,int f){
find(x);
int u=root;
if((t[u].val>x&&f)||(t[u].val<x&&!f)){
return u;
}
u=t[u].ch[f];
while(t[u].ch[f^1]){
u=t[u].ch[f^1];
}
return u;
//return t[u].val;
}
void pop(int x){
int l=next(x,0);
int n=next(x,1);
splay(l,0);
splay(n,l);
int del=t[n].ch[0];
if(t[del].cnt>1){
t[del].cnt--;
splay(del,0);
}
else{
t[n].ch[0]=0;
}
}
int rank(int x){
int u=root;
if(t[u].son<x){
return -1;
}
while(1){
int y=t[u].ch[0];
if(x>t[y].son+t[u].cnt){
x-=t[y].son+t[u].cnt;
u=t[u].ch[1];
}
else{
if(t[y].son>=x){
u=y;
}
else{
return t[u].val;
}
}
}
}
}S;
Treap
只会有旋555
Splay
非常熟悉的Splay
就平衡而言:
这玩意实际上不是非常平衡
因为是靠结构维护的平衡,所以不会非常平衡
不过因为有个叫摊还的,所以这玩意在最坏情况下是均摊单次
然后就是Splay了
Splay的旋转操作是双旋,即Splay:
首先是1字形:
这种旋两次
然后是之字形:
这种先旋一次
然后是单旋转,即Rotate:
核心一个事情是维护BST性质,
主要就是对于一个之字形而言:
一个之字应该成为与之反向的之字
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具