博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[总结] 替罪羊树学习笔记
阅读量:4695 次
发布时间:2019-06-09

本文共 3374 字,大约阅读时间需要 11 分钟。

突然不会写学习笔记了...

反正是给自己看的

那就想到哪写到哪吧

思想

不基于旋转而基于暴力重构的平衡树

采用懒惰删除法 每次删除只打标记,在重构时统一删除

如果某个点的子树过于不平衡或删除了过多的元素 那就需要进行重构

重构时暴力dfs整棵子树,碰见打了删除标记的节点就扔进内存池,否则按照中序遍历存下来,然后递归建满二叉树即可。

代码长这样:

void dfs(int &len,int x){    if(!x) return;    dfs(len,ls);    if(!del[x]) cz[++len]=x;    else dp[++dc]=x;    dfs(len,rs);}int build(int l,int r){    if(l>r) return 0;    int mid=l+r>>1;    int x=cz[mid];sze[x]=1;cnt[x]=1;ls=rs=0;del[x]=0;    if(l==r) return x;    ls=build(l,mid-1),rs=build(mid+1,r);    if(ls) fa[ls]=x;    if(rs) fa[rs]=x;    pushup(x); return x;}void pia(int x){    int f=fa[x],len=0;    dfs(len,x);    int t=build(1,len);    if(root==x) root=t;    else ch[f][ch[f][1]==x]=t,fa[t]=f;}

一定要注意及时更新信息

普通平衡树的代码:

#pragma GCC optimize(2)#include
using std::min;using std::max;using std::swap;using std::vector;typedef double db;typedef long long ll;#define pb(A) push_back(A)#define pii std::pair
#define all(A) A.begin(),A.end()#define mp(A,B) std::make_pair(A,B)const int N=1e6+5;const db alph=0.75;#define ls ch[x][0]#define rs ch[x][1]int n,tot,dp[N],dc,cz[N];int sze[N],ch[N][2],cnt[N];int val[N],root,del[N],fa[N];int newnode(){ int t=dc?dp[dc--]:++tot; fa[t]=cnt[t]=sze[t]=val[t]=ch[t][0]=ch[t][1]=del[t]=0; return t;}bool chk(int x){ return alph*sze[x]<=max(sze[ls],sze[rs]) or alph*cnt[x]>sze[x];}void dfs(int &len,int x){ if(!x) return; dfs(len,ls); if(!del[x]) cz[++len]=x; else dp[++dc]=x; dfs(len,rs);}void pushup(int x){ cnt[x]=cnt[ls]+cnt[rs]+1; sze[x]=sze[ls]+sze[rs]+!del[x];}int build(int l,int r){ if(l>r) return 0; int mid=l+r>>1; int x=cz[mid];sze[x]=1;cnt[x]=1;ls=rs=0;del[x]=0; if(l==r) return x; ls=build(l,mid-1),rs=build(mid+1,r); if(ls) fa[ls]=x; if(rs) fa[rs]=x; pushup(x); return x;}void pia(int x){ int f=fa[x],len=0; dfs(len,x); int t=build(1,len); if(root==x) root=t; else ch[f][ch[f][1]==x]=t,fa[t]=f;}int ins(int x,int v,int f,int &flag){ if(!x){ x=newnode(); cnt[x]=sze[x]=1,val[x]=v,fa[x]=f; return x; } int d=val[x]
=rk) erase(ls,rk,flag); else erase(rs,rk-sze[ls]-!del[x],flag); if(chk(x)) flag=x;}int kth(int x,int k){ if(!del[x]){ if(sze[ls]==k-1) return val[x]; if(sze[ls]>=k) return kth(ls,k); return kth(rs,k-sze[ls]-1); } else{ if(sze[ls]>=k) return kth(ls,k); else return kth(rs,k-sze[ls]); }}int find(int x,int k){ if(!x) return 0; if(val[x]>=k) return find(ls,k); else return find(rs,k)+sze[ls]+!del[x];}int getint(){ int X=0,w=0;char ch=getchar(); while(!isdigit(ch))w|=ch=='-',ch=getchar(); while( isdigit(ch))X=X*10+ch-48,ch=getchar(); if(w) return -X;return X;}signed main(){ n=getint(); while(n--){ int opt=getint(),x=getint(); if(opt==1 or opt==2){ int flag=0; if(opt==1) root=ins(root,x,0,flag); else erase(root,find(root,x)+1,flag); if(flag) pia(flag); } if(opt==3) printf("%d\n",find(root,x)+1); if(opt==4) printf("%d\n",kth(root,x)); if(opt==5) printf("%d\n",kth(root,find(root,x))); if(opt==6) printf("%d\n",kth(root,find(root,x+1)+1)); } return 0;}

突然想到了一种不用记录fa的方法哈哈哈哈哈!!!

我们需要记录fa的本质原因是因为在重构的时候要更改fa的ch数组

既然这样我们传参的时候传一个pair包括x和fa[x]不就好了!

哈哈哈哈哈我真是个小机灵鬼

转载于:https://www.cnblogs.com/YoungNeal/p/10300671.html

你可能感兴趣的文章
shell 中数组学习
查看>>
解决scrollView中嵌套编辑框导致不能上下滑动的问题
查看>>
<mvc:annotation-driven/>与<context:annotation-config/>的区别
查看>>
Dijkstra算法
查看>>
F01:金融学第一定律:时间的价值
查看>>
笔记--Day1--python基础1
查看>>
win8 中实现断点续传
查看>>
C语言条件编译(DEBUG思想)
查看>>
汇编语言实验三
查看>>
plsql+绿色版oracle连接远程数据库配置及提示缺少msvcr71.dll解决方法
查看>>
[py]python的继承体系
查看>>
[svc]Iaas Paas Saas区别
查看>>
datagridview实现复制粘贴
查看>>
c#winform程序的改名(修改名称)
查看>>
CSU 2079 觉醒!MACROSS!
查看>>
超详细的Web前端开发规范文档
查看>>
(2.12)Mysql之SQL基础——存储过程条件定义与错误处理
查看>>
SqlServer 凭据
查看>>
1062 Talent and Virtue (25)
查看>>
阿里云服务器 部署Apache Tomcat 后遇到自动Tomcat停止
查看>>