题解:

替罪羊树的模板和splay差距还是比较大的。。

按照我的splay的写法 真是都是问题。。

替罪羊树就是暴力的搞

当某颗子树大小大于这棵树的alpha时 就退出

另外删除的时候打懒标记删除

当有用个数少于alpha*n的时候,就重构

注意点:

1.找rank的时候要找比它小的个数,不能像splay那样取min

2.删除的时候要删排名为这个的,不能删这个数

以上两点的原因是

不能保证相同元素一定在左子树内,因为重构可能造成在右子树

另外找pre和scc也就不能和splay一样了

rank(x) 找的是编号最小的那个

rank(x)-1就是前驱

rank(x+1) 就是后继

替罪羊树不支持区间操作

应该写它的用处就是用来搞毒瘤树套树的。。

#include <bits/stdc++.h>
using namespace std;
#define rint register int
#define IL inline
#define rep(i,h,t) for (rint i=h;i<=t;i++)
#define dep(i,t,h) for (rint i=t;i>=h;i--)
#define mid ((h+t)>>1)
const double alpha=0.75;
const int INF=2e9+;
const int N=4e6+;
int s[N],n,m,top,rt,t1;
struct phs{
int ls[N],rs[N],siz[N],travel[N],cnt[N],v[N];
bool f[N];
void dfs(int x)
{
if (!x) return;
dfs(ls[x]);
if (f[x]) travel[++t1]=x;
else s[++top]=x;
dfs(rs[x]);
}
void build(int &x,int h,int t)
{
x=travel[mid];
if (h==t)
{
siz[x]=cnt[x]=;
ls[x]=rs[x]=;
return;
}
if (h<mid) build(ls[x],h,mid-); else ls[x]=;
build(rs[x],mid+,t);
siz[x]=siz[ls[x]]+siz[rs[x]]+;
cnt[x]=cnt[ls[x]]+cnt[rs[x]]+;
}
void rebuild(int &x)
{
t1=; dfs(x);
if (t1) build(x,,t1);
else x=;
}
void insert(int &x,int k)
{
if (!x)
{
x=s[top--]; v[x]=k;
siz[x]=cnt[x]=f[x]=;
ls[x]=rs[x]=;
return;
}
siz[x]++; cnt[x]++;
if (k<=v[x]) insert(ls[x],k);
else insert(rs[x],k);
if ((double)max(siz[ls[x]],siz[rs[x]])>(double)siz[x]*alpha)
{
rebuild(x);
}
}
void del(int x,int k)
{
siz[x]--;
if (f[x]&&k==v[x])
{
f[x]=; return;
}
if (k<=v[x]) del(ls[x],k);
else del(rs[x],k);
}
void del(int k)
{
int now=rt;
while (now)
{
siz[now]--;
if (f[now]&&k==siz[ls[now]]+)
{
f[now]=;
return;
}
if (k<=siz[ls[now]]) now=ls[now];
else k-=siz[ls[now]]+f[now],now=rs[now];
}
}
void delete2(int x)
{
del(x);
if ((double)siz[rt]<(double) alpha*cnt[rt]) rebuild(rt);
}
int rank(int x)
{
int now=rt,ans=;
while (now)
{
if (v[now]>=x) now=ls[now];
else ans+=siz[ls[now]]+f[now],now=rs[now];
}
return(ans);
}
int get_kth(int x)
{
int now=rt;
while (now)
{
if (f[now]&&x==siz[ls[now]]+) return(v[now]);
if (siz[ls[now]]>=x) now=ls[now];
else x-=siz[ls[now]]+f[now],now=rs[now];
}
}
}S;
int main()
{
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
ios::sync_with_stdio(false);
cin>>n;
dep(i,,) s[++top]=i;
rep(i,,n)
{
// cout<<i<<endl;
int kk,x;
cin>>kk>>x;
if (kk==)
{
S.insert(rt,x);
}
if (kk==)
{
S.delete2(S.rank(x));
}
if (kk==)
{
cout<<S.rank(x)<<endl;
}
if (kk==)
{
cout<<S.get_kth(x)<<endl;
}
if (kk==)
{
cout<<S.get_kth(S.rank(x)-)<<endl;
}
if (kk==)
{
cout<<S.get_kth(S.rank(x+))<<endl;
}
}
return ;
}

https://zhuanlan.zhihu.com/p/21263304

