感觉平衡树也没有以前想的那么玄乎,(其实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. php-5.6.26源代码 - include_once、require_once、include、require、eval 的opcode处理器

    # ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER 实现在文件 php-\Zend\zend_vm_execute.h static int ZEND_FASTCALL ...

  2. hadoop生态搭建(3节点)-03.zookeeper配置

    # https://www.oracle.com/technetwork/java/javase/downloads/java-archive-javase8-2177648.html # ===== ...

  3. 第三章 最简单的C程序设计——顺序程序设计

    一.数据的表现形式及其运算 1.常量和变量 在计算机高级语言中,数据有两种表现形式:常量和变量. 1.1.常量 在程序运行过程中,其值不能被改变的量称为常量.如:5,6,32,0.111. 数值常量就 ...

  4. 再谈js传值和传址

    js的传值和传址还是真绕,前回文说道 1.值类型是传值的 2.对象和数组是传址的 这两点通过例子的到了证实 然而还有一种情况没有讨论 即 函数的参数的传值和传址 通过实验,在函数中用一个新对象去覆盖传 ...

  5. 2 socket UDP通信

    1 socket套接字  class 对象 In [1]: import socket In [2]: help(socket.socket) class socket(_socket.socket) ...

  6. P1823 音乐会的等待(单调栈)

    P1823 音乐会的等待 题目描述 N个人正在排队进入一个音乐会.人们等得很无聊,于是他们开始转来转去,想在队伍里寻找自己的熟人.队列中任意两个人A和B,如果他们是相邻或他们之间没有人比A或B高,那么 ...

  7. 剁了xp,醉了win7

    装完win7,安装各种软件完毕,重启,然并卵.  cpu,内存飙升!! svchost.exe这个进程内存发疯了一样往上飙升 从 几十兆  到占用1个多G, 纳尼, 总共物理内存才2G. ╮(╯▽╰) ...

  8. Tapestry 权威讲解-备份

    http://blog.csdn.net/mindhawk/article/details/5021371#introduction

  9. Qt用委托绘制需要的图形的步骤

    1.拷贝一份option: QStyleOptionViewItemV4 opt = option; 2.获取到widget,也是通过QStyleOptionViewItem &option ...

  10. OpenCV入门:(二:加载,显示,修改以及保存图片)

    目标: 1.从图片文件打开图片(imread) 2.显示图片(namedWindow和imshow) 3.转换当前图片为灰色图片(cvtColor) 4.保存图片(imwrite) 代码: #incl ...