【替罪羊树】bzoj3224&luogu3369&cogs1829 [Tyvj 1728]普通平衡树


bzoj

洛谷

cogs


先长点芝士


替罪羊树也是一种很好写的平衡树qwq。。替罪羊树的核心思想就是重构。即当一棵子树的平衡被破坏,那么就把这棵树拍平,也就是树高为O(logn)的完美二叉树形态。这样看似复杂度很高,实则不然。可以证明,替罪羊树每次重构的复杂度都是均摊O(logn)的。

——蒯自WFJdalao的博客


插入和普通BST类似,只需要判断插入操作是否导致了这一条链上结点的大小平衡被破坏,如果有的话将深度最浅的点所在子树暴力重建。重建最简单的方法就是对这棵子树中序遍历后分治建树。通过势能分析可以证明每一次插入的均摊复杂度为\(logn\)。

查询和普通BST并无区别。

删除操作比较巧妙。对于一次删除,我们并不马上移除这个点,而是直接这个点上打上删除标记,查询时跳过该点。重构时可以顺便删除打了删除标记的点。当被删除结点的个数超过总结点数的\((1−α)\)倍时可以选择重构整棵树进行结构优化,并且显然这部分重构的复杂度不会超过\(O(nlogn)\)。

——蒯自xlightgod学长的博客


题解

上面说的很清楚了,然鹅我并不会“势能分析”呵呵哒

因为写treap写习惯了指针还挺好用的就尝试用指针写替罪羊树。。。我错了

然后我深陷二级指针的泥坑中无法自拔。。。

回归正题。。。

首先“拍平”就是把字树的中序遍历搞出来,然后暴力重建。。。好暴力

反正“可以证明,替罪羊树每次重构的复杂度都是均摊O(logn)的”,我不会证明。。。


Code