替罪羊树&&非旋treap的更多相关文章

  1. 平衡树简单教程及模板(splay, 替罪羊树, 非旋treap)

    原文链接https://www.cnblogs.com/zhouzhendong/p/Balanced-Binary-Tree.html 注意是简单教程,不是入门教程. splay 1. 旋转: 假设 ...

  2. [模板] 平衡树: Splay, 非旋Treap, 替罪羊树

    简介 二叉搜索树, 可以维护一个集合/序列, 同时维护节点的 \(size\), 因此可以支持 insert(v), delete(v), kth(p,k), rank(v)等操作. 另外, prev ...

  3. 非旋treap套线段树

    BZOJ3065. 去年用pascal 块链过了.. 今年来试了试非旋treap大法   注定被块链完爆 代码留这. 第一份 :辣鸡的  垃圾回收做法  跑得极慢 #include <bits/ ...

  4. 非旋 treap 结构体数组版(无指针)详解,有图有真相

    非旋  $treap$ (FHQ treap)的简单入门 前置技能 建议在掌握普通 treap 以及 左偏堆(也就是可并堆)食用本blog 原理 以随机数维护平衡,使树高期望为logn级别, FHQ  ...

  5. 2827: 千山鸟飞绝 非旋treap

    国际惯例的题面:看起来很不可做的样子,我们先来整理一下题意吧.就是,维护每个点曾经拥有过的最大的两个属性值,支持把点的位置移动.我们用map对每个位置进行离散化,对每个位置建立一个平衡树.为了方便分离 ...

  6. 2018.08.06 bzoj1500: [NOI2005]维修数列(非旋treap)

    传送门 平衡树好题. 我仍然是用的fhqtreap,感觉速度还行. 维护也比线段树splay什么的写起来简单. %%%非旋treap大法好. 代码: #include<bits/stdc++.h ...

  7. 非旋Treap总结 : 快过Splay 好用过传统Treap

    非旋$Treap$ 其高级名字叫$Fhq\ Treap$,既然叫$Treap$,它一定满足了$Treap$的性质(虽然可能来看这篇的人一定知道$Treap$,但我还是多说几句:$Fhp\ Treap$ ...

  8. 非旋treap

    目录 核心思想 核心操作 其他操作 参考程序 核心思想 主要的思想与treap是一样的.通过让二叉查找树同时满足堆(随机参数)的性质来防止深度过大.与普通treap不同的是非旋treap通过树的分裂与 ...

  9. 非旋Treap及其可持久化

    平衡树这种东西,我只会splay.splay比较好理解,并且好打,操作方便. 我以前学过SBT,但并不是很理解,所以就忘了怎么打了. 许多用平衡树的问题其实可以用线段树来解决,我们真正打平衡树的时候一 ...

随机推荐

  1. 关于apache配置映射端口

    step1.打开httpd.conf找到Listen 80这一行在后面添加Listen 8080Listen 8001Listen 8002Listen 8003也就是意味着每个项目占用一个端口,就像 ...

  2. 【原创】大叔经验分享(38)beeline连接hiveserver2报错impersonate

    beeline连接hiveserver2报错 Error: Could not open client transport with JDBC Uri: jdbc:hive2://localhost: ...

  3. Swift 通过字符串创建控制器

    由于Swift 中新增了一个命名空间(在同一个命名空间中的文件可以直接访问而不用引入头文件)的概念 所以通过字符串创建控制器需要带上命名空间 1 首先为Bundle 写一个分类  获取命名空间 ext ...

  4. js数组的实例方法sort() 排序方法的运用,不再只是.sort()

    1, sort() 不传回调函数的话,默认按照字母顺序(字符编码)的顺序进行排序. 2, sort() 通过传回调函数来控制从小到大的排序还是从大到小的排序: var arr = [1,23,5,6, ...

  5. bat如何实现自动创建文件夹(以当前时间命名)

    先比较直接的查看当前的日期和时间:(或者cmd中直接输入date,time查看) @echo off color 0a set dt=%date%%time% echo %dt% pause 1.使用 ...

  6. spark submit参数及调优

    park submit参数介绍 你可以通过spark-submit --help或者spark-shell --help来查看这些参数.   使用格式:  ./bin/spark-submit \   ...

  7. SpringCloud路由(网关)

    springcloud网关接口就类似于转发 搭建路由网关项目(ZuulDemo) 1.创建pom.xml <project xmlns="http://maven.apache.org ...

  8. JavaScript(JS)之简单介绍

    一.JavaScript的历史 1992年Nombas开发出C-minus-minus(C--)的嵌入式脚本语言(最初绑定在CEnvi软件中).后将其改名ScriptEase.(客户端执行的语言) N ...

  9. 字符串为空的比较 ==与equals() 区别(キ`゚Д゚´)!!基础很重要 !!!

    情况描述:我提交的代码,让老大审批了一次,讲真的,对于我来说受益匪浅,其中有一个印象很深的内容:一个字符串是否为空的判断,我以前敲代码一直都是这样写的,可是从来都没有意识到这个东西. 代码: if(s ...

  10. Python基础之面向过程编程

    要求:在文件里递归找到关于包含“Python”内容的文件的绝对路径并打印出来 #定义阶段 import os,time def init(func): #装饰器的作用是使下面的生成器初始化,yield ...