感觉平衡树也没有以前想的那么玄乎,(其实set超好用的),非旋式Treap挺好理解,和可并堆,二叉搜索树有很大联系

推荐博客:http://memphis.is-programmer.com/posts/46317.html

模板也是摘自这位dalao的

#include<bits/stdc++.h>
using namespace std;
#define maxn 2000005
#define rep(i,x,y) for(int i=x;i<=y;++i)
#define dep(i,x,y) for(int i=x;i>=y;--i) struct Treap{
Treap *l,*r;
int fix,key,size;
Treap(int key_):fix(rand()),key(key_),l(NULL),r(NULL),size(){} inline void updata(){
size=+(l?l->size:)+(r?r->size:);
}
}*root;
typedef pair<Treap*,Treap*> Droot;//用来Split返回两个根 inline int Size(Treap *x){return x?x->size:;}//这样求size可以防止访问空指针 Treap *Merge(Treap *A,Treap *B){//合并操作
if(!A)return B;
if(!B)return A;
if(A->fix<B->fix){
A->r=Merge(A->r,B);
A->updata();
return A;
}
else{
B->l=Merge(A,B->l);
B->updata();
return B;
}
} Droot Split(Treap *x,int k){//拆分操作
if(!x)return Droot(NULL,NULL);
Droot y;
if(Size(x->l)>=k){
y=Split(x->l,k);
x->l=y.second;
x->updata();
y.second=x;
}
else{
y=Split(x->r,k-Size(x->l)-);
x->r=y.first;
x->updata();
y.first=x;
}
return y;
} Treap *Build(int *a){//建造操作
static Treap *stack[maxn],*x,*last;
int p=;
rep(i,,a[]){
x=new Treap(a[i]);
last=NULL;
while(p && stack[p]->fix>x->fix){
stack[p]->updata();
last=stack[p];
stack[p--]=NULL;
}
if(p) stack[p]->r=x;
x->l=last;
stack[++p]=x;
}
while(p) stack[p--]->updata();
return stack[];
} int Findkth(int k){//查找第K小
Droot x=Split(root,k-);
Droot y=Split(x.second,);
Treap *ans=y.first;
root=Merge(Merge(x.first,ans),y.second);
return ans->key;
} int Getkth(Treap *x,int v){//询问一个数是第几大
if(!x)return ;
return v<x->key?Getkth(x->l,v):Getkth(x->r,v)+Size(x->l)+;
} void Insert(int v){//插入操作
int k=Getkth(root,v);
Droot x=Split(root,k);
Treap *n=new Treap(v);
root=Merge(Merge(x.first,n),x.second);
} void Delete(int k){//删除操作
Droot x=Split(root,k-);
Droot y=Split(x.second,);
root=Merge(x.first,y.second);
} int a[maxn],M,x,y; int main(){
scanf("%d",a);
rep(i,,a[]) scanf("%d",a+i);
sort(a+,a++a[]);
root=Build(a);
scanf("%d",&M);
while(M--){
char ch=getchar();
while(ch!='Q' && ch!='A' && ch!='D') ch=getchar();
scanf("%d",&x);
if(ch=='Q') printf("%d\n",Findkth(x));
if(ch=='A') Insert(x);
if(ch=='D') Delete(x);
}
}

改了一下之后就A了文艺平衡树