// It is made by XZZ
#include<cstdio>
#include<algorithm>
using namespace std;
#define rep(a,b,c) for(rg int a=b;a<=c;a++)
#define drep(a,b,c) for(rg int a=b;a>=c;a--)
#define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
#define il inline
#define rg register
#define vd void
typedef long long ll;
il int gi(){
rg int x=0,f=1;rg char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int maxn=1e6+2;
const double alpha=0.7777777;
int root,id,val[maxn],ch[maxn][2],siz[maxn],cover[maxn],b[maxn];
bool del[maxn];
il int newnode(int _val){val[++id]=_val,ch[id][0]=ch[id][1]=0,siz[id]=cover[id]=1;return id;}
il vd dfs(const int&rt){
if(!rt)return;
dfs(ch[rt][0]);
if(!del[rt])b[++b[0]]=rt;
dfs(ch[rt][1]);
}
il int divide(int l,int r){
if(l>r)return 0;
int mid=(l+r)>>1;
ch[b[mid]][0]=divide(l,mid-1);
ch[b[mid]][1]=divide(mid+1,r);
siz[b[mid]]=siz[ch[b[mid]][0]]+siz[ch[b[mid]][1]]+!del[b[mid]];
cover[b[mid]]=cover[ch[b[mid]][0]]+cover[ch[b[mid]][1]]+1;
return b[mid];
}
il vd rebuild(int&rt){
b[0]=0;dfs(rt);rt=divide(1,b[0]);
}
il int*_Insert(int&rt,const int&num){
if(!rt){rt=newnode(num);return NULL;}
++siz[rt],++cover[rt];
int*ret=_Insert(ch[rt][num>=val[rt]],num);
if(max(cover[ch[rt][0]],cover[ch[rt][1]])>alpha*cover[rt])ret=&rt;
return ret;
}
il vd Insert(const int&x){int*ls=_Insert(root,x);if(ls)rebuild(*ls);}
il int Rank(const int&x){
int ret=1,now=root;
while(now)
if(x<=val[now])now=ch[now][0];
else ret+=siz[ch[now][0]]+!del[now],now=ch[now][1];
return ret;
}
il int Kth(int k){
int now=root;
while(now){
if(!del[now]&&k==siz[ch[now][0]]+1)return val[now];
if(k<=siz[ch[now][0]])now=ch[now][0];
else k-=siz[ch[now][0]]+!del[now],now=ch[now][1];
}
}
il vd _Erase(int k){
int now=root;
while(now){
--siz[now];
if(!del[now]&&k==siz[ch[now][0]]+1){del[now]=1;return;}
if(k<=siz[ch[now][0]])now=ch[now][0];
else k-=siz[ch[now][0]]+!del[now],now=ch[now][1];
}
}
il vd Erase(const int&x){
_Erase(Rank(x));
if(siz[root]<cover[root]*alpha)rebuild(root);
}
int main(){
int n=gi(),opt,x;
while(n--){
opt=gi(),x=gi();
if(opt==1)Insert(x);
else if(opt==2)Erase(x);
else if(opt==3)printf("%d\n",Rank(x));
else if(opt==4)printf("%d\n",Kth(x));
else if(opt==5)printf("%d\n",Kth(Rank(x)-1));
else printf("%d\n",Kth(Rank(x+1)));
}
return 0;
}

【替罪羊树】bzoj3224&luogu3369&cogs1829 [Tyvj 1728]普通平衡树的更多相关文章

  1. (treap)[bzoj3224][洛谷3369][cogs1829]Tyvj 1728 普通平衡树

    Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数 ...

  2. bzoj3224 Tyvj 1728 普通平衡树(名次树+处理相同)

    3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 5354  Solved: 2196[Submit][Sta ...

  3. [BZOJ3224]Tyvj 1728 普通平衡树

    [BZOJ3224]Tyvj 1728 普通平衡树 试题描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个) ...

  4. bzoj3224: Tyvj 1728 普通平衡树(平衡树)

    bzoj3224: Tyvj 1728 普通平衡树(平衡树) 总结 a. cout<<(x=3)<<endl;这句话输出的值是3,那么对应的,在splay操作中,当父亲不为0的 ...

  5. BZOJ_3224 Tyvj 1728 普通平衡树 【离散化+权值线段树】

    一 题面 Tyvj 1728 普通平衡树 二 分析 比较明显是可以用平衡二叉搜索树(splay)做的. 用权值线段树做,前提就是要先离散化,因为权值线段树维护的值域信息. 板子. 三 AC代码 #in ...

  6. BZOJ 3224: Tyvj 1728 普通平衡树 or 洛谷 P3369 【模板】普通平衡树-Splay树模板题

    3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 22483  Solved: 10130[Submit][S ...

  7. cogs 1829. [Tyvj 1728]普通平衡树 权值线段树

    1829. [Tyvj 1728]普通平衡树 ★★★   输入文件:phs.in   输出文件:phs.out   简单对比时间限制:1 s   内存限制:1000 MB [题目描述] 您需要写一种数 ...

  8. BZOJ 3224 TYVJ 1728 普通平衡树 [Treap树模板]

    3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 7390  Solved: 3122 [Submit][S ...

  9. bzoj3224: Tyvj 1728 普通平衡树(splay)

    3224: Tyvj 1728 普通平衡树 题目:传送门 题解: 啦啦啦啦又来敲个模版水经验啦~ 代码: #include<cstdio> #include<cstring> ...

随机推荐

  1. BZOJ4807:車(组合数学,高精度)

    Description 众所周知,車是中国象棋中最厉害的一子之一,它能吃到同一行或同一列中的其他棋子.車跟車显然不能在一起打起来,于是rly一天又借来了许多许多的車在棋盘上摆了起来……他想知道,在N× ...

  2. [SHOI2010]最小生成树

    题目 首先让其余所有边都减\(1\)和让自己加\(1\)没什么区别 考虑\(kruskal\)的过程 首先边权大于这条边的是不用考虑的 考虑把那些边权比这条边小的调节到比这条边大,这样就相当于在生成树 ...

  3. CNN识别验证码1

    之前学习python的时候,想尝试用requests实现自动登陆,但是现在网站登陆都会有验证码保护,主要是为了防止暴力破解,任意用户注册.最近接触深度学习,cnn能够进行图像识别,能够进行验证码识别. ...

  4. 随手练——HDU Safe Or Unsafe (小根堆解决哈夫曼问题)

    HDU 2527 :http://acm.hdu.edu.cn/showproblem.php?pid=2527 哈夫曼树,学完就忘得差不多了,题目的意思都没看懂,有时间复习下,看了别人的才知道是怎么 ...

  5. 6、Android---运用手机多媒体(待完成)

    6.1.程序运行在手机上 6.2.使用通知 通知是Android中比较由特色的一个功能 当某个应用程序需要向用户发出一些提示信息时 而该程序由不在前台的显示 就可以借助通知来实现 6.2.1.通知的基 ...

  6. pymongo的安装和使用

    1.安装 MongoDB的python接口pymongo的安装方法有多种,如源码.easy_install.pip都可以.采用pip安装,很简单. pip install pymongo 安装完成后可 ...

  7. Android性能测试之Monkey使用

    内容中包含 base64string 图片造成字符过多,拒绝显示

  8. DPI在SDN中的部署方式

    目录 在sdn中的部署分类 将DPI部署到基础设施层 将DPI部署到控制层 将DPI部署到应用层 个人总结 参考文献 在sdn中的部署分类 DPI 可以分别部署到SDN的基础设施层.控制层和应用层. ...

  9. java 网站源码 六套模版 兼容手机平板PC freemaker 静态引擎 在线编辑模版

    官网 http://www.fhadmin.org/ 系统介绍: 1.网站后台采用主流的 SSM 框架 jsp JSTL,网站后台采用freemaker静态化模版引擎生成html 2.因为是生成的ht ...

  10. Java 深入理解内部类

    摘自海子:Java内部类详解 深入理解内部类 1.为什么成员内部类可以无条件访问外部类的成员? 在此之前,我们已经讨论过了成员内部类可以无条件访问外部类的成员,那具体究竟是如何实现的呢?下面通过反编译 ...