#include<bits/stdc++.h>
using namespace std;
#define maxn 2000005
#define rep(i,x,y) for(int i=x;i<=y;++i)
#define dep(i,x,y) for(int i=x;i>=y;--i)
int n;
struct Treap{
Treap *l,*r;
int fix,key,size;
bool fg;
Treap(int key_):fix(rand()),key(key_),l(NULL),r(NULL),size(){} inline void updata(){
size=+(l?l->size:)+(r?r->size:);
}
}*root;
typedef pair<Treap*,Treap*> Droot;//用来Split返回两个根 inline int Size(Treap *x){return x?x->size:;}//这样求size可以防止访问空指针
void pushdown(Treap *x){
if(!x->fg)return;
x->fg=;
swap(x->l,x->r);
if( x->l ) x->l->fg^=;
if( x->r ) x->r->fg^=;
}
Treap *Merge(Treap *A,Treap *B){//合并操作
if(!A)return B;
if(!B)return A;
pushdown(A);pushdown(B);
if(A->fix<B->fix){
A->r=Merge(A->r,B);
A->updata();
return A;
}
else{
B->l=Merge(A,B->l);
B->updata();
return B;
}
} Droot Split(Treap *x,int k){//拆分操作
if(!x)return Droot(NULL,NULL);
Droot y;
pushdown(x);
if(Size(x->l)>=k){
y=Split(x->l,k);
x->l=y.second;
x->updata();
y.second=x;
}
else{
y=Split(x->r,k-Size(x->l)-);
x->r=y.first;
x->updata();
y.first=x;
}
return y;
}
Treap *build(int L,int R){
if(L>R)return NULL;
int mid=(L+R)>>,key=mid-;
Treap *x =new Treap(key);
x->l = build(L,mid-);
x->r = build(mid+,R);
x->updata();
return x;
}
Treap *Build(int *a){//建造操作
static Treap *stack[maxn],*x,*last;
int p=;
rep(i,,a[]){
x=new Treap(a[i]);
last=NULL;
while(p && stack[p]->fix>x->fix){
stack[p]->updata();
last=stack[p];
stack[p--]=NULL;
}
if(p) stack[p]->r=x;
x->l=last;
stack[++p]=x;
}
while(p) stack[p--]->updata();
return stack[];
} void order(Treap *x){
if( x == NULL ) return;
pushdown(x);
order(x->l);
if(x->key >= && x->key<=n)printf("%d ",x->key);
order(x->r);
}
void rev(int L,int R){
Droot tmp1=Split(root,R+);
Droot tmp2=Split(tmp1.first,L);
tmp2.second->fg^=;
root = NULL;
root = Merge(tmp2.first,tmp2.second);
root = Merge(root,tmp1.second);
}
//int Findkth(int k){//查找第K小
// Droot x=Split(root,k-1);
// Droot y=Split(x.second,1);
// Treap *ans=y.first;
// root=Merge(Merge(x.first,ans),y.second);
// return ans->key;
//} //int Getkth(Treap *x,int v){//询问一个数是第几大
// if(!x)return 0;
// return v<x->key?Getkth(x->l,v):Getkth(x->r,v)+Size(x->l)+1;
//} //void Insert(int v){//插入操作
// int k=Getkth(root,v);
// Droot x=Split(root,k);
// Treap *n=new Treap(v);
// root=Merge(Merge(x.first,n),x.second);
//} //void Delete(int k){//删除操作
// Droot x=Split(root,k-1);
// Droot y=Split(x.second,1);
// root=Merge(x.first,y.second);
//} //int a[maxn],M,x,y;
int M;
int main(){
//scanf("%d",a);
//rep(i,1,a[0]) scanf("%d",a+i);
//sort(a+1,a+1+a[0]);
//root=Build(a);
scanf("%d",&n);
scanf("%d",&M);
root=build(,n+);
int L,R;
while(M--){
// char ch=getchar();
// while(ch!='Q' && ch!='A' && ch!='D') ch=getchar();
// scanf("%d",&x);
// if(ch=='Q') printf("%d\n",Findkth(x));
// if(ch=='A') Insert(x);
// if(ch=='D') Delete(x);
scanf("%d%d",&L,&R);
rev(L,R);
}
order(root);
}

再粘一个非指针版的我敬爱的学长szb写的,浙大一本爷

#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define mp make_pair
typedef pair<int,int> par;
const int N=;
const int inf=1e9;
int n,root,cnt;
int l[N],r[N],key[N],rnd[N],size[N];
int readin() {
int x=,f=; char ch=getchar();
while(ch>''||ch<'') {if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<='') {x=x*+ch-'';ch=getchar();}
return x*f;
}
void update(int x) {
size[x]=size[l[x]]+size[r[x]]+;
return;
}
int merge(int x,int y) {
if (!x||!y)
return x+y;
if (rnd[x]<rnd[y]) {
r[x]=merge(r[x],y);
update(x); return x;
}
else {
l[y]=merge(x,l[y]);
update(y); return y;
}
}
par split(int x,int k) {
if (k==)
return mp(,x);
int ls=l[x],rs=r[x];
if (k<=size[l[x]]) {
par t=split(l[x],k);
l[x]=t.second; update(x);
return mp(t.first,x);
}
else if (k==size[l[x]]+) {
r[x]=; update(x);
return mp(x,rs);
}
else {
par t=split(rs,k-(size[l[x]]+));
r[x]=t.first; update(x);
return mp(x,t.second);
}
}
int query_rank(int x,int k) {
int ans=,t=inf;
while(x) {
if (k==key[x]) t=min(t,ans+size[l[x]]+);
if (k>key[x]) ans+=(size[l[x]]+),x=r[x];
else x=l[x];
}
return t==inf?ans:t;
}
void insert(int x) {
int k=query_rank(root,x);
par t=split(root,k);
key[++cnt]=x,rnd[cnt]=rand(),size[cnt]=;
root=merge(t.first,cnt);
root=merge(root,t.second);
return;
}
void del(int x) {
int k=query_rank(root,x);
par t1=split(root,k);
par t2=split(t1.first,k-);
root=merge(t2.first,t1.second);
return;
}
int query_num(int x,int k) {
while() {
if (k==size[l[x]]+) return key[x];
if (k<=size[l[x]]) x=l[x];
else k-=(size[l[x]]+),x=r[x];
}
}
int query_pre(int x,int k) {
int ans=-inf;
while(x) {
if (key[x]<k)
ans=max(ans,key[x]),x=r[x];
else
x=l[x];
}
return ans;
}
int query_sub(int x,int k) {
int ans=inf;
while(x) {
if (key[x]>k)
ans=min(ans,key[x]),x=l[x];
else
x=r[x];
}
return ans;
}
int main() {
int opt,x;
n=readin();
for (int i=;i<=n;i++) {
opt=readin(),x=readin();
if (opt==) insert(x);
else if (opt==) del(x);
else if (opt==) printf("%d\n",query_rank(root,x));
else if (opt==) printf("%d\n",query_num(root,x));
else if (opt==) printf("%d\n",query_pre(root,x));
else printf("%d\n",query_sub(root,x));
}
return ;
}

序列终结者 ,调了好久发现区间截取错了那我咋A的文艺平衡树啊???啊~好像是那个程序建树的时候整个往后串了一位

#include<bits/stdc++.h>
using namespace std;
#define maxn 2000005
int n;
#define inf 1000000000
struct Treap{
Treap *l,*r;
int fix,key,size,mx,add;
bool fg;
Treap(int key_):fix(rand()),key(key_),l(NULL),r(NULL),size(),mx(),fg(),add(){}
void addv(int w){mx+=w;add+=w;key+=w;}
inline void updata(){
size=+(l?l->size:)+(r?r->size:);
mx=max(key,max((l?l->mx:-inf),(r?r->mx:-inf)));
}
}*root;
typedef pair<Treap*,Treap*> Droot;//用来Split返回两个根 inline int Size(Treap *x){return x?x->size:;}//这样求size可以防止访问空指针
void pushdown(Treap *x){
if(x->fg){
x->fg=;
swap(x->l,x->r);
if( x->l ) x->l->fg^=;
if( x->r ) x->r->fg^=;}
if(x->add){
if( x->l ) x->l->addv(x->add);
if( x->r ) x->r->addv(x->add);
x->add=;
}
}
Treap *Merge(Treap *A,Treap *B){//合并操作
if(!A)return B;
if(!B)return A;
pushdown(A);pushdown(B);
if(A->fix<B->fix){
A->r=Merge(A->r,B);
A->updata();
return A;
}
else{
B->l=Merge(A,B->l);
B->updata();
return B;
}
} Droot Split(Treap *x,int k){//拆分操作
if(!x)return Droot(NULL,NULL);
Droot y;
pushdown(x);
if(Size(x->l)>=k){
y=Split(x->l,k);
x->l=y.second;
x->updata();
y.second=x;
}
else{
y=Split(x->r,k-Size(x->l)-);
x->r=y.first;
x->updata();
y.first=x;
}
return y;
} void rev(int L,int R){
Droot tmp1=Split(root,R);
Droot tmp2=Split(tmp1.first,L-);
tmp2.second->fg^=;
root = Merge( Merge(tmp2.first,tmp2.second),tmp1.second);
}
void up(int L,int R,int v){
Droot tmp1=Split(root,R);
Droot tmp2=Split(tmp1.first,L-);
tmp2.second->addv(v);
root = Merge(Merge(tmp2.first,tmp2.second),tmp1.second);
}
int query(int L,int R){
Droot tmp1=Split(root,R);
Droot tmp2=Split(tmp1.first,L-);
int ret=tmp2.second->mx;
root = Merge(Merge(tmp2.first,tmp2.second),tmp1.second);
return ret;
}
int M;
int main(){
scanf("%d",&n);
scanf("%d",&M);
for(int i=;i<=n;i++){
Treap *a=new Treap();
root=Merge(root,a);
}
int L,R;
int f,v;
while(M--){
scanf("%d",&f);
if(f==){ scanf("%d%d%d",&L,&R,&v);
up(L,R,v);}
else if(f==){
scanf("%d%d",&L,&R); rev(L,R);
}
else {
scanf("%d%d",&L,&R);
printf("%d\n",query(L,R));
}
} }

Treap 模板的更多相关文章

  1. BZOJ 1588: Treap 模板

    1588: [HNOI2002]营业额统计 Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 12171  Solved: 4352 Description ...

  2. [luogu3369]普通平衡树(treap模板)

    解题关键:treap模板保存. #include<cstdio> #include<cstring> #include<algorithm> #include< ...

  3. Treap 模板 poj1442&hdu4557

    原理可以看hihocoder上面的讲解,很清楚,不多说了. 模板抄lrj训练指南上面的. /** Treap 实现 名次树 功能: 1.找到排名为k的元素 2.值为x的元素的名次 初始化:Node* ...

  4. 平衡树Treap模板与原理

    这次我们来讲一讲Treap(splay以后再更) 平衡树是一种排序二叉树(或二叉搜索树),所以排序二叉树可以迅速地判断两个值的大小,当然操作肯定不止那么多(不然我们还学什么). 而平衡树在排序二叉树的 ...

  5. POJ1442-查询第K大-Treap模板题

    模板题,以后要学splay,大概看一下treap就好了. #include <cstdio> #include <algorithm> #include <cstring ...

  6. 【Treap模板详细注释】BZOJ3224-普通平衡树

    模板题:D错因见注释 #include<iostream> #include<cstdio> #include<cstring> #include<algor ...

  7. 非旋treap模板

    bzoj3580 非旋转treap 在大神教导下发现split一段区间时先split右边再split左边比较好写 #include <cstdio> #include <cstdli ...

  8. codevs 4543 treap 模板

    type rec=record lc,rc,v,rnd,size,w,fa:longint; end; var n,root,tot,ans,opt,x,i,po:longint; tr:array[ ...

  9. Treap模板

    平衡树总是有用的,set由于过度封装没有办法实现找比x小的元素有多少个,这就显得很不方便了,所以封装了个Treap,万一以后用的着呢- -01 #pragma warning(disable:4996 ...

随机推荐

  1. Pig关系型运算符例子

    1.新建两个文件A.txt与B.txt, A.txt文件的内容如下: 0,1,2 1,3,4 B.txt文件的内容如下: 0,5,2 1,7,8 将这两个文件上传到目录/zwy/soft 2.定义关系 ...

  2. python递归函数(计算阶乘)

    def f1(x,x1=1): if x == 1: return x1 #x1这个值为我们所需要的值,所以返回 x1 *= x r = f1(x-1,x1) #r接收返回值,并在下面接着返回 ret ...

  3. MySQL共享表空间扩容

    一.什么是共享表空间和独占表空间 共享表空间以及独占表空间都是针对数据的存储方式而言的. 共享表空间: 某一个数据库的所有的表数据,索引文件全部放在一个文件中,默认这个共享表空间的文件路径在data目 ...

  4. EAS集锦

    前言 之前看过的相关BOS开发文档,整理了一些常用的API,一直没有来得及放上来,现在把整理的文件放上来,以备忘查看,分享.闲话少说,上干货! ps 图片不方便查看的话,可以拖住图片,加载到浏览器新页 ...

  5. Jmeter——小性能用例

    1.添加默认值,将代理服务器写入 2.添加HTTP请求头,将域名部分用变量形式写入:${__CSVRead(D:/number.txt,0)},这是为了查询不同页面,在D:/number.txt路径下 ...

  6. liunx运维必备150个基础命令

    经过上次的面试,总结了一下的linux系统常用命令: 命令 功能说明 线上查询及帮助命令(2个) man 查看命令帮助,命令的词典,更复杂的还有info,但不常用. help 查看Linux内置命令的 ...

  7. LeetCode 74——搜索二维矩阵

    1. 题目 2. 解答 若矩阵为空,比如 [], [[]],此时直接返回 false. 若目标值小于矩阵第一个元素或者大于矩阵最后一个元素,则目标值不在矩阵范围内,直接返回 false. 其他情况下, ...

  8. N-grams模型、停顿词(stopwords)和标准化处理 - NLP学习(2)

    在上一节<Tokenization - NLP(1)>的学习中,我们主要学习了如何将一串字符串分割成单独的字符,并且形成一个词汇集(vocabulary),之后我们将形成的词汇集合转换成计 ...

  9. 容器基础(十): 使用kubernetes部署应用

    概述 使用之前的脚本(env/server.py 得到 env/server:v0.1 镜像, env/worker.py 得到 env/worker:v0.1)得到的镜像,在部署好kubernete ...

  10. 英特尔CEO科再奇:尚未发现通过漏洞获取用户数据的行为

    1月9日消息,英特尔CEO科再奇在美国西部时间1月8日举行的2018年CES中发表主题演讲,他在开场时面向产业界谈到了最近报道的安全研究发现.科再奇表示:“在我们开始之前,我想借此机会感谢整个行业,为 ...